forked from hinterland/hearth
feat: vendor gitea 1.16.2
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
lib,
|
lib,
|
||||||
buildGoModule,
|
buildGo126Module,
|
||||||
makeWrapper,
|
makeWrapper,
|
||||||
git,
|
git,
|
||||||
bash,
|
bash,
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
openssh,
|
openssh,
|
||||||
fetchPnpmDeps,
|
fetchPnpmDeps,
|
||||||
pnpmConfigHook,
|
pnpmConfigHook,
|
||||||
pnpm,
|
pnpm_10,
|
||||||
stdenv,
|
stdenv,
|
||||||
sqliteSupport ? true,
|
sqliteSupport ? true,
|
||||||
nixosTests,
|
nixosTests,
|
||||||
@@ -18,8 +18,9 @@
|
|||||||
|
|
||||||
let
|
let
|
||||||
pname = "gitea";
|
pname = "gitea";
|
||||||
version = "1.25.4";
|
version = "1.26.2";
|
||||||
src = ./source;
|
src = ./source;
|
||||||
|
pnpm = pnpm_10;
|
||||||
|
|
||||||
frontend = stdenv.mkDerivation {
|
frontend = stdenv.mkDerivation {
|
||||||
pname = "gitea-frontend";
|
pname = "gitea-frontend";
|
||||||
@@ -28,8 +29,9 @@ let
|
|||||||
pnpmDeps = fetchPnpmDeps {
|
pnpmDeps = fetchPnpmDeps {
|
||||||
pname = "gitea-frontend";
|
pname = "gitea-frontend";
|
||||||
inherit version src;
|
inherit version src;
|
||||||
fetcherVersion = 2;
|
inherit pnpm;
|
||||||
hash = "sha256-0p7P68BvO3hv0utUbnPpHSpGLlV7F9HHmOITvJAb/ww=";
|
fetcherVersion = 3;
|
||||||
|
hash = "sha256-Qo0DLuZv+2GVLsBfCv/6CC9E/qhSE4HwV4StQL4HX4Y=";
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
@@ -48,11 +50,11 @@ let
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
buildGoModule rec {
|
buildGo126Module rec {
|
||||||
inherit pname version src;
|
inherit pname version src;
|
||||||
|
|
||||||
proxyVendor = true;
|
proxyVendor = true;
|
||||||
vendorHash = "sha256-y7HurJg+/V1cn8iKDXepk/ie/iNgiJXsQbDi1dhgark=";
|
vendorHash = "sha256-7+M1n8RSgB3gZ/2na4RF9kYOf90H0bnsJZMDKpgAy64=";
|
||||||
|
|
||||||
outputs = [
|
outputs = [
|
||||||
"out"
|
"out"
|
||||||
@@ -61,10 +63,17 @@ buildGoModule rec {
|
|||||||
|
|
||||||
patches = [ ./static-root-path.patch ];
|
patches = [ ./static-root-path.patch ];
|
||||||
|
|
||||||
overrideModAttrs = _: { postPatch = null; };
|
overrideModAttrs = _: {
|
||||||
|
postPatch = ''
|
||||||
|
substituteInPlace go.mod \
|
||||||
|
--replace-fail "go 1.26.3" "go 1.26"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
postPatch = ''
|
postPatch = ''
|
||||||
substituteInPlace modules/setting/server.go --subst-var data
|
substituteInPlace modules/setting/server.go --subst-var data
|
||||||
|
substituteInPlace go.mod \
|
||||||
|
--replace-fail "go 1.26.3" "go 1.26"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
subPackages = [ "." ];
|
subPackages = [ "." ];
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ tmp_dir = ".air"
|
|||||||
[build]
|
[build]
|
||||||
pre_cmd = ["killall -9 gitea 2>/dev/null || true"] # kill off potential zombie processes from previous runs
|
pre_cmd = ["killall -9 gitea 2>/dev/null || true"] # kill off potential zombie processes from previous runs
|
||||||
cmd = "make --no-print-directory backend"
|
cmd = "make --no-print-directory backend"
|
||||||
bin = "gitea"
|
entrypoint = ["./gitea"]
|
||||||
delay = 2000
|
delay = 2000
|
||||||
include_ext = ["go", "tmpl"]
|
include_ext = ["go", "tmpl"]
|
||||||
include_file = ["main.go"]
|
include_file = ["main.go"]
|
||||||
|
|||||||
@@ -13,14 +13,13 @@
|
|||||||
"ghcr.io/devcontainers/features/git-lfs:1.2.5": {},
|
"ghcr.io/devcontainers/features/git-lfs:1.2.5": {},
|
||||||
"ghcr.io/jsburckhardt/devcontainer-features/uv:1": {},
|
"ghcr.io/jsburckhardt/devcontainer-features/uv:1": {},
|
||||||
"ghcr.io/devcontainers/features/python:1": {
|
"ghcr.io/devcontainers/features/python:1": {
|
||||||
"version": "3.13"
|
"version": "3.14"
|
||||||
},
|
},
|
||||||
"ghcr.io/warrenbuckley/codespace-features/sqlite:1": {}
|
"ghcr.io/warrenbuckley/codespace-features/sqlite:1": {}
|
||||||
},
|
},
|
||||||
"customizations": {
|
"customizations": {
|
||||||
"vscode": {
|
"vscode": {
|
||||||
"settings": {},
|
"settings": {},
|
||||||
// same extensions as Gitpod, should match /.gitpod.yml
|
|
||||||
"extensions": [
|
"extensions": [
|
||||||
"editorconfig.editorconfig",
|
"editorconfig.editorconfig",
|
||||||
"dbaeumer.vscode-eslint",
|
"dbaeumer.vscode-eslint",
|
||||||
|
|||||||
@@ -74,6 +74,9 @@ cpu.out
|
|||||||
/VERSION
|
/VERSION
|
||||||
/.air
|
/.air
|
||||||
/.go-licenses
|
/.go-licenses
|
||||||
|
/Dockerfile
|
||||||
|
/Dockerfile.rootless
|
||||||
|
/.venv
|
||||||
|
|
||||||
# Files and folders that were previously generated
|
# Files and folders that were previously generated
|
||||||
/public/assets/img/webpack
|
/public/assets/img/webpack
|
||||||
|
|||||||
@@ -8,3 +8,4 @@
|
|||||||
/vendor/** -text -eol linguist-vendored
|
/vendor/** -text -eol linguist-vendored
|
||||||
/web_src/js/vendor/** -text -eol linguist-vendored
|
/web_src/js/vendor/** -text -eol linguist-vendored
|
||||||
Dockerfile.* linguist-language=Dockerfile
|
Dockerfile.* linguist-language=Dockerfile
|
||||||
|
Makefile.* linguist-language=Makefile
|
||||||
|
|||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
version: 2
|
||||||
|
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: github-actions
|
||||||
|
labels: [modifies/dependencies]
|
||||||
|
directory: /
|
||||||
|
schedule:
|
||||||
|
interval: daily
|
||||||
|
cooldown:
|
||||||
|
default-days: 5
|
||||||
+3
-5
@@ -43,15 +43,13 @@ modifies/internal:
|
|||||||
- ".editorconfig"
|
- ".editorconfig"
|
||||||
- ".eslintrc.cjs"
|
- ".eslintrc.cjs"
|
||||||
- ".golangci.yml"
|
- ".golangci.yml"
|
||||||
- ".gitpod.yml"
|
|
||||||
- ".markdownlint.yaml"
|
- ".markdownlint.yaml"
|
||||||
- ".spectral.yaml"
|
- ".spectral.yaml"
|
||||||
- "stylelint.config.js"
|
- "stylelint.config.*"
|
||||||
- ".yamllint.yaml"
|
- ".yamllint.yaml"
|
||||||
- ".github/**"
|
- ".github/**"
|
||||||
- ".gitea/**"
|
- ".gitea/**"
|
||||||
- ".devcontainer/**"
|
- ".devcontainer/**"
|
||||||
- "build.go"
|
|
||||||
- "build/**"
|
- "build/**"
|
||||||
- "contrib/**"
|
- "contrib/**"
|
||||||
|
|
||||||
@@ -85,9 +83,9 @@ docs-update-needed:
|
|||||||
topic/code-linting:
|
topic/code-linting:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file:
|
- any-glob-to-any-file:
|
||||||
- ".eslintrc.cjs"
|
|
||||||
- ".golangci.yml"
|
- ".golangci.yml"
|
||||||
- ".markdownlint.yaml"
|
- ".markdownlint.yaml"
|
||||||
- ".spectral.yaml"
|
- ".spectral.yaml"
|
||||||
- ".yamllint.yaml"
|
- ".yamllint.yaml"
|
||||||
- "stylelint.config.js"
|
- "eslint*.config.*"
|
||||||
|
- "stylelint.config.*"
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
name: cron-flake-updater
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * 0' # runs weekly on Sunday at 00:00
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
nix-flake-update:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
- uses: DeterminateSystems/determinate-nix-action@v3
|
||||||
|
- uses: DeterminateSystems/update-flake-lock@main
|
||||||
|
with:
|
||||||
|
pr-title: "Update Nix flake"
|
||||||
|
pr-labels: |
|
||||||
|
dependencies
|
||||||
@@ -9,8 +9,10 @@ jobs:
|
|||||||
cron-licenses:
|
cron-licenses:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.repository == 'go-gitea/gitea'
|
if: github.repository == 'go-gitea/gitea'
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-go@v6
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
@@ -18,7 +20,7 @@ jobs:
|
|||||||
- run: make generate-gitignore
|
- run: make generate-gitignore
|
||||||
timeout-minutes: 40
|
timeout-minutes: 40
|
||||||
- name: push translations to repo
|
- name: push translations to repo
|
||||||
uses: appleboy/git-push-action@v0.0.3
|
uses: appleboy/git-push-action@v1.2.0
|
||||||
with:
|
with:
|
||||||
author_email: "teabot@gitea.io"
|
author_email: "teabot@gitea.io"
|
||||||
author_name: GiteaBot
|
author_name: GiteaBot
|
||||||
|
|||||||
@@ -9,9 +9,11 @@ jobs:
|
|||||||
crowdin-pull:
|
crowdin-pull:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.repository == 'go-gitea/gitea'
|
if: github.repository == 'go-gitea/gitea'
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: crowdin/github-action@v1
|
- uses: crowdin/github-action@v2
|
||||||
with:
|
with:
|
||||||
upload_sources: true
|
upload_sources: true
|
||||||
upload_translations: false
|
upload_translations: false
|
||||||
@@ -27,7 +29,7 @@ jobs:
|
|||||||
- name: update locales
|
- name: update locales
|
||||||
run: ./build/update-locales.sh
|
run: ./build/update-locales.sh
|
||||||
- name: push translations to repo
|
- name: push translations to repo
|
||||||
uses: appleboy/git-push-action@v0.0.3
|
uses: appleboy/git-push-action@v1.2.0
|
||||||
with:
|
with:
|
||||||
author_email: "teabot@gitea.io"
|
author_email: "teabot@gitea.io"
|
||||||
author_name: GiteaBot
|
author_name: GiteaBot
|
||||||
|
|||||||
+12
-3
@@ -19,11 +19,15 @@ on:
|
|||||||
value: ${{ jobs.detect.outputs.swagger }}
|
value: ${{ jobs.detect.outputs.swagger }}
|
||||||
yaml:
|
yaml:
|
||||||
value: ${{ jobs.detect.outputs.yaml }}
|
value: ${{ jobs.detect.outputs.yaml }}
|
||||||
|
json:
|
||||||
|
value: ${{ jobs.detect.outputs.json }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
detect:
|
detect:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 3
|
timeout-minutes: 3
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
outputs:
|
outputs:
|
||||||
backend: ${{ steps.changes.outputs.backend }}
|
backend: ${{ steps.changes.outputs.backend }}
|
||||||
frontend: ${{ steps.changes.outputs.frontend }}
|
frontend: ${{ steps.changes.outputs.frontend }}
|
||||||
@@ -33,9 +37,10 @@ jobs:
|
|||||||
docker: ${{ steps.changes.outputs.docker }}
|
docker: ${{ steps.changes.outputs.docker }}
|
||||||
swagger: ${{ steps.changes.outputs.swagger }}
|
swagger: ${{ steps.changes.outputs.swagger }}
|
||||||
yaml: ${{ steps.changes.outputs.yaml }}
|
yaml: ${{ steps.changes.outputs.yaml }}
|
||||||
|
json: ${{ steps.changes.outputs.json }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: dorny/paths-filter@v3
|
- uses: dorny/paths-filter@v4
|
||||||
id: changes
|
id: changes
|
||||||
with:
|
with:
|
||||||
filters: |
|
filters: |
|
||||||
@@ -48,7 +53,7 @@ jobs:
|
|||||||
- "Makefile"
|
- "Makefile"
|
||||||
- ".golangci.yml"
|
- ".golangci.yml"
|
||||||
- ".editorconfig"
|
- ".editorconfig"
|
||||||
- "options/locale/locale_en-US.ini"
|
- "options/locale/locale_en-US.json"
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
- "*.js"
|
- "*.js"
|
||||||
@@ -80,6 +85,7 @@ jobs:
|
|||||||
- "uv.lock"
|
- "uv.lock"
|
||||||
|
|
||||||
docker:
|
docker:
|
||||||
|
- ".github/workflows/pull-docker-dryrun.yml"
|
||||||
- "Dockerfile"
|
- "Dockerfile"
|
||||||
- "Dockerfile.rootless"
|
- "Dockerfile.rootless"
|
||||||
- "docker/**"
|
- "docker/**"
|
||||||
@@ -98,3 +104,6 @@ jobs:
|
|||||||
- "**/*.yaml"
|
- "**/*.yaml"
|
||||||
- ".yamllint.yaml"
|
- ".yamllint.yaml"
|
||||||
- "pyproject.toml"
|
- "pyproject.toml"
|
||||||
|
|
||||||
|
json:
|
||||||
|
- "**/*.json"
|
||||||
|
|||||||
+73
-24
@@ -10,13 +10,17 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
files-changed:
|
files-changed:
|
||||||
uses: ./.github/workflows/files-changed.yml
|
uses: ./.github/workflows/files-changed.yml
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
lint-backend:
|
lint-backend:
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-go@v6
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
@@ -30,14 +34,18 @@ jobs:
|
|||||||
if: needs.files-changed.outputs.templates == 'true'
|
if: needs.files-changed.outputs.templates == 'true'
|
||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: astral-sh/setup-uv@v6
|
- uses: astral-sh/setup-uv@v8.0.0
|
||||||
- run: uv python install 3.12
|
- run: uv python install 3.14
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v5
|
||||||
- uses: actions/setup-node@v5
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 24
|
||||||
|
cache: pnpm
|
||||||
|
cache-dependency-path: pnpm-lock.yaml
|
||||||
- run: make deps-py
|
- run: make deps-py
|
||||||
- run: make deps-frontend
|
- run: make deps-frontend
|
||||||
- run: make lint-templates
|
- run: make lint-templates
|
||||||
@@ -46,23 +54,44 @@ jobs:
|
|||||||
if: needs.files-changed.outputs.yaml == 'true'
|
if: needs.files-changed.outputs.yaml == 'true'
|
||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: astral-sh/setup-uv@v6
|
- uses: astral-sh/setup-uv@v8.0.0
|
||||||
- run: uv python install 3.12
|
- run: uv python install 3.14
|
||||||
- run: make deps-py
|
- run: make deps-py
|
||||||
- run: make lint-yaml
|
- run: make lint-yaml
|
||||||
|
|
||||||
|
lint-json:
|
||||||
|
if: needs.files-changed.outputs.json == 'true'
|
||||||
|
needs: files-changed
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
- uses: pnpm/action-setup@v5
|
||||||
|
- uses: actions/setup-node@v5
|
||||||
|
with:
|
||||||
|
node-version: 24
|
||||||
|
- run: make deps-frontend
|
||||||
|
- run: make lint-json
|
||||||
|
|
||||||
lint-swagger:
|
lint-swagger:
|
||||||
if: needs.files-changed.outputs.swagger == 'true'
|
if: needs.files-changed.outputs.swagger == 'true'
|
||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v5
|
||||||
- uses: actions/setup-node@v5
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 24
|
||||||
|
cache: pnpm
|
||||||
|
cache-dependency-path: pnpm-lock.yaml
|
||||||
- run: make deps-frontend
|
- run: make deps-frontend
|
||||||
- run: make lint-swagger
|
- run: make lint-swagger
|
||||||
|
|
||||||
@@ -70,8 +99,10 @@ jobs:
|
|||||||
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'
|
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
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-go@v6
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
@@ -82,8 +113,10 @@ jobs:
|
|||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-go@v6
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
@@ -99,8 +132,10 @@ jobs:
|
|||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-go@v6
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
@@ -114,8 +149,10 @@ jobs:
|
|||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-go@v6
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
@@ -127,12 +164,16 @@ jobs:
|
|||||||
if: needs.files-changed.outputs.frontend == 'true' || needs.files-changed.outputs.actions == 'true'
|
if: needs.files-changed.outputs.frontend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v5
|
||||||
- uses: actions/setup-node@v5
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 24
|
||||||
|
cache: pnpm
|
||||||
|
cache-dependency-path: pnpm-lock.yaml
|
||||||
- run: make deps-frontend
|
- run: make deps-frontend
|
||||||
- run: make lint-frontend
|
- run: make lint-frontend
|
||||||
- run: make checks-frontend
|
- run: make checks-frontend
|
||||||
@@ -143,8 +184,10 @@ jobs:
|
|||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-go@v6
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
@@ -175,12 +218,16 @@ jobs:
|
|||||||
if: needs.files-changed.outputs.docs == 'true' || needs.files-changed.outputs.actions == 'true'
|
if: needs.files-changed.outputs.docs == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v5
|
||||||
- uses: actions/setup-node@v5
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 24
|
||||||
|
cache: pnpm
|
||||||
|
cache-dependency-path: pnpm-lock.yaml
|
||||||
- run: make deps-frontend
|
- run: make deps-frontend
|
||||||
- run: make lint-md
|
- run: make lint-md
|
||||||
|
|
||||||
@@ -188,8 +235,10 @@ jobs:
|
|||||||
if: needs.files-changed.outputs.actions == 'true' || needs.files-changed.outputs.actions == 'true'
|
if: needs.files-changed.outputs.actions == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-go@v6
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
|
|||||||
+20
-12
@@ -10,11 +10,15 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
files-changed:
|
files-changed:
|
||||||
uses: ./.github/workflows/files-changed.yml
|
uses: ./.github/workflows/files-changed.yml
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
test-pgsql:
|
test-pgsql:
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
services:
|
services:
|
||||||
pgsql:
|
pgsql:
|
||||||
image: postgres:14
|
image: postgres:14
|
||||||
@@ -38,7 +42,7 @@ jobs:
|
|||||||
ports:
|
ports:
|
||||||
- "9000:9000"
|
- "9000:9000"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-go@v6
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
@@ -59,37 +63,39 @@ jobs:
|
|||||||
RACE_ENABLED: true
|
RACE_ENABLED: true
|
||||||
TEST_TAGS: gogit
|
TEST_TAGS: gogit
|
||||||
TEST_LDAP: 1
|
TEST_LDAP: 1
|
||||||
USE_REPO_TEST_DIR: 1
|
|
||||||
|
|
||||||
test-sqlite:
|
test-sqlite:
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-go@v6
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
check-latest: true
|
check-latest: true
|
||||||
- run: make deps-backend
|
- run: make deps-backend
|
||||||
- run: make backend
|
- run: GOEXPERIMENT='' make backend
|
||||||
env:
|
env:
|
||||||
TAGS: bindata gogit sqlite sqlite_unlock_notify
|
TAGS: bindata gogit sqlite sqlite_unlock_notify
|
||||||
- name: run migration tests
|
- name: run migration tests
|
||||||
run: make test-sqlite-migration
|
run: make test-sqlite-migration
|
||||||
- name: run tests
|
- name: run tests
|
||||||
run: make test-sqlite
|
run: GOEXPERIMENT='' make test-sqlite
|
||||||
timeout-minutes: 50
|
timeout-minutes: 50
|
||||||
env:
|
env:
|
||||||
TAGS: bindata gogit sqlite sqlite_unlock_notify
|
TAGS: bindata gogit sqlite sqlite_unlock_notify
|
||||||
RACE_ENABLED: true
|
RACE_ENABLED: true
|
||||||
TEST_TAGS: gogit sqlite sqlite_unlock_notify
|
TEST_TAGS: gogit sqlite sqlite_unlock_notify
|
||||||
USE_REPO_TEST_DIR: 1
|
|
||||||
|
|
||||||
test-unit:
|
test-unit:
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
services:
|
services:
|
||||||
elasticsearch:
|
elasticsearch:
|
||||||
image: elasticsearch:7.5.0
|
image: elasticsearch:7.5.0
|
||||||
@@ -124,7 +130,7 @@ jobs:
|
|||||||
ports:
|
ports:
|
||||||
- 10000:10000
|
- 10000:10000
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-go@v6
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
@@ -142,7 +148,7 @@ jobs:
|
|||||||
RACE_ENABLED: true
|
RACE_ENABLED: true
|
||||||
GITHUB_READ_TOKEN: ${{ secrets.GITHUB_READ_TOKEN }}
|
GITHUB_READ_TOKEN: ${{ secrets.GITHUB_READ_TOKEN }}
|
||||||
- name: unit-tests-gogit
|
- name: unit-tests-gogit
|
||||||
run: make unit-test-coverage test-check
|
run: GOEXPERIMENT='' make unit-test-coverage test-check
|
||||||
env:
|
env:
|
||||||
TAGS: bindata gogit
|
TAGS: bindata gogit
|
||||||
RACE_ENABLED: true
|
RACE_ENABLED: true
|
||||||
@@ -152,6 +158,8 @@ jobs:
|
|||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
services:
|
services:
|
||||||
mysql:
|
mysql:
|
||||||
# the bitnami mysql image has more options than the official one, it's easier to customize
|
# the bitnami mysql image has more options than the official one, it's easier to customize
|
||||||
@@ -177,7 +185,7 @@ jobs:
|
|||||||
- "587:587"
|
- "587:587"
|
||||||
- "993:993"
|
- "993:993"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-go@v6
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
@@ -196,13 +204,14 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
TAGS: bindata
|
TAGS: bindata
|
||||||
RACE_ENABLED: true
|
RACE_ENABLED: true
|
||||||
USE_REPO_TEST_DIR: 1
|
|
||||||
TEST_INDEXER_CODE_ES_URL: "http://elastic:changeme@elasticsearch:9200"
|
TEST_INDEXER_CODE_ES_URL: "http://elastic:changeme@elasticsearch:9200"
|
||||||
|
|
||||||
test-mssql:
|
test-mssql:
|
||||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
services:
|
services:
|
||||||
mssql:
|
mssql:
|
||||||
image: mcr.microsoft.com/mssql/server:2019-latest
|
image: mcr.microsoft.com/mssql/server:2019-latest
|
||||||
@@ -217,7 +226,7 @@ jobs:
|
|||||||
ports:
|
ports:
|
||||||
- 10000:10000
|
- 10000:10000
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-go@v6
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
@@ -234,4 +243,3 @@ jobs:
|
|||||||
timeout-minutes: 50
|
timeout-minutes: 50
|
||||||
env:
|
env:
|
||||||
TAGS: bindata
|
TAGS: bindata
|
||||||
USE_REPO_TEST_DIR: 1
|
|
||||||
|
|||||||
+19
-14
@@ -10,26 +10,31 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
files-changed:
|
files-changed:
|
||||||
uses: ./.github/workflows/files-changed.yml
|
uses: ./.github/workflows/files-changed.yml
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
regular:
|
container:
|
||||||
if: needs.files-changed.outputs.docker == 'true' || needs.files-changed.outputs.actions == 'true'
|
if: needs.files-changed.outputs.docker == 'true'
|
||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: docker/setup-buildx-action@v3
|
- uses: actions/checkout@v6
|
||||||
- uses: docker/build-push-action@v5
|
- uses: docker/setup-qemu-action@v4
|
||||||
|
- uses: docker/setup-buildx-action@v4
|
||||||
|
- name: Build regular container image
|
||||||
|
uses: docker/build-push-action@v7
|
||||||
with:
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64,linux/riscv64
|
||||||
push: false
|
push: false
|
||||||
tags: gitea/gitea:linux-amd64
|
cache-from: type=registry,ref=ghcr.io/go-gitea/gitea:buildcache-rootful
|
||||||
|
- name: Build rootless container image
|
||||||
rootless:
|
uses: docker/build-push-action@v7
|
||||||
if: needs.files-changed.outputs.docker == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
needs: files-changed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: docker/setup-buildx-action@v3
|
|
||||||
- uses: docker/build-push-action@v5
|
|
||||||
with:
|
with:
|
||||||
|
context: .
|
||||||
push: false
|
push: false
|
||||||
|
platforms: linux/amd64,linux/arm64,linux/riscv64
|
||||||
file: Dockerfile.rootless
|
file: Dockerfile.rootless
|
||||||
tags: gitea/gitea:linux-amd64
|
cache-from: type=registry,ref=ghcr.io/go-gitea/gitea:buildcache-rootless
|
||||||
|
|||||||
+19
-11
@@ -10,26 +10,34 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
files-changed:
|
files-changed:
|
||||||
uses: ./.github/workflows/files-changed.yml
|
uses: ./.github/workflows/files-changed.yml
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
test-e2e:
|
test-e2e:
|
||||||
# the "test-e2e" won't pass, and it seems that there is no useful test, so skip
|
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.frontend == 'true'
|
||||||
# if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.frontend == 'true' || needs.files-changed.outputs.actions == 'true'
|
|
||||||
if: false
|
|
||||||
needs: files-changed
|
needs: files-changed
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/setup-go@v6
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
check-latest: true
|
check-latest: true
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v5
|
||||||
- uses: actions/setup-node@v5
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 24
|
||||||
- run: make deps-frontend frontend deps-backend
|
cache: pnpm
|
||||||
- run: pnpm exec playwright install --with-deps
|
cache-dependency-path: pnpm-lock.yaml
|
||||||
- run: make test-e2e-sqlite
|
- run: make deps-frontend
|
||||||
timeout-minutes: 40
|
- run: make frontend
|
||||||
|
- run: make deps-backend
|
||||||
|
- run: make gitea-e2e
|
||||||
|
- run: make playwright
|
||||||
|
- run: make test-e2e
|
||||||
|
timeout-minutes: 10
|
||||||
env:
|
env:
|
||||||
USE_REPO_TEST_DIR: 1
|
FORCE_COLOR: 1
|
||||||
|
GITEA_TEST_E2E_DEBUG: 1
|
||||||
|
|||||||
+1
-1
@@ -15,6 +15,6 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/labeler@v5
|
- uses: actions/labeler@v6
|
||||||
with:
|
with:
|
||||||
sync-labels: true
|
sync-labels: true
|
||||||
|
|||||||
+52
-60
@@ -11,8 +11,10 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
nightly-binary:
|
nightly-binary:
|
||||||
runs-on: namespace-profile-gitea-release-binary
|
runs-on: namespace-profile-gitea-release-binary
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
# 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
|
# 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
|
- run: git fetch --unshallow --quiet --tags --force
|
||||||
@@ -20,10 +22,12 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
check-latest: true
|
check-latest: true
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v5
|
||||||
- uses: actions/setup-node@v5
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 24
|
||||||
|
cache: pnpm
|
||||||
|
cache-dependency-path: pnpm-lock.yaml
|
||||||
- run: make deps-frontend deps-backend
|
- run: make deps-frontend deps-backend
|
||||||
# xgo build
|
# xgo build
|
||||||
- run: make release
|
- run: make release
|
||||||
@@ -31,7 +35,7 @@ jobs:
|
|||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
TAGS: bindata sqlite sqlite_unlock_notify
|
||||||
- name: import gpg key
|
- name: import gpg key
|
||||||
id: import_gpg
|
id: import_gpg
|
||||||
uses: crazy-max/ghaction-import-gpg@v6
|
uses: crazy-max/ghaction-import-gpg@v7
|
||||||
with:
|
with:
|
||||||
gpg_private_key: ${{ secrets.GPGSIGN_KEY }}
|
gpg_private_key: ${{ secrets.GPGSIGN_KEY }}
|
||||||
passphrase: ${{ secrets.GPGSIGN_PASSPHRASE }}
|
passphrase: ${{ secrets.GPGSIGN_PASSPHRASE }}
|
||||||
@@ -48,7 +52,7 @@ jobs:
|
|||||||
echo "Cleaned name is ${REF_NAME}"
|
echo "Cleaned name is ${REF_NAME}"
|
||||||
echo "branch=${REF_NAME}-nightly" >> "$GITHUB_OUTPUT"
|
echo "branch=${REF_NAME}-nightly" >> "$GITHUB_OUTPUT"
|
||||||
- name: configure aws
|
- name: configure aws
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
uses: aws-actions/configure-aws-credentials@v6
|
||||||
with:
|
with:
|
||||||
aws-region: ${{ secrets.AWS_REGION }}
|
aws-region: ${{ secrets.AWS_REGION }}
|
||||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
@@ -56,88 +60,76 @@ jobs:
|
|||||||
- name: upload binaries to s3
|
- name: upload binaries to s3
|
||||||
run: |
|
run: |
|
||||||
aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress
|
aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress
|
||||||
nightly-docker-rootful:
|
|
||||||
|
nightly-container:
|
||||||
runs-on: namespace-profile-gitea-release-docker
|
runs-on: namespace-profile-gitea-release-docker
|
||||||
permissions:
|
permissions:
|
||||||
|
contents: read
|
||||||
packages: write # to publish to ghcr.io
|
packages: write # to publish to ghcr.io
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
# 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
|
# 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
|
- run: git fetch --unshallow --quiet --tags --force
|
||||||
- uses: actions/setup-go@v6
|
- uses: docker/setup-qemu-action@v4
|
||||||
with:
|
- uses: docker/setup-buildx-action@v4
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- uses: docker/setup-qemu-action@v3
|
|
||||||
- uses: docker/setup-buildx-action@v3
|
|
||||||
- name: Get cleaned branch name
|
- name: Get cleaned branch name
|
||||||
id: clean_name
|
id: clean_name
|
||||||
run: |
|
run: |
|
||||||
REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\///' -e 's/release\/v//')
|
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"
|
echo "branch=${REF_NAME}-nightly" >> "$GITHUB_OUTPUT"
|
||||||
|
- uses: docker/metadata-action@v6
|
||||||
|
id: meta
|
||||||
|
with:
|
||||||
|
images: |-
|
||||||
|
gitea/gitea
|
||||||
|
ghcr.io/go-gitea/gitea
|
||||||
|
tags: |
|
||||||
|
type=raw,value=${{ steps.clean_name.outputs.branch }}
|
||||||
|
annotations: |
|
||||||
|
org.opencontainers.image.authors="maintainers@gitea.io"
|
||||||
|
- uses: docker/metadata-action@v6
|
||||||
|
id: meta_rootless
|
||||||
|
with:
|
||||||
|
images: |-
|
||||||
|
gitea/gitea
|
||||||
|
ghcr.io/go-gitea/gitea
|
||||||
|
# each tag below will have the suffix of -rootless
|
||||||
|
flavor: |
|
||||||
|
suffix=-rootless
|
||||||
|
tags: |
|
||||||
|
type=raw,value=${{ steps.clean_name.outputs.branch }}
|
||||||
|
annotations: |
|
||||||
|
org.opencontainers.image.authors="maintainers@gitea.io"
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v4
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
- name: Login to GHCR using PAT
|
- name: Login to GHCR using PAT
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v4
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: fetch go modules
|
- name: build regular docker image
|
||||||
run: make vendor
|
uses: docker/build-push-action@v7
|
||||||
- name: build rootful docker image
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm64,linux/riscv64
|
platforms: linux/amd64,linux/arm64,linux/riscv64
|
||||||
push: true
|
push: true
|
||||||
tags: |-
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
gitea/gitea:${{ steps.clean_name.outputs.branch }}
|
annotations: ${{ steps.meta.outputs.annotations }}
|
||||||
ghcr.io/go-gitea/gitea:${{ steps.clean_name.outputs.branch }}
|
cache-from: type=registry,ref=ghcr.io/go-gitea/gitea:buildcache-rootful
|
||||||
nightly-docker-rootless:
|
cache-to: type=registry,ref=ghcr.io/go-gitea/gitea:buildcache-rootful,mode=max
|
||||||
runs-on: namespace-profile-gitea-release-docker
|
|
||||||
permissions:
|
|
||||||
packages: write # to publish to ghcr.io
|
|
||||||
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@v6
|
|
||||||
with:
|
|
||||||
go-version-file: go.mod
|
|
||||||
check-latest: true
|
|
||||||
- uses: docker/setup-qemu-action@v3
|
|
||||||
- uses: docker/setup-buildx-action@v3
|
|
||||||
- name: Get cleaned branch name
|
|
||||||
id: clean_name
|
|
||||||
run: |
|
|
||||||
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
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
- name: Login to GHCR using PAT
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.repository_owner }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: fetch go modules
|
|
||||||
run: make vendor
|
|
||||||
- name: build rootless docker image
|
- name: build rootless docker image
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v7
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64,linux/riscv64
|
||||||
push: true
|
push: true
|
||||||
file: Dockerfile.rootless
|
file: Dockerfile.rootless
|
||||||
tags: |-
|
tags: ${{ steps.meta_rootless.outputs.tags }}
|
||||||
gitea/gitea:${{ steps.clean_name.outputs.branch }}-rootless
|
annotations: ${{ steps.meta_rootless.outputs.annotations }}
|
||||||
ghcr.io/go-gitea/gitea:${{ steps.clean_name.outputs.branch }}-rootless
|
cache-from: type=registry,ref=ghcr.io/go-gitea/gitea:buildcache-rootless
|
||||||
|
cache-to: type=registry,ref=ghcr.io/go-gitea/gitea:buildcache-rootless,mode=max
|
||||||
|
|||||||
+37
-49
@@ -12,8 +12,10 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
binary:
|
binary:
|
||||||
runs-on: namespace-profile-gitea-release-binary
|
runs-on: namespace-profile-gitea-release-binary
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
# 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
|
# 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
|
- run: git fetch --unshallow --quiet --tags --force
|
||||||
@@ -21,10 +23,12 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
check-latest: true
|
check-latest: true
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v5
|
||||||
- uses: actions/setup-node@v5
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 24
|
||||||
|
cache: pnpm
|
||||||
|
cache-dependency-path: pnpm-lock.yaml
|
||||||
- run: make deps-frontend deps-backend
|
- run: make deps-frontend deps-backend
|
||||||
# xgo build
|
# xgo build
|
||||||
- run: make release
|
- run: make release
|
||||||
@@ -32,7 +36,7 @@ jobs:
|
|||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
TAGS: bindata sqlite sqlite_unlock_notify
|
||||||
- name: import gpg key
|
- name: import gpg key
|
||||||
id: import_gpg
|
id: import_gpg
|
||||||
uses: crazy-max/ghaction-import-gpg@v6
|
uses: crazy-max/ghaction-import-gpg@v7
|
||||||
with:
|
with:
|
||||||
gpg_private_key: ${{ secrets.GPGSIGN_KEY }}
|
gpg_private_key: ${{ secrets.GPGSIGN_KEY }}
|
||||||
passphrase: ${{ secrets.GPGSIGN_PASSPHRASE }}
|
passphrase: ${{ secrets.GPGSIGN_PASSPHRASE }}
|
||||||
@@ -49,7 +53,7 @@ jobs:
|
|||||||
echo "Cleaned name is ${REF_NAME}"
|
echo "Cleaned name is ${REF_NAME}"
|
||||||
echo "branch=${REF_NAME}" >> "$GITHUB_OUTPUT"
|
echo "branch=${REF_NAME}" >> "$GITHUB_OUTPUT"
|
||||||
- name: configure aws
|
- name: configure aws
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
uses: aws-actions/configure-aws-credentials@v6
|
||||||
with:
|
with:
|
||||||
aws-region: ${{ secrets.AWS_REGION }}
|
aws-region: ${{ secrets.AWS_REGION }}
|
||||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
@@ -58,7 +62,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress
|
aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress
|
||||||
- name: Install GH CLI
|
- name: Install GH CLI
|
||||||
uses: dev-hanz-ops/install-gh-cli-action@v0.1.0
|
uses: dev-hanz-ops/install-gh-cli-action@v0.2.1
|
||||||
with:
|
with:
|
||||||
gh-cli-version: 2.39.1
|
gh-cli-version: 2.39.1
|
||||||
- name: create github release
|
- name: create github release
|
||||||
@@ -66,18 +70,20 @@ jobs:
|
|||||||
gh release create ${{ github.ref_name }} --title ${{ github.ref_name }} --draft --notes-from-tag dist/release/*
|
gh release create ${{ github.ref_name }} --title ${{ github.ref_name }} --draft --notes-from-tag dist/release/*
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
docker-rootful:
|
|
||||||
|
container:
|
||||||
runs-on: namespace-profile-gitea-release-docker
|
runs-on: namespace-profile-gitea-release-docker
|
||||||
permissions:
|
permissions:
|
||||||
|
contents: read
|
||||||
packages: write # to publish to ghcr.io
|
packages: write # to publish to ghcr.io
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
# 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
|
# 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
|
- run: git fetch --unshallow --quiet --tags --force
|
||||||
- uses: docker/setup-qemu-action@v3
|
- uses: docker/setup-qemu-action@v4
|
||||||
- uses: docker/setup-buildx-action@v3
|
- uses: docker/setup-buildx-action@v4
|
||||||
- uses: docker/metadata-action@v5
|
- uses: docker/metadata-action@v6
|
||||||
id: meta
|
id: meta
|
||||||
with:
|
with:
|
||||||
images: |-
|
images: |-
|
||||||
@@ -88,38 +94,10 @@ jobs:
|
|||||||
# 1.2.3-rc0
|
# 1.2.3-rc0
|
||||||
tags: |
|
tags: |
|
||||||
type=semver,pattern={{version}}
|
type=semver,pattern={{version}}
|
||||||
- name: Login to Docker Hub
|
annotations: |
|
||||||
uses: docker/login-action@v3
|
org.opencontainers.image.authors="maintainers@gitea.io"
|
||||||
with:
|
- uses: docker/metadata-action@v6
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
id: meta_rootless
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
- name: Login to GHCR using PAT
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.repository_owner }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: build rootful docker image
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
platforms: linux/amd64,linux/arm64,linux/riscv64
|
|
||||||
push: true
|
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
||||||
docker-rootless:
|
|
||||||
runs-on: namespace-profile-gitea-release-docker
|
|
||||||
permissions:
|
|
||||||
packages: write # to publish to ghcr.io
|
|
||||||
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:
|
with:
|
||||||
images: |-
|
images: |-
|
||||||
gitea/gitea
|
gitea/gitea
|
||||||
@@ -131,23 +109,33 @@ jobs:
|
|||||||
# 1.2.3-rc0
|
# 1.2.3-rc0
|
||||||
tags: |
|
tags: |
|
||||||
type=semver,pattern={{version}}
|
type=semver,pattern={{version}}
|
||||||
|
annotations: |
|
||||||
|
org.opencontainers.image.authors="maintainers@gitea.io"
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v4
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
- name: Login to GHCR using PAT
|
- name: Login to GHCR using PAT
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v4
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: build rootless docker image
|
- name: build regular container image
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v7
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64,linux/riscv64
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
annotations: ${{ steps.meta.outputs.annotations }}
|
||||||
|
- name: build rootless container image
|
||||||
|
uses: docker/build-push-action@v7
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm64,linux/riscv64
|
platforms: linux/amd64,linux/arm64,linux/riscv64
|
||||||
push: true
|
push: true
|
||||||
file: Dockerfile.rootless
|
file: Dockerfile.rootless
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta_rootless.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
annotations: ${{ steps.meta_rootless.outputs.annotations }}
|
||||||
|
|||||||
+36
-47
@@ -15,9 +15,10 @@ jobs:
|
|||||||
binary:
|
binary:
|
||||||
runs-on: namespace-profile-gitea-release-binary
|
runs-on: namespace-profile-gitea-release-binary
|
||||||
permissions:
|
permissions:
|
||||||
|
contents: read
|
||||||
packages: write # to publish to ghcr.io
|
packages: write # to publish to ghcr.io
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
# 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
|
# 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
|
- run: git fetch --unshallow --quiet --tags --force
|
||||||
@@ -25,10 +26,12 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
check-latest: true
|
check-latest: true
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v5
|
||||||
- uses: actions/setup-node@v5
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 24
|
||||||
|
cache: pnpm
|
||||||
|
cache-dependency-path: pnpm-lock.yaml
|
||||||
- run: make deps-frontend deps-backend
|
- run: make deps-frontend deps-backend
|
||||||
# xgo build
|
# xgo build
|
||||||
- run: make release
|
- run: make release
|
||||||
@@ -36,7 +39,7 @@ jobs:
|
|||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
TAGS: bindata sqlite sqlite_unlock_notify
|
||||||
- name: import gpg key
|
- name: import gpg key
|
||||||
id: import_gpg
|
id: import_gpg
|
||||||
uses: crazy-max/ghaction-import-gpg@v6
|
uses: crazy-max/ghaction-import-gpg@v7
|
||||||
with:
|
with:
|
||||||
gpg_private_key: ${{ secrets.GPGSIGN_KEY }}
|
gpg_private_key: ${{ secrets.GPGSIGN_KEY }}
|
||||||
passphrase: ${{ secrets.GPGSIGN_PASSPHRASE }}
|
passphrase: ${{ secrets.GPGSIGN_PASSPHRASE }}
|
||||||
@@ -53,7 +56,7 @@ jobs:
|
|||||||
echo "Cleaned name is ${REF_NAME}"
|
echo "Cleaned name is ${REF_NAME}"
|
||||||
echo "branch=${REF_NAME}" >> "$GITHUB_OUTPUT"
|
echo "branch=${REF_NAME}" >> "$GITHUB_OUTPUT"
|
||||||
- name: configure aws
|
- name: configure aws
|
||||||
uses: aws-actions/configure-aws-credentials@v4
|
uses: aws-actions/configure-aws-credentials@v6
|
||||||
with:
|
with:
|
||||||
aws-region: ${{ secrets.AWS_REGION }}
|
aws-region: ${{ secrets.AWS_REGION }}
|
||||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
@@ -62,7 +65,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress
|
aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress
|
||||||
- name: Install GH CLI
|
- name: Install GH CLI
|
||||||
uses: dev-hanz-ops/install-gh-cli-action@v0.1.0
|
uses: dev-hanz-ops/install-gh-cli-action@v0.2.1
|
||||||
with:
|
with:
|
||||||
gh-cli-version: 2.39.1
|
gh-cli-version: 2.39.1
|
||||||
- name: create github release
|
- name: create github release
|
||||||
@@ -70,18 +73,20 @@ jobs:
|
|||||||
gh release create ${{ github.ref_name }} --title ${{ github.ref_name }} --notes-from-tag dist/release/*
|
gh release create ${{ github.ref_name }} --title ${{ github.ref_name }} --notes-from-tag dist/release/*
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
docker-rootful:
|
|
||||||
|
container:
|
||||||
runs-on: namespace-profile-gitea-release-docker
|
runs-on: namespace-profile-gitea-release-docker
|
||||||
permissions:
|
permissions:
|
||||||
|
contents: read
|
||||||
packages: write # to publish to ghcr.io
|
packages: write # to publish to ghcr.io
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
# 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
|
# 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
|
- run: git fetch --unshallow --quiet --tags --force
|
||||||
- uses: docker/setup-qemu-action@v3
|
- uses: docker/setup-qemu-action@v4
|
||||||
- uses: docker/setup-buildx-action@v3
|
- uses: docker/setup-buildx-action@v4
|
||||||
- uses: docker/metadata-action@v5
|
- uses: docker/metadata-action@v6
|
||||||
id: meta
|
id: meta
|
||||||
with:
|
with:
|
||||||
images: |-
|
images: |-
|
||||||
@@ -96,36 +101,10 @@ jobs:
|
|||||||
type=semver,pattern={{version}}
|
type=semver,pattern={{version}}
|
||||||
type=semver,pattern={{major}}
|
type=semver,pattern={{major}}
|
||||||
type=semver,pattern={{major}}.{{minor}}
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
- name: Login to Docker Hub
|
annotations: |
|
||||||
uses: docker/login-action@v3
|
org.opencontainers.image.authors="maintainers@gitea.io"
|
||||||
with:
|
- uses: docker/metadata-action@v6
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
id: meta_rootless
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
- name: Login to GHCR using PAT
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.repository_owner }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: build rootful docker image
|
|
||||||
uses: docker/build-push-action@v5
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
platforms: linux/amd64,linux/arm64,linux/riscv64
|
|
||||||
push: true
|
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
||||||
docker-rootless:
|
|
||||||
runs-on: namespace-profile-gitea-release-docker
|
|
||||||
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:
|
with:
|
||||||
images: |-
|
images: |-
|
||||||
gitea/gitea
|
gitea/gitea
|
||||||
@@ -142,23 +121,33 @@ jobs:
|
|||||||
type=semver,pattern={{version}}
|
type=semver,pattern={{version}}
|
||||||
type=semver,pattern={{major}}
|
type=semver,pattern={{major}}
|
||||||
type=semver,pattern={{major}}.{{minor}}
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
|
annotations: |
|
||||||
|
org.opencontainers.image.authors="maintainers@gitea.io"
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v4
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
- name: Login to GHCR using PAT
|
- name: Login to GHCR using PAT
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v4
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: build rootless docker image
|
- name: build regular container image
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v7
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64,linux/riscv64
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
annotations: ${{ steps.meta.outputs.annotations }}
|
||||||
|
- name: build rootless container image
|
||||||
|
uses: docker/build-push-action@v7
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm64,linux/riscv64
|
platforms: linux/amd64,linux/arm64,linux/riscv64
|
||||||
push: true
|
push: true
|
||||||
file: Dockerfile.rootless
|
file: Dockerfile.rootless
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta_rootless.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
annotations: ${{ steps.meta_rootless.outputs.annotations }}
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ __debug_bin*
|
|||||||
# Visual Studio
|
# Visual Studio
|
||||||
/.vs/
|
/.vs/
|
||||||
|
|
||||||
|
# mise version managment tool
|
||||||
|
mise.toml
|
||||||
|
|
||||||
*.cgo1.go
|
*.cgo1.go
|
||||||
*.cgo2.c
|
*.cgo2.c
|
||||||
_cgo_defun.c
|
_cgo_defun.c
|
||||||
@@ -52,6 +55,7 @@ cpu.out
|
|||||||
*.log.*.gz
|
*.log.*.gz
|
||||||
|
|
||||||
/gitea
|
/gitea
|
||||||
|
/gitea-e2e
|
||||||
/gitea-vet
|
/gitea-vet
|
||||||
/debug
|
/debug
|
||||||
/integrations.test
|
/integrations.test
|
||||||
@@ -64,13 +68,9 @@ cpu.out
|
|||||||
/indexers
|
/indexers
|
||||||
/log
|
/log
|
||||||
/public/assets/img/avatar
|
/public/assets/img/avatar
|
||||||
|
/tests/e2e-output
|
||||||
/tests/integration/gitea-integration-*
|
/tests/integration/gitea-integration-*
|
||||||
/tests/integration/indexers-*
|
/tests/integration/indexers-*
|
||||||
/tests/e2e/gitea-e2e-*
|
|
||||||
/tests/e2e/indexers-*
|
|
||||||
/tests/e2e/reports
|
|
||||||
/tests/e2e/test-artifacts
|
|
||||||
/tests/e2e/test-snapshots
|
|
||||||
/tests/*.ini
|
/tests/*.ini
|
||||||
/tests/**/*.git/**/*.sample
|
/tests/**/*.git/**/*.sample
|
||||||
/node_modules
|
/node_modules
|
||||||
@@ -79,6 +79,7 @@ cpu.out
|
|||||||
/yarn-error.log
|
/yarn-error.log
|
||||||
/npm-debug.log*
|
/npm-debug.log*
|
||||||
/.pnpm-store
|
/.pnpm-store
|
||||||
|
/public/assets/.vite
|
||||||
/public/assets/js
|
/public/assets/js
|
||||||
/public/assets/css
|
/public/assets/css
|
||||||
/public/assets/fonts
|
/public/assets/fonts
|
||||||
@@ -86,10 +87,7 @@ cpu.out
|
|||||||
/vendor
|
/vendor
|
||||||
/VERSION
|
/VERSION
|
||||||
/.air
|
/.air
|
||||||
/.go-licenses
|
|
||||||
|
|
||||||
# Files and folders that were previously generated
|
|
||||||
/public/assets/img/webpack
|
|
||||||
|
|
||||||
# Snapcraft
|
# Snapcraft
|
||||||
/gitea_a*.txt
|
/gitea_a*.txt
|
||||||
@@ -118,7 +116,10 @@ prime/
|
|||||||
/.goosehints
|
/.goosehints
|
||||||
/.windsurfrules
|
/.windsurfrules
|
||||||
/.github/copilot-instructions.md
|
/.github/copilot-instructions.md
|
||||||
/AGENT.md
|
|
||||||
/CLAUDE.md
|
|
||||||
/llms.txt
|
/llms.txt
|
||||||
|
|
||||||
|
# Ignore worktrees when working on multiple branches
|
||||||
|
.worktrees/
|
||||||
|
|
||||||
|
# A Makefile for custom make targets
|
||||||
|
Makefile.local
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
tasks:
|
|
||||||
- name: Setup
|
|
||||||
init: |
|
|
||||||
cp -r contrib/ide/vscode .vscode
|
|
||||||
make deps
|
|
||||||
make build
|
|
||||||
command: |
|
|
||||||
gp sync-done setup
|
|
||||||
exit 0
|
|
||||||
- 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
|
|
||||||
mkdir -p custom/conf/
|
|
||||||
echo -e "[server]\nROOT_URL = ${url}/" > custom/conf/app.ini
|
|
||||||
echo -e "\n[database]\nDB_TYPE = sqlite3\nPATH = $GITPOD_REPO_ROOT/data/gitea.db" >> custom/conf/app.ini
|
|
||||||
fi
|
|
||||||
export TAGS="sqlite sqlite_unlock_notify"
|
|
||||||
make watch-backend
|
|
||||||
- name: Run frontend
|
|
||||||
command: |
|
|
||||||
gp sync-await setup
|
|
||||||
make watch-frontend
|
|
||||||
openMode: split-right
|
|
||||||
|
|
||||||
vscode:
|
|
||||||
extensions:
|
|
||||||
- editorconfig.editorconfig
|
|
||||||
- dbaeumer.vscode-eslint
|
|
||||||
- golang.go
|
|
||||||
- stylelint.vscode-stylelint
|
|
||||||
- DavidAnson.vscode-markdownlint
|
|
||||||
- Vue.volar
|
|
||||||
- ms-azuretools.vscode-docker
|
|
||||||
- vitest.explorer
|
|
||||||
- cweijan.vscode-database-client2
|
|
||||||
- GitHub.vscode-pull-request-github
|
|
||||||
|
|
||||||
ports:
|
|
||||||
- name: Gitea
|
|
||||||
port: 3000
|
|
||||||
@@ -6,15 +6,19 @@ linters:
|
|||||||
default: none
|
default: none
|
||||||
enable:
|
enable:
|
||||||
- bidichk
|
- bidichk
|
||||||
|
- bodyclose
|
||||||
- depguard
|
- depguard
|
||||||
- dupl
|
- dupl
|
||||||
- errcheck
|
- errcheck
|
||||||
- forbidigo
|
- forbidigo
|
||||||
|
- gocheckcompilerdirectives
|
||||||
- gocritic
|
- gocritic
|
||||||
- govet
|
- govet
|
||||||
- ineffassign
|
- ineffassign
|
||||||
- mirror
|
- mirror
|
||||||
|
- modernize
|
||||||
- nakedret
|
- nakedret
|
||||||
|
- nilnil
|
||||||
- nolintlint
|
- nolintlint
|
||||||
- perfsprint
|
- perfsprint
|
||||||
- revive
|
- revive
|
||||||
@@ -45,6 +49,8 @@ linters:
|
|||||||
desc: do not use the ini package, use gitea's config system instead
|
desc: do not use the ini package, use gitea's config system instead
|
||||||
- pkg: gitea.com/go-chi/cache
|
- pkg: gitea.com/go-chi/cache
|
||||||
desc: do not use the go-chi cache package, use gitea's cache system
|
desc: do not use the go-chi cache package, use gitea's cache system
|
||||||
|
- pkg: github.com/pkg/errors
|
||||||
|
desc: use builtin errors package instead
|
||||||
nolintlint:
|
nolintlint:
|
||||||
allow-unused: false
|
allow-unused: false
|
||||||
require-explanation: true
|
require-explanation: true
|
||||||
@@ -55,38 +61,28 @@ linters:
|
|||||||
disabled-checks:
|
disabled-checks:
|
||||||
- ifElseChain
|
- ifElseChain
|
||||||
- singleCaseSwitch # Every time this occurred in the code, there was no other way.
|
- singleCaseSwitch # Every time this occurred in the code, there was no other way.
|
||||||
|
- deprecatedComment # conflicts with go-swagger comments
|
||||||
revive:
|
revive:
|
||||||
severity: error
|
severity: error
|
||||||
rules:
|
rules:
|
||||||
- name: atomic
|
|
||||||
- name: bare-return
|
|
||||||
- name: blank-imports
|
- name: blank-imports
|
||||||
- name: constant-logical-expr
|
- name: constant-logical-expr
|
||||||
- name: context-as-argument
|
- name: context-as-argument
|
||||||
- name: context-keys-type
|
- name: context-keys-type
|
||||||
- name: dot-imports
|
- name: dot-imports
|
||||||
- name: duplicated-imports
|
|
||||||
- name: empty-lines
|
- name: empty-lines
|
||||||
- name: error-naming
|
|
||||||
- name: error-return
|
- name: error-return
|
||||||
- name: error-strings
|
- name: error-strings
|
||||||
- name: errorf
|
|
||||||
- name: exported
|
- name: exported
|
||||||
- name: identical-branches
|
- name: identical-branches
|
||||||
- name: if-return
|
- name: if-return
|
||||||
- name: increment-decrement
|
- name: increment-decrement
|
||||||
- name: indent-error-flow
|
|
||||||
- name: modifies-value-receiver
|
- name: modifies-value-receiver
|
||||||
- name: package-comments
|
- name: package-comments
|
||||||
- name: range
|
|
||||||
- name: receiver-naming
|
|
||||||
- name: redefines-builtin-id
|
- name: redefines-builtin-id
|
||||||
- name: string-of-int
|
|
||||||
- name: superfluous-else
|
- name: superfluous-else
|
||||||
- name: time-naming
|
- name: time-naming
|
||||||
- name: unconditional-recursion
|
|
||||||
- name: unexported-return
|
- name: unexported-return
|
||||||
- name: unreachable-code
|
|
||||||
- name: var-declaration
|
- name: var-declaration
|
||||||
- name: var-naming
|
- name: var-naming
|
||||||
arguments:
|
arguments:
|
||||||
@@ -107,6 +103,12 @@ linters:
|
|||||||
- require-error
|
- require-error
|
||||||
usetesting:
|
usetesting:
|
||||||
os-temp-dir: true
|
os-temp-dir: true
|
||||||
|
perfsprint:
|
||||||
|
concat-loop: false
|
||||||
|
govet:
|
||||||
|
enable:
|
||||||
|
- nilness
|
||||||
|
- unusedwrite
|
||||||
exclusions:
|
exclusions:
|
||||||
generated: lax
|
generated: lax
|
||||||
presets:
|
presets:
|
||||||
@@ -118,16 +120,12 @@ linters:
|
|||||||
- linters:
|
- linters:
|
||||||
- dupl
|
- dupl
|
||||||
- errcheck
|
- errcheck
|
||||||
- gocyclo
|
|
||||||
- gosec
|
|
||||||
- staticcheck
|
- staticcheck
|
||||||
- unparam
|
- unparam
|
||||||
path: _test\.go
|
path: _test\.go
|
||||||
- linters:
|
- linters:
|
||||||
- dupl
|
- dupl
|
||||||
- errcheck
|
- errcheck
|
||||||
- gocyclo
|
|
||||||
- gosec
|
|
||||||
path: models/migrations/v
|
path: models/migrations/v
|
||||||
- linters:
|
- linters:
|
||||||
- forbidigo
|
- forbidigo
|
||||||
@@ -139,12 +137,8 @@ linters:
|
|||||||
- gocritic
|
- gocritic
|
||||||
text: (?i)`ID' should not be capitalized
|
text: (?i)`ID' should not be capitalized
|
||||||
- linters:
|
- linters:
|
||||||
- deadcode
|
|
||||||
- unused
|
- unused
|
||||||
text: (?i)swagger
|
text: (?i)swagger
|
||||||
- linters:
|
|
||||||
- staticcheck
|
|
||||||
text: (?i)argument x is overwritten before first use
|
|
||||||
- linters:
|
- linters:
|
||||||
- gocritic
|
- gocritic
|
||||||
text: '(?i)commentFormatting: put a space between `//` and comment text'
|
text: '(?i)commentFormatting: put a space between `//` and comment text'
|
||||||
@@ -153,6 +147,7 @@ linters:
|
|||||||
text: '(?i)exitAfterDefer:'
|
text: '(?i)exitAfterDefer:'
|
||||||
paths:
|
paths:
|
||||||
- node_modules
|
- node_modules
|
||||||
|
- .venv
|
||||||
- public
|
- public
|
||||||
- web_src
|
- web_src
|
||||||
- third_party$
|
- third_party$
|
||||||
@@ -172,6 +167,7 @@ formatters:
|
|||||||
generated: lax
|
generated: lax
|
||||||
paths:
|
paths:
|
||||||
- node_modules
|
- node_modules
|
||||||
|
- .venv
|
||||||
- public
|
- public
|
||||||
- web_src
|
- web_src
|
||||||
- third_party$
|
- third_party$
|
||||||
|
|||||||
@@ -21,9 +21,7 @@ rules:
|
|||||||
comments-indentation:
|
comments-indentation:
|
||||||
level: error
|
level: error
|
||||||
|
|
||||||
document-start:
|
document-start: disable
|
||||||
level: error
|
|
||||||
present: false
|
|
||||||
|
|
||||||
document-end:
|
document-end:
|
||||||
present: false
|
present: false
|
||||||
|
|||||||
@@ -4,7 +4,538 @@ This changelog goes through the changes that have been made in each release
|
|||||||
without substantial changes to our git log; to see the highlights of what has
|
without substantial changes to our git log; to see the highlights of what has
|
||||||
been added to each release, please refer to the [blog](https://blog.gitea.com).
|
been added to each release, please refer to the [blog](https://blog.gitea.com).
|
||||||
|
|
||||||
## [1.25.4](https://github.com/go-gitea/gitea/releases/tag/1.25.4) - 2026-01-15
|
## [1.26.2](https://github.com/go-gitea/gitea/releases/tag/1.26.2) - 2026-05-20
|
||||||
|
|
||||||
|
* SECURITY
|
||||||
|
* fix(permissions): Fix reading permission (#37769)
|
||||||
|
* fix(actions): make artifact signature payloads unambiguous (#37707)
|
||||||
|
* fix: Unify public-only token filtering in API queries and repo access checks (#37118)
|
||||||
|
* fix: Add missed token scope checking (#37735)
|
||||||
|
* fix(oauth): bind token exchanges to the original client request (#37704)
|
||||||
|
* fix(oauth): strengthen PKCE validation and refresh token replay protection (#37706)
|
||||||
|
* fix(web): enforce token scopes on raw, media, and attachment downloads (#37698)
|
||||||
|
* fix(security): enforce wiki git writes and LFS token access at request time (#37695)
|
||||||
|
* feat(api): encrypt AWS creds (#37679)
|
||||||
|
* fix(deps): update dependency mermaid to v11.15.0 [security], add e2e test
|
||||||
|
* fix(packages): Add label for private and internal package and fix composor package source permission check (#37610)
|
||||||
|
* fix(git): Fix smart http request scope bug (#37583)
|
||||||
|
* Fix basic auth bug (#37503)
|
||||||
|
* Fix allow maintainer edit permission check (#37479) (#37484)
|
||||||
|
* Fix URL sanitization to handle schemeless credentials (#37440) (#37471)
|
||||||
|
* Fix attachment Content-Security-Policy (#37455) (#37464)
|
||||||
|
* chore(deps): bump go-git/go-git/v5 to 5.19.0 (#37608)
|
||||||
|
|
||||||
|
* BUGFIXES
|
||||||
|
* fix(pull): handle empty pull request files view to allow reviews (#37783)
|
||||||
|
* fix(markup): make RenderString never fail (#37779)
|
||||||
|
* fix: add natural sort to sortTreeViewNodes (#37772)
|
||||||
|
* fix: package creation unique conflict (#37774)
|
||||||
|
* fix!: add DEFAULT_TITLE_SOURCE setting for pull request title default behavior (#37465)
|
||||||
|
* fix: Allow direct commits for unprotected files with push restrictions (#37657)
|
||||||
|
* fix(actions): wrong assumption that run id always >= job id (#37737)
|
||||||
|
* fix(auth): set User-Agent on avatar fetch and sync avatar on link-account register (#37564) (#37588)
|
||||||
|
* fix(actions): deadlock between PrepareRunAndInsert and UpdateTaskByState (#37692)
|
||||||
|
* fix(repo): /generate must sync the branch table for the new repo (#37693)
|
||||||
|
* build: Fix snap build (1.26)
|
||||||
|
* fix(actions): run TransferLogs on UpdateLog{Rows:[], NoMore:true} (#37631)
|
||||||
|
* fix show correct mergebase
|
||||||
|
* fix: make clone URL respect public URL detection setting (#37615)
|
||||||
|
* fix: "run as root" check (#37622)
|
||||||
|
* chore(deps): update dependency go to v1.26.3 (#37601)
|
||||||
|
* Compare dropdown fails when selecting branch with no common merge-base (#37470)
|
||||||
|
* fix: treat email addresses case-insensitively (#37600)
|
||||||
|
* fix(actions): fix blank lines after ::endgroup:: (#37597)
|
||||||
|
* fix(actions): report individual step status in workflow job API response (#37592)
|
||||||
|
* fix: Invalid UTF-8 commit messages in JSON API responses (#37542)
|
||||||
|
* fix: use consistent GetUser family functions (#37553)
|
||||||
|
* fix(api): return 409 message instead of empty JSON for wrong commit id (#37572)
|
||||||
|
* fix(actions): prevent panic when workflow contains null jobs (#37570)
|
||||||
|
* Make ServeSetHeaders default to download attachment if filename exists (#37552) (#37555)
|
||||||
|
* Fix(actions): validate workflow param to prevent 500 error (#37546) (#37554)
|
||||||
|
* Don't unblock run-level-concurrency-blocked runs in the resolver (#37461) (#37538)
|
||||||
|
* Fix(packages): use file names for generic web downloads (#37514) (#37520)
|
||||||
|
* Fix merge autodetect can't close other PRs but only the last one when multiple PRs are pushed at once (#37512) (#37516)
|
||||||
|
* Fix update branch protection order (#37508) (#37513)
|
||||||
|
* Fix mCaptcha broken after Vite migration (#37492) (#37509)
|
||||||
|
* Fix review submission from single-commit PR view (#37475) (#37485)
|
||||||
|
* Fix scheduled action panic with null event payload (#37459) (#37466)
|
||||||
|
* Make GetPossibleUserByID can handle deleted user (#37430) (#37431)
|
||||||
|
* Remove excessive quote from terraform instructions (#37424) (#37426)
|
||||||
|
* Fix color regressions, add `priority` color (#37417) (#37421)
|
||||||
|
|
||||||
|
* MISC
|
||||||
|
* Add CurrentURL template variable back (#37444) (#37449)
|
||||||
|
|
||||||
|
## [1.26.1](https://github.com/go-gitea/gitea/releases/tag/v1.26.1) - 2026-04-21
|
||||||
|
|
||||||
|
* BUGFIXES
|
||||||
|
* Add event.schedule context for schedule actions task (#37320) (#37348)
|
||||||
|
* Fix an issue where changing an organization's visibility caused problems when users had forked its repositories. (#37324) (#37344)
|
||||||
|
* Use modern "git update-index --cacheinfo" syntax to support more file names (#37338) (#37343)
|
||||||
|
* Fix URL related escaping for oauth2 (#37334) (#37340)
|
||||||
|
* When the requested arch rpm is missing fall back to noarch (#37236) (#37339)
|
||||||
|
* Fix actions concurrency groups cross-branch leak (#37311) (#37331)
|
||||||
|
* Fix bug when accessing user badges (#37321) (#37329)
|
||||||
|
* Fix AppFullLink (#37325) (#37328)
|
||||||
|
* Fix container auth for public instance (#37290) (#37294)
|
||||||
|
* Enhance GetActionWorkflow to support fallback references (#37189) (#37283)
|
||||||
|
* Fix vite manifest update masking build errors (#37279) (#37310)
|
||||||
|
* Fix Mermaid diagrams failing when node labels contain line breaks (#37296) (#37299)
|
||||||
|
* Use TriggerEvent instead of Event in workflow runs API response for scheduled runs (#37288) #37360
|
||||||
|
* Add URL to Learn more about blocking a user. (#37355) #37367
|
||||||
|
* Fix button layout shift when collapsing file tree in editor (#37363) #37375
|
||||||
|
* Fix org team assignee/reviewer lookups for team member permissions (#37365) #37391
|
||||||
|
* Fix repo init README EOL (#37388) #37399
|
||||||
|
* Fix: dump with default zip type produces uncompressed zip (#37401)#37402
|
||||||
|
|
||||||
|
## [1.26.0](https://github.com/go-gitea/gitea/releases/tag/v1.26.0) - 2026-04-17
|
||||||
|
|
||||||
|
* BREAKING
|
||||||
|
* Correct swagger annotations for enums, status codes, and notification state (#37030)
|
||||||
|
* Remove GET API registration-token (#36801)
|
||||||
|
* Support Actions `concurrency` syntax (#32751)
|
||||||
|
* Make PUBLIC_URL_DETECTION default to "auto" (#36955)
|
||||||
|
* SECURITY
|
||||||
|
* Bound PageSize in `ListUnadoptedRepositories` (#36884)
|
||||||
|
* FEATURES
|
||||||
|
* Support Actions `concurrency` syntax (#32751)
|
||||||
|
* Add terraform state registry (#36710)
|
||||||
|
* Instance-wide (global) info banner and maintenance mode (#36571)
|
||||||
|
* Support rendering OpenAPI spec (#36449)
|
||||||
|
* Add keyboard shortcuts for repository file and code search (#36416)
|
||||||
|
* Add support for archive-upload rpc (#36391)
|
||||||
|
* Add ability to download subpath archive (#36371)
|
||||||
|
* Add workflow dependencies visualization (#26062) (#36248) & Restyle Workflow Graph (#36912)
|
||||||
|
* Automatic generation of release notes (#35977)
|
||||||
|
* Add "Go to file", "Delete Directory" to repo file list page (#35911)
|
||||||
|
* Introduce "config edit-ini" sub command to help maintaining INI config file (#35735)
|
||||||
|
* Add button to re-run failed jobs in Actions (#36924)
|
||||||
|
* Support actions and reusable workflows from private repos (#32562)
|
||||||
|
* Add summary to action runs view (#36883)
|
||||||
|
* Add user badges (#36752)
|
||||||
|
* Add configurable permissions for Actions automatic tokens (#36173)
|
||||||
|
* Add per-runner "Disable/Pause" (#36776)
|
||||||
|
* Feature non-zipped actions artifacts (action v7 / nodejs / npm v6.2.0) (#36786)
|
||||||
|
* PERFORMANCE
|
||||||
|
* WorkflowDispatch API optionally return runid (#36706)
|
||||||
|
* Add render cache for SVG icons (#36863)
|
||||||
|
* Load `mentionValues` asynchronously (#36739)
|
||||||
|
* Lazy-load some Vue components, fix heatmap chunk loading on every page (#36719)
|
||||||
|
* Load heatmap data asynchronously (#36622)
|
||||||
|
* Use prev/next pagination for user profile activities page to speed up (#36642)
|
||||||
|
* Refactor cat-file batch operations and support `--batch-command` approach (#35775)
|
||||||
|
* Use merge tree to detect conflicts when possible (#36400)
|
||||||
|
* ENHANCEMENTS
|
||||||
|
* Implement logout redirection for reverse proxy auth setups (#36085) (#37171)
|
||||||
|
* Adds option to force update new branch in contents routes (#35592)
|
||||||
|
* Add viewer controller for mermaid (zoom, drag) (#36557)
|
||||||
|
* Add code editor setting dropdowns (#36534)
|
||||||
|
* Add `elk` layout support to mermaid (#36486)
|
||||||
|
* Add resolve/unresolve review comment API endpoints (#36441)
|
||||||
|
* Allow configuring default PR base branch (fixes #36412) (#36425)
|
||||||
|
* Add support for RPM Errata (updateinfo.xml) (#37125)
|
||||||
|
* Require additional user confirmation for making repo private (#36959)
|
||||||
|
* Add `actions.WORKFLOW_DIRS` setting (#36619)
|
||||||
|
* Avoid opening new tab when downloading actions logs (#36740)
|
||||||
|
* Implements OIDC RP-Initiated Logout (#36724)
|
||||||
|
* Show workflow link (#37070)
|
||||||
|
* Desaturate dark theme background colors (#37056)
|
||||||
|
* Refactor "org teams" page and help new users to "add member" to an org (#37051)
|
||||||
|
* Add webhook name field to improve webhook identification (#37025) (#37040)
|
||||||
|
* Make task list checkboxes clickable in the preview tab (#37010)
|
||||||
|
* Improve severity labels in Actions logs and tweak colors (#36993)
|
||||||
|
* Linkify URLs in Actions workflow logs (#36986)
|
||||||
|
* Allow text selection on checkbox labels (#36970)
|
||||||
|
* Support dark/light theme images in markdown (#36922)
|
||||||
|
* Enable native dark mode for swagger-ui (#36899)
|
||||||
|
* Rework checkbox styling, remove `input` border hover effect (#36870)
|
||||||
|
* Refactor storage content-type handling of ServeDirectURL (#36804)
|
||||||
|
* Use "Enable Gravatar" but not "Disable" (#36771)
|
||||||
|
* Use case-insensitive matching for Git error "Not a valid object name" (#36728)
|
||||||
|
* Add "Copy Source" to markup comment menu (#36726)
|
||||||
|
* Change image transparency grid to CSS (#36711)
|
||||||
|
* Add "Run" prefix for unnamed action steps (#36624)
|
||||||
|
* Persist actions log time display settings in `localStorage` (#36623)
|
||||||
|
* Use first commit title for multi-commit PRs and fix auto-focus title field (#36606)
|
||||||
|
* Improve BuildCaseInsensitiveLike with lowercase (#36598)
|
||||||
|
* Improve diff highlighting (#36583)
|
||||||
|
* Exclude cancelled runs from failure-only email notifications (#36569)
|
||||||
|
* Use full-file highlighting for diff sections (#36561)
|
||||||
|
* Color command/error logs in Actions log (#36538)
|
||||||
|
* Add paging headers (#36521)
|
||||||
|
* Improve timeline entries for WIP prefix changes in pull requests (#36518)
|
||||||
|
* Add FOLDER_ICON_THEME configuration option (#36496)
|
||||||
|
* Normalize guessed languages for code highlighting (#36450)
|
||||||
|
* Add chunked transfer encoding support for LFS uploads (#36380)
|
||||||
|
* Indicate when only optional checks failed (#36367)
|
||||||
|
* Add 'allow_maintainer_edit' API option for creating a pull request (#36283)
|
||||||
|
* Support closing keywords with URL references (#36221)
|
||||||
|
* Improve diff file headers (#36215)
|
||||||
|
* Fix and enhance comment editor monospace toggle (#36181)
|
||||||
|
* Add git.DIFF_RENAME_SIMILARITY_THRESHOLD option (#36164)
|
||||||
|
* Add matching pair insertion to markdown textarea (#36121)
|
||||||
|
* Add sorting/filtering to admin user search API endpoint (#36112)
|
||||||
|
* Allow action user have read permission in public repo like other user (#36095)
|
||||||
|
* Disable matchBrackets in monaco (#36089)
|
||||||
|
* Use GitHub-style commit message for squash merge (#35987)
|
||||||
|
* Make composer registry support tar.gz and tar.bz2 and fix bugs (#35958)
|
||||||
|
* Add GITEA_PR_INDEX env variable to githooks (#35938)
|
||||||
|
* Add proper error message if session provider can not be created (#35520)
|
||||||
|
* Add button to copy file name in PR files (#35509)
|
||||||
|
* Move `X_FRAME_OPTIONS` setting from `cors` to `security` section (#30256)
|
||||||
|
* Add placeholder content for empty content page (#37114)
|
||||||
|
* Add `DEFAULT_DELETE_BRANCH_AFTER_MERGE` setting (#36917)
|
||||||
|
* Redirect to the only OAuth2 provider when no other login methods and fix various problems (#36901)
|
||||||
|
* Add admin badge to navbar avatar (#36790)
|
||||||
|
* Add `never` option to `PUBLIC_URL_DETECTION` configuration (#36785)
|
||||||
|
* Add background and run count to actions list page (#36707)
|
||||||
|
* Add icon to buttons "Close with Comment", "Close Pull Request", "Close Issue" (#36654)
|
||||||
|
* Add support for in_progress event in workflow_run webhook (#36979)
|
||||||
|
* Report commit status for pull_request_review events (#36589)
|
||||||
|
* Render merged pull request title as such in dashboard feed (#36479)
|
||||||
|
* Feature to be able to filter project boards by milestones (#36321)
|
||||||
|
* Use user id in noreply emails (#36550)
|
||||||
|
* Enable pagination on GiteaDownloader.getIssueReactions() (#36549)
|
||||||
|
* Remove striped tables in UI (#36509)
|
||||||
|
* Improve control char rendering and escape button styling (#37094)
|
||||||
|
* Support legacy run/job index-based URLs and refactor migration 326 (#37008)
|
||||||
|
* Add date to "No Contributions" tooltip (#36190)
|
||||||
|
* Show edit page confirmation dialog on tree view file change (#36130)
|
||||||
|
* Mention proc-receive in text for dashboard.resync_all_hooks func (#35991)
|
||||||
|
* Reuse selectable style for wiki (#35990)
|
||||||
|
* Support blue yellow colorblind theme (#35910)
|
||||||
|
* Support selecting theme on the footer (#35741)
|
||||||
|
* Improve online runner check (#35722)
|
||||||
|
* Add quick approve button on PR page (#35678)
|
||||||
|
* Enable commenting on expanded lines in PR diffs (#35662)
|
||||||
|
* Print PR-Title into tooltip for actions (#35579)
|
||||||
|
* Use explicit, stronger defaults for newly generated repo signing keys for Debian (#36236)
|
||||||
|
* Improve the compare page (#36261)
|
||||||
|
* Unify repo names in system notices (#36491)
|
||||||
|
* Move package settings to package instead of being tied to version (#37026)
|
||||||
|
* Add Actions API rerun endpoints for runs and jobs (#36768)
|
||||||
|
* Add branch_count to repository API (#35351) (#36743)
|
||||||
|
* Add created_by filter to SearchIssues (#36670)
|
||||||
|
* Allow admins to rename non-local users (#35970)
|
||||||
|
* Support updating branch via API (#35951)
|
||||||
|
* Add an option to automatically verify SSH keys from LDAP (#35927)
|
||||||
|
* Make "update file" API can create a new file when SHA is not set (#35738)
|
||||||
|
* Update issue.go with labels documentation (labels content, not ids) (#35522)
|
||||||
|
* Expose content_version for optimistic locking on issue and PR edits (#37035)
|
||||||
|
* Pass ServeHeaderOptions by value instead of pointer, fine tune httplib tests (#36982)
|
||||||
|
* BUGFIXES
|
||||||
|
* Frontend iframe renderer framework: 3D models, OpenAPI (#37233) (#37273)
|
||||||
|
* Fix CODEOWNERS absolute path matching. (#37244) (#37264)
|
||||||
|
* Swift registry metadata: preserve more JSON fields and accept empty metadata (#37254) (#37261)
|
||||||
|
* Fix user ssh key exporting and tests (#37256) (#37258)
|
||||||
|
* Fix team member avatar size and add tooltip (#37253)
|
||||||
|
* Fix commit title rendering in action run and blame (#37243) (#37251)
|
||||||
|
* Fix corrupted JSON caused by goccy library (#37214) (#37220)
|
||||||
|
* Add test for "fetch redirect", add CSS value validation for external render (#37207) (#37216)
|
||||||
|
* Fix incorrect concurrency check (#37205) (#37215)
|
||||||
|
* Fix handle missing base branch in PR commits API (#37193) (#37203)
|
||||||
|
* Fix encoding for Matrix Webhooks (#37190) (#37201)
|
||||||
|
* Fix handle fork-only commits in compare API (#37185) (#37199)
|
||||||
|
* Indicate form field readonly via background, fix RunUser config (#37175, #37180) (#37178)
|
||||||
|
* Report structurally invalid workflows to users (#37116) (#37164)
|
||||||
|
* Fix API not persisting pull request unit config when has_pull_requests is not set (#36718)
|
||||||
|
* Rename CSS variables and improve colorblind themes (#36353)
|
||||||
|
* Hide `add-matcher` and `remove-matcher` from actions job logs (#36520)
|
||||||
|
* Prevent navigation keys from triggering actions during IME composition (#36540)
|
||||||
|
* Fix vertical alignment of `.commit-sign-badge` children (#36570)
|
||||||
|
* Fix duplicate startup warnings in admin panel (#36641)
|
||||||
|
* Fix CODEOWNERS review request attribution using comment metadata (#36348)
|
||||||
|
* Fix HTML tags appearing in wiki table of contents (#36284)
|
||||||
|
* Fix various bugs (#37096)
|
||||||
|
* Fix various legacy problems (#37092)
|
||||||
|
* Fix RPM Registry 404 when package name contains 'package' (#37087)
|
||||||
|
* Merge some standalone Vite entries into index.js (#37085)
|
||||||
|
* Fix various problems (#37077)
|
||||||
|
* Fix issue label deletion with Actions tokens (#37013)
|
||||||
|
* Hide delete branch or tag buttons in mirror or archived repositories. (#37006)
|
||||||
|
* Fix org contact email not clearable once set (#36975)
|
||||||
|
* Fix a bug when forking a repository in an organization (#36950)
|
||||||
|
* Preserve sort order of exclusive labels from template repo (#36931)
|
||||||
|
* Make container registry support Apple Container (basic auth) (#36920)
|
||||||
|
* Fix the wrong push commits in the pull request when force push (#36914)
|
||||||
|
* Add class "list-header-filters" to the div for projects (#36889)
|
||||||
|
* Fix dbfs error handling (#36844)
|
||||||
|
* Fix incorrect viewed files counter if reverted change was viewed (#36819)
|
||||||
|
* Refactor avatar package, support default avatar fallback (#36788)
|
||||||
|
* Fix README symlink resolution in subdirectories like .github (#36775)
|
||||||
|
* Fix CSS stacking context issue in actions log (#36749)
|
||||||
|
* Add gpg signing for merge rebase and update by rebase (#36701)
|
||||||
|
* Delete non-exist branch should return 404 (#36694)
|
||||||
|
* Fix `TestActionsCollaborativeOwner` (#36657)
|
||||||
|
* Fix multi-arch Docker build SIGILL by splitting frontend stage (#36646)
|
||||||
|
* Fix linguist-detectable attribute being ignored for configuration files (#36640)
|
||||||
|
* Fix state desync in ComboMarkdownEditor (#36625)
|
||||||
|
* Unify DEFAULT_SHOW_FULL_NAME output in templates and dropdown (#36597)
|
||||||
|
* Pull Request Pusher should be the author of the merge (#36581)
|
||||||
|
* Fix various version parsing problems (#36553)
|
||||||
|
* Fix highlight diff result (#36539)
|
||||||
|
* Fix mirror sync parser and fix mirror messages (#36504)
|
||||||
|
* Fix bug when list pull request commits (#36485)
|
||||||
|
* Fix various bugs (#36446)
|
||||||
|
* Fix issue filter menu layout (#36426)
|
||||||
|
* Restrict branch naming when new change matches with protection rules (#36405)
|
||||||
|
* Fix link/origin referrer and login redirect (#36279)
|
||||||
|
* Generate IDs for HTML headings without id attribute (#36233)
|
||||||
|
* Use a migration test instead of a wrong test which populated the meta test repositories and fix a migration bug (#36160)
|
||||||
|
* Fix issue close timeline icon (#36138)
|
||||||
|
* Fix diff blob excerpt expansion (#35922)
|
||||||
|
* Fix external render (#35727)
|
||||||
|
* Fix review request webhook bug (#35339) (#35723)
|
||||||
|
* Fix shutdown waitgroup panic (#35676)
|
||||||
|
* Cleanup ActionRun creation (#35624)
|
||||||
|
* Fix possible bug when migrating issues/pull requests (#33487)
|
||||||
|
* Various fixes (#36697)
|
||||||
|
* Apply notify/register mail flags during install load (#37120)
|
||||||
|
* Repair duration display for bad stopped timestamps (#37121)
|
||||||
|
* Fix(upgrade.sh): use HTTPS for GPG key import and restore SELinux context after upgrade (#36930)
|
||||||
|
* Fix various trivial problems (#36921)
|
||||||
|
* Fix various trivial problems (#36953)
|
||||||
|
* Fix NuGet package upload error handling (#37074)
|
||||||
|
* Fix CodeQL code scanning alerts (#36858)
|
||||||
|
* Refactor issue sidebar and fix various problems (#37045)
|
||||||
|
* Fix various problems (#37029)
|
||||||
|
* Fix relative-time RangeError (#37021)
|
||||||
|
* Fix chroma lexer mapping (#36629)
|
||||||
|
* Fix typos and grammar in English locale (#36751)
|
||||||
|
* Fix milestone/project text overflow in issue sidebar (#36741)
|
||||||
|
* Fix `no-content` message not rendering after comment edit (#36733)
|
||||||
|
* Fix theme loading in development (#36605)
|
||||||
|
* Fix workflow run jobs API returning null steps (#36603)
|
||||||
|
* Fix timeline event layout overflow with long content (#36595)
|
||||||
|
* Fix minor UI issues in runner edit page (#36590)
|
||||||
|
* Fix incorrect vendored detections (#36508)
|
||||||
|
* Fix editorconfig not respected in PR Conversation view (#36492)
|
||||||
|
* Don't create self-references in merged PRs (#36490)
|
||||||
|
* Fix potential incorrect runID in run status update (#36437)
|
||||||
|
* Fix file-tree ui error when adding files to repo without commits (#36312)
|
||||||
|
* Improve image captcha contrast for dark mode (#36265)
|
||||||
|
* Fix panic in blame view when a file has only a single commit (#36230)
|
||||||
|
* Fix spelling error in migrate-storage cmd utility (#36226)
|
||||||
|
* Fix code highlighting on blame page (#36157)
|
||||||
|
* Fix nilnil in onedev downloader (#36154)
|
||||||
|
* Fix actions lint (#36029)
|
||||||
|
* Fix oauth2 session gob register (#36017)
|
||||||
|
* Fix Arch repo pacman.conf snippet (#35825)
|
||||||
|
* Fix a number of `strictNullChecks`-related issues (#35795)
|
||||||
|
* Fix URLJoin, markup render link reoslving, sign-in/up/linkaccount page common data (#36861)
|
||||||
|
* Hide delete directory button for mirror or archive repository and disable the menu item if user have no permission (#36384)
|
||||||
|
* Update message severity colors, fix navbar double border (#37019)
|
||||||
|
* Inline and lazy-load EasyMDE CSS, fix border colors (#36714)
|
||||||
|
* Closed milestones with no issues now show as 100% completed (#36220)
|
||||||
|
* Add test for ExtendCommentTreePathLength migration and fix bugs (#35791)
|
||||||
|
* Only turn links to current instance into hash links (#36237)
|
||||||
|
* Fix typos in code comments: doesnt, dont, wont (#36890)
|
||||||
|
* REFACTOR
|
||||||
|
* Clean up and improve non-gitea js error filter (#37148) (#37155)
|
||||||
|
* Always show owner/repo name in compare page dropdowns (#37172) (#37200)
|
||||||
|
* Remove dead CSS rules (#37173) (#37177)
|
||||||
|
* Replace Monaco with CodeMirror (#36764)
|
||||||
|
* Replace CSRF cookie with `CrossOriginProtection` (#36183)
|
||||||
|
* Replace index with id in actions routes (#36842)
|
||||||
|
* Remove unnecessary function parameter (#35765)
|
||||||
|
* Move jobparser from act repository to Gitea (#36699)
|
||||||
|
* Refactor compare router param parse (#36105)
|
||||||
|
* Optimize 'refreshAccesses' to perform update without removing then adding (#35702)
|
||||||
|
* Clean up checkbox cursor styles (#37016)
|
||||||
|
* Remove undocumented support of signing key in the repository git configuration file (#36143)
|
||||||
|
* Switch `cmd/` to use constructor functions. (#36962)
|
||||||
|
* Use `relative-time` to render absolute dates (#36238)
|
||||||
|
* Some refactors about GetMergeBase (#36186)
|
||||||
|
* Some small refactors (#36163)
|
||||||
|
* Use gitRepo as parameter instead of repopath when invoking sign functions (#36162)
|
||||||
|
* Move blame to gitrepo (#36161)
|
||||||
|
* Move some functions to gitrepo package to reduce RepoPath reference directly (#36126)
|
||||||
|
* Use gitrepo's clone and push when possible (#36093)
|
||||||
|
* Remove mermaid margin workaround (#35732)
|
||||||
|
* Move some functions to gitrepo package (#35543)
|
||||||
|
* Move GetDiverging functions to gitrepo (#35524)
|
||||||
|
* Use global lock instead of status pool for cron lock (#35507)
|
||||||
|
* Use explicit mux instead of DefaultServeMux (#36276)
|
||||||
|
* Use gitrepo's push function (#36245)
|
||||||
|
* Pass request context to generateAdditionalHeadersForIssue (#36274)
|
||||||
|
* Move assign project when creating pull request to the same database transaction (#36244)
|
||||||
|
* Move catfile batch to a sub package of git module (#36232)
|
||||||
|
* Use gitrepo.Repository instead of wikipath (#35398)
|
||||||
|
* Use experimental go json v2 library (#35392)
|
||||||
|
* Refactor template render (#36438)
|
||||||
|
* Refactor GetRepoRawDiffForFile to avoid unnecessary pipe or goroutine (#36434)
|
||||||
|
* Refactor text utility classes to Tailwind CSS (#36703)
|
||||||
|
* Refactor git command stdio pipe (#36422)
|
||||||
|
* Refactor git command context & pipeline (#36406)
|
||||||
|
* Refactor git command stdio pipe (#36393)
|
||||||
|
* Remove unused functions (#36672)
|
||||||
|
* Refactor Actions Token Access (#35688)
|
||||||
|
* Move commit related functions to gitrepo package (#35600)
|
||||||
|
* Move archive function to repo_model and gitrepo (#35514)
|
||||||
|
* Move some functions to gitrepo package (#35503)
|
||||||
|
* Use git model to detect whether branch exist instead of gitrepo method (#35459)
|
||||||
|
* Some refactor for repo path (#36251)
|
||||||
|
* Extract helper functions from SearchIssues (#36158)
|
||||||
|
* Refactor merge conan and container auth preserve actions taskID (#36560)
|
||||||
|
* Refactor Nuget Auth to reuse Basic Auth Token Validation (#36558)
|
||||||
|
* Refactor ActionsTaskID (#36503)
|
||||||
|
* Refactor auth middleware (#36848)
|
||||||
|
* Refactor code render and render control chars (#37078)
|
||||||
|
* Clean up AppURL, remove legacy origin-url webcomponent (#37090)
|
||||||
|
* Remove `util.URLJoin` and replace all callers with direct path concatenation (#36867)
|
||||||
|
* Replace legacy tw-flex utility classes with flex-text-block/inline (#36778)
|
||||||
|
* Mark unused&immature activitypub as "not implemented" (#36789)
|
||||||
|
* TESTING
|
||||||
|
* Add e2e tests for server push events (#36879)
|
||||||
|
* Rework e2e tests (#36634)
|
||||||
|
* Add e2e reaction test, improve accessibility, enable parallel testing (#37081)
|
||||||
|
* Increase e2e test timeouts on CI to fix flaky tests (#37053)
|
||||||
|
* BUILD
|
||||||
|
* Upgrade go-git to v5.18.0 (#37269)
|
||||||
|
* Replace rollup-plugin-license with rolldown-license-plugin (#37130) (#37158)
|
||||||
|
* Bump min go version to 1.26.2 (#37139) (#37143)
|
||||||
|
* Convert locale files from ini to json format (#35489)
|
||||||
|
* Bump golangci-lint to 2.7.2, enable modernize stringsbuilder (#36180)
|
||||||
|
* Port away from `flake-utils` (#35675)
|
||||||
|
* Remove nolint (#36252)
|
||||||
|
* Update the Unlicense copy to latest version (#36636)
|
||||||
|
* Update to go 1.26.0 and golangci-lint 2.9.0 (#36588)
|
||||||
|
* Replace `google/go-licenses` with custom generation (#36575)
|
||||||
|
* Update go dependencies (#36548)
|
||||||
|
* Bump appleboy/git-push-action from 1.0.0 to 1.2.0 (#36306)
|
||||||
|
* Remove fomantic form module (#36222)
|
||||||
|
* Bump setup-node to v6, re-enable cache (#36207)
|
||||||
|
* Bump crowdin/github-action from 1 to 2 (#36204)
|
||||||
|
* Revert "Bump alpine to 3.23 (#36185)" (#36202)
|
||||||
|
* Update chroma to v2.21.1 (#36201)
|
||||||
|
* Bump astral-sh/setup-uv from 6 to 7 (#36198)
|
||||||
|
* Bump docker/build-push-action from 5 to 6 (#36197)
|
||||||
|
* Bump aws-actions/configure-aws-credentials from 4 to 5 (#36196)
|
||||||
|
* Bump dev-hanz-ops/install-gh-cli-action from 0.1.0 to 0.2.1 (#36195)
|
||||||
|
* Add JSON linting (#36192)
|
||||||
|
* Enable dependabot for actions (#36191)
|
||||||
|
* Bump alpine to 3.23 (#36185)
|
||||||
|
* Update chroma to v2.21.0 (#36171)
|
||||||
|
* Update JS deps and eslint enhancements (#36147)
|
||||||
|
* Update JS deps (#36091)
|
||||||
|
* update golangci-lint to v2.7.0 (#36079)
|
||||||
|
* Update JS deps, fix deprecations (#36040)
|
||||||
|
* Update JS deps (#35978)
|
||||||
|
* Add toolchain directive to go.mod (#35901)
|
||||||
|
* Move `gitea-vet` to use `go tool` (#35878)
|
||||||
|
* Update to go 1.25.4 (#35877)
|
||||||
|
* Enable TypeScript `strictNullChecks` (#35843)
|
||||||
|
* Enable `vue/require-typed-ref` eslint rule (#35764)
|
||||||
|
* Update JS dependencies (#35759)
|
||||||
|
* Move `codeformat` folder to tools (#35758)
|
||||||
|
* Update dependencies (#35733)
|
||||||
|
* Bump happy-dom from 20.0.0 to 20.0.2 (#35677)
|
||||||
|
* Bump setup-go to v6 (#35660)
|
||||||
|
* Update JS deps, misc tweaks (#35643)
|
||||||
|
* Bump happy-dom from 19.0.2 to 20.0.0 (#35625)
|
||||||
|
* Use bundled version of spectral (#35573)
|
||||||
|
* Update JS and PY deps (#35565)
|
||||||
|
* Bump github.com/wneessen/go-mail from 0.6.2 to 0.7.1 (#35557)
|
||||||
|
* Migrate from webpack to vite (#37002)
|
||||||
|
* Update JS dependencies and misc tweaks (#37064)
|
||||||
|
* Update to eslint 10 (#36925)
|
||||||
|
* Optimize Docker build with dependency layer caching (#36864)
|
||||||
|
* Update JS deps (#36850)
|
||||||
|
* Update tool dependencies and fix new lint issues (#36702)
|
||||||
|
* Remove redundant linter rules (#36658)
|
||||||
|
* Move Fomantic dropdown CSS to custom module (#36530)
|
||||||
|
* Remove and forbid `@ts-expect-error` (#36513)
|
||||||
|
* Refactor git command stderr handling (#36402)
|
||||||
|
* Enable gocheckcompilerdirectives linter (#36156)
|
||||||
|
* Replace `lint-go-gopls` with additional `govet` linters (#36028)
|
||||||
|
* Update golangci-lint to v2.6.0 (#35801)
|
||||||
|
* Misc tool tweaks (#35734)
|
||||||
|
* Add cache to container build (#35697)
|
||||||
|
* Upgrade vite (#37126)
|
||||||
|
* Update `setup-uv` to v8.0.0 (#37101)
|
||||||
|
* Upgrade `go-git` to v5.17.2 and related dependencies (#37060)
|
||||||
|
* Raise minimum Node.js version to 22.18.0 (#37058)
|
||||||
|
* Upgrade `golang.org/x/image` to v0.38.0 (#37054)
|
||||||
|
* Update minimum go version to 1.26.1, golangci-lint to 2.11.2, fix test style (#36876)
|
||||||
|
* Enable eslint concurrency (#36878)
|
||||||
|
* Vendor relative-time-element as local web component (#36853)
|
||||||
|
* Update material-icon-theme v5.32.0 (#36832)
|
||||||
|
* Update Go dependencies (#36781)
|
||||||
|
* Upgrade minimatch (#36760)
|
||||||
|
* Remove i18n backport tool at the moment because of translation format changed (#36643)
|
||||||
|
* Update emoji data for Unicode 16 (#36596)
|
||||||
|
* Update JS dependencies, adjust webpack config, misc fixes (#36431)
|
||||||
|
* Update material-icon-theme to v5.31.0 (#36427)
|
||||||
|
* Update JS and PY deps (#36383)
|
||||||
|
* Bump alpine to 3.23, add platforms to `docker-dryrun` (#36379)
|
||||||
|
* Update JS deps (#36354)
|
||||||
|
* Update goldmark to v1.7.16 (#36343)
|
||||||
|
* Update chroma to v2.22.0 (#36342)
|
||||||
|
* DOCS
|
||||||
|
* Update AI Contribution Policy (#37022)
|
||||||
|
* Update AGENTS.md with additional guidelines (#37018)
|
||||||
|
* Add missing cron tasks to example ini (#37012)
|
||||||
|
* Add AI Contribution Policy to CONTRIBUTING.md (#36651)
|
||||||
|
* Minor punctuation improvement in CONTRIBUTING.md (#36291)
|
||||||
|
* Add documentation for markdown anchor post-processing (#36443)
|
||||||
|
* MISC
|
||||||
|
* Correct spelling (#36783)
|
||||||
|
* Update Nix flake (#37110)
|
||||||
|
* Update Nix flake (#37024)
|
||||||
|
* Add valid github scopes (#36977)
|
||||||
|
* Update Nix flake (#36943)
|
||||||
|
* Update Nix flake (#36902)
|
||||||
|
* Update Nix flake (#36857)
|
||||||
|
* Update Nix flake (#36787)
|
||||||
|
|
||||||
|
## [1.25.5](https://github.com/go-gitea/gitea/releases/tag/v1.25.5) - 2026-03-10
|
||||||
|
|
||||||
|
* SECURITY
|
||||||
|
* Toolchain Update to Go 1.25.6 (#36480) (#36487)
|
||||||
|
* Adjust the toolchain version (#36537) (#36542)
|
||||||
|
* Update toolchain to 1.25.8 for v1.25 (#36888)
|
||||||
|
* Prevent redirect bypasses via backslash-encoded paths (#36660) (#36716)
|
||||||
|
* Fix get release draft permission check (#36659) (#36715)
|
||||||
|
* Fix a bug user could change another user's primary email (#36586) (#36607)
|
||||||
|
* Fix OAuth2 authorization code expiry and reuse handling (#36797) (#36851)
|
||||||
|
* Add validation constraints for repository creation fields (#36671) (#36757)
|
||||||
|
* Fix bug to check whether user can update pull request branch or rebase branch (#36465) (#36838)
|
||||||
|
* Add migration http transport for push/sync mirror lfs (#36665) (#36691)
|
||||||
|
* Fix track time list permission check (#36662) (#36744)
|
||||||
|
* Fix track time issue id (#36664) (#36689)
|
||||||
|
* Fix path resolving (#36734) (#36746)
|
||||||
|
* Fix dump release asset bug (#36799) (#36839)
|
||||||
|
* Fix org permission API visibility checks for hidden members and private orgs (#36798) (#36841)
|
||||||
|
* Fix forwarded proto handling for public URL detection (#36810) (#36836)
|
||||||
|
* Add a git grep search timeout (#36809) (#36835)
|
||||||
|
* Fix oauth2 s256 (#36462) (#36477)
|
||||||
|
* ENHANCEMENTS
|
||||||
|
* Make `security-check` informational only (#36681) (#36852)
|
||||||
|
* Upgrade to github.com/cloudflare/circl 1.6.3, svgo 4.0.1, markdownlint-cli 0.48.0 (#36840)
|
||||||
|
* Add some validation on values provided to USER_DISABLED_FEATURES and EXTERNAL_USER_DISABLED_FEATURES (#36688) (#36692)
|
||||||
|
* Upgrade gogit to 5.16.5 (#36687)
|
||||||
|
* Add wrap to runner label list (#36565) (#36574)
|
||||||
|
* Add dnf5 command for Fedora in RPM package instructions (#36527) (#36572)
|
||||||
|
* Allow scroll propagation outside code editor (#36502) (#36510)
|
||||||
|
* BUGFIXES
|
||||||
|
* Fix non-admins unable to automerge PRs from forks (#36833) (#36843)
|
||||||
|
* Fix bug when pushing mirror with wiki (#36795) (#36807)
|
||||||
|
* Fix artifacts v4 backend upload problems (#36805) (#36834)
|
||||||
|
* Fix CRAN package version validation to allow more than 4 version components (#36813) (#36821)
|
||||||
|
* Fix force push time-line commit comments of pull request (#36653) (#36717)
|
||||||
|
* Fix SVG height calculation in diff viewer (#36748) (#36750)
|
||||||
|
* Fix push time bug (#36693) (#36713)
|
||||||
|
* Fix bug the protected branch rule name is conflicted with renamed branch name (#36650) (#36661)
|
||||||
|
* Fix bug when do LFS GC (#36500) (#36608)
|
||||||
|
* Fix focus lost bugs in the Monaco editor (#36609)
|
||||||
|
* Reprocess htmx content after loading more files (#36568) (#36577)
|
||||||
|
* Fix assignee sidebar links and empty placeholder (#36559) (#36563)
|
||||||
|
* Fix issues filter dropdown showing empty label scope section (#36535) (#36544)
|
||||||
|
* Fix various mermaid bugs (#36547) (#36552)
|
||||||
|
* Fix data race when uploading container blobs concurrently (#36524) (#36526)
|
||||||
|
* Correct spacing between username and bot label (#36473) (#36484)
|
||||||
|
|
||||||
|
## [1.25.4](https://github.com/go-gitea/gitea/releases/tag/v1.25.4) - 2026-01-15
|
||||||
|
|
||||||
* SECURITY
|
* SECURITY
|
||||||
* Release attachments must belong to the intended repo (#36347) (#36375)
|
* Release attachments must belong to the intended repo (#36347) (#36375)
|
||||||
@@ -20,7 +551,8 @@ been added to each release, please refer to the [blog](https://blog.gitea.com).
|
|||||||
* Add more routes to the "expensive" list (#36290)
|
* Add more routes to the "expensive" list (#36290)
|
||||||
* Make "commit statuses" API accept slashes in "ref" (#36264) (#36275)
|
* Make "commit statuses" API accept slashes in "ref" (#36264) (#36275)
|
||||||
* BUGFIXES
|
* BUGFIXES
|
||||||
* Fix markdown newline handling during IME composition (#36421) #36424
|
* Fix git http service handling (#36396)
|
||||||
|
* Fix markdown newline handling during IME composition (#36421) (#36424)
|
||||||
* Fix missing repository id when migrating release attachments (#36389)
|
* Fix missing repository id when migrating release attachments (#36389)
|
||||||
* Fix bug when compare in the pull request (#36363) (#36372)
|
* Fix bug when compare in the pull request (#36363) (#36372)
|
||||||
* Fix incorrect text content detection (#36364) (#36369)
|
* Fix incorrect text content detection (#36364) (#36369)
|
||||||
@@ -35,7 +567,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.com).
|
|||||||
* Fix regression in writing authorized principals (#36213) (#36218)
|
* Fix regression in writing authorized principals (#36213) (#36218)
|
||||||
* Fix WebAuthn error checking (#36219) (#36235)
|
* Fix WebAuthn error checking (#36219) (#36235)
|
||||||
|
|
||||||
## [1.25.3](https://github.com/go-gitea/gitea/releases/tag/1.25.3) - 2025-12-17
|
## [1.25.3](https://github.com/go-gitea/gitea/releases/tag/v1.25.3) - 2025-12-17
|
||||||
|
|
||||||
* SECURITY
|
* SECURITY
|
||||||
* Bump toolchain to go1.25.5, misc fixes (#36082)
|
* Bump toolchain to go1.25.5, misc fixes (#36082)
|
||||||
@@ -62,7 +594,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.com).
|
|||||||
* Fix error handling in mailer and wiki services (#36041) (#36053)
|
* Fix error handling in mailer and wiki services (#36041) (#36053)
|
||||||
* Fix bugs when comparing and creating pull request (#36166) (#36144)
|
* Fix bugs when comparing and creating pull request (#36166) (#36144)
|
||||||
|
|
||||||
## [1.25.2](https://github.com/go-gitea/gitea/releases/tag/1.25.2) - 2025-11-23
|
## [1.25.2](https://github.com/go-gitea/gitea/releases/tag/v1.25.2) - 2025-11-23
|
||||||
|
|
||||||
* SECURITY
|
* SECURITY
|
||||||
* Upgrade golang.org/x/crypto to 0.45.0 (#35985) (#35988)
|
* Upgrade golang.org/x/crypto to 0.45.0 (#35985) (#35988)
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
@AGENTS.md
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
- [Contribution Guidelines](#contribution-guidelines)
|
- [Contribution Guidelines](#contribution-guidelines)
|
||||||
- [Introduction](#introduction)
|
- [Introduction](#introduction)
|
||||||
|
- [AI Contribution Policy](#ai-contribution-policy)
|
||||||
- [Issues](#issues)
|
- [Issues](#issues)
|
||||||
- [How to report issues](#how-to-report-issues)
|
- [How to report issues](#how-to-report-issues)
|
||||||
- [Types of issues](#types-of-issues)
|
- [Types of issues](#types-of-issues)
|
||||||
@@ -67,6 +68,21 @@ Sensitive security-related issues should be reported to [security@gitea.io](mail
|
|||||||
|
|
||||||
For configuring IDEs for Gitea development, see the [contributed IDE configurations](contrib/ide/).
|
For configuring IDEs for Gitea development, see the [contributed IDE configurations](contrib/ide/).
|
||||||
|
|
||||||
|
## AI Contribution Policy
|
||||||
|
|
||||||
|
Contributions made with the assistance of AI tools are welcome, but contributors must use them responsibly and disclose that use clearly.
|
||||||
|
|
||||||
|
1. Review AI-generated code closely before marking a pull request ready for review.
|
||||||
|
2. Manually test the changes and add appropriate automated tests where feasible.
|
||||||
|
3. Only use AI to assist in contributions that you understand well enough to explain, defend, and revise yourself during review.
|
||||||
|
4. Disclose AI-assisted content clearly.
|
||||||
|
5. Do not use AI to reply to questions about your issue or pull request. The questions are for you, not an AI model.
|
||||||
|
6. AI may be used to help draft issues and pull requests, but contributors remain responsible for the accuracy, completeness, and intent of what they submit.
|
||||||
|
|
||||||
|
Maintainers reserve the right to close pull requests and issues that do not disclose AI assistance, that appear to be low-quality AI-generated content, or where the contributor cannot explain or defend the proposed changes themselves.
|
||||||
|
|
||||||
|
We welcome new contributors, but cannot sustain the effort of supporting contributors who primarily defer to AI rather than engaging substantively with the review process.
|
||||||
|
|
||||||
## Issues
|
## Issues
|
||||||
|
|
||||||
### How to report issues
|
### How to report issues
|
||||||
@@ -80,7 +96,7 @@ 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://demo.gitea.com>, 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 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.
|
Please be kind—remember that Gitea comes at no cost to you, and you're getting free help.
|
||||||
|
|
||||||
### Types of issues
|
### Types of issues
|
||||||
|
|
||||||
@@ -166,24 +182,32 @@ Here's how to run the test suite:
|
|||||||
|
|
||||||
- code lint
|
- code lint
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
| :-------------------- | :---------------------------------------------------------------- |
|
| :-------------------- | :--------------------------------------------------------------------------- |
|
||||||
|``make lint`` | lint everything (not needed if you only change the front- **or** backend) |
|
|``make lint`` | lint everything (not needed if you only change the front- **or** backend) |
|
||||||
|``make lint-frontend`` | lint frontend files |
|
|``make lint-frontend`` | lint frontend files |
|
||||||
|``make lint-backend`` | lint backend files |
|
|``make lint-backend`` | lint backend files |
|
||||||
|
|
||||||
- run tests (we suggest running them on Linux)
|
- run tests (we suggest running them on Linux)
|
||||||
|
|
||||||
| Command | Action | |
|
| 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-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) |
|
|``make test-e2e`` | run [end-to-end](tests/e2e) test(s) using Playwright | |
|
||||||
|
|
||||||
|
- E2E test environment variables
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
| :-------------------------------- | :---------------------------------------------------------- |
|
||||||
|
| ``GITEA_TEST_E2E_DEBUG`` | When set, show Gitea server output |
|
||||||
|
| ``GITEA_TEST_E2E_FLAGS`` | Additional flags passed to Playwright, for example ``--ui`` |
|
||||||
|
| ``GITEA_TEST_E2E_TIMEOUT_FACTOR`` | Timeout multiplier (default: 3 on CI, 1 locally) |
|
||||||
|
|
||||||
## Translation
|
## Translation
|
||||||
|
|
||||||
All translation work happens on [Crowdin](https://translate.gitea.com).
|
All translation work happens on [Crowdin](https://translate.gitea.com).
|
||||||
The only translation that is maintained in this repository is [the English translation](https://github.com/go-gitea/gitea/blob/main/options/locale/locale_en-US.ini).
|
The only translation that is maintained in this repository is [the English translation](https://github.com/go-gitea/gitea/blob/main/options/locale/locale_en-US.json).
|
||||||
It is synced regularly with Crowdin. \
|
It is synced regularly with Crowdin. \
|
||||||
Other locales on main branch **should not** be updated manually as they will be overwritten with each sync. \
|
Other locales on main branch **should not** be updated manually as they will be overwritten with each sync. \
|
||||||
Once a language has reached a **satisfactory percentage** of translated keys (~25%), it will be synced back into this repo and included in the next released version.
|
Once a language has reached a **satisfactory percentage** of translated keys (~25%), it will be synced back into this repo and included in the next released version.
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
# Build stage
|
# syntax=docker/dockerfile:1
|
||||||
FROM docker.io/library/golang:1.25-alpine3.22 AS build-env
|
# Build frontend on the native platform to avoid QEMU-related issues with nodejs ecosystem
|
||||||
|
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.26-alpine3.23 AS frontend-build
|
||||||
|
RUN apk --no-cache add build-base git nodejs pnpm
|
||||||
|
WORKDIR /src
|
||||||
|
COPY package.json pnpm-lock.yaml .npmrc ./
|
||||||
|
RUN --mount=type=cache,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile
|
||||||
|
COPY --exclude=.git/ . .
|
||||||
|
RUN make frontend
|
||||||
|
|
||||||
ARG GOPROXY
|
# Build backend for each target platform
|
||||||
ENV GOPROXY=${GOPROXY:-direct}
|
FROM docker.io/library/golang:1.26-alpine3.23 AS build-env
|
||||||
|
|
||||||
ARG GITEA_VERSION
|
ARG GITEA_VERSION
|
||||||
ARG TAGS="sqlite sqlite_unlock_notify"
|
ARG TAGS="sqlite sqlite_unlock_notify"
|
||||||
@@ -12,37 +19,32 @@ ARG CGO_EXTRA_CFLAGS
|
|||||||
# Build deps
|
# Build deps
|
||||||
RUN apk --no-cache add \
|
RUN apk --no-cache add \
|
||||||
build-base \
|
build-base \
|
||||||
git \
|
git
|
||||||
nodejs \
|
|
||||||
npm \
|
|
||||||
&& npm install -g pnpm@10 \
|
|
||||||
&& rm -rf /var/cache/apk/*
|
|
||||||
|
|
||||||
# Setup repo
|
|
||||||
COPY . ${GOPATH}/src/code.gitea.io/gitea
|
|
||||||
WORKDIR ${GOPATH}/src/code.gitea.io/gitea
|
WORKDIR ${GOPATH}/src/code.gitea.io/gitea
|
||||||
|
COPY go.mod go.sum ./
|
||||||
|
RUN go mod download
|
||||||
|
# Use COPY instead of bind mount as read-only one breaks makefile state tracking and read-write one needs binary to be moved as it's discarded.
|
||||||
|
# ".git" directory is mounted separately later only for version data extraction.
|
||||||
|
COPY --exclude=.git/ . .
|
||||||
|
COPY --from=frontend-build /src/public/assets public/assets
|
||||||
|
|
||||||
# Checkout version if set
|
# Build gitea, .git mount is required for version data
|
||||||
RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
|
RUN --mount=type=cache,target="/root/.cache/go-build" \
|
||||||
&& make clean-all build
|
--mount=type=bind,source=".git/",target=".git/" \
|
||||||
|
make backend
|
||||||
|
|
||||||
# Begin env-to-ini build
|
|
||||||
RUN go build contrib/environment-to-ini/environment-to-ini.go
|
|
||||||
|
|
||||||
# Copy local files
|
|
||||||
COPY docker/root /tmp/local
|
COPY docker/root /tmp/local
|
||||||
|
|
||||||
# Set permissions
|
# Set permissions for builds that made under windows which strips the executable bit from file
|
||||||
RUN chmod 755 /tmp/local/usr/bin/entrypoint \
|
RUN chmod 755 /tmp/local/usr/bin/entrypoint \
|
||||||
/tmp/local/usr/local/bin/gitea \
|
/tmp/local/usr/local/bin/* \
|
||||||
/tmp/local/etc/s6/gitea/* \
|
/tmp/local/etc/s6/gitea/* \
|
||||||
/tmp/local/etc/s6/openssh/* \
|
/tmp/local/etc/s6/openssh/* \
|
||||||
/tmp/local/etc/s6/.s6-svscan/* \
|
/tmp/local/etc/s6/.s6-svscan/* \
|
||||||
/go/src/code.gitea.io/gitea/gitea \
|
/go/src/code.gitea.io/gitea/gitea
|
||||||
/go/src/code.gitea.io/gitea/environment-to-ini
|
|
||||||
|
|
||||||
FROM docker.io/library/alpine:3.22
|
FROM docker.io/library/alpine:3.23 AS gitea
|
||||||
LABEL maintainer="maintainers@gitea.io"
|
|
||||||
|
|
||||||
EXPOSE 22 3000
|
EXPOSE 22 3000
|
||||||
|
|
||||||
@@ -57,8 +59,7 @@ RUN apk --no-cache add \
|
|||||||
s6 \
|
s6 \
|
||||||
sqlite \
|
sqlite \
|
||||||
su-exec \
|
su-exec \
|
||||||
gnupg \
|
gnupg
|
||||||
&& rm -rf /var/cache/apk/*
|
|
||||||
|
|
||||||
RUN addgroup \
|
RUN addgroup \
|
||||||
-S -g 1000 \
|
-S -g 1000 \
|
||||||
@@ -72,14 +73,14 @@ RUN addgroup \
|
|||||||
git && \
|
git && \
|
||||||
echo "git:*" | chpasswd -e
|
echo "git:*" | chpasswd -e
|
||||||
|
|
||||||
|
COPY --from=build-env /tmp/local /
|
||||||
|
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
||||||
|
|
||||||
ENV USER=git
|
ENV USER=git
|
||||||
ENV GITEA_CUSTOM=/data/gitea
|
ENV GITEA_CUSTOM=/data/gitea
|
||||||
|
|
||||||
VOLUME ["/data"]
|
VOLUME ["/data"]
|
||||||
|
|
||||||
|
# HINT: HEALTH-CHECK-ENDPOINT: don't use HEALTHCHECK, search this hint keyword for more information
|
||||||
ENTRYPOINT ["/usr/bin/entrypoint"]
|
ENTRYPOINT ["/usr/bin/entrypoint"]
|
||||||
CMD ["/usr/bin/s6-svscan", "/etc/s6"]
|
CMD ["/usr/bin/s6-svscan", "/etc/s6"]
|
||||||
|
|
||||||
COPY --from=build-env /tmp/local /
|
|
||||||
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
|
|
||||||
|
|||||||
@@ -1,46 +1,45 @@
|
|||||||
# Build stage
|
# syntax=docker/dockerfile:1
|
||||||
FROM docker.io/library/golang:1.25-alpine3.22 AS build-env
|
# Build frontend on the native platform to avoid QEMU-related issues with nodejs ecosystem
|
||||||
|
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.26-alpine3.23 AS frontend-build
|
||||||
|
RUN apk --no-cache add build-base git nodejs pnpm
|
||||||
|
WORKDIR /src
|
||||||
|
COPY package.json pnpm-lock.yaml .npmrc ./
|
||||||
|
RUN --mount=type=cache,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile
|
||||||
|
COPY --exclude=.git/ . .
|
||||||
|
RUN make frontend
|
||||||
|
|
||||||
ARG GOPROXY
|
# Build backend for each target platform
|
||||||
ENV GOPROXY=${GOPROXY:-direct}
|
FROM docker.io/library/golang:1.26-alpine3.23 AS build-env
|
||||||
|
|
||||||
ARG GITEA_VERSION
|
ARG GITEA_VERSION
|
||||||
ARG TAGS="sqlite sqlite_unlock_notify"
|
ARG TAGS="sqlite sqlite_unlock_notify"
|
||||||
ENV TAGS="bindata timetzdata $TAGS"
|
ENV TAGS="bindata timetzdata $TAGS"
|
||||||
ARG CGO_EXTRA_CFLAGS
|
ARG CGO_EXTRA_CFLAGS
|
||||||
|
|
||||||
#Build deps
|
# Build deps
|
||||||
RUN apk --no-cache add \
|
RUN apk --no-cache add \
|
||||||
build-base \
|
build-base \
|
||||||
git \
|
git
|
||||||
nodejs \
|
|
||||||
npm \
|
|
||||||
&& npm install -g pnpm@10 \
|
|
||||||
&& rm -rf /var/cache/apk/*
|
|
||||||
|
|
||||||
# Setup repo
|
|
||||||
COPY . ${GOPATH}/src/code.gitea.io/gitea
|
|
||||||
WORKDIR ${GOPATH}/src/code.gitea.io/gitea
|
WORKDIR ${GOPATH}/src/code.gitea.io/gitea
|
||||||
|
COPY go.mod go.sum ./
|
||||||
|
RUN go mod download
|
||||||
|
# See the comments in Dockerfile
|
||||||
|
COPY --exclude=.git/ . .
|
||||||
|
COPY --from=frontend-build /src/public/assets public/assets
|
||||||
|
|
||||||
# Checkout version if set
|
# Build gitea, .git mount is required for version data
|
||||||
RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
|
RUN --mount=type=cache,target="/root/.cache/go-build" \
|
||||||
&& make clean-all build
|
--mount=type=bind,source=".git/",target=".git/" \
|
||||||
|
make backend
|
||||||
|
|
||||||
# Begin env-to-ini build
|
|
||||||
RUN go build contrib/environment-to-ini/environment-to-ini.go
|
|
||||||
|
|
||||||
# Copy local files
|
|
||||||
COPY docker/rootless /tmp/local
|
COPY docker/rootless /tmp/local
|
||||||
|
|
||||||
# Set permissions
|
# Set permissions for builds that made under windows which strips the executable bit from file
|
||||||
RUN chmod 755 /tmp/local/usr/local/bin/docker-entrypoint.sh \
|
RUN chmod 755 /tmp/local/usr/local/bin/* \
|
||||||
/tmp/local/usr/local/bin/docker-setup.sh \
|
/go/src/code.gitea.io/gitea/gitea
|
||||||
/tmp/local/usr/local/bin/gitea \
|
|
||||||
/go/src/code.gitea.io/gitea/gitea \
|
|
||||||
/go/src/code.gitea.io/gitea/environment-to-ini
|
|
||||||
|
|
||||||
FROM docker.io/library/alpine:3.22
|
FROM docker.io/library/alpine:3.23 AS gitea-rootless
|
||||||
LABEL maintainer="maintainers@gitea.io"
|
|
||||||
|
|
||||||
EXPOSE 2222 3000
|
EXPOSE 2222 3000
|
||||||
|
|
||||||
@@ -52,8 +51,7 @@ RUN apk --no-cache add \
|
|||||||
git \
|
git \
|
||||||
curl \
|
curl \
|
||||||
gnupg \
|
gnupg \
|
||||||
openssh-keygen \
|
openssh-keygen
|
||||||
&& rm -rf /var/cache/apk/*
|
|
||||||
|
|
||||||
RUN addgroup \
|
RUN addgroup \
|
||||||
-S -g 1000 \
|
-S -g 1000 \
|
||||||
@@ -71,7 +69,6 @@ RUN chown git:git /var/lib/gitea /etc/gitea
|
|||||||
|
|
||||||
COPY --from=build-env /tmp/local /
|
COPY --from=build-env /tmp/local /
|
||||||
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
||||||
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
|
|
||||||
|
|
||||||
# git:git
|
# git:git
|
||||||
USER 1000:1000
|
USER 1000:1000
|
||||||
@@ -86,5 +83,6 @@ ENV HOME="/var/lib/gitea/git"
|
|||||||
VOLUME ["/var/lib/gitea", "/etc/gitea"]
|
VOLUME ["/var/lib/gitea", "/etc/gitea"]
|
||||||
WORKDIR /var/lib/gitea
|
WORKDIR /var/lib/gitea
|
||||||
|
|
||||||
|
# HINT: HEALTH-CHECK-ENDPOINT: don't use HEALTHCHECK, search this hint keyword for more information
|
||||||
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/usr/local/bin/docker-entrypoint.sh"]
|
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/usr/local/bin/docker-entrypoint.sh"]
|
||||||
CMD []
|
CMD []
|
||||||
|
|||||||
@@ -64,3 +64,4 @@ metiftikci <metiftikci@hotmail.com> (@metiftikci)
|
|||||||
Christopher Homberger <christopher.homberger@web.de> (@ChristopherHX)
|
Christopher Homberger <christopher.homberger@web.de> (@ChristopherHX)
|
||||||
Tobias Balle-Petersen <tobiasbp@gmail.com> (@tobiasbp)
|
Tobias Balle-Petersen <tobiasbp@gmail.com> (@tobiasbp)
|
||||||
TheFox <thefox0x7@gmail.com> (@TheFox0x7)
|
TheFox <thefox0x7@gmail.com> (@TheFox0x7)
|
||||||
|
Nicolas <bircni@icloud.com> (@bircni)
|
||||||
+132
-251
@@ -1,22 +1,9 @@
|
|||||||
ifeq ($(USE_REPO_TEST_DIR),1)
|
|
||||||
|
|
||||||
# This rule replaces the whole Makefile when we're trying to use /tmp repository temporary files
|
|
||||||
location = $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
|
|
||||||
self := $(location)
|
|
||||||
|
|
||||||
%:
|
|
||||||
@tmpdir=`mktemp --tmpdir -d` ; \
|
|
||||||
echo Using temporary directory $$tmpdir for test repositories ; \
|
|
||||||
USE_REPO_TEST_DIR= $(MAKE) -f $(self) --no-print-directory REPO_TEST_DIR=$$tmpdir/ $@ ; \
|
|
||||||
STATUS=$$? ; rm -r "$$tmpdir" ; exit $$STATUS
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
# This is the "normal" part of the Makefile
|
|
||||||
|
|
||||||
DIST := dist
|
DIST := dist
|
||||||
DIST_DIRS := $(DIST)/binaries $(DIST)/release
|
DIST_DIRS := $(DIST)/binaries $(DIST)/release
|
||||||
IMPORT := code.gitea.io/gitea
|
|
||||||
|
# By default use go's 1.25 experimental json v2 library when building
|
||||||
|
# TODO: remove when no longer experimental
|
||||||
|
export GOEXPERIMENT ?= jsonv2
|
||||||
|
|
||||||
GO ?= go
|
GO ?= go
|
||||||
SHASUM ?= shasum -a 256
|
SHASUM ?= shasum -a 256
|
||||||
@@ -27,17 +14,14 @@ XGO_VERSION := go-1.25.x
|
|||||||
|
|
||||||
AIR_PACKAGE ?= github.com/air-verse/air@v1
|
AIR_PACKAGE ?= github.com/air-verse/air@v1
|
||||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3
|
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3
|
||||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.9.1
|
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.9.2
|
||||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.4.0
|
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.11.4
|
||||||
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.15
|
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.15
|
||||||
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.7.0
|
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.8.0
|
||||||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@717e3cb29becaaf00e56953556c6d80f8a01b286
|
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.33.1
|
||||||
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
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
|
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1
|
||||||
ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1.7.8
|
ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1.7.11
|
||||||
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.20.0
|
|
||||||
GOPLS_MODERNIZE_PACKAGE ?= golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@v0.20.0
|
|
||||||
|
|
||||||
DOCKER_IMAGE ?= gitea/gitea
|
DOCKER_IMAGE ?= gitea/gitea
|
||||||
DOCKER_TAG ?= latest
|
DOCKER_TAG ?= latest
|
||||||
@@ -69,9 +53,11 @@ endif
|
|||||||
ifeq ($(IS_WINDOWS),yes)
|
ifeq ($(IS_WINDOWS),yes)
|
||||||
GOFLAGS := -v -buildmode=exe
|
GOFLAGS := -v -buildmode=exe
|
||||||
EXECUTABLE ?= gitea.exe
|
EXECUTABLE ?= gitea.exe
|
||||||
|
EXECUTABLE_E2E ?= gitea-e2e.exe
|
||||||
else
|
else
|
||||||
GOFLAGS := -v
|
GOFLAGS := -v
|
||||||
EXECUTABLE ?= gitea
|
EXECUTABLE ?= gitea
|
||||||
|
EXECUTABLE_E2E ?= gitea-e2e
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(shell sed --version 2>/dev/null | grep -q GNU && echo gnu),gnu)
|
ifeq ($(shell sed --version 2>/dev/null | grep -q GNU && echo gnu),gnu)
|
||||||
@@ -82,7 +68,6 @@ endif
|
|||||||
|
|
||||||
EXTRA_GOFLAGS ?=
|
EXTRA_GOFLAGS ?=
|
||||||
|
|
||||||
MAKE_VERSION := $(shell "$(MAKE)" -v | cat | head -n 1)
|
|
||||||
MAKE_EVIDENCE_DIR := .make_evidence
|
MAKE_EVIDENCE_DIR := .make_evidence
|
||||||
|
|
||||||
GOTESTFLAGS ?=
|
GOTESTFLAGS ?=
|
||||||
@@ -96,15 +81,6 @@ STORED_VERSION_FILE := VERSION
|
|||||||
GITHUB_REF_TYPE ?= branch
|
GITHUB_REF_TYPE ?= branch
|
||||||
GITHUB_REF_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
GITHUB_REF_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||||
|
|
||||||
# Enable typescript support in Node.js before 22.18
|
|
||||||
# TODO: Remove this once we can raise the minimum Node.js version to 22.18 (alpine >= 3.23)
|
|
||||||
NODE_VERSION := $(shell printf "%03d%03d%03d" $(shell node -v 2>/dev/null | cut -c2- | tr '.' ' '))
|
|
||||||
ifeq ($(shell test "$(NODE_VERSION)" -lt "022018000"; echo $$?),0)
|
|
||||||
NODE_VARS := NODE_OPTIONS="--experimental-strip-types"
|
|
||||||
else
|
|
||||||
NODE_VARS :=
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifneq ($(GITHUB_REF_TYPE),branch)
|
ifneq ($(GITHUB_REF_TYPE),branch)
|
||||||
VERSION ?= $(subst v,,$(GITHUB_REF_NAME))
|
VERSION ?= $(subst v,,$(GITHUB_REF_NAME))
|
||||||
GITEA_VERSION ?= $(VERSION)
|
GITEA_VERSION ?= $(VERSION)
|
||||||
@@ -128,17 +104,18 @@ ifeq ($(VERSION),main)
|
|||||||
VERSION := main-nightly
|
VERSION := main-nightly
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)"
|
LDFLAGS := $(LDFLAGS) -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)"
|
||||||
|
|
||||||
LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64,linux/riscv64
|
LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64,linux/riscv64
|
||||||
|
|
||||||
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/))
|
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,$(shell $(GO) list ./... | grep -v /vendor/))
|
||||||
MIGRATE_TEST_PACKAGES ?= $(shell $(GO) list code.gitea.io/gitea/models/migrations/...)
|
MIGRATE_TEST_PACKAGES ?= $(shell $(GO) list code.gitea.io/gitea/models/migrations/...)
|
||||||
|
|
||||||
WEBPACK_SOURCES := $(shell find web_src/js web_src/css -type f)
|
FRONTEND_SOURCES := $(shell find web_src/js web_src/css -type f)
|
||||||
WEBPACK_CONFIGS := webpack.config.ts tailwind.config.ts
|
FRONTEND_CONFIGS := vite.config.ts tailwind.config.ts
|
||||||
WEBPACK_DEST := public/assets/js/index.js public/assets/css/index.css
|
FRONTEND_DEST := public/assets/.vite/manifest.json
|
||||||
WEBPACK_DEST_ENTRIES := public/assets/js public/assets/css public/assets/fonts
|
FRONTEND_DEST_ENTRIES := public/assets/js public/assets/css public/assets/fonts public/assets/.vite
|
||||||
|
FRONTEND_DEV_LOG_LEVEL ?= warn
|
||||||
|
|
||||||
BINDATA_DEST_WILDCARD := modules/migration/bindata.* modules/public/bindata.* modules/options/bindata.* modules/templates/bindata.*
|
BINDATA_DEST_WILDCARD := modules/migration/bindata.* modules/public/bindata.* modules/options/bindata.* modules/templates/bindata.*
|
||||||
|
|
||||||
@@ -148,7 +125,6 @@ SVG_DEST_DIR := public/assets/img/svg
|
|||||||
|
|
||||||
AIR_TMP_DIR := .air
|
AIR_TMP_DIR := .air
|
||||||
|
|
||||||
GO_LICENSE_TMP_DIR := .go-licenses
|
|
||||||
GO_LICENSE_FILE := assets/go-licenses.json
|
GO_LICENSE_FILE := assets/go-licenses.json
|
||||||
|
|
||||||
TAGS ?=
|
TAGS ?=
|
||||||
@@ -157,24 +133,21 @@ TAGS_EVIDENCE := $(MAKE_EVIDENCE_DIR)/tags
|
|||||||
|
|
||||||
TEST_TAGS ?= $(TAGS_SPLIT) sqlite sqlite_unlock_notify
|
TEST_TAGS ?= $(TAGS_SPLIT) sqlite sqlite_unlock_notify
|
||||||
|
|
||||||
TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(DIST) $(MAKE_EVIDENCE_DIR) $(AIR_TMP_DIR) $(GO_LICENSE_TMP_DIR)
|
TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(DIST) $(MAKE_EVIDENCE_DIR) $(AIR_TMP_DIR)
|
||||||
|
|
||||||
GO_DIRS := build cmd models modules routers services tests
|
GO_DIRS := build cmd models modules routers services tests tools
|
||||||
WEB_DIRS := web_src/js web_src/css
|
WEB_DIRS := web_src/js web_src/css
|
||||||
|
|
||||||
ESLINT_FILES := web_src/js tools *.ts tests/e2e
|
ESLINT_FILES := web_src/js tools *.ts tests/e2e
|
||||||
STYLELINT_FILES := web_src/css web_src/js/components/*.vue
|
STYLELINT_FILES := web_src/css web_src/js/components/*.vue
|
||||||
SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) templates options/locale/locale_en-US.ini .github $(filter-out CHANGELOG.md, $(wildcard *.go *.md *.yml *.yaml *.toml)) $(filter-out tools/misspellings.csv, $(wildcard tools/*))
|
SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) templates options/locale/locale_en-US.json .github $(filter-out CHANGELOG.md, $(wildcard *.go *.md *.yml *.yaml *.toml))
|
||||||
EDITORCONFIG_FILES := templates .github/workflows options/locale/locale_en-US.ini
|
EDITORCONFIG_FILES := templates .github/workflows options/locale/locale_en-US.json
|
||||||
|
|
||||||
GO_SOURCES := $(wildcard *.go)
|
GO_SOURCES := $(wildcard *.go)
|
||||||
GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go")
|
GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go")
|
||||||
GO_SOURCES += $(GENERATED_GO_DEST)
|
GO_SOURCES += $(GENERATED_GO_DEST)
|
||||||
|
|
||||||
# Force installation of playwright dependencies by setting this flag
|
ESLINT_CONCURRENCY ?= 2
|
||||||
ifdef DEPS_PLAYWRIGHT
|
|
||||||
PLAYWRIGHT_FLAGS += --with-deps
|
|
||||||
endif
|
|
||||||
|
|
||||||
SWAGGER_SPEC := templates/swagger/v1_json.tmpl
|
SWAGGER_SPEC := templates/swagger/v1_json.tmpl
|
||||||
SWAGGER_SPEC_INPUT := templates/swagger/v1_input.json
|
SWAGGER_SPEC_INPUT := templates/swagger/v1_input.json
|
||||||
@@ -195,26 +168,20 @@ TEST_MSSQL_DBNAME ?= gitea
|
|||||||
TEST_MSSQL_USERNAME ?= sa
|
TEST_MSSQL_USERNAME ?= sa
|
||||||
TEST_MSSQL_PASSWORD ?= MwantsaSecurePassword1
|
TEST_MSSQL_PASSWORD ?= MwantsaSecurePassword1
|
||||||
|
|
||||||
|
# Include local Makefile
|
||||||
|
# Makefile.local is listed in .gitignore
|
||||||
|
sinclude Makefile.local
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: build
|
all: build
|
||||||
|
|
||||||
.PHONY: help
|
.PHONY: help
|
||||||
help: Makefile ## print Makefile help information.
|
help: Makefile ## print Makefile help information.
|
||||||
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m[TARGETS] default target: build\033[0m\n\n\033[35mTargets:\033[0m\n"} /^[0-9A-Za-z._-]+:.*?##/ { printf " \033[36m%-45s\033[0m %s\n", $$1, $$2 }' Makefile #$(MAKEFILE_LIST)
|
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m[TARGETS] default target: build\033[0m\n\n\033[35mTargets:\033[0m\n"} /^[0-9A-Za-z._-]+:.*?##/ { printf " \033[36m%-45s\033[0m %s\n", $$1, $$2 }' Makefile #$(MAKEFILE_LIST)
|
||||||
@printf " \033[36m%-46s\033[0m %s\n" "test-e2e[#TestSpecificName]" "test end to end using playwright"
|
@printf " \033[36m%-46s\033[0m %s\n" "test-e2e" "test end to end using playwright"
|
||||||
@printf " \033[36m%-46s\033[0m %s\n" "test[#TestSpecificName]" "run unit test"
|
@printf " \033[36m%-46s\033[0m %s\n" "test[#TestSpecificName]" "run unit test"
|
||||||
@printf " \033[36m%-46s\033[0m %s\n" "test-sqlite[#TestSpecificName]" "run integration test for sqlite"
|
@printf " \033[36m%-46s\033[0m %s\n" "test-sqlite[#TestSpecificName]" "run integration test for sqlite"
|
||||||
|
|
||||||
.PHONY: go-check
|
|
||||||
go-check:
|
|
||||||
$(eval MIN_GO_VERSION_STR := $(shell grep -Eo '^go\s+[0-9]+\.[0-9]+' go.mod | cut -d' ' -f2))
|
|
||||||
$(eval MIN_GO_VERSION := $(shell printf "%03d%03d" $(shell echo '$(MIN_GO_VERSION_STR)' | tr '.' ' ')))
|
|
||||||
$(eval GO_VERSION := $(shell printf "%03d%03d" $(shell $(GO) version | grep -Eo '[0-9]+\.[0-9]+' | tr '.' ' ');))
|
|
||||||
@if [ "$(GO_VERSION)" -lt "$(MIN_GO_VERSION)" ]; then \
|
|
||||||
echo "Gitea requires Go $(MIN_GO_VERSION_STR) or greater to build. You can get it at https://go.dev/dl/"; \
|
|
||||||
exit 1; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
.PHONY: git-check
|
.PHONY: git-check
|
||||||
git-check:
|
git-check:
|
||||||
@if git lfs >/dev/null 2>&1 ; then : ; else \
|
@if git lfs >/dev/null 2>&1 ; then : ; else \
|
||||||
@@ -222,39 +189,24 @@ git-check:
|
|||||||
exit 1; \
|
exit 1; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
.PHONY: node-check
|
|
||||||
node-check:
|
|
||||||
$(eval MIN_NODE_VERSION_STR := $(shell grep -Eo '"node":.*[0-9.]+"' package.json | sed -n 's/.*[^0-9.]\([0-9.]*\)"/\1/p'))
|
|
||||||
$(eval MIN_NODE_VERSION := $(shell printf "%03d%03d%03d" $(shell echo '$(MIN_NODE_VERSION_STR)' | tr '.' ' ')))
|
|
||||||
$(eval PNPM_MISSING := $(shell hash pnpm > /dev/null 2>&1 || echo 1))
|
|
||||||
@if [ "$(NODE_VERSION)" -lt "$(MIN_NODE_VERSION)" ]; then \
|
|
||||||
echo "Gitea requires Node.js $(MIN_NODE_VERSION_STR) or greater to build. You can get it at https://nodejs.org/en/download/"; \
|
|
||||||
exit 1; \
|
|
||||||
fi
|
|
||||||
@if [ "$(PNPM_MISSING)" = "1" ]; then \
|
|
||||||
echo "Gitea requires pnpm to build. You can install it at https://pnpm.io/installation"; \
|
|
||||||
exit 1; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
.PHONY: clean-all
|
.PHONY: clean-all
|
||||||
clean-all: clean ## delete backend, frontend and integration files
|
clean-all: clean ## delete backend, frontend and integration files
|
||||||
rm -rf $(WEBPACK_DEST_ENTRIES) node_modules
|
rm -rf $(FRONTEND_DEST_ENTRIES) node_modules
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean: ## delete backend and integration files
|
clean: ## delete backend and integration files
|
||||||
rm -rf $(EXECUTABLE) $(DIST) $(BINDATA_DEST_WILDCARD) \
|
rm -rf $(EXECUTABLE) $(EXECUTABLE_E2E) $(DIST) $(BINDATA_DEST_WILDCARD) \
|
||||||
integrations*.test \
|
integrations*.test \
|
||||||
e2e*.test \
|
|
||||||
tests/integration/gitea-integration-* \
|
tests/integration/gitea-integration-* \
|
||||||
tests/integration/indexers-* \
|
tests/integration/indexers-* \
|
||||||
tests/mysql.ini tests/pgsql.ini tests/mssql.ini man/ \
|
tests/sqlite.ini tests/mysql.ini tests/pgsql.ini tests/mssql.ini man/ \
|
||||||
tests/e2e/gitea-e2e-*/ \
|
tests/e2e/gitea-e2e-*/ \
|
||||||
tests/e2e/indexers-*/ \
|
tests/e2e/indexers-*/ \
|
||||||
tests/e2e/reports/ tests/e2e/test-artifacts/ tests/e2e/test-snapshots/
|
tests/e2e/reports/ tests/e2e/test-artifacts/ tests/e2e/test-snapshots/
|
||||||
|
|
||||||
.PHONY: fmt
|
.PHONY: fmt
|
||||||
fmt: ## format the Go and template code
|
fmt: ## format the Go and template code
|
||||||
@GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) $(GO) run build/code-batch-process.go gitea-fmt -w '{file-list}'
|
@GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) $(GO) run tools/code-batch-process.go gitea-fmt -w '{file-list}'
|
||||||
$(eval TEMPLATES := $(shell find templates -type f -name '*.tmpl'))
|
$(eval TEMPLATES := $(shell find templates -type f -name '*.tmpl'))
|
||||||
@# strip whitespace after '{{' or '(' and before '}}' or ')' unless there is only
|
@# strip whitespace after '{{' or '(' and before '}}' or ')' unless there is only
|
||||||
@# whitespace before it
|
@# whitespace before it
|
||||||
@@ -272,19 +224,6 @@ fmt-check: fmt
|
|||||||
exit 1; \
|
exit 1; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
.PHONY: fix
|
|
||||||
fix: ## apply automated fixes to Go code
|
|
||||||
$(GO) run $(GOPLS_MODERNIZE_PACKAGE) -fix ./...
|
|
||||||
|
|
||||||
.PHONY: fix-check
|
|
||||||
fix-check: fix
|
|
||||||
@diff=$$(git diff --color=always $(GO_SOURCES)); \
|
|
||||||
if [ -n "$$diff" ]; then \
|
|
||||||
echo "Please run 'make fix' and commit the result:"; \
|
|
||||||
printf "%s" "$${diff}"; \
|
|
||||||
exit 1; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
.PHONY: $(TAGS_EVIDENCE)
|
.PHONY: $(TAGS_EVIDENCE)
|
||||||
$(TAGS_EVIDENCE):
|
$(TAGS_EVIDENCE):
|
||||||
@mkdir -p $(MAKE_EVIDENCE_DIR)
|
@mkdir -p $(MAKE_EVIDENCE_DIR)
|
||||||
@@ -324,7 +263,7 @@ checks: checks-frontend checks-backend ## run various consistency checks
|
|||||||
checks-frontend: lockfile-check svg-check ## check frontend files
|
checks-frontend: lockfile-check svg-check ## check frontend files
|
||||||
|
|
||||||
.PHONY: checks-backend
|
.PHONY: checks-backend
|
||||||
checks-backend: tidy-check swagger-check fmt-check fix-check swagger-validate security-check ## check backend files
|
checks-backend: tidy-check swagger-check fmt-check swagger-validate security-check ## check backend files
|
||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint: lint-frontend lint-backend lint-spell ## lint everything
|
lint: lint-frontend lint-backend lint-spell ## lint everything
|
||||||
@@ -339,44 +278,48 @@ lint-frontend: lint-js lint-css ## lint frontend files
|
|||||||
lint-frontend-fix: lint-js-fix lint-css-fix ## lint frontend files and fix issues
|
lint-frontend-fix: lint-js-fix lint-css-fix ## lint frontend files and fix issues
|
||||||
|
|
||||||
.PHONY: lint-backend
|
.PHONY: lint-backend
|
||||||
lint-backend: lint-go lint-go-gitea-vet lint-go-gopls lint-editorconfig ## lint backend files
|
lint-backend: lint-go lint-go-gitea-vet lint-editorconfig ## lint backend files
|
||||||
|
|
||||||
.PHONY: lint-backend-fix
|
.PHONY: lint-backend-fix
|
||||||
lint-backend-fix: lint-go-fix lint-go-gitea-vet lint-editorconfig ## lint backend files and fix issues
|
lint-backend-fix: lint-go-fix lint-go-gitea-vet lint-editorconfig ## lint backend files and fix issues
|
||||||
|
|
||||||
.PHONY: lint-js
|
.PHONY: lint-js
|
||||||
lint-js: node_modules ## lint js files
|
lint-js: node_modules ## lint js and ts files
|
||||||
$(NODE_VARS) pnpm exec eslint --color --max-warnings=0 --flag unstable_native_nodejs_ts_config $(ESLINT_FILES)
|
pnpm exec eslint --color --max-warnings=0 --concurrency $(ESLINT_CONCURRENCY) $(ESLINT_FILES)
|
||||||
$(NODE_VARS) pnpm exec vue-tsc
|
pnpm exec vue-tsc
|
||||||
|
|
||||||
.PHONY: lint-js-fix
|
.PHONY: lint-js-fix
|
||||||
lint-js-fix: node_modules ## lint js files and fix issues
|
lint-js-fix: node_modules ## lint js and ts files and fix issues
|
||||||
$(NODE_VARS) pnpm exec eslint --color --max-warnings=0 --flag unstable_native_nodejs_ts_config $(ESLINT_FILES) --fix
|
pnpm exec eslint --color --max-warnings=0 --concurrency $(ESLINT_CONCURRENCY) $(ESLINT_FILES) --fix
|
||||||
$(NODE_VARS) pnpm exec vue-tsc
|
pnpm exec vue-tsc
|
||||||
|
|
||||||
.PHONY: lint-css
|
.PHONY: lint-css
|
||||||
lint-css: node_modules ## lint css files
|
lint-css: node_modules ## lint css files
|
||||||
$(NODE_VARS) pnpm exec stylelint --color --max-warnings=0 $(STYLELINT_FILES)
|
pnpm exec stylelint --color --max-warnings=0 $(STYLELINT_FILES)
|
||||||
|
|
||||||
.PHONY: lint-css-fix
|
.PHONY: lint-css-fix
|
||||||
lint-css-fix: node_modules ## lint css files and fix issues
|
lint-css-fix: node_modules ## lint css files and fix issues
|
||||||
$(NODE_VARS) pnpm exec stylelint --color --max-warnings=0 $(STYLELINT_FILES) --fix
|
pnpm exec stylelint --color --max-warnings=0 $(STYLELINT_FILES) --fix
|
||||||
|
|
||||||
.PHONY: lint-swagger
|
.PHONY: lint-swagger
|
||||||
lint-swagger: node_modules ## lint swagger files
|
lint-swagger: node_modules ## lint swagger files
|
||||||
$(NODE_VARS) pnpm exec spectral lint -q -F hint $(SWAGGER_SPEC)
|
pnpm exec spectral lint -q -F hint $(SWAGGER_SPEC)
|
||||||
|
|
||||||
.PHONY: lint-md
|
.PHONY: lint-md
|
||||||
lint-md: node_modules ## lint markdown files
|
lint-md: node_modules ## lint markdown files
|
||||||
$(NODE_VARS) pnpm exec markdownlint *.md
|
pnpm exec markdownlint *.md
|
||||||
|
|
||||||
|
.PHONY: lint-md-fix
|
||||||
|
lint-md-fix: node_modules ## lint markdown files and fix issues
|
||||||
|
pnpm exec markdownlint --fix *.md
|
||||||
|
|
||||||
.PHONY: lint-spell
|
.PHONY: lint-spell
|
||||||
lint-spell: ## lint spelling
|
lint-spell: ## lint spelling
|
||||||
@go run $(MISSPELL_PACKAGE) -dict tools/misspellings.csv -error $(SPELLCHECK_FILES)
|
@git ls-files $(SPELLCHECK_FILES) | xargs go run $(MISSPELL_PACKAGE) -dict assets/misspellings.csv -error
|
||||||
|
|
||||||
.PHONY: lint-spell-fix
|
.PHONY: lint-spell-fix
|
||||||
lint-spell-fix: ## lint spelling and fix issues
|
lint-spell-fix: ## lint spelling and fix issues
|
||||||
@go run $(MISSPELL_PACKAGE) -dict tools/misspellings.csv -w $(SPELLCHECK_FILES)
|
@git ls-files $(SPELLCHECK_FILES) | xargs go run $(MISSPELL_PACKAGE) -dict assets/misspellings.csv -w
|
||||||
|
|
||||||
.PHONY: lint-go
|
.PHONY: lint-go
|
||||||
lint-go: ## lint go files
|
lint-go: ## lint go files
|
||||||
@@ -396,13 +339,7 @@ lint-go-windows:
|
|||||||
.PHONY: lint-go-gitea-vet
|
.PHONY: lint-go-gitea-vet
|
||||||
lint-go-gitea-vet: ## lint go files with gitea-vet
|
lint-go-gitea-vet: ## lint go files with gitea-vet
|
||||||
@echo "Running gitea-vet..."
|
@echo "Running gitea-vet..."
|
||||||
@GOOS= GOARCH= $(GO) build code.gitea.io/gitea-vet
|
@$(GO) vet -vettool="$(shell GOOS= GOARCH= go tool -n gitea-vet)" ./...
|
||||||
@$(GO) vet -vettool=gitea-vet ./...
|
|
||||||
|
|
||||||
.PHONY: lint-go-gopls
|
|
||||||
lint-go-gopls: ## lint go files with gopls
|
|
||||||
@echo "Running gopls check..."
|
|
||||||
@GO=$(GO) GOPLS_PACKAGE=$(GOPLS_PACKAGE) tools/lint-go-gopls.sh $(GO_SOURCES)
|
|
||||||
|
|
||||||
.PHONY: lint-editorconfig
|
.PHONY: lint-editorconfig
|
||||||
lint-editorconfig:
|
lint-editorconfig:
|
||||||
@@ -422,17 +359,24 @@ lint-templates: .venv node_modules ## lint template files
|
|||||||
lint-yaml: .venv ## lint yaml files
|
lint-yaml: .venv ## lint yaml files
|
||||||
@uv run --frozen yamllint -s .
|
@uv run --frozen yamllint -s .
|
||||||
|
|
||||||
|
.PHONY: lint-json
|
||||||
|
lint-json: node_modules ## lint json files
|
||||||
|
pnpm exec eslint -c eslint.json.config.ts --color --max-warnings=0 --concurrency $(ESLINT_CONCURRENCY)
|
||||||
|
|
||||||
|
.PHONY: lint-json-fix
|
||||||
|
lint-json-fix: node_modules ## lint and fix json files
|
||||||
|
pnpm exec eslint -c eslint.json.config.ts --color --max-warnings=0 --concurrency $(ESLINT_CONCURRENCY) --fix
|
||||||
|
|
||||||
.PHONY: watch
|
.PHONY: watch
|
||||||
watch: ## watch everything and continuously rebuild
|
watch: ## watch everything and continuously rebuild
|
||||||
@bash tools/watch.sh
|
@bash tools/watch.sh
|
||||||
|
|
||||||
.PHONY: watch-frontend
|
.PHONY: watch-frontend
|
||||||
watch-frontend: node-check node_modules ## watch frontend files and continuously rebuild
|
watch-frontend: node_modules ## start vite dev server for frontend
|
||||||
@rm -rf $(WEBPACK_DEST_ENTRIES)
|
NODE_ENV=development pnpm exec vite --logLevel $(FRONTEND_DEV_LOG_LEVEL)
|
||||||
NODE_ENV=development $(NODE_VARS) pnpm exec webpack --watch --progress --disable-interpret
|
|
||||||
|
|
||||||
.PHONY: watch-backend
|
.PHONY: watch-backend
|
||||||
watch-backend: go-check ## watch backend files and continuously rebuild
|
watch-backend: ## watch backend files and continuously rebuild
|
||||||
GITEA_RUN_MODE=dev $(GO) run $(AIR_PACKAGE) -c .air.toml
|
GITEA_RUN_MODE=dev $(GO) run $(AIR_PACKAGE) -c .air.toml
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
@@ -445,7 +389,7 @@ test-backend: ## test backend files
|
|||||||
|
|
||||||
.PHONY: test-frontend
|
.PHONY: test-frontend
|
||||||
test-frontend: node_modules ## test frontend files
|
test-frontend: node_modules ## test frontend files
|
||||||
$(NODE_VARS) pnpm exec vitest
|
pnpm exec vitest
|
||||||
|
|
||||||
.PHONY: test-check
|
.PHONY: test-check
|
||||||
test-check:
|
test-check:
|
||||||
@@ -468,7 +412,7 @@ test\#%:
|
|||||||
coverage:
|
coverage:
|
||||||
grep '^\(mode: .*\)\|\(.*:[0-9]\+\.[0-9]\+,[0-9]\+\.[0-9]\+ [0-9]\+ [0-9]\+\)$$' coverage.out > coverage-bodged.out
|
grep '^\(mode: .*\)\|\(.*:[0-9]\+\.[0-9]\+,[0-9]\+\.[0-9]\+ [0-9]\+ [0-9]\+\)$$' coverage.out > coverage-bodged.out
|
||||||
grep '^\(mode: .*\)\|\(.*:[0-9]\+\.[0-9]\+,[0-9]\+\.[0-9]\+ [0-9]\+ [0-9]\+\)$$' integration.coverage.out > integration.coverage-bodged.out
|
grep '^\(mode: .*\)\|\(.*:[0-9]\+\.[0-9]\+,[0-9]\+\.[0-9]\+ [0-9]\+ [0-9]\+\)$$' integration.coverage.out > integration.coverage-bodged.out
|
||||||
$(GO) run build/gocovmerge.go integration.coverage-bodged.out coverage-bodged.out > coverage.all
|
$(GO) run tools/gocovmerge.go integration.coverage-bodged.out coverage-bodged.out > coverage.all
|
||||||
|
|
||||||
.PHONY: unit-test-coverage
|
.PHONY: unit-test-coverage
|
||||||
unit-test-coverage:
|
unit-test-coverage:
|
||||||
@@ -498,25 +442,20 @@ tidy-check: tidy
|
|||||||
go-licenses: $(GO_LICENSE_FILE) ## regenerate go licenses
|
go-licenses: $(GO_LICENSE_FILE) ## regenerate go licenses
|
||||||
|
|
||||||
$(GO_LICENSE_FILE): go.mod go.sum
|
$(GO_LICENSE_FILE): go.mod go.sum
|
||||||
@rm -rf $(GO_LICENSE_FILE)
|
GO=$(GO) $(GO) run build/generate-go-licenses.go $(GO_LICENSE_FILE)
|
||||||
$(GO) install $(GO_LICENSES_PACKAGE)
|
|
||||||
-GOOS=linux CGO_ENABLED=1 go-licenses save . --force --save_path=$(GO_LICENSE_TMP_DIR) 2>/dev/null
|
|
||||||
$(GO) run build/generate-go-licenses.go $(GO_LICENSE_TMP_DIR) $(GO_LICENSE_FILE)
|
|
||||||
@rm -rf $(GO_LICENSE_TMP_DIR)
|
|
||||||
|
|
||||||
generate-ini-sqlite:
|
generate-ini-sqlite:
|
||||||
sed -e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
|
sed -e 's|{{WORK_PATH}}|$(CURDIR)/tests/$(or $(TEST_TYPE),integration)/gitea-$(or $(TEST_TYPE),integration)-sqlite|g' \
|
||||||
-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
|
-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
|
||||||
-e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \
|
|
||||||
tests/sqlite.ini.tmpl > tests/sqlite.ini
|
tests/sqlite.ini.tmpl > tests/sqlite.ini
|
||||||
|
|
||||||
.PHONY: test-sqlite
|
.PHONY: test-sqlite
|
||||||
test-sqlite: integrations.sqlite.test generate-ini-sqlite
|
test-sqlite: integrations.sqlite.test generate-ini-sqlite
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.sqlite.test
|
GITEA_TEST_CONF=tests/sqlite.ini ./integrations.sqlite.test
|
||||||
|
|
||||||
.PHONY: test-sqlite\#%
|
.PHONY: test-sqlite\#%
|
||||||
test-sqlite\#%: integrations.sqlite.test generate-ini-sqlite
|
test-sqlite\#%: integrations.sqlite.test generate-ini-sqlite
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.sqlite.test -test.run $(subst .,/,$*)
|
GITEA_TEST_CONF=tests/sqlite.ini ./integrations.sqlite.test -test.run $(subst .,/,$*)
|
||||||
|
|
||||||
.PHONY: test-sqlite-migration
|
.PHONY: test-sqlite-migration
|
||||||
test-sqlite-migration: migrations.sqlite.test migrations.individual.sqlite.test
|
test-sqlite-migration: migrations.sqlite.test migrations.individual.sqlite.test
|
||||||
@@ -526,18 +465,17 @@ generate-ini-mysql:
|
|||||||
-e 's|{{TEST_MYSQL_DBNAME}}|${TEST_MYSQL_DBNAME}|g' \
|
-e 's|{{TEST_MYSQL_DBNAME}}|${TEST_MYSQL_DBNAME}|g' \
|
||||||
-e 's|{{TEST_MYSQL_USERNAME}}|${TEST_MYSQL_USERNAME}|g' \
|
-e 's|{{TEST_MYSQL_USERNAME}}|${TEST_MYSQL_USERNAME}|g' \
|
||||||
-e 's|{{TEST_MYSQL_PASSWORD}}|${TEST_MYSQL_PASSWORD}|g' \
|
-e 's|{{TEST_MYSQL_PASSWORD}}|${TEST_MYSQL_PASSWORD}|g' \
|
||||||
-e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
|
-e 's|{{WORK_PATH}}|$(CURDIR)/tests/$(or $(TEST_TYPE),integration)/gitea-$(or $(TEST_TYPE),integration)-mysql|g' \
|
||||||
-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
|
-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
|
||||||
-e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \
|
|
||||||
tests/mysql.ini.tmpl > tests/mysql.ini
|
tests/mysql.ini.tmpl > tests/mysql.ini
|
||||||
|
|
||||||
.PHONY: test-mysql
|
.PHONY: test-mysql
|
||||||
test-mysql: integrations.mysql.test generate-ini-mysql
|
test-mysql: integrations.mysql.test generate-ini-mysql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./integrations.mysql.test
|
GITEA_TEST_CONF=tests/mysql.ini ./integrations.mysql.test
|
||||||
|
|
||||||
.PHONY: test-mysql\#%
|
.PHONY: test-mysql\#%
|
||||||
test-mysql\#%: integrations.mysql.test generate-ini-mysql
|
test-mysql\#%: integrations.mysql.test generate-ini-mysql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./integrations.mysql.test -test.run $(subst .,/,$*)
|
GITEA_TEST_CONF=tests/mysql.ini ./integrations.mysql.test -test.run $(subst .,/,$*)
|
||||||
|
|
||||||
.PHONY: test-mysql-migration
|
.PHONY: test-mysql-migration
|
||||||
test-mysql-migration: migrations.mysql.test migrations.individual.mysql.test
|
test-mysql-migration: migrations.mysql.test migrations.individual.mysql.test
|
||||||
@@ -549,18 +487,17 @@ generate-ini-pgsql:
|
|||||||
-e 's|{{TEST_PGSQL_PASSWORD}}|${TEST_PGSQL_PASSWORD}|g' \
|
-e 's|{{TEST_PGSQL_PASSWORD}}|${TEST_PGSQL_PASSWORD}|g' \
|
||||||
-e 's|{{TEST_PGSQL_SCHEMA}}|${TEST_PGSQL_SCHEMA}|g' \
|
-e 's|{{TEST_PGSQL_SCHEMA}}|${TEST_PGSQL_SCHEMA}|g' \
|
||||||
-e 's|{{TEST_MINIO_ENDPOINT}}|${TEST_MINIO_ENDPOINT}|g' \
|
-e 's|{{TEST_MINIO_ENDPOINT}}|${TEST_MINIO_ENDPOINT}|g' \
|
||||||
-e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
|
-e 's|{{WORK_PATH}}|$(CURDIR)/tests/$(or $(TEST_TYPE),integration)/gitea-$(or $(TEST_TYPE),integration)-pgsql|g' \
|
||||||
-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
|
-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
|
||||||
-e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \
|
|
||||||
tests/pgsql.ini.tmpl > tests/pgsql.ini
|
tests/pgsql.ini.tmpl > tests/pgsql.ini
|
||||||
|
|
||||||
.PHONY: test-pgsql
|
.PHONY: test-pgsql
|
||||||
test-pgsql: integrations.pgsql.test generate-ini-pgsql
|
test-pgsql: integrations.pgsql.test generate-ini-pgsql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./integrations.pgsql.test
|
GITEA_TEST_CONF=tests/pgsql.ini ./integrations.pgsql.test
|
||||||
|
|
||||||
.PHONY: test-pgsql\#%
|
.PHONY: test-pgsql\#%
|
||||||
test-pgsql\#%: integrations.pgsql.test generate-ini-pgsql
|
test-pgsql\#%: integrations.pgsql.test generate-ini-pgsql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./integrations.pgsql.test -test.run $(subst .,/,$*)
|
GITEA_TEST_CONF=tests/pgsql.ini ./integrations.pgsql.test -test.run $(subst .,/,$*)
|
||||||
|
|
||||||
.PHONY: test-pgsql-migration
|
.PHONY: test-pgsql-migration
|
||||||
test-pgsql-migration: migrations.pgsql.test migrations.individual.pgsql.test
|
test-pgsql-migration: migrations.pgsql.test migrations.individual.pgsql.test
|
||||||
@@ -570,89 +507,53 @@ generate-ini-mssql:
|
|||||||
-e 's|{{TEST_MSSQL_DBNAME}}|${TEST_MSSQL_DBNAME}|g' \
|
-e 's|{{TEST_MSSQL_DBNAME}}|${TEST_MSSQL_DBNAME}|g' \
|
||||||
-e 's|{{TEST_MSSQL_USERNAME}}|${TEST_MSSQL_USERNAME}|g' \
|
-e 's|{{TEST_MSSQL_USERNAME}}|${TEST_MSSQL_USERNAME}|g' \
|
||||||
-e 's|{{TEST_MSSQL_PASSWORD}}|${TEST_MSSQL_PASSWORD}|g' \
|
-e 's|{{TEST_MSSQL_PASSWORD}}|${TEST_MSSQL_PASSWORD}|g' \
|
||||||
-e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
|
-e 's|{{WORK_PATH}}|$(CURDIR)/tests/$(or $(TEST_TYPE),integration)/gitea-$(or $(TEST_TYPE),integration)-mssql|g' \
|
||||||
-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
|
-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
|
||||||
-e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \
|
|
||||||
tests/mssql.ini.tmpl > tests/mssql.ini
|
tests/mssql.ini.tmpl > tests/mssql.ini
|
||||||
|
|
||||||
.PHONY: test-mssql
|
.PHONY: test-mssql
|
||||||
test-mssql: integrations.mssql.test generate-ini-mssql
|
test-mssql: integrations.mssql.test generate-ini-mssql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./integrations.mssql.test
|
GITEA_TEST_CONF=tests/mssql.ini ./integrations.mssql.test
|
||||||
|
|
||||||
.PHONY: test-mssql\#%
|
.PHONY: test-mssql\#%
|
||||||
test-mssql\#%: integrations.mssql.test generate-ini-mssql
|
test-mssql\#%: integrations.mssql.test generate-ini-mssql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./integrations.mssql.test -test.run $(subst .,/,$*)
|
GITEA_TEST_CONF=tests/mssql.ini ./integrations.mssql.test -test.run $(subst .,/,$*)
|
||||||
|
|
||||||
.PHONY: test-mssql-migration
|
.PHONY: test-mssql-migration
|
||||||
test-mssql-migration: migrations.mssql.test migrations.individual.mssql.test
|
test-mssql-migration: migrations.mssql.test migrations.individual.mssql.test
|
||||||
|
|
||||||
.PHONY: playwright
|
.PHONY: playwright
|
||||||
playwright: deps-frontend
|
playwright: deps-frontend
|
||||||
$(NODE_VARS) pnpm exec playwright install $(PLAYWRIGHT_FLAGS)
|
@# on GitHub Actions VMs, playwright's system deps are pre-installed
|
||||||
|
@pnpm exec playwright install $(if $(GITHUB_ACTIONS),,--with-deps) chromium firefox $(PLAYWRIGHT_FLAGS)
|
||||||
.PHONY: test-e2e%
|
|
||||||
test-e2e%: TEST_TYPE ?= e2e
|
|
||||||
# Clear display env variable. Otherwise, chromium tests can fail.
|
|
||||||
DISPLAY=
|
|
||||||
|
|
||||||
.PHONY: test-e2e
|
.PHONY: test-e2e
|
||||||
test-e2e: test-e2e-sqlite
|
test-e2e: playwright $(EXECUTABLE_E2E)
|
||||||
|
@EXECUTABLE=$(EXECUTABLE_E2E) ./tools/test-e2e.sh $(GITEA_TEST_E2E_FLAGS)
|
||||||
.PHONY: test-e2e-sqlite
|
|
||||||
test-e2e-sqlite: playwright e2e.sqlite.test generate-ini-sqlite
|
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./e2e.sqlite.test
|
|
||||||
|
|
||||||
.PHONY: test-e2e-sqlite\#%
|
|
||||||
test-e2e-sqlite\#%: playwright e2e.sqlite.test generate-ini-sqlite
|
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./e2e.sqlite.test -test.run TestE2e/$*
|
|
||||||
|
|
||||||
.PHONY: test-e2e-mysql
|
|
||||||
test-e2e-mysql: playwright e2e.mysql.test generate-ini-mysql
|
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./e2e.mysql.test
|
|
||||||
|
|
||||||
.PHONY: test-e2e-mysql\#%
|
|
||||||
test-e2e-mysql\#%: playwright e2e.mysql.test generate-ini-mysql
|
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./e2e.mysql.test -test.run TestE2e/$*
|
|
||||||
|
|
||||||
.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
|
|
||||||
|
|
||||||
.PHONY: test-e2e-pgsql\#%
|
|
||||||
test-e2e-pgsql\#%: playwright e2e.pgsql.test generate-ini-pgsql
|
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./e2e.pgsql.test -test.run TestE2e/$*
|
|
||||||
|
|
||||||
.PHONY: test-e2e-mssql
|
|
||||||
test-e2e-mssql: playwright e2e.mssql.test generate-ini-mssql
|
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./e2e.mssql.test
|
|
||||||
|
|
||||||
.PHONY: test-e2e-mssql\#%
|
|
||||||
test-e2e-mssql\#%: playwright e2e.mssql.test generate-ini-mssql
|
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./e2e.mssql.test -test.run TestE2e/$*
|
|
||||||
|
|
||||||
.PHONY: bench-sqlite
|
.PHONY: bench-sqlite
|
||||||
bench-sqlite: integrations.sqlite.test generate-ini-sqlite
|
bench-sqlite: integrations.sqlite.test generate-ini-sqlite
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.sqlite.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
|
GITEA_TEST_CONF=tests/sqlite.ini ./integrations.sqlite.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
|
||||||
|
|
||||||
.PHONY: bench-mysql
|
.PHONY: bench-mysql
|
||||||
bench-mysql: integrations.mysql.test generate-ini-mysql
|
bench-mysql: integrations.mysql.test generate-ini-mysql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./integrations.mysql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
|
GITEA_TEST_CONF=tests/mysql.ini ./integrations.mysql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
|
||||||
|
|
||||||
.PHONY: bench-mssql
|
.PHONY: bench-mssql
|
||||||
bench-mssql: integrations.mssql.test generate-ini-mssql
|
bench-mssql: integrations.mssql.test generate-ini-mssql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./integrations.mssql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
|
GITEA_TEST_CONF=tests/mssql.ini ./integrations.mssql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
|
||||||
|
|
||||||
.PHONY: bench-pgsql
|
.PHONY: bench-pgsql
|
||||||
bench-pgsql: integrations.pgsql.test generate-ini-pgsql
|
bench-pgsql: integrations.pgsql.test generate-ini-pgsql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./integrations.pgsql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
|
GITEA_TEST_CONF=tests/pgsql.ini ./integrations.pgsql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
|
||||||
|
|
||||||
.PHONY: integration-test-coverage
|
.PHONY: integration-test-coverage
|
||||||
integration-test-coverage: integrations.cover.test generate-ini-mysql
|
integration-test-coverage: integrations.cover.test generate-ini-mysql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./integrations.cover.test -test.coverprofile=integration.coverage.out
|
GITEA_TEST_CONF=tests/mysql.ini ./integrations.cover.test -test.coverprofile=integration.coverage.out
|
||||||
|
|
||||||
.PHONY: integration-test-coverage-sqlite
|
.PHONY: integration-test-coverage-sqlite
|
||||||
integration-test-coverage-sqlite: integrations.cover.sqlite.test generate-ini-sqlite
|
integration-test-coverage-sqlite: integrations.cover.sqlite.test generate-ini-sqlite
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.cover.sqlite.test -test.coverprofile=integration.coverage.out
|
GITEA_TEST_CONF=tests/sqlite.ini ./integrations.cover.sqlite.test -test.coverprofile=integration.coverage.out
|
||||||
|
|
||||||
integrations.mysql.test: git-check $(GO_SOURCES)
|
integrations.mysql.test: git-check $(GO_SOURCES)
|
||||||
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.mysql.test
|
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.mysql.test
|
||||||
@@ -675,66 +576,54 @@ integrations.cover.sqlite.test: git-check $(GO_SOURCES)
|
|||||||
.PHONY: migrations.mysql.test
|
.PHONY: migrations.mysql.test
|
||||||
migrations.mysql.test: $(GO_SOURCES) generate-ini-mysql
|
migrations.mysql.test: $(GO_SOURCES) generate-ini-mysql
|
||||||
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mysql.test
|
$(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
|
GITEA_TEST_CONF=tests/mysql.ini ./migrations.mysql.test
|
||||||
|
|
||||||
.PHONY: migrations.pgsql.test
|
.PHONY: migrations.pgsql.test
|
||||||
migrations.pgsql.test: $(GO_SOURCES) generate-ini-pgsql
|
migrations.pgsql.test: $(GO_SOURCES) generate-ini-pgsql
|
||||||
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.pgsql.test
|
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.pgsql.test
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./migrations.pgsql.test
|
GITEA_TEST_CONF=tests/pgsql.ini ./migrations.pgsql.test
|
||||||
|
|
||||||
.PHONY: migrations.mssql.test
|
.PHONY: migrations.mssql.test
|
||||||
migrations.mssql.test: $(GO_SOURCES) generate-ini-mssql
|
migrations.mssql.test: $(GO_SOURCES) generate-ini-mssql
|
||||||
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mssql.test
|
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mssql.test
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./migrations.mssql.test
|
GITEA_TEST_CONF=tests/mssql.ini ./migrations.mssql.test
|
||||||
|
|
||||||
.PHONY: migrations.sqlite.test
|
.PHONY: migrations.sqlite.test
|
||||||
migrations.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
|
migrations.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
|
||||||
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.sqlite.test -tags '$(TEST_TAGS)'
|
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.sqlite.test -tags '$(TEST_TAGS)'
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./migrations.sqlite.test
|
GITEA_TEST_CONF=tests/sqlite.ini ./migrations.sqlite.test
|
||||||
|
|
||||||
.PHONY: migrations.individual.mysql.test
|
.PHONY: migrations.individual.mysql.test
|
||||||
migrations.individual.mysql.test: $(GO_SOURCES)
|
migrations.individual.mysql.test: $(GO_SOURCES) generate-ini-mysql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -p 1 $(MIGRATE_TEST_PACKAGES)
|
GITEA_TEST_CONF=tests/mysql.ini $(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -p 1 $(MIGRATE_TEST_PACKAGES)
|
||||||
|
|
||||||
.PHONY: migrations.individual.sqlite.test\#%
|
.PHONY: migrations.individual.sqlite.test\#%
|
||||||
migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite
|
migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
|
GITEA_TEST_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
|
||||||
|
|
||||||
.PHONY: migrations.individual.pgsql.test
|
.PHONY: migrations.individual.pgsql.test
|
||||||
migrations.individual.pgsql.test: $(GO_SOURCES)
|
migrations.individual.pgsql.test: $(GO_SOURCES) generate-ini-pgsql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -p 1 $(MIGRATE_TEST_PACKAGES)
|
GITEA_TEST_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -p 1 $(MIGRATE_TEST_PACKAGES)
|
||||||
|
|
||||||
.PHONY: migrations.individual.pgsql.test\#%
|
.PHONY: migrations.individual.pgsql.test\#%
|
||||||
migrations.individual.pgsql.test\#%: $(GO_SOURCES) generate-ini-pgsql
|
migrations.individual.pgsql.test\#%: $(GO_SOURCES) generate-ini-pgsql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
|
GITEA_TEST_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
|
||||||
|
|
||||||
.PHONY: migrations.individual.mssql.test
|
.PHONY: migrations.individual.mssql.test
|
||||||
migrations.individual.mssql.test: $(GO_SOURCES) generate-ini-mssql
|
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)
|
GITEA_TEST_CONF=tests/mssql.ini $(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -p 1 $(MIGRATE_TEST_PACKAGES)
|
||||||
|
|
||||||
.PHONY: migrations.individual.mssql.test\#%
|
.PHONY: migrations.individual.mssql.test\#%
|
||||||
migrations.individual.mssql.test\#%: $(GO_SOURCES) generate-ini-mssql
|
migrations.individual.mssql.test\#%: $(GO_SOURCES) generate-ini-mssql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
|
GITEA_TEST_CONF=tests/mssql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
|
||||||
|
|
||||||
.PHONY: migrations.individual.sqlite.test
|
.PHONY: migrations.individual.sqlite.test
|
||||||
migrations.individual.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
|
migrations.individual.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -p 1 $(MIGRATE_TEST_PACKAGES)
|
GITEA_TEST_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -p 1 $(MIGRATE_TEST_PACKAGES)
|
||||||
|
|
||||||
.PHONY: migrations.individual.sqlite.test\#%
|
.PHONY: migrations.individual.sqlite.test\#%
|
||||||
migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite
|
migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
|
GITEA_TEST_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
|
||||||
|
|
||||||
e2e.mysql.test: $(GO_SOURCES)
|
|
||||||
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.mysql.test
|
|
||||||
|
|
||||||
e2e.pgsql.test: $(GO_SOURCES)
|
|
||||||
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.pgsql.test
|
|
||||||
|
|
||||||
e2e.mssql.test: $(GO_SOURCES)
|
|
||||||
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.mssql.test
|
|
||||||
|
|
||||||
e2e.sqlite.test: $(GO_SOURCES)
|
|
||||||
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.sqlite.test -tags '$(TEST_TAGS)'
|
|
||||||
|
|
||||||
.PHONY: check
|
.PHONY: check
|
||||||
check: test
|
check: test
|
||||||
@@ -747,10 +636,10 @@ install: $(wildcard *.go)
|
|||||||
build: frontend backend ## build everything
|
build: frontend backend ## build everything
|
||||||
|
|
||||||
.PHONY: frontend
|
.PHONY: frontend
|
||||||
frontend: $(WEBPACK_DEST) ## build frontend files
|
frontend: $(FRONTEND_DEST) ## build frontend files
|
||||||
|
|
||||||
.PHONY: backend
|
.PHONY: backend
|
||||||
backend: go-check generate-backend $(EXECUTABLE) ## build backend files
|
backend: generate-backend $(EXECUTABLE) ## build backend files
|
||||||
|
|
||||||
# We generate the backend before the frontend in case we in future we want to generate things in the frontend from generated files in backend
|
# We generate the backend before the frontend in case we in future we want to generate things in the frontend from generated files in backend
|
||||||
.PHONY: generate
|
.PHONY: generate
|
||||||
@@ -766,14 +655,17 @@ generate-go: $(TAGS_PREREQ)
|
|||||||
|
|
||||||
.PHONY: security-check
|
.PHONY: security-check
|
||||||
security-check:
|
security-check:
|
||||||
go run $(GOVULNCHECK_PACKAGE) -show color ./...
|
GOEXPERIMENT= go run $(GOVULNCHECK_PACKAGE) -show color ./... || true
|
||||||
|
|
||||||
$(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ)
|
$(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ)
|
||||||
ifneq ($(and $(STATIC),$(findstring pam,$(TAGS))),)
|
ifneq ($(and $(STATIC),$(findstring pam,$(TAGS))),)
|
||||||
$(error pam support set via TAGS doesn't support static builds)
|
$(error pam support set via TAGS does not support static builds)
|
||||||
endif
|
endif
|
||||||
CGO_ENABLED="$(CGO_ENABLED)" CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(EXTLDFLAGS) $(LDFLAGS)' -o $@
|
CGO_ENABLED="$(CGO_ENABLED)" CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(EXTLDFLAGS) $(LDFLAGS)' -o $@
|
||||||
|
|
||||||
|
$(EXECUTABLE_E2E): $(GO_SOURCES) $(FRONTEND_DEST)
|
||||||
|
CGO_ENABLED=1 $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TEST_TAGS)' -ldflags '-s -w $(EXTLDFLAGS) $(LDFLAGS)' -o $@
|
||||||
|
|
||||||
.PHONY: release
|
.PHONY: release
|
||||||
release: frontend generate release-windows release-linux release-darwin release-freebsd release-copy release-compress vendor release-sources release-check
|
release: frontend generate release-windows release-linux release-darwin release-freebsd release-copy release-compress vendor release-sources release-check
|
||||||
|
|
||||||
@@ -844,15 +736,12 @@ deps-tools: ## install tool dependencies
|
|||||||
$(GO) install $(MISSPELL_PACKAGE) & \
|
$(GO) install $(MISSPELL_PACKAGE) & \
|
||||||
$(GO) install $(SWAGGER_PACKAGE) & \
|
$(GO) install $(SWAGGER_PACKAGE) & \
|
||||||
$(GO) install $(XGO_PACKAGE) & \
|
$(GO) install $(XGO_PACKAGE) & \
|
||||||
$(GO) install $(GO_LICENSES_PACKAGE) & \
|
|
||||||
$(GO) install $(GOVULNCHECK_PACKAGE) & \
|
$(GO) install $(GOVULNCHECK_PACKAGE) & \
|
||||||
$(GO) install $(ACTIONLINT_PACKAGE) & \
|
$(GO) install $(ACTIONLINT_PACKAGE) & \
|
||||||
$(GO) install $(GOPLS_PACKAGE) & \
|
|
||||||
$(GO) install $(GOPLS_MODERNIZE_PACKAGE) & \
|
|
||||||
wait
|
wait
|
||||||
|
|
||||||
node_modules: pnpm-lock.yaml
|
node_modules: pnpm-lock.yaml
|
||||||
$(NODE_VARS) pnpm install --frozen-lockfile
|
pnpm install --frozen-lockfile
|
||||||
@touch node_modules
|
@touch node_modules
|
||||||
|
|
||||||
.venv: uv.lock
|
.venv: uv.lock
|
||||||
@@ -860,36 +749,41 @@ node_modules: pnpm-lock.yaml
|
|||||||
@touch .venv
|
@touch .venv
|
||||||
|
|
||||||
.PHONY: update
|
.PHONY: update
|
||||||
update: update-js update-py ## update js and py dependencies
|
update: update-go update-js update-py ## update dependencies
|
||||||
|
|
||||||
|
.PHONY: update-go
|
||||||
|
update-go: ## update go dependencies
|
||||||
|
$(GO) get -u ./...
|
||||||
|
$(MAKE) tidy
|
||||||
|
|
||||||
.PHONY: update-js
|
.PHONY: update-js
|
||||||
update-js: node-check | node_modules ## update js dependencies
|
update-js: node_modules ## update js dependencies
|
||||||
$(NODE_VARS) pnpm exec updates -u -f package.json
|
pnpm exec updates -u -f package.json
|
||||||
rm -rf node_modules pnpm-lock.yaml
|
rm -rf node_modules pnpm-lock.yaml
|
||||||
$(NODE_VARS) pnpm install
|
pnpm install
|
||||||
$(NODE_VARS) pnpm exec nolyfill install
|
pnpm exec nolyfill install
|
||||||
$(NODE_VARS) pnpm install
|
pnpm install
|
||||||
@touch node_modules
|
@touch node_modules
|
||||||
|
|
||||||
.PHONY: update-py
|
.PHONY: update-py
|
||||||
update-py: node-check | node_modules ## update py dependencies
|
update-py: node_modules ## update py dependencies
|
||||||
$(NODE_VARS) pnpm exec updates -u -f pyproject.toml
|
pnpm exec updates -u -f pyproject.toml
|
||||||
rm -rf .venv uv.lock
|
rm -rf .venv uv.lock
|
||||||
uv sync
|
uv sync
|
||||||
@touch .venv
|
@touch .venv
|
||||||
|
|
||||||
.PHONY: webpack
|
.PHONY: vite
|
||||||
webpack: $(WEBPACK_DEST) ## build webpack files
|
vite: $(FRONTEND_DEST) ## build vite files
|
||||||
|
|
||||||
$(WEBPACK_DEST): $(WEBPACK_SOURCES) $(WEBPACK_CONFIGS) pnpm-lock.yaml
|
$(FRONTEND_DEST): $(FRONTEND_SOURCES) $(FRONTEND_CONFIGS) pnpm-lock.yaml
|
||||||
@$(MAKE) -s node-check node_modules
|
@$(MAKE) -s node_modules
|
||||||
@rm -rf $(WEBPACK_DEST_ENTRIES)
|
@rm -rf $(FRONTEND_DEST_ENTRIES)
|
||||||
@echo "Running webpack..."
|
@echo "Running vite build..."
|
||||||
@BROWSERSLIST_IGNORE_OLD_DATA=true $(NODE_VARS) pnpm exec webpack --disable-interpret
|
@pnpm exec vite build
|
||||||
@touch $(WEBPACK_DEST)
|
@touch $(FRONTEND_DEST)
|
||||||
|
|
||||||
.PHONY: svg
|
.PHONY: svg
|
||||||
svg: node-check | node_modules ## build svg files
|
svg: node_modules ## build svg files
|
||||||
rm -rf $(SVG_DEST_DIR)
|
rm -rf $(SVG_DEST_DIR)
|
||||||
node tools/generate-svg.ts
|
node tools/generate-svg.ts
|
||||||
|
|
||||||
@@ -905,7 +799,7 @@ svg-check: svg
|
|||||||
|
|
||||||
.PHONY: lockfile-check
|
.PHONY: lockfile-check
|
||||||
lockfile-check:
|
lockfile-check:
|
||||||
$(NODE_VARS) pnpm install --frozen-lockfile
|
pnpm install --frozen-lockfile
|
||||||
@diff=$$(git diff --color=always pnpm-lock.yaml); \
|
@diff=$$(git diff --color=always pnpm-lock.yaml); \
|
||||||
if [ -n "$$diff" ]; then \
|
if [ -n "$$diff" ]; then \
|
||||||
echo "pnpm-lock.yaml is inconsistent with package.json"; \
|
echo "pnpm-lock.yaml is inconsistent with package.json"; \
|
||||||
@@ -914,16 +808,6 @@ lockfile-check:
|
|||||||
exit 1; \
|
exit 1; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
.PHONY: update-translations
|
|
||||||
update-translations:
|
|
||||||
mkdir -p ./translations
|
|
||||||
cd ./translations && curl -L https://crowdin.com/download/project/gitea.zip > gitea.zip && unzip gitea.zip
|
|
||||||
rm ./translations/gitea.zip
|
|
||||||
$(SED_INPLACE) -e 's/="/=/g' -e 's/"$$//g' ./translations/*.ini
|
|
||||||
$(SED_INPLACE) -e 's/\\"/"/g' ./translations/*.ini
|
|
||||||
mv ./translations/*.ini ./options/locale/
|
|
||||||
rmdir ./translations
|
|
||||||
|
|
||||||
.PHONY: generate-gitignore
|
.PHONY: generate-gitignore
|
||||||
generate-gitignore: ## update gitignore files
|
generate-gitignore: ## update gitignore files
|
||||||
$(GO) run build/generate-gitignores.go
|
$(GO) run build/generate-gitignores.go
|
||||||
@@ -945,9 +829,6 @@ docker:
|
|||||||
docker build --disable-content-trust=false -t $(DOCKER_REF) .
|
docker build --disable-content-trust=false -t $(DOCKER_REF) .
|
||||||
# support also build args docker build --build-arg GITEA_VERSION=v1.2.3 --build-arg TAGS="bindata sqlite sqlite_unlock_notify" .
|
# support also build args docker build --build-arg GITEA_VERSION=v1.2.3 --build-arg TAGS="bindata sqlite sqlite_unlock_notify" .
|
||||||
|
|
||||||
# This endif closes the if at the top of the file
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Disable parallel execution because it would break some targets that don't
|
# Disable parallel execution because it would break some targets that don't
|
||||||
# specify exact dependencies like 'backend' which does currently not depend
|
# specify exact dependencies like 'backend' which does currently not depend
|
||||||
# on 'frontend' to enable Node.js-less builds from source tarballs.
|
# on 'frontend' to enable Node.js-less builds from source tarballs.
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
[](https://www.codetriage.com/go-gitea/gitea "Help Contribute to Open Source")
|
[](https://www.codetriage.com/go-gitea/gitea "Help Contribute to Open Source")
|
||||||
[](https://opencollective.com/gitea "Become a backer/sponsor of gitea")
|
[](https://opencollective.com/gitea "Become a backer/sponsor of gitea")
|
||||||
[](https://opensource.org/licenses/MIT "License: MIT")
|
[](https://opensource.org/licenses/MIT "License: MIT")
|
||||||
[](https://gitpod.io/#https://github.com/go-gitea/gitea)
|
|
||||||
[](https://translate.gitea.com "Crowdin")
|
[](https://translate.gitea.com "Crowdin")
|
||||||
|
|
||||||
[繁體中文](./README.zh-tw.md) | [简体中文](./README.zh-cn.md)
|
[繁體中文](./README.zh-tw.md) | [简体中文](./README.zh-cn.md)
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
[](https://www.codetriage.com/go-gitea/gitea "Help Contribute to Open Source")
|
[](https://www.codetriage.com/go-gitea/gitea "Help Contribute to Open Source")
|
||||||
[](https://opencollective.com/gitea "Become a backer/sponsor of gitea")
|
[](https://opencollective.com/gitea "Become a backer/sponsor of gitea")
|
||||||
[](https://opensource.org/licenses/MIT "License: MIT")
|
[](https://opensource.org/licenses/MIT "License: MIT")
|
||||||
[](https://gitpod.io/#https://github.com/go-gitea/gitea)
|
|
||||||
[](https://translate.gitea.com "Crowdin")
|
[](https://translate.gitea.com "Crowdin")
|
||||||
|
|
||||||
[English](./README.md) | [繁體中文](./README.zh-tw.md)
|
[English](./README.md) | [繁體中文](./README.zh-tw.md)
|
||||||
@@ -46,7 +45,7 @@
|
|||||||
`build` 目标分为两个子目标:
|
`build` 目标分为两个子目标:
|
||||||
|
|
||||||
- `make backend` 需要 [Go Stable](https://go.dev/dl/),所需版本在 [go.mod](/go.mod) 中定义。
|
- `make backend` 需要 [Go Stable](https://go.dev/dl/),所需版本在 [go.mod](/go.mod) 中定义。
|
||||||
- `make frontend` 需要 [Node.js LTS](https://nodejs.org/en/download/) 或更高版本。
|
- `make frontend` 需要 [Node.js LTS](https://nodejs.org/en/download/) 或更高版本以及 [pnpm](https://pnpm.io/installation)。
|
||||||
|
|
||||||
需要互联网连接来下载 go 和 npm 模块。从包含预构建前端文件的官方源代码压缩包构建时,不会触发 `frontend` 目标,因此可以在没有 Node.js 的情况下构建。
|
需要互联网连接来下载 go 和 npm 模块。从包含预构建前端文件的官方源代码压缩包构建时,不会触发 `frontend` 目标,因此可以在没有 Node.js 的情况下构建。
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
[](https://www.codetriage.com/go-gitea/gitea "Help Contribute to Open Source")
|
[](https://www.codetriage.com/go-gitea/gitea "Help Contribute to Open Source")
|
||||||
[](https://opencollective.com/gitea "Become a backer/sponsor of gitea")
|
[](https://opencollective.com/gitea "Become a backer/sponsor of gitea")
|
||||||
[](https://opensource.org/licenses/MIT "License: MIT")
|
[](https://opensource.org/licenses/MIT "License: MIT")
|
||||||
[](https://gitpod.io/#https://github.com/go-gitea/gitea)
|
|
||||||
[](https://translate.gitea.com "Crowdin")
|
[](https://translate.gitea.com "Crowdin")
|
||||||
|
|
||||||
[English](./README.md) | [简体中文](./README.zh-cn.md)
|
[English](./README.md) | [简体中文](./README.zh-cn.md)
|
||||||
@@ -46,7 +45,7 @@
|
|||||||
`build` 目標分為兩個子目標:
|
`build` 目標分為兩個子目標:
|
||||||
|
|
||||||
- `make backend` 需要 [Go Stable](https://go.dev/dl/),所需版本在 [go.mod](/go.mod) 中定義。
|
- `make backend` 需要 [Go Stable](https://go.dev/dl/),所需版本在 [go.mod](/go.mod) 中定義。
|
||||||
- `make frontend` 需要 [Node.js LTS](https://nodejs.org/en/download/) 或更高版本。
|
- `make frontend` 需要 [Node.js LTS](https://nodejs.org/en/download/) 或更高版本以及 [pnpm](https://pnpm.io/installation)。
|
||||||
|
|
||||||
需要互聯網連接來下載 go 和 npm 模塊。從包含預構建前端文件的官方源代碼壓縮包構建時,不會觸發 `frontend` 目標,因此可以在沒有 Node.js 的情況下構建。
|
需要互聯網連接來下載 go 和 npm 模塊。從包含預構建前端文件的官方源代碼壓縮包構建時,不會觸發 `frontend` 目標,因此可以在沒有 Node.js 的情況下構建。
|
||||||
|
|
||||||
|
|||||||
Generated
+11483
-1
File diff suppressed because one or more lines are too long
+159
-144
File diff suppressed because one or more lines are too long
@@ -1,14 +0,0 @@
|
|||||||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
//go:build vendor
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
// Libraries that are included to vendor utilities used during Makefile build.
|
|
||||||
// These libraries will not be included in a normal compilation.
|
|
||||||
|
|
||||||
import (
|
|
||||||
// for vet
|
|
||||||
_ "code.gitea.io/gitea-vet"
|
|
||||||
)
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
//go:build ignore
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/container"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if len(os.Args) != 2 {
|
|
||||||
println("usage: backport-locales <to-ref>")
|
|
||||||
println("eg: backport-locales release/v1.19")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
mustNoErr := func(err error) {
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
collectInis := func(ref string) map[string]setting.ConfigProvider {
|
|
||||||
inis := map[string]setting.ConfigProvider{}
|
|
||||||
err := filepath.WalkDir("options/locale", func(path string, d os.DirEntry, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if d.IsDir() || !strings.HasSuffix(d.Name(), ".ini") {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
cfg, err := setting.NewConfigProviderForLocale(path)
|
|
||||||
mustNoErr(err)
|
|
||||||
inis[path] = cfg
|
|
||||||
fmt.Printf("collecting: %s @ %s\n", path, ref)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
mustNoErr(err)
|
|
||||||
return inis
|
|
||||||
}
|
|
||||||
|
|
||||||
// collect new locales from current working directory
|
|
||||||
inisNew := collectInis("HEAD")
|
|
||||||
|
|
||||||
// switch to the target ref, and collect the old locales
|
|
||||||
cmd := exec.Command("git", "checkout", os.Args[1])
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
mustNoErr(cmd.Run())
|
|
||||||
inisOld := collectInis(os.Args[1])
|
|
||||||
|
|
||||||
// use old en-US as the base, and copy the new translations to the old locales
|
|
||||||
enUsOld := inisOld["options/locale/locale_en-US.ini"]
|
|
||||||
brokenWarned := make(container.Set[string])
|
|
||||||
for path, iniOld := range inisOld {
|
|
||||||
if iniOld == enUsOld {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
iniNew := inisNew[path]
|
|
||||||
if iniNew == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, secEnUS := range enUsOld.Sections() {
|
|
||||||
secOld := iniOld.Section(secEnUS.Name())
|
|
||||||
secNew := iniNew.Section(secEnUS.Name())
|
|
||||||
for _, keyEnUs := range secEnUS.Keys() {
|
|
||||||
if secNew.HasKey(keyEnUs.Name()) {
|
|
||||||
oldStr := secOld.Key(keyEnUs.Name()).String()
|
|
||||||
newStr := secNew.Key(keyEnUs.Name()).String()
|
|
||||||
broken := oldStr != "" && strings.Count(oldStr, "%") != strings.Count(newStr, "%")
|
|
||||||
broken = broken || strings.Contains(oldStr, "\n") || strings.Contains(oldStr, "\n")
|
|
||||||
if broken {
|
|
||||||
brokenWarned.Add(secOld.Name() + "." + keyEnUs.Name())
|
|
||||||
fmt.Println("----")
|
|
||||||
fmt.Printf("WARNING: skip broken locale: %s , [%s] %s\n", path, secEnUS.Name(), keyEnUs.Name())
|
|
||||||
fmt.Printf("\told: %s\n", strings.ReplaceAll(oldStr, "\n", "\\n"))
|
|
||||||
fmt.Printf("\tnew: %s\n", strings.ReplaceAll(newStr, "\n", "\\n"))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
secOld.Key(keyEnUs.Name()).SetValue(newStr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mustNoErr(iniOld.SaveTo(path))
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("========")
|
|
||||||
|
|
||||||
for path, iniNew := range inisNew {
|
|
||||||
for _, sec := range iniNew.Sections() {
|
|
||||||
for _, key := range sec.Keys() {
|
|
||||||
str := sec.Key(key.Name()).String()
|
|
||||||
broken := strings.Contains(str, "\n")
|
|
||||||
broken = broken || strings.HasPrefix(str, "`") != strings.HasSuffix(str, "`")
|
|
||||||
broken = broken || strings.HasPrefix(str, "\"`")
|
|
||||||
broken = broken || strings.HasPrefix(str, "`\"")
|
|
||||||
broken = broken || strings.Count(str, `"`)%2 == 1
|
|
||||||
broken = broken || strings.Count(str, "`")%2 == 1
|
|
||||||
if broken && !brokenWarned.Contains(sec.Name()+"."+key.Name()) {
|
|
||||||
fmt.Printf("WARNING: found broken locale: %s , [%s] %s\n", path, sec.Name(), key.Name())
|
|
||||||
fmt.Printf("\tstr: %s\n", strings.ReplaceAll(str, "\n", "\\n"))
|
|
||||||
fmt.Println("----")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -24,8 +24,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
gemojiURL = "https://raw.githubusercontent.com/github/gemoji/master/db/emoji.json"
|
gemojiURL = "https://raw.githubusercontent.com/rhysd/gemoji/537ff2d7e0496e9964824f7f73ec7ece88c9765a/db/emoji.json"
|
||||||
maxUnicodeVersion = 15
|
maxUnicodeVersion = 16
|
||||||
)
|
)
|
||||||
|
|
||||||
var flagOut = flag.String("o", "modules/emoji/emoji_data.go", "out")
|
var flagOut = flag.String("o", "modules/emoji/emoji_data.go", "out")
|
||||||
@@ -149,8 +149,8 @@ func generate() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// write a JSON file to use with tribute (write before adding skin tones since we can't support them there yet)
|
// write a JSON file to use with tribute (write before adding skin tones since we can't support them there yet)
|
||||||
file, _ := json.Marshal(data)
|
file, _ := json.MarshalIndent(data, "", " ")
|
||||||
_ = os.WriteFile("assets/emoji.json", file, 0o644)
|
_ = os.WriteFile("assets/emoji.json", append(file, '\n'), 0o644)
|
||||||
|
|
||||||
// Add skin tones to emoji that support it
|
// Add skin tones to emoji that support it
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -8,99 +8,220 @@ package main
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/container"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// regexp is based on go-license, excluding README and NOTICE
|
// regexp is based on go-license, excluding README and NOTICE
|
||||||
// https://github.com/google/go-licenses/blob/master/licenses/find.go
|
// https://github.com/google/go-licenses/blob/master/licenses/find.go
|
||||||
|
// also defined in vite.config.ts
|
||||||
var licenseRe = regexp.MustCompile(`^(?i)((UN)?LICEN(S|C)E|COPYING).*$`)
|
var licenseRe = regexp.MustCompile(`^(?i)((UN)?LICEN(S|C)E|COPYING).*$`)
|
||||||
|
|
||||||
|
// primaryLicenseRe matches exact primary license filenames without suffixes.
|
||||||
|
// When a directory has both primary and variant files (e.g. LICENSE and
|
||||||
|
// LICENSE.docs), only the primary files are kept.
|
||||||
|
var primaryLicenseRe = regexp.MustCompile(`^(?i)(LICEN[SC]E|COPYING)$`)
|
||||||
|
|
||||||
|
// ignoredNames are LicenseEntry.Name values to exclude from the output.
|
||||||
|
var ignoredNames = map[string]bool{
|
||||||
|
"code.gitea.io/gitea": true,
|
||||||
|
"code.gitea.io/gitea/options/license": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
var excludedExt = map[string]bool{
|
||||||
|
".gitignore": true,
|
||||||
|
".go": true,
|
||||||
|
".mod": true,
|
||||||
|
".sum": true,
|
||||||
|
".toml": true,
|
||||||
|
".yaml": true,
|
||||||
|
".yml": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
type ModuleInfo struct {
|
||||||
|
Path string
|
||||||
|
Dir string
|
||||||
|
PkgDirs []string // directories of packages imported from this module
|
||||||
|
}
|
||||||
|
|
||||||
type LicenseEntry struct {
|
type LicenseEntry struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
LicenseText string `json:"licenseText"`
|
LicenseText string `json:"licenseText"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
// getModules returns all dependency modules with their local directory paths
|
||||||
if len(os.Args) != 3 {
|
// and the package directories used from each module.
|
||||||
fmt.Println("usage: go run generate-go-licenses.go <base-dir> <out-json-file>")
|
func getModules(goCmd string) []ModuleInfo {
|
||||||
|
cmd := exec.Command(goCmd, "list", "-deps", "-f",
|
||||||
|
"{{if .Module}}{{.Module.Path}}\t{{.Module.Dir}}\t{{.Dir}}{{end}}", "./...")
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
// Use GOOS=linux with CGO to ensure we capture all platform-specific
|
||||||
|
// dependencies, matching the CI environment.
|
||||||
|
cmd.Env = append(os.Environ(), "GOOS=linux", "GOARCH=amd64", "CGO_ENABLED=1")
|
||||||
|
output, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "failed to run 'go list -deps': %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
base, out := os.Args[1], os.Args[2]
|
var modules []ModuleInfo
|
||||||
|
seen := make(map[string]int) // module path -> index in modules
|
||||||
// Add ext for excluded files because license_test.go will be included for some reason.
|
for _, line := range strings.Split(string(output), "\n") {
|
||||||
// And there are more files that should be excluded, check with:
|
line = strings.TrimSpace(line)
|
||||||
//
|
if line == "" {
|
||||||
// go run github.com/google/go-licenses@v1.6.0 save . --force --save_path=.go-licenses 2>/dev/null
|
continue
|
||||||
// find .go-licenses -type f | while read FILE; do echo "${$(basename $FILE)##*.}"; done | sort -u
|
|
||||||
// AUTHORS
|
|
||||||
// COPYING
|
|
||||||
// LICENSE
|
|
||||||
// Makefile
|
|
||||||
// NOTICE
|
|
||||||
// gitignore
|
|
||||||
// go
|
|
||||||
// md
|
|
||||||
// mod
|
|
||||||
// sum
|
|
||||||
// toml
|
|
||||||
// txt
|
|
||||||
// yml
|
|
||||||
//
|
|
||||||
// It could be removed once we have a better regex.
|
|
||||||
excludedExt := container.SetOf(".gitignore", ".go", ".mod", ".sum", ".toml", ".yml")
|
|
||||||
|
|
||||||
var paths []string
|
|
||||||
err := filepath.WalkDir(base, func(path string, entry fs.DirEntry, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
if entry.IsDir() || !licenseRe.MatchString(entry.Name()) || excludedExt.Contains(filepath.Ext(entry.Name())) {
|
parts := strings.Split(line, "\t")
|
||||||
return nil
|
if len(parts) != 3 {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
paths = append(paths, path)
|
modPath, modDir, pkgDir := parts[0], parts[1], parts[2]
|
||||||
return nil
|
if idx, ok := seen[modPath]; ok {
|
||||||
})
|
modules[idx].PkgDirs = append(modules[idx].PkgDirs, pkgDir)
|
||||||
if err != nil {
|
} else {
|
||||||
panic(err)
|
seen[modPath] = len(modules)
|
||||||
|
modules = append(modules, ModuleInfo{
|
||||||
|
Path: modPath,
|
||||||
|
Dir: modDir,
|
||||||
|
PkgDirs: []string{pkgDir},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return modules
|
||||||
|
}
|
||||||
|
|
||||||
|
// findLicenseFiles scans a module's root directory and its used package
|
||||||
|
// directories for license files. It also walks up from each package directory
|
||||||
|
// to the module root, scanning intermediate directories. Subdirectory licenses
|
||||||
|
// are only included if their text differs from the root license(s).
|
||||||
|
func findLicenseFiles(mod ModuleInfo) []LicenseEntry {
|
||||||
|
var entries []LicenseEntry
|
||||||
|
seenTexts := make(map[string]bool)
|
||||||
|
|
||||||
|
// First, collect root-level license files.
|
||||||
|
entries = append(entries, scanDirForLicenses(mod.Dir, mod.Path, "")...)
|
||||||
|
for _, e := range entries {
|
||||||
|
seenTexts[e.LicenseText] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Strings(paths)
|
// Then check each package directory and all intermediate parent directories
|
||||||
|
// up to the module root for license files with unique text.
|
||||||
|
seenDirs := map[string]bool{mod.Dir: true}
|
||||||
|
for _, pkgDir := range mod.PkgDirs {
|
||||||
|
for dir := pkgDir; dir != mod.Dir && strings.HasPrefix(dir, mod.Dir); dir = filepath.Dir(dir) {
|
||||||
|
if seenDirs[dir] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
seenDirs[dir] = true
|
||||||
|
for _, e := range scanDirForLicenses(dir, mod.Path, mod.Dir) {
|
||||||
|
if !seenTexts[e.LicenseText] {
|
||||||
|
seenTexts[e.LicenseText] = true
|
||||||
|
entries = append(entries, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entries
|
||||||
|
}
|
||||||
|
|
||||||
|
// scanDirForLicenses reads a single directory for license files and returns entries.
|
||||||
|
// If moduleRoot is non-empty, paths are made relative to it.
|
||||||
|
func scanDirForLicenses(dir, modulePath, moduleRoot string) []LicenseEntry {
|
||||||
|
dirEntries, err := os.ReadDir(dir)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
var entries []LicenseEntry
|
var entries []LicenseEntry
|
||||||
for _, filePath := range paths {
|
for _, entry := range dirEntries {
|
||||||
licenseText, err := os.ReadFile(filePath)
|
if entry.IsDir() {
|
||||||
if err != nil {
|
continue
|
||||||
panic(err)
|
|
||||||
}
|
}
|
||||||
|
name := entry.Name()
|
||||||
pkgPath := filepath.ToSlash(filePath)
|
if !licenseRe.MatchString(name) {
|
||||||
pkgPath = strings.TrimPrefix(pkgPath, base+"/")
|
continue
|
||||||
pkgName := path.Dir(pkgPath)
|
}
|
||||||
|
if excludedExt[strings.ToLower(filepath.Ext(name))] {
|
||||||
// There might be a bug somewhere in go-licenses that sometimes interprets the
|
|
||||||
// root package as "." and sometimes as "code.gitea.io/gitea". Workaround by
|
|
||||||
// removing both of them for the sake of stable output.
|
|
||||||
if pkgName == "." || pkgName == "code.gitea.io/gitea" {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
content, err := os.ReadFile(filepath.Join(dir, name))
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
entryName := modulePath
|
||||||
|
entryPath := modulePath + "/" + name
|
||||||
|
if moduleRoot != "" {
|
||||||
|
rel, _ := filepath.Rel(moduleRoot, dir)
|
||||||
|
if rel != "." {
|
||||||
|
relSlash := filepath.ToSlash(rel)
|
||||||
|
entryName = modulePath + "/" + relSlash
|
||||||
|
entryPath = modulePath + "/" + relSlash + "/" + name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
entries = append(entries, LicenseEntry{
|
entries = append(entries, LicenseEntry{
|
||||||
Name: pkgName,
|
Name: entryName,
|
||||||
Path: pkgPath,
|
Path: entryPath,
|
||||||
LicenseText: string(licenseText),
|
LicenseText: string(content),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When multiple license files exist, prefer primary files (e.g. LICENSE)
|
||||||
|
// over variants with suffixes (e.g. LICENSE.docs, LICENSE-2.0.txt).
|
||||||
|
// If no primary file exists, keep only the first variant.
|
||||||
|
if len(entries) > 1 {
|
||||||
|
var primary []LicenseEntry
|
||||||
|
for _, e := range entries {
|
||||||
|
fileName := e.Path[strings.LastIndex(e.Path, "/")+1:]
|
||||||
|
if primaryLicenseRe.MatchString(fileName) {
|
||||||
|
primary = append(primary, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(primary) > 0 {
|
||||||
|
return primary
|
||||||
|
}
|
||||||
|
return entries[:1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if len(os.Args) != 2 {
|
||||||
|
fmt.Println("usage: go run generate-go-licenses.go <out-json-file>")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
out := os.Args[1]
|
||||||
|
|
||||||
|
goCmd := "go"
|
||||||
|
if env := os.Getenv("GO"); env != "" {
|
||||||
|
goCmd = env
|
||||||
|
}
|
||||||
|
|
||||||
|
modules := getModules(goCmd)
|
||||||
|
|
||||||
|
var entries []LicenseEntry
|
||||||
|
for _, mod := range modules {
|
||||||
|
entries = append(entries, findLicenseFiles(mod)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
entries = slices.DeleteFunc(entries, func(e LicenseEntry) bool {
|
||||||
|
return ignoredNames[e.Name]
|
||||||
|
})
|
||||||
|
|
||||||
|
sort.Slice(entries, func(i, j int) bool {
|
||||||
|
return entries[i].Path < entries[j].Path
|
||||||
|
})
|
||||||
|
|
||||||
jsonBytes, err := json.MarshalIndent(entries, "", " ")
|
jsonBytes, err := json.MarshalIndent(entries, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|||||||
@@ -1,52 +1,22 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# this script runs in alpine image which only has `sh` shell
|
# this script runs in alpine image which only has `sh` shell
|
||||||
|
if [ ! -f ./options/locale/locale_en-US.json ]; then
|
||||||
set +e
|
|
||||||
if sed --version 2>/dev/null | grep -q GNU; then
|
|
||||||
SED_INPLACE="sed -i"
|
|
||||||
else
|
|
||||||
SED_INPLACE="sed -i ''"
|
|
||||||
fi
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if [ ! -f ./options/locale/locale_en-US.ini ]; then
|
|
||||||
echo "please run this script in the root directory of the project"
|
echo "please run this script in the root directory of the project"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mv ./options/locale/locale_en-US.ini ./options/
|
mv ./options/locale/locale_en-US.json ./options/
|
||||||
|
|
||||||
# the "ini" library for locale has many quirks, its behavior is different from Crowdin.
|
|
||||||
# see i18n_test.go for more details
|
|
||||||
|
|
||||||
# this script helps to unquote the Crowdin outputs for the quirky ini library
|
|
||||||
# * find all `key="...\"..."` lines
|
|
||||||
# * remove the leading quote
|
|
||||||
# * remove the trailing quote
|
|
||||||
# * unescape the quotes
|
|
||||||
# * eg: key="...\"..." => key=..."...
|
|
||||||
$SED_INPLACE -r -e '/^[-.A-Za-z0-9_]+[ ]*=[ ]*".*"$/ {
|
|
||||||
s/^([-.A-Za-z0-9_]+)[ ]*=[ ]*"/\1=/
|
|
||||||
s/"$//
|
|
||||||
s/\\"/"/g
|
|
||||||
}' ./options/locale/*.ini
|
|
||||||
|
|
||||||
# * if the escaped line is incomplete like `key="...` or `key=..."`, quote it with backticks
|
|
||||||
# * eg: key="... => key=`"...`
|
|
||||||
# * eg: key=..." => key=`..."`
|
|
||||||
$SED_INPLACE -r -e 's/^([-.A-Za-z0-9_]+)[ ]*=[ ]*(".*[^"])$/\1=`\2`/' ./options/locale/*.ini
|
|
||||||
$SED_INPLACE -r -e 's/^([-.A-Za-z0-9_]+)[ ]*=[ ]*([^"].*")$/\1=`\2`/' ./options/locale/*.ini
|
|
||||||
|
|
||||||
# Remove translation under 25% of en_us
|
# Remove translation under 25% of en_us
|
||||||
baselines=$(wc -l "./options/locale_en-US.ini" | cut -d" " -f1)
|
baselines=$(cat "./options/locale_en-US.json" | wc -l)
|
||||||
baselines=$((baselines / 4))
|
baselines=$((baselines / 4))
|
||||||
for filename in ./options/locale/*.ini; do
|
for filename in ./options/locale/*.json; do
|
||||||
lines=$(wc -l "$filename" | cut -d" " -f1)
|
lines=$(cat "$filename" | wc -l)
|
||||||
if [ $lines -lt $baselines ]; then
|
if [ "$lines" -lt "$baselines" ]; then
|
||||||
echo "Removing $filename: $lines/$baselines"
|
echo "Removing $filename: $lines/$baselines"
|
||||||
rm "$filename"
|
rm "$filename"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
mv ./options/locale_en-US.ini ./options/locale/
|
mv ./options/locale_en-US.json ./options/locale/
|
||||||
|
|||||||
@@ -13,17 +13,18 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
func newActionsCommand() *cli.Command {
|
||||||
// CmdActions represents the available actions sub-commands.
|
return &cli.Command{
|
||||||
CmdActions = &cli.Command{
|
|
||||||
Name: "actions",
|
Name: "actions",
|
||||||
Usage: "Manage Gitea Actions",
|
Usage: "Manage Gitea Actions",
|
||||||
Commands: []*cli.Command{
|
Commands: []*cli.Command{
|
||||||
subcmdActionsGenRunnerToken,
|
newActionsGenerateRunnerTokenCommand(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
subcmdActionsGenRunnerToken = &cli.Command{
|
func newActionsGenerateRunnerTokenCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "generate-runner-token",
|
Name: "generate-runner-token",
|
||||||
Usage: "Generate a new token for a runner to use to register with the server",
|
Usage: "Generate a new token for a runner to use to register with the server",
|
||||||
Action: runGenerateActionsRunnerToken,
|
Action: runGenerateActionsRunnerToken,
|
||||||
@@ -37,7 +38,7 @@ var (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
func runGenerateActionsRunnerToken(ctx context.Context, c *cli.Command) error {
|
func runGenerateActionsRunnerToken(ctx context.Context, c *cli.Command) error {
|
||||||
setting.MustInstalled()
|
setting.MustInstalled()
|
||||||
|
|||||||
@@ -18,36 +18,41 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
func newAdminCommand() *cli.Command {
|
||||||
// CmdAdmin represents the available admin sub-command.
|
return &cli.Command{
|
||||||
CmdAdmin = &cli.Command{
|
|
||||||
Name: "admin",
|
Name: "admin",
|
||||||
Usage: "Perform common administrative operations",
|
Usage: "Perform common administrative operations",
|
||||||
Commands: []*cli.Command{
|
Commands: []*cli.Command{
|
||||||
subcmdUser,
|
newUserCommand(),
|
||||||
subcmdRepoSyncReleases,
|
newRepoSyncReleasesCommand(),
|
||||||
subcmdRegenerate,
|
newRegenerateCommand(),
|
||||||
subcmdAuth,
|
newAuthCommand(),
|
||||||
subcmdSendMail,
|
newSendMailCommand(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
subcmdRepoSyncReleases = &cli.Command{
|
func newRepoSyncReleasesCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "repo-sync-releases",
|
Name: "repo-sync-releases",
|
||||||
Usage: "Synchronize repository releases with tags",
|
Usage: "Synchronize repository releases with tags",
|
||||||
Action: runRepoSyncReleases,
|
Action: runRepoSyncReleases,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
subcmdRegenerate = &cli.Command{
|
func newRegenerateCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "regenerate",
|
Name: "regenerate",
|
||||||
Usage: "Regenerate specific files",
|
Usage: "Regenerate specific files",
|
||||||
Commands: []*cli.Command{
|
Commands: []*cli.Command{
|
||||||
microcmdRegenHooks,
|
newRegenerateHooksCommand(),
|
||||||
microcmdRegenKeys,
|
newRegenerateKeysCommand(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
subcmdAuth = &cli.Command{
|
func newAuthCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "auth",
|
Name: "auth",
|
||||||
Usage: "Modify external auth providers",
|
Usage: "Modify external auth providers",
|
||||||
Commands: []*cli.Command{
|
Commands: []*cli.Command{
|
||||||
@@ -59,12 +64,14 @@ var (
|
|||||||
microcmdAuthUpdateLdapSimpleAuth(),
|
microcmdAuthUpdateLdapSimpleAuth(),
|
||||||
microcmdAuthAddSMTP(),
|
microcmdAuthAddSMTP(),
|
||||||
microcmdAuthUpdateSMTP(),
|
microcmdAuthUpdateSMTP(),
|
||||||
microcmdAuthList,
|
newAuthListCommand(),
|
||||||
microcmdAuthDelete,
|
newAuthDeleteCommand(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
subcmdSendMail = &cli.Command{
|
func newSendMailCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "sendmail",
|
Name: "sendmail",
|
||||||
Usage: "Send a message to all users",
|
Usage: "Send a message to all users",
|
||||||
Action: runSendMail,
|
Action: runSendMail,
|
||||||
@@ -86,7 +93,7 @@ var (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
func idFlag() *cli.Int64Flag {
|
func idFlag() *cli.Int64Flag {
|
||||||
return &cli.Int64Flag{
|
return &cli.Int64Flag{
|
||||||
@@ -121,7 +128,7 @@ func runRepoSyncReleases(ctx context.Context, _ *cli.Command) error {
|
|||||||
}
|
}
|
||||||
log.Trace("Processing next %d repos of %d", len(repos), count)
|
log.Trace("Processing next %d repos of %d", len(repos), count)
|
||||||
for _, repo := range repos {
|
for _, repo := range repos {
|
||||||
log.Trace("Synchronizing repo %s with path %s", repo.FullName(), repo.RepoPath())
|
log.Trace("Synchronizing repo %s with path %s", repo.FullName(), repo.RelativePath())
|
||||||
gitRepo, err := gitrepo.OpenRepository(ctx, repo)
|
gitRepo, err := gitrepo.OpenRepository(ctx, repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("OpenRepository: %v", err)
|
log.Warn("OpenRepository: %v", err)
|
||||||
@@ -134,7 +141,7 @@ func runRepoSyncReleases(ctx context.Context, _ *cli.Command) error {
|
|||||||
}
|
}
|
||||||
log.Trace(" currentNumReleases is %d, running SyncReleasesWithTags", oldnum)
|
log.Trace(" currentNumReleases is %d, running SyncReleasesWithTags", oldnum)
|
||||||
|
|
||||||
if err = repo_module.SyncReleasesWithTags(ctx, repo, gitRepo); err != nil {
|
if _, err = repo_module.SyncReleasesWithTags(ctx, repo, gitRepo); err != nil {
|
||||||
log.Warn(" SyncReleasesWithTags: %v", err)
|
log.Warn(" SyncReleasesWithTags: %v", err)
|
||||||
gitRepo.Close()
|
gitRepo.Close()
|
||||||
continue
|
continue
|
||||||
@@ -147,7 +154,7 @@ func runRepoSyncReleases(ctx context.Context, _ *cli.Command) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Trace(" repo %s releases synchronized to tags: from %d to %d",
|
log.Trace("repo %s releases synchronized to tags: from %d to %d",
|
||||||
repo.FullName(), oldnum, count)
|
repo.FullName(), oldnum, count)
|
||||||
gitRepo.Close()
|
gitRepo.Close()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,14 +17,17 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
func newAuthDeleteCommand() *cli.Command {
|
||||||
microcmdAuthDelete = &cli.Command{
|
return &cli.Command{
|
||||||
Name: "delete",
|
Name: "delete",
|
||||||
Usage: "Delete specific auth source",
|
Usage: "Delete specific auth source",
|
||||||
Flags: []cli.Flag{idFlag()},
|
Flags: []cli.Flag{idFlag()},
|
||||||
Action: runDeleteAuth,
|
Action: runDeleteAuth,
|
||||||
}
|
}
|
||||||
microcmdAuthList = &cli.Command{
|
}
|
||||||
|
|
||||||
|
func newAuthListCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Usage: "List auth sources",
|
Usage: "List auth sources",
|
||||||
Action: runListAuth,
|
Action: runListAuth,
|
||||||
@@ -55,7 +58,7 @@ var (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
func runListAuth(ctx context.Context, c *cli.Command) error {
|
func runListAuth(ctx context.Context, c *cli.Command) error {
|
||||||
if err := initDB(ctx); err != nil {
|
if err := initDB(ctx); err != nil {
|
||||||
|
|||||||
@@ -94,6 +94,10 @@ func commonLdapCLIFlags() []cli.Flag {
|
|||||||
Name: "public-ssh-key-attribute",
|
Name: "public-ssh-key-attribute",
|
||||||
Usage: "The attribute of the user’s LDAP record containing the user’s public ssh key.",
|
Usage: "The attribute of the user’s LDAP record containing the user’s public ssh key.",
|
||||||
},
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "ssh-keys-are-verified",
|
||||||
|
Usage: "Set to true to automatically flag SSH keys in LDAP as verified.",
|
||||||
|
},
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "skip-local-2fa",
|
Name: "skip-local-2fa",
|
||||||
Usage: "Set to true to skip local 2fa for users authenticated by this source",
|
Usage: "Set to true to skip local 2fa for users authenticated by this source",
|
||||||
@@ -294,6 +298,9 @@ func parseLdapConfig(c *cli.Command, config *ldap.Source) error {
|
|||||||
if c.IsSet("public-ssh-key-attribute") {
|
if c.IsSet("public-ssh-key-attribute") {
|
||||||
config.AttributeSSHPublicKey = c.String("public-ssh-key-attribute")
|
config.AttributeSSHPublicKey = c.String("public-ssh-key-attribute")
|
||||||
}
|
}
|
||||||
|
if c.IsSet("ssh-keys-are-verified") {
|
||||||
|
config.SSHKeysAreVerified = c.Bool("ssh-keys-are-verified")
|
||||||
|
}
|
||||||
if c.IsSet("avatar-attribute") {
|
if c.IsSet("avatar-attribute") {
|
||||||
config.AttributeAvatar = c.String("avatar-attribute")
|
config.AttributeAvatar = c.String("avatar-attribute")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ func TestAddLdapBindDn(t *testing.T) {
|
|||||||
},
|
},
|
||||||
getAuthSourceByID: func(ctx context.Context, id int64) (*auth.Source, error) {
|
getAuthSourceByID: func(ctx context.Context, id int64) (*auth.Source, error) {
|
||||||
assert.FailNow(t, "getAuthSourceByID called", "case %d: should not call getAuthSourceByID", n)
|
assert.FailNow(t, "getAuthSourceByID called", "case %d: should not call getAuthSourceByID", n)
|
||||||
return nil, nil
|
return nil, nil //nolint:nilnil // mock function covering improper behavior
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -463,7 +463,7 @@ func TestAddLdapSimpleAuth(t *testing.T) {
|
|||||||
},
|
},
|
||||||
getAuthSourceByID: func(ctx context.Context, id int64) (*auth.Source, error) {
|
getAuthSourceByID: func(ctx context.Context, id int64) (*auth.Source, error) {
|
||||||
assert.FailNow(t, "getAuthSourceById called", "case %d: should not call getAuthSourceByID", n)
|
assert.FailNow(t, "getAuthSourceById called", "case %d: should not call getAuthSourceByID", n)
|
||||||
return nil, nil
|
return nil, nil //nolint:nilnil // mock function covering improper behavior
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,19 +13,21 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
func newRegenerateHooksCommand() *cli.Command {
|
||||||
microcmdRegenHooks = &cli.Command{
|
return &cli.Command{
|
||||||
Name: "hooks",
|
Name: "hooks",
|
||||||
Usage: "Regenerate git-hooks",
|
Usage: "Regenerate git-hooks",
|
||||||
Action: runRegenerateHooks,
|
Action: runRegenerateHooks,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
microcmdRegenKeys = &cli.Command{
|
func newRegenerateKeysCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "keys",
|
Name: "keys",
|
||||||
Usage: "Regenerate authorized_keys file",
|
Usage: "Regenerate authorized_keys file",
|
||||||
Action: runRegenerateKeys,
|
Action: runRegenerateKeys,
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
func runRegenerateHooks(ctx context.Context, _ *cli.Command) error {
|
func runRegenerateHooks(ctx context.Context, _ *cli.Command) error {
|
||||||
if err := initDB(ctx); err != nil {
|
if err := initDB(ctx); err != nil {
|
||||||
|
|||||||
@@ -7,15 +7,17 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var subcmdUser = &cli.Command{
|
func newUserCommand() *cli.Command {
|
||||||
Name: "user",
|
return &cli.Command{
|
||||||
Usage: "Modify users",
|
Name: "user",
|
||||||
Commands: []*cli.Command{
|
Usage: "Modify users",
|
||||||
microcmdUserCreate(),
|
Commands: []*cli.Command{
|
||||||
microcmdUserList,
|
microcmdUserCreate(),
|
||||||
microcmdUserChangePassword(),
|
newUserListCommand(),
|
||||||
microcmdUserDelete(),
|
microcmdUserChangePassword(),
|
||||||
microcmdUserGenerateAccessToken,
|
microcmdUserDelete(),
|
||||||
microcmdUserMustChangePassword(),
|
newUserGenerateAccessTokenCommand(),
|
||||||
},
|
microcmdUserMustChangePassword(),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,6 +151,7 @@ func runCreateUser(ctx context.Context, c *cli.Command) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// codeql[disable-next-line=go/clear-text-logging]
|
||||||
fmt.Printf("generated random password is '%s'\n", password)
|
fmt.Printf("generated random password is '%s'\n", password)
|
||||||
} else if userType == user_model.UserTypeIndividual {
|
} else if userType == user_model.UserTypeIndividual {
|
||||||
return errors.New("must set either password or random-password flag")
|
return errors.New("must set either password or random-password flag")
|
||||||
|
|||||||
@@ -14,32 +14,34 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var microcmdUserGenerateAccessToken = &cli.Command{
|
func newUserGenerateAccessTokenCommand() *cli.Command {
|
||||||
Name: "generate-access-token",
|
return &cli.Command{
|
||||||
Usage: "Generate an access token for a specific user",
|
Name: "generate-access-token",
|
||||||
Flags: []cli.Flag{
|
Usage: "Generate an access token for a specific user",
|
||||||
&cli.StringFlag{
|
Flags: []cli.Flag{
|
||||||
Name: "username",
|
&cli.StringFlag{
|
||||||
Aliases: []string{"u"},
|
Name: "username",
|
||||||
Usage: "Username",
|
Aliases: []string{"u"},
|
||||||
|
Usage: "Username",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "token-name",
|
||||||
|
Aliases: []string{"t"},
|
||||||
|
Usage: "Token name",
|
||||||
|
Value: "gitea-admin",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "raw",
|
||||||
|
Usage: "Display only the token value",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "scopes",
|
||||||
|
Value: "all",
|
||||||
|
Usage: `Comma separated list of scopes to apply to access token, examples: "all", "public-only,read:issue", "write:repository,write:user"`,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
Action: runGenerateAccessToken,
|
||||||
Name: "token-name",
|
}
|
||||||
Aliases: []string{"t"},
|
|
||||||
Usage: "Token name",
|
|
||||||
Value: "gitea-admin",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "raw",
|
|
||||||
Usage: "Display only the token value",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "scopes",
|
|
||||||
Value: "all",
|
|
||||||
Usage: `Comma separated list of scopes to apply to access token, examples: "all", "public-only,read:issue", "write:repository,write:user"`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: runGenerateAccessToken,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func runGenerateAccessToken(ctx context.Context, c *cli.Command) error {
|
func runGenerateAccessToken(ctx context.Context, c *cli.Command) error {
|
||||||
|
|||||||
@@ -14,16 +14,18 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var microcmdUserList = &cli.Command{
|
func newUserListCommand() *cli.Command {
|
||||||
Name: "list",
|
return &cli.Command{
|
||||||
Usage: "List users",
|
Name: "list",
|
||||||
Action: runListUsers,
|
Usage: "List users",
|
||||||
Flags: []cli.Flag{
|
Action: runListUsers,
|
||||||
&cli.BoolFlag{
|
Flags: []cli.Flag{
|
||||||
Name: "admin",
|
&cli.BoolFlag{
|
||||||
Usage: "List only admin users",
|
Name: "admin",
|
||||||
|
Usage: "List only admin users",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func runListUsers(ctx context.Context, c *cli.Command) error {
|
func runListUsers(ctx context.Context, c *cli.Command) error {
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ func runMustChangePassword(ctx context.Context, c *cli.Command) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// codeql[disable-next-line=go/clear-text-logging]
|
||||||
fmt.Printf("Updated %d users setting MustChangePassword to %t\n", n, mustChangePassword)
|
fmt.Printf("Updated %d users setting MustChangePassword to %t\n", n, mustChangePassword)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,156 @@
|
|||||||
|
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
|
"github.com/urfave/cli/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func cmdConfig() *cli.Command {
|
||||||
|
subcmdConfigEditIni := &cli.Command{
|
||||||
|
Name: "edit-ini",
|
||||||
|
Usage: "Load an existing INI file, apply environment variables, keep specified keys, and output to a new INI file.",
|
||||||
|
Description: `
|
||||||
|
Help users to edit the Gitea configuration INI file.
|
||||||
|
|
||||||
|
# Keep Specified Keys
|
||||||
|
|
||||||
|
If you need to re-create the configuration file with only a subset of keys,
|
||||||
|
you can provide an INI template file for the kept keys and use the "--config-keep-keys" flag.
|
||||||
|
For example, if a helm chart needs to reset the settings and only keep SECRET_KEY,
|
||||||
|
it can use a template file (only keys take effect, values are ignored):
|
||||||
|
|
||||||
|
[security]
|
||||||
|
SECRET_KEY=
|
||||||
|
|
||||||
|
$ ./gitea config edit-ini --config app-old.ini --config-keep-keys app-keys.ini --out app-new.ini
|
||||||
|
|
||||||
|
# Map Environment Variables to INI Configuration
|
||||||
|
|
||||||
|
Environment variables of the form "GITEA__section_name__KEY_NAME"
|
||||||
|
will be mapped to the ini section "[section_name]" and the key
|
||||||
|
"KEY_NAME" with the value as provided.
|
||||||
|
|
||||||
|
Environment variables of the form "GITEA__section_name__KEY_NAME__FILE"
|
||||||
|
will be mapped to the ini section "[section_name]" and the key
|
||||||
|
"KEY_NAME" with the value loaded from the specified file.
|
||||||
|
|
||||||
|
Environment variable keys can only contain characters "0-9A-Z_",
|
||||||
|
if a section or key name contains dot ".", it needs to be escaped as _0x2E_.
|
||||||
|
For example, to apply this config:
|
||||||
|
|
||||||
|
[git.config]
|
||||||
|
foo.bar=val
|
||||||
|
|
||||||
|
$ export GITEA__git_0x2E_config__foo_0x2E_bar=val
|
||||||
|
|
||||||
|
# Put All Together
|
||||||
|
|
||||||
|
$ ./gitea config edit-ini --config app.ini --config-keep-keys app-keys.ini --apply-env {--in-place|--out app-new.ini}
|
||||||
|
`,
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
// "--config" flag is provided by global flags, and this flag is also used by "environment-to-ini" script wrapper
|
||||||
|
// "--in-place" is also used by "environment-to-ini" script wrapper for its old behavior: always overwrite the existing config file
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "in-place",
|
||||||
|
Usage: "Output to the same config file as input. This flag will be ignored if --out is set.",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "config-keep-keys",
|
||||||
|
Usage: "An INI template file containing keys for keeping. Only the keys defined in the INI template will be kept from old config. If not set, all keys will be kept.",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "apply-env",
|
||||||
|
Usage: "Apply all GITEA__* variables from the environment to the config.",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "out",
|
||||||
|
Usage: "Destination config file to write to.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: runConfigEditIni,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &cli.Command{
|
||||||
|
Name: "config",
|
||||||
|
Usage: "Manage Gitea configuration",
|
||||||
|
Commands: []*cli.Command{
|
||||||
|
subcmdConfigEditIni,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runConfigEditIni(_ context.Context, c *cli.Command) error {
|
||||||
|
// the config system may change the environment variables, so get a copy first, to be used later
|
||||||
|
env := append([]string{}, os.Environ()...)
|
||||||
|
|
||||||
|
// don't use the guessed setting.CustomConf, instead, require the user to provide --config explicitly
|
||||||
|
if !c.IsSet("config") {
|
||||||
|
return errors.New("flag is required but not set: --config")
|
||||||
|
}
|
||||||
|
configFileIn := c.String("config")
|
||||||
|
|
||||||
|
cfgIn, err := setting.NewConfigProviderFromFile(configFileIn)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to load config file %q: %v", configFileIn, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine output config file: use "--out" flag or use "--in-place" flag to overwrite input file
|
||||||
|
inPlace := c.Bool("in-place")
|
||||||
|
configFileOut := c.String("out")
|
||||||
|
if configFileOut == "" {
|
||||||
|
if !inPlace {
|
||||||
|
return errors.New("either --in-place or --out must be specified")
|
||||||
|
}
|
||||||
|
configFileOut = configFileIn // in-place edit
|
||||||
|
}
|
||||||
|
|
||||||
|
needWriteOut := configFileOut != configFileIn
|
||||||
|
|
||||||
|
cfgOut := cfgIn
|
||||||
|
configKeepKeys := c.String("config-keep-keys")
|
||||||
|
if configKeepKeys != "" {
|
||||||
|
needWriteOut = true
|
||||||
|
cfgOut, err = setting.NewConfigProviderFromFile(configKeepKeys)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to load config-keep-keys template file %q: %v", configKeepKeys, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, secOut := range cfgOut.Sections() {
|
||||||
|
for _, keyOut := range secOut.Keys() {
|
||||||
|
secIn := cfgIn.Section(secOut.Name())
|
||||||
|
keyIn := setting.ConfigSectionKey(secIn, keyOut.Name())
|
||||||
|
if keyIn != nil {
|
||||||
|
keyOut.SetValue(keyIn.String())
|
||||||
|
} else {
|
||||||
|
secOut.DeleteKey(keyOut.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(secOut.Keys()) == 0 {
|
||||||
|
cfgOut.DeleteSection(secOut.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Bool("apply-env") {
|
||||||
|
if setting.EnvironmentToConfig(cfgOut, env) {
|
||||||
|
needWriteOut = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if needWriteOut {
|
||||||
|
err = cfgOut.SaveTo(configFileOut)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConfigEdit(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
configOld := tmpDir + "/app-old.ini"
|
||||||
|
configTemplate := tmpDir + "/app-template.ini"
|
||||||
|
_ = os.WriteFile(configOld, []byte(`
|
||||||
|
[sec]
|
||||||
|
k1=v1
|
||||||
|
k2=v2
|
||||||
|
`), os.ModePerm)
|
||||||
|
|
||||||
|
_ = os.WriteFile(configTemplate, []byte(`
|
||||||
|
[sec]
|
||||||
|
k1=in-template
|
||||||
|
|
||||||
|
[sec2]
|
||||||
|
k3=v3
|
||||||
|
`), os.ModePerm)
|
||||||
|
|
||||||
|
t.Setenv("GITEA__EnV__KeY", "val")
|
||||||
|
|
||||||
|
t.Run("OutputToNewWithEnv", func(t *testing.T) {
|
||||||
|
configNew := tmpDir + "/app-new.ini"
|
||||||
|
err := NewMainApp(AppVersion{}).Run(t.Context(), []string{
|
||||||
|
"./gitea", "--config", configOld,
|
||||||
|
"config", "edit-ini",
|
||||||
|
"--apply-env",
|
||||||
|
"--config-keep-keys", configTemplate,
|
||||||
|
"--out", configNew,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// "k1" old value is kept because its key is in the template
|
||||||
|
// "k2" is removed because it isn't in the template
|
||||||
|
// "k3" isn't in new config because it isn't in the old config
|
||||||
|
// [env] is applied from environment variable
|
||||||
|
data, _ := os.ReadFile(configNew)
|
||||||
|
require.Equal(t, `[sec]
|
||||||
|
k1 = v1
|
||||||
|
|
||||||
|
[env]
|
||||||
|
KeY = val
|
||||||
|
`, string(data))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("OutputToExisting(environment-to-ini)", func(t *testing.T) {
|
||||||
|
// the legacy "environment-to-ini" (now a wrapper script) behavior:
|
||||||
|
// if no "--out", then "--in-place" must be used to overwrite the existing "--config" file
|
||||||
|
err := NewMainApp(AppVersion{}).Run(t.Context(), []string{
|
||||||
|
"./gitea", "config", "edit-ini",
|
||||||
|
"--apply-env",
|
||||||
|
"--config", configOld,
|
||||||
|
})
|
||||||
|
require.ErrorContains(t, err, "either --in-place or --out must be specified")
|
||||||
|
|
||||||
|
// simulate the "environment-to-ini" behavior with "--in-place"
|
||||||
|
err = NewMainApp(AppVersion{}).Run(t.Context(), []string{
|
||||||
|
"./gitea", "config", "edit-ini",
|
||||||
|
"--in-place",
|
||||||
|
"--apply-env",
|
||||||
|
"--config", configOld,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
data, _ := os.ReadFile(configOld)
|
||||||
|
require.Equal(t, `[sec]
|
||||||
|
k1 = v1
|
||||||
|
k2 = v2
|
||||||
|
|
||||||
|
[env]
|
||||||
|
KeY = val
|
||||||
|
`, string(data))
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -13,23 +13,24 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdDocs represents the available docs sub-command.
|
func newDocsCommand() *cli.Command {
|
||||||
var CmdDocs = &cli.Command{
|
return &cli.Command{
|
||||||
Name: "docs",
|
Name: "docs",
|
||||||
Usage: "Output CLI documentation",
|
Usage: "Output CLI documentation",
|
||||||
Description: "A command to output Gitea's CLI documentation, optionally to a file.",
|
Description: "A command to output Gitea's CLI documentation, optionally to a file.",
|
||||||
Action: runDocs,
|
Action: runDocs,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "man",
|
Name: "man",
|
||||||
Usage: "Output man pages instead",
|
Usage: "Output man pages instead",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "output",
|
||||||
|
Aliases: []string{"o"},
|
||||||
|
Usage: "Path to output to instead of stdout (will overwrite if exists)",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
}
|
||||||
Name: "output",
|
|
||||||
Aliases: []string{"o"},
|
|
||||||
Usage: "Path to output to instead of stdout (will overwrite if exists)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func runDocs(_ context.Context, cmd *cli.Command) error {
|
func runDocs(_ context.Context, cmd *cli.Command) error {
|
||||||
|
|||||||
@@ -24,73 +24,77 @@ import (
|
|||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdDoctor represents the available doctor sub-command.
|
func newDoctorCommand() *cli.Command {
|
||||||
var CmdDoctor = &cli.Command{
|
return &cli.Command{
|
||||||
Name: "doctor",
|
Name: "doctor",
|
||||||
Usage: "Diagnose and optionally fix problems, convert or re-create database tables",
|
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.",
|
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.",
|
||||||
|
Commands: []*cli.Command{
|
||||||
Commands: []*cli.Command{
|
newDoctorCheckCommand(),
|
||||||
cmdDoctorCheck,
|
newRecreateTableCommand(),
|
||||||
cmdRecreateTable,
|
newDoctorConvertCommand(),
|
||||||
cmdDoctorConvert,
|
},
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmdDoctorCheck = &cli.Command{
|
func newDoctorCheckCommand() *cli.Command {
|
||||||
Name: "check",
|
return &cli.Command{
|
||||||
Usage: "Diagnose and optionally fix problems",
|
Name: "check",
|
||||||
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.",
|
Usage: "Diagnose and optionally fix problems",
|
||||||
Action: runDoctorCheck,
|
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.",
|
||||||
Flags: []cli.Flag{
|
Action: runDoctorCheck,
|
||||||
&cli.BoolFlag{
|
Flags: []cli.Flag{
|
||||||
Name: "list",
|
&cli.BoolFlag{
|
||||||
Usage: "List the available checks",
|
Name: "list",
|
||||||
|
Usage: "List the available checks",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "default",
|
||||||
|
Usage: "Run the default checks (if neither --run or --all is set, this is the default behaviour)",
|
||||||
|
},
|
||||||
|
&cli.StringSliceFlag{
|
||||||
|
Name: "run",
|
||||||
|
Usage: "Run the provided checks - (if --default is set, the default checks will also run)",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "all",
|
||||||
|
Usage: "Run all the available checks",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "fix",
|
||||||
|
Usage: "Automatically fix what we can",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "log-file",
|
||||||
|
Usage: `Name of the log file (no verbose log output by default). Set to "-" to output to stdout`,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "color",
|
||||||
|
Aliases: []string{"H"},
|
||||||
|
Usage: "Use color for outputted information",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
&cli.BoolFlag{
|
}
|
||||||
Name: "default",
|
|
||||||
Usage: "Run the default checks (if neither --run or --all is set, this is the default behaviour)",
|
|
||||||
},
|
|
||||||
&cli.StringSliceFlag{
|
|
||||||
Name: "run",
|
|
||||||
Usage: "Run the provided checks - (if --default is set, the default checks will also run)",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "all",
|
|
||||||
Usage: "Run all the available checks",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "fix",
|
|
||||||
Usage: "Automatically fix what we can",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "log-file",
|
|
||||||
Usage: `Name of the log file (no verbose log output by default). Set to "-" to output to stdout`,
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "color",
|
|
||||||
Aliases: []string{"H"},
|
|
||||||
Usage: "Use color for outputted information",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmdRecreateTable = &cli.Command{
|
func newRecreateTableCommand() *cli.Command {
|
||||||
Name: "recreate-table",
|
return &cli.Command{
|
||||||
Usage: "Recreate tables from XORM definitions and copy the data.",
|
Name: "recreate-table",
|
||||||
ArgsUsage: "[TABLE]... : (TABLEs to recreate - leave blank for all)",
|
Usage: "Recreate tables from XORM definitions and copy the data.",
|
||||||
Flags: []cli.Flag{
|
ArgsUsage: "[TABLE]... : (TABLEs to recreate - leave blank for all)",
|
||||||
&cli.BoolFlag{
|
Flags: []cli.Flag{
|
||||||
Name: "debug",
|
&cli.BoolFlag{
|
||||||
Usage: "Print SQL commands sent",
|
Name: "debug",
|
||||||
|
Usage: "Print SQL commands sent",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
Description: `The database definitions Gitea uses change across versions, sometimes changing default values and leaving old unused columns.
|
||||||
Description: `The database definitions Gitea uses change across versions, sometimes changing default values and leaving old unused columns.
|
|
||||||
|
|
||||||
This command will cause Xorm to recreate tables, copying over the data and deleting the old table.
|
This command will cause Xorm to recreate tables, copying over the data and deleting the old table.
|
||||||
|
|
||||||
You should back-up your database before doing this and ensure that your database is up-to-date first.`,
|
You should back-up your database before doing this and ensure that your database is up-to-date first.`,
|
||||||
Action: runRecreateTable,
|
Action: runRecreateTable,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func runRecreateTable(ctx context.Context, cmd *cli.Command) error {
|
func runRecreateTable(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
|||||||
@@ -14,12 +14,13 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// cmdDoctorConvert represents the available convert sub-command.
|
func newDoctorConvertCommand() *cli.Command {
|
||||||
var cmdDoctorConvert = &cli.Command{
|
return &cli.Command{
|
||||||
Name: "convert",
|
Name: "convert",
|
||||||
Usage: "Convert the database",
|
Usage: "Convert the database",
|
||||||
Description: "A command to convert an existing MySQL database from utf8 to utf8mb4 or MSSQL database from varchar to nvarchar",
|
Description: "A command to convert an existing MySQL database from utf8 to utf8mb4 or MSSQL database from varchar to nvarchar",
|
||||||
Action: runDoctorConvert,
|
Action: runDoctorConvert,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func runDoctorConvert(ctx context.Context, cmd *cli.Command) error {
|
func runDoctorConvert(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ func TestDoctorRun(t *testing.T) {
|
|||||||
SkipDatabaseInitialization: true,
|
SkipDatabaseInitialization: true,
|
||||||
})
|
})
|
||||||
app := &cli.Command{
|
app := &cli.Command{
|
||||||
Commands: []*cli.Command{cmdDoctorCheck},
|
Commands: []*cli.Command{newDoctorCheckCommand()},
|
||||||
}
|
}
|
||||||
err := app.Run(t.Context(), []string{"./gitea", "check", "--run", "test-check"})
|
err := app.Run(t.Context(), []string{"./gitea", "check", "--run", "test-check"})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|||||||
@@ -23,78 +23,79 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdDump represents the available dump sub-command.
|
func newDumpCommand() *cli.Command {
|
||||||
var CmdDump = &cli.Command{
|
return &cli.Command{
|
||||||
Name: "dump",
|
Name: "dump",
|
||||||
Usage: "Dump Gitea files and database",
|
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`,
|
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,
|
Action: runDump,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "file",
|
Name: "file",
|
||||||
Aliases: []string{"f"},
|
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.`,
|
Usage: `Name of the dump file which will be created, default to "gitea-dump-{time}.zip". Supply '-' for stdout. See type for available types.`,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "verbose",
|
||||||
|
Aliases: []string{"V"},
|
||||||
|
Usage: "Show process details",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "quiet",
|
||||||
|
Aliases: []string{"q"},
|
||||||
|
Usage: "Only display warnings and errors",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "tempdir",
|
||||||
|
Aliases: []string{"t"},
|
||||||
|
Value: os.TempDir(),
|
||||||
|
Usage: "Temporary dir path",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "database",
|
||||||
|
Aliases: []string{"d"},
|
||||||
|
Usage: "Specify the database SQL syntax: sqlite3, mysql, mssql, postgres",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "skip-repository",
|
||||||
|
Aliases: []string{"R"},
|
||||||
|
Usage: "Skip the repository dumping",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "skip-log",
|
||||||
|
Aliases: []string{"L"},
|
||||||
|
Usage: "Skip the log dumping",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "skip-custom-dir",
|
||||||
|
Usage: "Skip custom directory",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "skip-lfs-data",
|
||||||
|
Usage: "Skip LFS data",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "skip-attachment-data",
|
||||||
|
Usage: "Skip attachment data",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "skip-package-data",
|
||||||
|
Usage: "Skip package data",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "skip-index",
|
||||||
|
Usage: "Skip bleve index data",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "skip-db",
|
||||||
|
Usage: "Skip database",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "type",
|
||||||
|
Usage: `Dump output format, default to "zip", supported types: ` + strings.Join(dump.SupportedOutputTypes, ", "),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
&cli.BoolFlag{
|
}
|
||||||
Name: "verbose",
|
|
||||||
Aliases: []string{"V"},
|
|
||||||
Usage: "Show process details",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "quiet",
|
|
||||||
Aliases: []string{"q"},
|
|
||||||
Usage: "Only display warnings and errors",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "tempdir",
|
|
||||||
Aliases: []string{"t"},
|
|
||||||
Value: os.TempDir(),
|
|
||||||
Usage: "Temporary dir path",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "database",
|
|
||||||
Aliases: []string{"d"},
|
|
||||||
Usage: "Specify the database SQL syntax: sqlite3, mysql, mssql, postgres",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "skip-repository",
|
|
||||||
Aliases: []string{"R"},
|
|
||||||
Usage: "Skip the repository dumping",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "skip-log",
|
|
||||||
Aliases: []string{"L"},
|
|
||||||
Usage: "Skip the log dumping",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "skip-custom-dir",
|
|
||||||
Usage: "Skip custom directory",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "skip-lfs-data",
|
|
||||||
Usage: "Skip LFS data",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "skip-attachment-data",
|
|
||||||
Usage: "Skip attachment data",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "skip-package-data",
|
|
||||||
Usage: "Skip package data",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "skip-index",
|
|
||||||
Usage: "Skip bleve index data",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "skip-db",
|
|
||||||
Usage: "Skip database",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "type",
|
|
||||||
Usage: `Dump output format, default to "zip", supported types: ` + strings.Join(dump.SupportedOutputTypes, ", "),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func fatal(format string, args ...any) {
|
func fatal(format string, args ...any) {
|
||||||
|
|||||||
@@ -22,61 +22,62 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdDumpRepository represents the available dump repository sub-command.
|
func newDumpRepositoryCommand() *cli.Command {
|
||||||
var CmdDumpRepository = &cli.Command{
|
return &cli.Command{
|
||||||
Name: "dump-repo",
|
Name: "dump-repo",
|
||||||
Usage: "Dump the repository from git/github/gitea/gitlab",
|
Usage: "Dump the repository from git/github/gitea/gitlab",
|
||||||
Description: "This is a command for dumping the repository data.",
|
Description: "This is a command for dumping the repository data.",
|
||||||
Action: runDumpRepository,
|
Action: runDumpRepository,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "git_service",
|
Name: "git_service",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Git service, git, github, gitea, gitlab. If clone_addr could be recognized, this could be ignored.",
|
Usage: "Git service, git, github, gitea, gitlab. If clone_addr could be recognized, this could be ignored.",
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "repo_dir",
|
Name: "repo_dir",
|
||||||
Aliases: []string{"r"},
|
Aliases: []string{"r"},
|
||||||
Value: "./data",
|
Value: "./data",
|
||||||
Usage: "Repository dir path to store the data",
|
Usage: "Repository dir path to store the data",
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "clone_addr",
|
Name: "clone_addr",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "The URL will be clone, currently could be a git/github/gitea/gitlab http/https URL",
|
Usage: "The URL will be clone, currently could be a git/github/gitea/gitlab http/https URL",
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "auth_username",
|
Name: "auth_username",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "The username to visit the clone_addr",
|
Usage: "The username to visit the clone_addr",
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "auth_password",
|
Name: "auth_password",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "The password to visit the clone_addr",
|
Usage: "The password to visit the clone_addr",
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "auth_token",
|
Name: "auth_token",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "The personal token to visit the clone_addr",
|
Usage: "The personal token to visit the clone_addr",
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "owner_name",
|
Name: "owner_name",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "The data will be stored on a directory with owner name if not empty",
|
Usage: "The data will be stored on a directory with owner name if not empty",
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "repo_name",
|
Name: "repo_name",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "The data will be stored on a directory with repository name if not empty",
|
Usage: "The data will be stored on a directory with repository name if not empty",
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "units",
|
Name: "units",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: `Which items will be migrated, one or more units should be separated as comma.
|
Usage: `Which items will be migrated, one or more units should be separated as comma.
|
||||||
wiki, issues, labels, releases, release_assets, milestones, pull_requests, comments are allowed. Empty means all units.`,
|
wiki, issues, labels, releases, release_assets, milestones, pull_requests, comments are allowed. Empty means all units.`,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func runDumpRepository(ctx context.Context, cmd *cli.Command) error {
|
func runDumpRepository(ctx context.Context, cmd *cli.Command) error {
|
||||||
|
|||||||
@@ -23,20 +23,23 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdEmbedded represents the available extract sub-command.
|
var matchedAssetFiles []assetFile
|
||||||
var (
|
|
||||||
CmdEmbedded = &cli.Command{
|
func newEmbeddedCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "embedded",
|
Name: "embedded",
|
||||||
Usage: "Extract embedded resources",
|
Usage: "Extract embedded resources",
|
||||||
Description: "A command for extracting embedded resources, like templates and images",
|
Description: "A command for extracting embedded resources, like templates and images",
|
||||||
Commands: []*cli.Command{
|
Commands: []*cli.Command{
|
||||||
subcmdList,
|
newEmbeddedListCommand(),
|
||||||
subcmdView,
|
newEmbeddedViewCommand(),
|
||||||
subcmdExtract,
|
newEmbeddedExtractCommand(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
subcmdList = &cli.Command{
|
func newEmbeddedListCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Usage: "List files matching the given pattern",
|
Usage: "List files matching the given pattern",
|
||||||
Action: runList,
|
Action: runList,
|
||||||
@@ -48,8 +51,10 @@ var (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
subcmdView = &cli.Command{
|
func newEmbeddedViewCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "view",
|
Name: "view",
|
||||||
Usage: "View a file matching the given pattern",
|
Usage: "View a file matching the given pattern",
|
||||||
Action: runView,
|
Action: runView,
|
||||||
@@ -61,8 +66,10 @@ var (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
subcmdExtract = &cli.Command{
|
func newEmbeddedExtractCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "extract",
|
Name: "extract",
|
||||||
Usage: "Extract resources",
|
Usage: "Extract resources",
|
||||||
Action: runExtract,
|
Action: runExtract,
|
||||||
@@ -91,9 +98,7 @@ var (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
matchedAssetFiles []assetFile
|
|
||||||
)
|
|
||||||
|
|
||||||
type assetFile struct {
|
type assetFile struct {
|
||||||
fs *assetfs.LayeredFS
|
fs *assetfs.LayeredFS
|
||||||
|
|||||||
@@ -15,45 +15,52 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
func newGenerateCommand() *cli.Command {
|
||||||
// CmdGenerate represents the available generate sub-command.
|
return &cli.Command{
|
||||||
CmdGenerate = &cli.Command{
|
|
||||||
Name: "generate",
|
Name: "generate",
|
||||||
Usage: "Generate Gitea's secrets/keys/tokens",
|
Usage: "Generate Gitea's secrets/keys/tokens",
|
||||||
Commands: []*cli.Command{
|
Commands: []*cli.Command{
|
||||||
subcmdSecret,
|
newGenerateSecretCommand(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
subcmdSecret = &cli.Command{
|
func newGenerateSecretCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "secret",
|
Name: "secret",
|
||||||
Usage: "Generate a secret token",
|
Usage: "Generate a secret token",
|
||||||
Commands: []*cli.Command{
|
Commands: []*cli.Command{
|
||||||
microcmdGenerateInternalToken,
|
newGenerateInternalTokenCommand(),
|
||||||
microcmdGenerateLfsJwtSecret,
|
newGenerateLfsJWTSecretCommand(),
|
||||||
microcmdGenerateSecretKey,
|
newGenerateSecretKeyCommand(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
microcmdGenerateInternalToken = &cli.Command{
|
func newGenerateInternalTokenCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "INTERNAL_TOKEN",
|
Name: "INTERNAL_TOKEN",
|
||||||
Usage: "Generate a new INTERNAL_TOKEN",
|
Usage: "Generate a new INTERNAL_TOKEN",
|
||||||
Action: runGenerateInternalToken,
|
Action: runGenerateInternalToken,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
microcmdGenerateLfsJwtSecret = &cli.Command{
|
func newGenerateLfsJWTSecretCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "JWT_SECRET",
|
Name: "JWT_SECRET",
|
||||||
Aliases: []string{"LFS_JWT_SECRET"},
|
Aliases: []string{"LFS_JWT_SECRET"},
|
||||||
Usage: "Generate a new JWT_SECRET",
|
Usage: "Generate a new JWT_SECRET",
|
||||||
Action: runGenerateLfsJwtSecret,
|
Action: runGenerateLfsJwtSecret,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
microcmdGenerateSecretKey = &cli.Command{
|
func newGenerateSecretKeyCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "SECRET_KEY",
|
Name: "SECRET_KEY",
|
||||||
Usage: "Generate a new SECRET_KEY",
|
Usage: "Generate a new SECRET_KEY",
|
||||||
Action: runGenerateSecretKey,
|
Action: runGenerateSecretKey,
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
func runGenerateInternalToken(_ context.Context, c *cli.Command) error {
|
func runGenerateInternalToken(_ context.Context, c *cli.Command) error {
|
||||||
internalToken, err := generate.NewInternalToken()
|
internalToken, err := generate.NewInternalToken()
|
||||||
@@ -71,11 +78,7 @@ func runGenerateInternalToken(_ context.Context, c *cli.Command) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runGenerateLfsJwtSecret(_ context.Context, c *cli.Command) error {
|
func runGenerateLfsJwtSecret(_ context.Context, c *cli.Command) error {
|
||||||
_, jwtSecretBase64, err := generate.NewJwtSecretWithBase64()
|
_, jwtSecretBase64 := generate.NewJwtSecretWithBase64()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("%s", jwtSecretBase64)
|
fmt.Printf("%s", jwtSecretBase64)
|
||||||
|
|
||||||
if isatty.IsTerminal(os.Stdout.Fd()) {
|
if isatty.IsTerminal(os.Stdout.Fd()) {
|
||||||
@@ -91,6 +94,7 @@ func runGenerateSecretKey(_ context.Context, c *cli.Command) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// codeql[disable-next-line=go/clear-text-logging]
|
||||||
fmt.Printf("%s", secretKey)
|
fmt.Printf("%s", secretKey)
|
||||||
|
|
||||||
if isatty.IsTerminal(os.Stdout.Fd()) {
|
if isatty.IsTerminal(os.Stdout.Fd()) {
|
||||||
|
|||||||
@@ -28,23 +28,24 @@ const (
|
|||||||
hookBatchSize = 500
|
hookBatchSize = 500
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
func newHookCommand() *cli.Command {
|
||||||
// CmdHook represents the available hooks sub-command.
|
return &cli.Command{
|
||||||
CmdHook = &cli.Command{
|
|
||||||
Name: "hook",
|
Name: "hook",
|
||||||
Usage: "(internal) Should only be called by Git",
|
Usage: "(internal) Should only be called by Git",
|
||||||
Hidden: true, // internal commands shouldn't be visible
|
Hidden: true, // internal commands shouldn't be visible
|
||||||
Description: "Delegate commands to corresponding Git hooks",
|
Description: "Delegate commands to corresponding Git hooks",
|
||||||
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||||
Commands: []*cli.Command{
|
Commands: []*cli.Command{
|
||||||
subcmdHookPreReceive,
|
newHookPreReceiveCommand(),
|
||||||
subcmdHookUpdate,
|
newHookUpdateCommand(),
|
||||||
subcmdHookPostReceive,
|
newHookPostReceiveCommand(),
|
||||||
subcmdHookProcReceive,
|
newHookProcReceiveCommand(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
subcmdHookPreReceive = &cli.Command{
|
func newHookPreReceiveCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "pre-receive",
|
Name: "pre-receive",
|
||||||
Usage: "Delegate pre-receive Git hook",
|
Usage: "Delegate pre-receive Git hook",
|
||||||
Description: "This command should only be called by Git",
|
Description: "This command should only be called by Git",
|
||||||
@@ -55,7 +56,10 @@ var (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
subcmdHookUpdate = &cli.Command{
|
}
|
||||||
|
|
||||||
|
func newHookUpdateCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "update",
|
Name: "update",
|
||||||
Usage: "Delegate update Git hook",
|
Usage: "Delegate update Git hook",
|
||||||
Description: "This command should only be called by Git",
|
Description: "This command should only be called by Git",
|
||||||
@@ -66,7 +70,10 @@ var (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
subcmdHookPostReceive = &cli.Command{
|
}
|
||||||
|
|
||||||
|
func newHookPostReceiveCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "post-receive",
|
Name: "post-receive",
|
||||||
Usage: "Delegate post-receive Git hook",
|
Usage: "Delegate post-receive Git hook",
|
||||||
Description: "This command should only be called by Git",
|
Description: "This command should only be called by Git",
|
||||||
@@ -77,8 +84,11 @@ var (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
// Note: new hook since git 2.29
|
}
|
||||||
subcmdHookProcReceive = &cli.Command{
|
|
||||||
|
// Note: new hook since git 2.29
|
||||||
|
func newHookProcReceiveCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "proc-receive",
|
Name: "proc-receive",
|
||||||
Usage: "Delegate proc-receive Git hook",
|
Usage: "Delegate proc-receive Git hook",
|
||||||
Description: "This command should only be called by Git",
|
Description: "This command should only be called by Git",
|
||||||
@@ -89,7 +99,7 @@ var (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
type delayWriter struct {
|
type delayWriter struct {
|
||||||
internal io.Writer
|
internal io.Writer
|
||||||
@@ -194,7 +204,7 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
userID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPusherID), 10, 64)
|
userID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPusherID), 10, 64)
|
||||||
prID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPRID), 10, 64)
|
prID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPRID), 10, 64)
|
||||||
deployKeyID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvDeployKeyID), 10, 64)
|
deployKeyID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvDeployKeyID), 10, 64)
|
||||||
actionPerm, _ := strconv.ParseInt(os.Getenv(repo_module.EnvActionPerm), 10, 64)
|
actionsTaskID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvActionsTaskID), 10, 64)
|
||||||
|
|
||||||
hookOptions := private.HookOptions{
|
hookOptions := private.HookOptions{
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
@@ -204,7 +214,8 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
GitPushOptions: pushOptions(),
|
GitPushOptions: pushOptions(),
|
||||||
PullRequestID: prID,
|
PullRequestID: prID,
|
||||||
DeployKeyID: deployKeyID,
|
DeployKeyID: deployKeyID,
|
||||||
ActionPerm: int(actionPerm),
|
ActionsTaskID: actionsTaskID,
|
||||||
|
IsWiki: isWiki,
|
||||||
}
|
}
|
||||||
|
|
||||||
scanner := bufio.NewScanner(os.Stdin)
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
@@ -275,6 +286,9 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
lastline = 0
|
lastline = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
return fail(ctx, "Hook failed: stdin read error", "scanner error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
hookOptions.OldCommitIDs = oldCommitIDs[:count]
|
hookOptions.OldCommitIDs = oldCommitIDs[:count]
|
||||||
@@ -318,7 +332,7 @@ func runHookPostReceive(ctx context.Context, c *cli.Command) error {
|
|||||||
setup(ctx, c.Bool("debug"))
|
setup(ctx, c.Bool("debug"))
|
||||||
|
|
||||||
// First of all run update-server-info no matter what
|
// First of all run update-server-info no matter what
|
||||||
if _, _, err := gitcmd.NewCommand("update-server-info").RunStdString(ctx, nil); err != nil {
|
if err := gitcmd.NewCommand("update-server-info").RunWithStderr(ctx); err != nil {
|
||||||
return fmt.Errorf("failed to call 'git update-server-info': %w", err)
|
return fmt.Errorf("failed to call 'git update-server-info': %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,6 +380,7 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
GitPushOptions: pushOptions(),
|
GitPushOptions: pushOptions(),
|
||||||
PullRequestID: prID,
|
PullRequestID: prID,
|
||||||
PushTrigger: repo_module.PushTrigger(os.Getenv(repo_module.EnvPushTrigger)),
|
PushTrigger: repo_module.PushTrigger(os.Getenv(repo_module.EnvPushTrigger)),
|
||||||
|
IsWiki: isWiki,
|
||||||
}
|
}
|
||||||
oldCommitIDs := make([]string, hookBatchSize)
|
oldCommitIDs := make([]string, hookBatchSize)
|
||||||
newCommitIDs := make([]string, hookBatchSize)
|
newCommitIDs := make([]string, hookBatchSize)
|
||||||
@@ -413,6 +428,11 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
count = 0
|
count = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
_ = dWriter.Close()
|
||||||
|
hookPrintResults(results)
|
||||||
|
return fail(ctx, "Hook failed: stdin read error", "scanner error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
if wasEmpty && masterPushed {
|
if wasEmpty && masterPushed {
|
||||||
@@ -513,6 +533,7 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
|
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
repoUser := os.Getenv(repo_module.EnvRepoUsername)
|
repoUser := os.Getenv(repo_module.EnvRepoUsername)
|
||||||
|
isWiki, _ := strconv.ParseBool(os.Getenv(repo_module.EnvRepoIsWiki))
|
||||||
repoName := os.Getenv(repo_module.EnvRepoName)
|
repoName := os.Getenv(repo_module.EnvRepoName)
|
||||||
pusherID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPusherID), 10, 64)
|
pusherID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPusherID), 10, 64)
|
||||||
pusherName := os.Getenv(repo_module.EnvPusherName)
|
pusherName := os.Getenv(repo_module.EnvPusherName)
|
||||||
@@ -590,14 +611,15 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
UserName: pusherName,
|
UserName: pusherName,
|
||||||
UserID: pusherID,
|
UserID: pusherID,
|
||||||
GitPushOptions: make(map[string]string),
|
GitPushOptions: make(map[string]string),
|
||||||
|
IsWiki: isWiki,
|
||||||
}
|
}
|
||||||
hookOptions.OldCommitIDs = make([]string, 0, hookBatchSize)
|
hookOptions.OldCommitIDs = make([]string, 0, hookBatchSize)
|
||||||
hookOptions.NewCommitIDs = make([]string, 0, hookBatchSize)
|
hookOptions.NewCommitIDs = make([]string, 0, hookBatchSize)
|
||||||
hookOptions.RefFullNames = make([]git.RefName, 0, hookBatchSize)
|
hookOptions.RefFullNames = make([]git.RefName, 0, hookBatchSize)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
// note: pktLineTypeUnknow means pktLineTypeFlush and pktLineTypeData all allowed
|
// note: pktLineTypeUnknown means pktLineTypeFlush and pktLineTypeData all allowed
|
||||||
rs, err = readPktLine(ctx, reader, pktLineTypeUnknow)
|
rs, err = readPktLine(ctx, reader, pktLineTypeUnknown)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -616,7 +638,7 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
|
|
||||||
if hasPushOptions {
|
if hasPushOptions {
|
||||||
for {
|
for {
|
||||||
rs, err = readPktLine(ctx, reader, pktLineTypeUnknow)
|
rs, err = readPktLine(ctx, reader, pktLineTypeUnknown)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -713,8 +735,8 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
type pktLineType int64
|
type pktLineType int64
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// UnKnow type
|
// Unknown type
|
||||||
pktLineTypeUnknow pktLineType = 0
|
pktLineTypeUnknown pktLineType = 0
|
||||||
// flush-pkt "0000"
|
// flush-pkt "0000"
|
||||||
pktLineTypeFlush pktLineType = iota
|
pktLineTypeFlush pktLineType = iota
|
||||||
// data line
|
// data line
|
||||||
|
|||||||
@@ -15,40 +15,42 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdKeys represents the available keys sub-command
|
// NewKeysCommand returns the internal SSH key lookup sub-command.
|
||||||
var CmdKeys = &cli.Command{
|
func NewKeysCommand() *cli.Command {
|
||||||
Name: "keys",
|
return &cli.Command{
|
||||||
Usage: "(internal) Should only be called by SSH server",
|
Name: "keys",
|
||||||
Hidden: true, // internal commands shouldn't be visible
|
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",
|
Hidden: true, // internal commands shouldn't be visible
|
||||||
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
Description: "Queries the Gitea database to get the authorized command for a given ssh key fingerprint",
|
||||||
Action: runKeys,
|
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||||
Flags: []cli.Flag{
|
Action: runKeys,
|
||||||
&cli.StringFlag{
|
Flags: []cli.Flag{
|
||||||
Name: "expected",
|
&cli.StringFlag{
|
||||||
Aliases: []string{"e"},
|
Name: "expected",
|
||||||
Value: "git",
|
Aliases: []string{"e"},
|
||||||
Usage: "Expected user for whom provide key commands",
|
Value: "git",
|
||||||
|
Usage: "Expected user for whom provide key commands",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "username",
|
||||||
|
Aliases: []string{"u"},
|
||||||
|
Value: "",
|
||||||
|
Usage: "Username trying to log in by SSH",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "type",
|
||||||
|
Aliases: []string{"t"},
|
||||||
|
Value: "",
|
||||||
|
Usage: "Type of the SSH key provided to the SSH Server (requires content to be provided too)",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "content",
|
||||||
|
Aliases: []string{"k"},
|
||||||
|
Value: "",
|
||||||
|
Usage: "Base64 encoded content of the SSH key provided to the SSH Server (requires type to be provided too)",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
}
|
||||||
Name: "username",
|
|
||||||
Aliases: []string{"u"},
|
|
||||||
Value: "",
|
|
||||||
Usage: "Username trying to log in by SSH",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "type",
|
|
||||||
Aliases: []string{"t"},
|
|
||||||
Value: "",
|
|
||||||
Usage: "Type of the SSH key provided to the SSH Server (requires content to be provided too)",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "content",
|
|
||||||
Aliases: []string{"k"},
|
|
||||||
Value: "",
|
|
||||||
Usage: "Base64 encoded content of the SSH key provided to the SSH Server (requires type to be provided too)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func runKeys(ctx context.Context, c *cli.Command) error {
|
func runKeys(ctx context.Context, c *cli.Command) error {
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ func runSendMail(ctx context.Context, c *cli.Command) error {
|
|||||||
setting.MustInstalled()
|
setting.MustInstalled()
|
||||||
|
|
||||||
subject := c.String("title")
|
subject := c.String("title")
|
||||||
confirmSkiped := c.Bool("force")
|
confirmSkipped := c.Bool("force")
|
||||||
body := c.String("content")
|
body := c.String("content")
|
||||||
|
|
||||||
if !confirmSkiped {
|
if !confirmSkipped {
|
||||||
if len(body) == 0 {
|
if len(body) == 0 {
|
||||||
fmt.Print("warning: Content is empty")
|
fmt.Print("warning: Content is empty")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,34 +112,36 @@ func NewMainApp(appVer AppVersion) *cli.Command {
|
|||||||
Usage: "Set custom path (defaults to '{WorkPath}/custom')",
|
Usage: "Set custom path (defaults to '{WorkPath}/custom')",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
webCmd := newWebCommand()
|
||||||
// these sub-commands need to use a config file
|
// these sub-commands need to use a config file
|
||||||
subCmdWithConfig := []*cli.Command{
|
subCmdWithConfig := []*cli.Command{
|
||||||
CmdWeb,
|
webCmd,
|
||||||
CmdServ,
|
newServCommand(),
|
||||||
CmdHook,
|
newHookCommand(),
|
||||||
CmdKeys,
|
NewKeysCommand(),
|
||||||
CmdDump,
|
newDumpCommand(),
|
||||||
CmdAdmin,
|
newAdminCommand(),
|
||||||
CmdMigrate,
|
newMigrateCommand(),
|
||||||
CmdDoctor,
|
newDoctorCommand(),
|
||||||
CmdManager,
|
newManagerCommand(),
|
||||||
CmdEmbedded,
|
newEmbeddedCommand(),
|
||||||
CmdMigrateStorage,
|
newMigrateStorageCommand(),
|
||||||
CmdDumpRepository,
|
newDumpRepositoryCommand(),
|
||||||
CmdRestoreRepository,
|
newRestoreRepositoryCommand(),
|
||||||
CmdActions,
|
newActionsCommand(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// these sub-commands do not need the config file, and they do not depend on any path or environment variable.
|
// these sub-commands do not need the config file, and they do not depend on any path or environment variable.
|
||||||
subCmdStandalone := []*cli.Command{
|
subCmdStandalone := []*cli.Command{
|
||||||
|
cmdConfig(),
|
||||||
cmdCert(),
|
cmdCert(),
|
||||||
CmdGenerate,
|
newGenerateCommand(),
|
||||||
CmdDocs,
|
newDocsCommand(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: we should eventually drop the default command,
|
// TODO: we should eventually drop the default command,
|
||||||
// but not sure whether it would break Windows users who used to double-click the EXE to run.
|
// but not sure whether it would break Windows users who used to double-click the EXE to run.
|
||||||
app.DefaultCommand = CmdWeb.Name
|
app.DefaultCommand = webCmd.Name
|
||||||
|
|
||||||
app.Before = PrepareConsoleLoggerLevel(log.INFO)
|
app.Before = PrepareConsoleLoggerLevel(log.INFO)
|
||||||
for i := range subCmdWithConfig {
|
for i := range subCmdWithConfig {
|
||||||
@@ -148,7 +150,7 @@ func NewMainApp(appVer AppVersion) *cli.Command {
|
|||||||
app.Commands = append(app.Commands, subCmdWithConfig...)
|
app.Commands = append(app.Commands, subCmdWithConfig...)
|
||||||
app.Commands = append(app.Commands, subCmdStandalone...)
|
app.Commands = append(app.Commands, subCmdStandalone...)
|
||||||
|
|
||||||
setting.InitGiteaEnvVars()
|
setting.UnsetUnnecessaryEnvVars()
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -157,6 +157,7 @@ func TestCliCmd(t *testing.T) {
|
|||||||
|
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
t.Run(c.cmd, func(t *testing.T) {
|
t.Run(c.cmd, func(t *testing.T) {
|
||||||
|
defer test.MockVariableValue(&setting.InstallLock, false)()
|
||||||
app := newTestApp(cli.Command{
|
app := newTestApp(cli.Command{
|
||||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||||
_, _ = fmt.Fprint(cmd.Root().Writer, makePathOutput(setting.AppWorkPath, setting.CustomPath, setting.CustomConf))
|
_, _ = fmt.Fprint(cmd.Root().Writer, makePathOutput(setting.AppWorkPath, setting.CustomPath, setting.CustomConf))
|
||||||
@@ -170,7 +171,10 @@ func TestCliCmd(t *testing.T) {
|
|||||||
r, err := runTestApp(app, args...)
|
r, err := runTestApp(app, args...)
|
||||||
assert.NoError(t, err, c.cmd)
|
assert.NoError(t, err, c.cmd)
|
||||||
assert.NotEmpty(t, c.exp, c.cmd)
|
assert.NotEmpty(t, c.exp, c.cmd)
|
||||||
assert.Contains(t, r.Stdout, c.exp, c.cmd)
|
if !assert.Contains(t, r.Stdout, c.exp, c.cmd) {
|
||||||
|
t.Log("Full output:\n" + r.Stdout)
|
||||||
|
t.Log("Expected:\n" + c.exp)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,22 +13,24 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
func newManagerCommand() *cli.Command {
|
||||||
// CmdManager represents the manager command
|
return &cli.Command{
|
||||||
CmdManager = &cli.Command{
|
|
||||||
Name: "manager",
|
Name: "manager",
|
||||||
Usage: "Manage the running gitea process",
|
Usage: "Manage the running gitea process",
|
||||||
Description: "This is a command for managing the running gitea process",
|
Description: "This is a command for managing the running gitea process",
|
||||||
Commands: []*cli.Command{
|
Commands: []*cli.Command{
|
||||||
subcmdShutdown,
|
newShutdownCommand(),
|
||||||
subcmdRestart,
|
newRestartCommand(),
|
||||||
subcmdReloadTemplates,
|
newReloadTemplatesCommand(),
|
||||||
subcmdFlushQueues,
|
newFlushQueuesCommand(),
|
||||||
subcmdLogging,
|
newLoggingCommand(),
|
||||||
subCmdProcesses,
|
newProcessesCommand(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
subcmdShutdown = &cli.Command{
|
}
|
||||||
|
|
||||||
|
func newShutdownCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "shutdown",
|
Name: "shutdown",
|
||||||
Usage: "Gracefully shutdown the running process",
|
Usage: "Gracefully shutdown the running process",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
@@ -38,7 +40,10 @@ var (
|
|||||||
},
|
},
|
||||||
Action: runShutdown,
|
Action: runShutdown,
|
||||||
}
|
}
|
||||||
subcmdRestart = &cli.Command{
|
}
|
||||||
|
|
||||||
|
func newRestartCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "restart",
|
Name: "restart",
|
||||||
Usage: "Gracefully restart the running process - (not implemented for windows servers)",
|
Usage: "Gracefully restart the running process - (not implemented for windows servers)",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
@@ -48,7 +53,10 @@ var (
|
|||||||
},
|
},
|
||||||
Action: runRestart,
|
Action: runRestart,
|
||||||
}
|
}
|
||||||
subcmdReloadTemplates = &cli.Command{
|
}
|
||||||
|
|
||||||
|
func newReloadTemplatesCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "reload-templates",
|
Name: "reload-templates",
|
||||||
Usage: "Reload template files in the running process",
|
Usage: "Reload template files in the running process",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
@@ -58,7 +66,10 @@ var (
|
|||||||
},
|
},
|
||||||
Action: runReloadTemplates,
|
Action: runReloadTemplates,
|
||||||
}
|
}
|
||||||
subcmdFlushQueues = &cli.Command{
|
}
|
||||||
|
|
||||||
|
func newFlushQueuesCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "flush-queues",
|
Name: "flush-queues",
|
||||||
Usage: "Flush queues in the running process",
|
Usage: "Flush queues in the running process",
|
||||||
Action: runFlushQueues,
|
Action: runFlushQueues,
|
||||||
@@ -77,7 +88,10 @@ var (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
subCmdProcesses = &cli.Command{
|
}
|
||||||
|
|
||||||
|
func newProcessesCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "processes",
|
Name: "processes",
|
||||||
Usage: "Display running processes within the current process",
|
Usage: "Display running processes within the current process",
|
||||||
Action: runProcesses,
|
Action: runProcesses,
|
||||||
@@ -107,7 +121,7 @@ var (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
func runShutdown(ctx context.Context, c *cli.Command) error {
|
func runShutdown(ctx context.Context, c *cli.Command) error {
|
||||||
setup(ctx, c.Bool("debug"))
|
setup(ctx, c.Bool("debug"))
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
func defaultLoggingFlags() []cli.Flag {
|
||||||
defaultLoggingFlags = []cli.Flag{
|
return []cli.Flag{
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "logger",
|
Name: "logger",
|
||||||
Usage: `Logger name - will default to "default"`,
|
Usage: `Logger name - will default to "default"`,
|
||||||
@@ -57,8 +57,10 @@ var (
|
|||||||
Name: "debug",
|
Name: "debug",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
subcmdLogging = &cli.Command{
|
func newLoggingCommand() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
Name: "logging",
|
Name: "logging",
|
||||||
Usage: "Adjust logging commands",
|
Usage: "Adjust logging commands",
|
||||||
Commands: []*cli.Command{
|
Commands: []*cli.Command{
|
||||||
@@ -109,7 +111,7 @@ var (
|
|||||||
{
|
{
|
||||||
Name: "file",
|
Name: "file",
|
||||||
Usage: "Add a file logger",
|
Usage: "Add a file logger",
|
||||||
Flags: append(defaultLoggingFlags, []cli.Flag{
|
Flags: append(defaultLoggingFlags(), []cli.Flag{
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "filename",
|
Name: "filename",
|
||||||
Aliases: []string{"f"},
|
Aliases: []string{"f"},
|
||||||
@@ -150,7 +152,7 @@ var (
|
|||||||
}, {
|
}, {
|
||||||
Name: "conn",
|
Name: "conn",
|
||||||
Usage: "Add a net conn logger",
|
Usage: "Add a net conn logger",
|
||||||
Flags: append(defaultLoggingFlags, []cli.Flag{
|
Flags: append(defaultLoggingFlags(), []cli.Flag{
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "reconnect-on-message",
|
Name: "reconnect-on-message",
|
||||||
Aliases: []string{"R"},
|
Aliases: []string{"R"},
|
||||||
@@ -191,7 +193,7 @@ var (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
func runRemoveLogger(ctx context.Context, c *cli.Command) error {
|
func runRemoveLogger(ctx context.Context, c *cli.Command) error {
|
||||||
setup(ctx, c.Bool("debug"))
|
setup(ctx, c.Bool("debug"))
|
||||||
|
|||||||
@@ -14,12 +14,13 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdMigrate represents the available migrate sub-command.
|
func newMigrateCommand() *cli.Command {
|
||||||
var CmdMigrate = &cli.Command{
|
return &cli.Command{
|
||||||
Name: "migrate",
|
Name: "migrate",
|
||||||
Usage: "Migrate the database",
|
Usage: "Migrate the database",
|
||||||
Description: `This is a command for migrating the database, so that you can run "gitea admin create user" before starting the server.`,
|
Description: `This is a command for migrating the database, so that you can run "gitea admin create user" before starting the server.`,
|
||||||
Action: runMigrate,
|
Action: runMigrate,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func runMigrate(ctx context.Context, c *cli.Command) error {
|
func runMigrate(ctx context.Context, c *cli.Command) error {
|
||||||
|
|||||||
@@ -25,107 +25,108 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdMigrateStorage represents the available migrate storage sub-command.
|
func newMigrateStorageCommand() *cli.Command {
|
||||||
var CmdMigrateStorage = &cli.Command{
|
return &cli.Command{
|
||||||
Name: "migrate-storage",
|
Name: "migrate-storage",
|
||||||
Usage: "Migrate the storage",
|
Usage: "Migrate the storage",
|
||||||
Description: "Copies stored files from storage configured in app.ini to parameter-configured storage",
|
Description: "Copies stored files from storage configured in app.ini to parameter-configured storage",
|
||||||
Action: runMigrateStorage,
|
Action: runMigrateStorage,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "type",
|
Name: "type",
|
||||||
Aliases: []string{"t"},
|
Aliases: []string{"t"},
|
||||||
Value: "",
|
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', 'actions-artifacts'",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "storage",
|
||||||
|
Aliases: []string{"s"},
|
||||||
|
Value: "",
|
||||||
|
Usage: "New storage type: local (default), minio or azureblob",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "path",
|
||||||
|
Aliases: []string{"p"},
|
||||||
|
Value: "",
|
||||||
|
Usage: "New storage placement if store is local (leave blank for default)",
|
||||||
|
},
|
||||||
|
// Minio Storage special configurations
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "minio-endpoint",
|
||||||
|
Value: "",
|
||||||
|
Usage: "Minio storage endpoint",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "minio-access-key-id",
|
||||||
|
Value: "",
|
||||||
|
Usage: "Minio storage accessKeyID",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "minio-secret-access-key",
|
||||||
|
Value: "",
|
||||||
|
Usage: "Minio storage secretAccessKey",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "minio-bucket",
|
||||||
|
Value: "",
|
||||||
|
Usage: "Minio storage bucket",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "minio-location",
|
||||||
|
Value: "",
|
||||||
|
Usage: "Minio storage location to create bucket",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "minio-base-path",
|
||||||
|
Value: "",
|
||||||
|
Usage: "Minio storage base path on the bucket",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "minio-use-ssl",
|
||||||
|
Usage: "Enable SSL for minio",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "minio-insecure-skip-verify",
|
||||||
|
Usage: "Skip SSL verification",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "minio-checksum-algorithm",
|
||||||
|
Value: "",
|
||||||
|
Usage: "Minio checksum algorithm (default/md5)",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "minio-bucket-lookup-type",
|
||||||
|
Value: "",
|
||||||
|
Usage: "Minio bucket lookup type",
|
||||||
|
},
|
||||||
|
// Azure Blob Storage special configurations
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "azureblob-endpoint",
|
||||||
|
Value: "",
|
||||||
|
Usage: "Azure Blob storage endpoint",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "azureblob-account-name",
|
||||||
|
Value: "",
|
||||||
|
Usage: "Azure Blob storage account name",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "azureblob-account-key",
|
||||||
|
Value: "",
|
||||||
|
Usage: "Azure Blob storage account key",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "azureblob-container",
|
||||||
|
Value: "",
|
||||||
|
Usage: "Azure Blob storage container",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "azureblob-base-path",
|
||||||
|
Value: "",
|
||||||
|
Usage: "Azure Blob storage base path",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
}
|
||||||
Name: "storage",
|
|
||||||
Aliases: []string{"s"},
|
|
||||||
Value: "",
|
|
||||||
Usage: "New storage type: local (default), minio or azureblob",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "path",
|
|
||||||
Aliases: []string{"p"},
|
|
||||||
Value: "",
|
|
||||||
Usage: "New storage placement if store is local (leave blank for default)",
|
|
||||||
},
|
|
||||||
// Minio Storage special configurations
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "minio-endpoint",
|
|
||||||
Value: "",
|
|
||||||
Usage: "Minio storage endpoint",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "minio-access-key-id",
|
|
||||||
Value: "",
|
|
||||||
Usage: "Minio storage accessKeyID",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "minio-secret-access-key",
|
|
||||||
Value: "",
|
|
||||||
Usage: "Minio storage secretAccessKey",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "minio-bucket",
|
|
||||||
Value: "",
|
|
||||||
Usage: "Minio storage bucket",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "minio-location",
|
|
||||||
Value: "",
|
|
||||||
Usage: "Minio storage location to create bucket",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "minio-base-path",
|
|
||||||
Value: "",
|
|
||||||
Usage: "Minio storage base path on the bucket",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "minio-use-ssl",
|
|
||||||
Usage: "Enable SSL for minio",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "minio-insecure-skip-verify",
|
|
||||||
Usage: "Skip SSL verification",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "minio-checksum-algorithm",
|
|
||||||
Value: "",
|
|
||||||
Usage: "Minio checksum algorithm (default/md5)",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "minio-bucket-lookup-type",
|
|
||||||
Value: "",
|
|
||||||
Usage: "Minio bucket lookup type",
|
|
||||||
},
|
|
||||||
// Azure Blob Storage special configurations
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "azureblob-endpoint",
|
|
||||||
Value: "",
|
|
||||||
Usage: "Azure Blob storage endpoint",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "azureblob-account-name",
|
|
||||||
Value: "",
|
|
||||||
Usage: "Azure Blob storage account name",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "azureblob-account-key",
|
|
||||||
Value: "",
|
|
||||||
Usage: "Azure Blob storage account key",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "azureblob-container",
|
|
||||||
Value: "",
|
|
||||||
Usage: "Azure Blob storage container",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "azureblob-base-path",
|
|
||||||
Value: "",
|
|
||||||
Usage: "Azure Blob storage base path",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func migrateAttachments(ctx context.Context, dstStorage storage.ObjectStorage) error {
|
func migrateAttachments(ctx context.Context, dstStorage storage.ObjectStorage) error {
|
||||||
|
|||||||
@@ -13,40 +13,41 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdRestoreRepository represents the available restore a repository sub-command.
|
func newRestoreRepositoryCommand() *cli.Command {
|
||||||
var CmdRestoreRepository = &cli.Command{
|
return &cli.Command{
|
||||||
Name: "restore-repo",
|
Name: "restore-repo",
|
||||||
Usage: "Restore the repository from disk",
|
Usage: "Restore the repository from disk",
|
||||||
Description: "This is a command for restoring the repository data.",
|
Description: "This is a command for restoring the repository data.",
|
||||||
Action: runRestoreRepository,
|
Action: runRestoreRepository,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "repo_dir",
|
Name: "repo_dir",
|
||||||
Aliases: []string{"r"},
|
Aliases: []string{"r"},
|
||||||
Value: "./data",
|
Value: "./data",
|
||||||
Usage: "Repository dir path to restore from",
|
Usage: "Repository dir path to restore from",
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "owner_name",
|
Name: "owner_name",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Restore destination owner name",
|
Usage: "Restore destination owner name",
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "repo_name",
|
Name: "repo_name",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Restore destination repository name",
|
Usage: "Restore destination repository name",
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "units",
|
Name: "units",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: `Which items will be restored, one or more units should be separated as comma.
|
Usage: `Which items will be restored, one or more units should be separated as comma.
|
||||||
wiki, issues, labels, releases, release_assets, milestones, pull_requests, comments are allowed. Empty means all units.`,
|
wiki, issues, labels, releases, release_assets, milestones, pull_requests, comments are allowed. Empty means all units.`,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "validation",
|
||||||
|
Usage: "Sanity check the content of the files before trying to load them",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
&cli.BoolFlag{
|
}
|
||||||
Name: "validation",
|
|
||||||
Usage: "Sanity check the content of the files before trying to load them",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func runRestoreRepository(ctx context.Context, c *cli.Command) error {
|
func runRestoreRepository(ctx context.Context, c *cli.Command) error {
|
||||||
|
|||||||
@@ -35,22 +35,23 @@ import (
|
|||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdServ represents the available serv sub-command.
|
func newServCommand() *cli.Command {
|
||||||
var CmdServ = &cli.Command{
|
return &cli.Command{
|
||||||
Name: "serv",
|
Name: "serv",
|
||||||
Usage: "(internal) Should only be called by SSH shell",
|
Usage: "(internal) Should only be called by SSH shell",
|
||||||
Description: "Serv provides access auth for repositories",
|
Description: "Serv provides access auth for repositories",
|
||||||
Hidden: true, // Internal commands shouldn't be visible in help
|
Hidden: true, // Internal commands shouldn't be visible in help
|
||||||
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||||
Action: runServ,
|
Action: runServ,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "enable-pprof",
|
Name: "enable-pprof",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "debug",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
&cli.BoolFlag{
|
}
|
||||||
Name: "debug",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func setup(ctx context.Context, debug bool) {
|
func setup(ctx context.Context, debug bool) {
|
||||||
|
|||||||
@@ -8,14 +8,13 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/pprof"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
_ "net/http/pprof" // Used for debugging if enabled and a web server is running
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/container"
|
"code.gitea.io/gitea/modules/container"
|
||||||
"code.gitea.io/gitea/modules/graceful"
|
"code.gitea.io/gitea/modules/graceful"
|
||||||
"code.gitea.io/gitea/modules/gtprof"
|
"code.gitea.io/gitea/modules/gtprof"
|
||||||
@@ -23,6 +22,7 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/process"
|
"code.gitea.io/gitea/modules/process"
|
||||||
"code.gitea.io/gitea/modules/public"
|
"code.gitea.io/gitea/modules/public"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/templates"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
"code.gitea.io/gitea/routers"
|
"code.gitea.io/gitea/routers"
|
||||||
"code.gitea.io/gitea/routers/install"
|
"code.gitea.io/gitea/routers/install"
|
||||||
@@ -34,42 +34,43 @@ import (
|
|||||||
// PIDFile could be set from build tag
|
// PIDFile could be set from build tag
|
||||||
var PIDFile = "/run/gitea.pid"
|
var PIDFile = "/run/gitea.pid"
|
||||||
|
|
||||||
// CmdWeb represents the available web sub-command.
|
func newWebCommand() *cli.Command {
|
||||||
var CmdWeb = &cli.Command{
|
return &cli.Command{
|
||||||
Name: "web",
|
Name: "web",
|
||||||
Usage: "Start Gitea web server",
|
Usage: "Start Gitea web server",
|
||||||
Description: `Gitea web server is the only thing you need to run,
|
Description: `Gitea web server is the only thing you need to run,
|
||||||
and it takes care of all the other things for you`,
|
and it takes care of all the other things for you`,
|
||||||
Before: PrepareConsoleLoggerLevel(log.INFO),
|
Before: PrepareConsoleLoggerLevel(log.INFO),
|
||||||
Action: runWeb,
|
Action: runWeb,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "port",
|
Name: "port",
|
||||||
Aliases: []string{"p"},
|
Aliases: []string{"p"},
|
||||||
Value: "3000",
|
Value: "3000",
|
||||||
Usage: "Temporary port number to prevent conflict",
|
Usage: "Temporary port number to prevent conflict",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "install-port",
|
||||||
|
Value: "3000",
|
||||||
|
Usage: "Temporary port number to run the install page on to prevent conflict",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "pid",
|
||||||
|
Aliases: []string{"P"},
|
||||||
|
Value: PIDFile,
|
||||||
|
Usage: "Custom pid file path",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "quiet",
|
||||||
|
Aliases: []string{"q"},
|
||||||
|
Usage: "Only display Fatal logging errors until logging is set-up",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "verbose",
|
||||||
|
Usage: "Set initial logging to TRACE level until logging is properly set-up",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
}
|
||||||
Name: "install-port",
|
|
||||||
Value: "3000",
|
|
||||||
Usage: "Temporary port number to run the install page on to prevent conflict",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "pid",
|
|
||||||
Aliases: []string{"P"},
|
|
||||||
Value: PIDFile,
|
|
||||||
Usage: "Custom pid file path",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "quiet",
|
|
||||||
Aliases: []string{"q"},
|
|
||||||
Usage: "Only display Fatal logging errors until logging is set-up",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "verbose",
|
|
||||||
Usage: "Set initial logging to TRACE level until logging is properly set-up",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func runHTTPRedirector() {
|
func runHTTPRedirector() {
|
||||||
@@ -156,7 +157,6 @@ func serveInstall(cmd *cli.Command) error {
|
|||||||
case <-graceful.GetManager().IsShutdown():
|
case <-graceful.GetManager().IsShutdown():
|
||||||
<-graceful.GetManager().Done()
|
<-graceful.GetManager().Done()
|
||||||
log.Info("PID: %d Gitea Web Finished", os.Getpid())
|
log.Info("PID: %d Gitea Web Finished", os.Getpid())
|
||||||
log.GetManager().Close()
|
|
||||||
return err
|
return err
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
@@ -164,8 +164,6 @@ func serveInstall(cmd *cli.Command) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func serveInstalled(c *cli.Command) error {
|
func serveInstalled(c *cli.Command) error {
|
||||||
setting.InitCfgProvider(setting.CustomConf)
|
|
||||||
setting.LoadCommonSettings()
|
|
||||||
setting.MustInstalled()
|
setting.MustInstalled()
|
||||||
|
|
||||||
showWebStartupMessage("Prepare to run web server")
|
showWebStartupMessage("Prepare to run web server")
|
||||||
@@ -231,27 +229,26 @@ func serveInstalled(c *cli.Command) error {
|
|||||||
err := listen(webRoutes, true)
|
err := listen(webRoutes, true)
|
||||||
<-graceful.GetManager().Done()
|
<-graceful.GetManager().Done()
|
||||||
log.Info("PID: %d Gitea Web Finished", os.Getpid())
|
log.Info("PID: %d Gitea Web Finished", os.Getpid())
|
||||||
log.GetManager().Close()
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func servePprof() {
|
func servePprof() {
|
||||||
// FIXME: it shouldn't use the global DefaultServeMux, and it should use a proper context
|
mux := http.NewServeMux()
|
||||||
http.DefaultServeMux.Handle("/debug/fgprof", fgprof.Handler())
|
mux.HandleFunc("/debug/pprof/", pprof.Index)
|
||||||
|
mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
|
||||||
|
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
|
||||||
|
mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
|
||||||
|
mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
|
||||||
|
mux.Handle("/debug/fgprof", fgprof.Handler())
|
||||||
|
// FIXME: it should use a proper context
|
||||||
_, _, finished := process.GetManager().AddTypedContext(context.TODO(), "Web: PProf Server", process.SystemProcessType, true)
|
_, _, finished := process.GetManager().AddTypedContext(context.TODO(), "Web: PProf Server", process.SystemProcessType, true)
|
||||||
// The pprof server is for debug purpose only, it shouldn't be exposed on public network. At the moment, it's not worth introducing a configurable option for it.
|
// The pprof server is for debug purpose only, it shouldn't be exposed on public network. At the moment, it's not worth introducing a configurable option for it.
|
||||||
log.Info("Starting pprof server on localhost:6060")
|
log.Info("Starting pprof server on localhost:6060")
|
||||||
log.Info("Stopped pprof server: %v", http.ListenAndServe("localhost:6060", nil))
|
log.Info("Stopped pprof server: %v", http.ListenAndServe("localhost:6060", mux))
|
||||||
finished()
|
finished()
|
||||||
}
|
}
|
||||||
|
|
||||||
func runWeb(ctx context.Context, cmd *cli.Command) error {
|
func runWeb(ctx context.Context, cmd *cli.Command) error {
|
||||||
defer func() {
|
|
||||||
if panicked := recover(); panicked != nil {
|
|
||||||
log.Fatal("PANIC: %v\n%s", panicked, log.Stack(2))
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if subCmdName, valid := isValidDefaultSubCommand(cmd); !valid {
|
if subCmdName, valid := isValidDefaultSubCommand(cmd); !valid {
|
||||||
return fmt.Errorf("unknown command: %s", subCmdName)
|
return fmt.Errorf("unknown command: %s", subCmdName)
|
||||||
}
|
}
|
||||||
@@ -271,6 +268,10 @@ func runWeb(ctx context.Context, cmd *cli.Command) error {
|
|||||||
createPIDFile(cmd.String("pid"))
|
createPIDFile(cmd.String("pid"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// init the HTML renderer and load templates, if error happens, it will report the error immediately and exit with error log
|
||||||
|
// in dev mode, it won't exit, but watch the template files for changes
|
||||||
|
_ = templates.PageRenderer()
|
||||||
|
|
||||||
if !setting.InstallLock {
|
if !setting.InstallLock {
|
||||||
if err := serveInstall(cmd); err != nil {
|
if err := serveInstall(cmd); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -124,8 +125,8 @@ func runACME(listenAddr string, m http.Handler) error {
|
|||||||
defer finished()
|
defer finished()
|
||||||
|
|
||||||
log.Info("Running Let's Encrypt handler on %s", setting.HTTPAddr+":"+setting.PortToRedirect)
|
log.Info("Running Let's Encrypt handler on %s", setting.HTTPAddr+":"+setting.PortToRedirect)
|
||||||
// all traffic coming into HTTP will be redirect to HTTPS automatically (LE HTTP-01 validation happens here)
|
// all traffic coming into HTTP will be redirected to HTTPS automatically (LE HTTP-01 validation happens here)
|
||||||
err := runHTTP("tcp", setting.HTTPAddr+":"+setting.PortToRedirect, "Let's Encrypt HTTP Challenge", myACME.HTTPChallengeHandler(http.HandlerFunc(runLetsEncryptFallbackHandler)), setting.RedirectorUseProxyProtocol)
|
err := runHTTP("tcp", net.JoinHostPort(setting.HTTPAddr, setting.PortToRedirect), "Let's Encrypt HTTP Challenge", myACME.HTTPChallengeHandler(http.HandlerFunc(runLetsEncryptFallbackHandler)), setting.RedirectorUseProxyProtocol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Failed to start the Let's Encrypt handler on port %s: %v", setting.PortToRedirect, err)
|
log.Fatal("Failed to start the Let's Encrypt handler on port %s: %v", setting.PortToRedirect, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/go-github/v74/github"
|
"github.com/google/go-github/v84/github"
|
||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
Environment To Ini
|
|
||||||
==================
|
|
||||||
|
|
||||||
Multiple docker users have requested that the Gitea docker is changed
|
|
||||||
to permit arbitrary configuration via environment variables.
|
|
||||||
|
|
||||||
Gitea needs to use an ini file for configuration because the running
|
|
||||||
environment that starts the docker may not be the same as that used
|
|
||||||
by the hooks. An ini file also gives a good default and means that
|
|
||||||
users do not have to completely provide a full environment.
|
|
||||||
|
|
||||||
With those caveats above, this command provides a generic way of
|
|
||||||
converting suitably structured environment variables into any ini
|
|
||||||
value.
|
|
||||||
|
|
||||||
To use the command is very simple just run it and the default gitea
|
|
||||||
app.ini will be rewritten to take account of the variables provided,
|
|
||||||
however there are various options to give slightly different
|
|
||||||
behavior and these can be interrogated with the `-h` option.
|
|
||||||
|
|
||||||
The environment variables should be of the form:
|
|
||||||
|
|
||||||
GITEA__SECTION_NAME__KEY_NAME
|
|
||||||
|
|
||||||
Note, SECTION_NAME in the notation above is case-insensitive.
|
|
||||||
|
|
||||||
Environment variables are usually restricted to a reduced character
|
|
||||||
set "0-9A-Z_" - in order to allow the setting of sections with
|
|
||||||
characters outside of that set, they should be escaped as following:
|
|
||||||
"_0X2E_" for "." and "_0X2D_" for "-". The entire section and key names
|
|
||||||
can be escaped as a UTF8 byte string if necessary. E.g. to configure:
|
|
||||||
|
|
||||||
"""
|
|
||||||
...
|
|
||||||
[log.console]
|
|
||||||
COLORIZE=false
|
|
||||||
STDERR=true
|
|
||||||
...
|
|
||||||
"""
|
|
||||||
|
|
||||||
You would set the environment variables: "GITEA__LOG_0x2E_CONSOLE__COLORIZE=false"
|
|
||||||
and "GITEA__LOG_0x2E_CONSOLE__STDERR=false". Other examples can be found
|
|
||||||
on the configuration cheat sheet.
|
|
||||||
|
|
||||||
To build locally, run:
|
|
||||||
|
|
||||||
go build contrib/environment-to-ini/environment-to-ini.go
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
|
|
||||||
"github.com/urfave/cli/v3"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
app := cli.Command{}
|
|
||||||
app.Name = "environment-to-ini"
|
|
||||||
app.Usage = "Use provided environment to update configuration ini"
|
|
||||||
app.Description = `As a helper to allow docker users to update the gitea configuration
|
|
||||||
through the environment, this command allows environment variables to
|
|
||||||
be mapped to values in the ini.
|
|
||||||
|
|
||||||
Environment variables of the form "GITEA__SECTION_NAME__KEY_NAME"
|
|
||||||
will be mapped to the ini section "[section_name]" and the key
|
|
||||||
"KEY_NAME" with the value as provided.
|
|
||||||
|
|
||||||
Environment variables of the form "GITEA__SECTION_NAME__KEY_NAME__FILE"
|
|
||||||
will be mapped to the ini section "[section_name]" and the key
|
|
||||||
"KEY_NAME" with the value loaded from the specified file.
|
|
||||||
|
|
||||||
Environment variables are usually restricted to a reduced character
|
|
||||||
set "0-9A-Z_" - in order to allow the setting of sections with
|
|
||||||
characters outside of that set, they should be escaped as following:
|
|
||||||
"_0X2E_" for ".". The entire section and key names can be escaped as
|
|
||||||
a UTF8 byte string if necessary. E.g. to configure:
|
|
||||||
|
|
||||||
"""
|
|
||||||
...
|
|
||||||
[log.console]
|
|
||||||
COLORIZE=false
|
|
||||||
STDERR=true
|
|
||||||
...
|
|
||||||
"""
|
|
||||||
|
|
||||||
You would set the environment variables: "GITEA__LOG_0x2E_CONSOLE__COLORIZE=false"
|
|
||||||
and "GITEA__LOG_0x2E_CONSOLE__STDERR=false". Other examples can be found
|
|
||||||
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",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "config",
|
|
||||||
Aliases: []string{"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",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "out",
|
|
||||||
Aliases: []string{"o"},
|
|
||||||
Value: "",
|
|
||||||
Usage: "Destination file to write to",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
app.Action = runEnvironmentToIni
|
|
||||||
err := app.Run(context.Background(), os.Args)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Failed to run app with %s: %v", os.Args, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func runEnvironmentToIni(_ context.Context, c *cli.Command) error {
|
|
||||||
// the config system may change the environment variables, so get a copy first, to be used later
|
|
||||||
env := append([]string{}, os.Environ()...)
|
|
||||||
setting.InitWorkPathAndCfgProvider(os.Getenv, setting.ArgWorkPathAndCustomConf{
|
|
||||||
WorkPath: c.String("work-path"),
|
|
||||||
CustomPath: c.String("custom-path"),
|
|
||||||
CustomConf: c.String("config"),
|
|
||||||
})
|
|
||||||
|
|
||||||
cfg, err := setting.NewConfigProviderFromFile(setting.CustomConf)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Failed to load custom conf '%s': %v", setting.CustomConf, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
changed := setting.EnvironmentToConfig(cfg, env)
|
|
||||||
|
|
||||||
// try to save the config file
|
|
||||||
destination := c.String("out")
|
|
||||||
if len(destination) == 0 {
|
|
||||||
destination = setting.CustomConf
|
|
||||||
}
|
|
||||||
if destination != setting.CustomConf || changed {
|
|
||||||
log.Info("Settings saved to: %q", destination)
|
|
||||||
err = cfg.SaveTo(destination)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -108,7 +108,9 @@ curl --connect-timeout 10 --silent --show-error --fail --location -O "$binurl{,.
|
|||||||
sha256sum -c "${binname}.xz.sha256"
|
sha256sum -c "${binname}.xz.sha256"
|
||||||
if [[ -z "${ignore_gpg:-}" ]]; then
|
if [[ -z "${ignore_gpg:-}" ]]; then
|
||||||
require gpg
|
require gpg
|
||||||
gpg --keyserver keys.openpgp.org --recv 7C9E68152594688862D62AF62D9AE806EC1592E2
|
# try to use curl first, it uses standard tcp 443 port and works better behind strict firewall rules
|
||||||
|
curl -fsSL --connect-timeout 10 "https://keys.openpgp.org/vks/v1/by-fingerprint/7C9E68152594688862D62AF62D9AE806EC1592E2" | gpg --import \
|
||||||
|
|| gpg --keyserver keys.openpgp.org --recv 7C9E68152594688862D62AF62D9AE806EC1592E2
|
||||||
gpg --verify "${binname}.xz.asc" "${binname}.xz" || { echo 'Signature does not match'; exit 1; }
|
gpg --verify "${binname}.xz.asc" "${binname}.xz" || { echo 'Signature does not match'; exit 1; }
|
||||||
fi
|
fi
|
||||||
rm "${binname}".xz.{sha256,asc}
|
rm "${binname}".xz.{sha256,asc}
|
||||||
@@ -127,6 +129,8 @@ echo "Creating backup in $giteahome"
|
|||||||
giteacmd dump $backupopts
|
giteacmd dump $backupopts
|
||||||
echo "Updating binary at $giteabin"
|
echo "Updating binary at $giteabin"
|
||||||
cp -f "$giteabin" "$giteabin.bak" && mv -f "$binname" "$giteabin"
|
cp -f "$giteabin" "$giteabin.bak" && mv -f "$binname" "$giteabin"
|
||||||
|
# Restore SELinux context if applicable (e.g. RHEL/Fedora)
|
||||||
|
command -v restorecon &>/dev/null && restorecon -v "$giteabin" || true
|
||||||
$service_start
|
$service_start
|
||||||
$service_status
|
$service_status
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ base_path: "."
|
|||||||
base_url: "https://api.crowdin.com"
|
base_url: "https://api.crowdin.com"
|
||||||
preserve_hierarchy: true
|
preserve_hierarchy: true
|
||||||
files:
|
files:
|
||||||
- source: "/options/locale/locale_en-US.ini"
|
- source: "/options/locale/locale_en-US.json"
|
||||||
translation: "/options/locale/locale_%locale%.ini"
|
translation: "/options/locale/locale_%locale%.json"
|
||||||
type: "ini"
|
type: "json"
|
||||||
skip_untranslated_strings: true
|
skip_untranslated_strings: true
|
||||||
export_only_approved: true
|
export_only_approved: true
|
||||||
update_option: "update_as_unapproved"
|
update_option: "update_as_unapproved"
|
||||||
|
|||||||
@@ -1,2 +1,8 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# $1 = exit code of the run script, $2 = signal
|
||||||
|
if [ "$1" -ne 0 ]; then
|
||||||
|
# avoid immediately restarting the sshd service, which may cause CPU 100% if the error (permission, configuration) is not fixed
|
||||||
|
echo "openssh failed with exit code $1 - waiting a short delay before attempting a restart"
|
||||||
|
sleep 3
|
||||||
|
fi
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
exec /app/gitea/gitea config edit-ini --in-place --apply-env "$@"
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
exec /app/gitea/gitea config edit-ini --in-place --apply-env "$@"
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import arrayFunc from 'eslint-plugin-array-func';
|
import arrayFunc from 'eslint-plugin-array-func';
|
||||||
import comments from '@eslint-community/eslint-plugin-eslint-comments';
|
import comments from '@eslint-community/eslint-plugin-eslint-comments';
|
||||||
|
import deMorgan from 'eslint-plugin-de-morgan';
|
||||||
import github from 'eslint-plugin-github';
|
import github from 'eslint-plugin-github';
|
||||||
import globals from 'globals';
|
import globals from 'globals';
|
||||||
import importPlugin from 'eslint-plugin-import-x';
|
import importPlugin from 'eslint-plugin-import-x';
|
||||||
import noUseExtendNative from 'eslint-plugin-no-use-extend-native';
|
|
||||||
import playwright from 'eslint-plugin-playwright';
|
import playwright from 'eslint-plugin-playwright';
|
||||||
import regexp from 'eslint-plugin-regexp';
|
import regexp from 'eslint-plugin-regexp';
|
||||||
import sonarjs from 'eslint-plugin-sonarjs';
|
import sonarjs from 'eslint-plugin-sonarjs';
|
||||||
@@ -16,10 +16,22 @@ import vue from 'eslint-plugin-vue';
|
|||||||
import vueScopedCss from 'eslint-plugin-vue-scoped-css';
|
import vueScopedCss from 'eslint-plugin-vue-scoped-css';
|
||||||
import wc from 'eslint-plugin-wc';
|
import wc from 'eslint-plugin-wc';
|
||||||
import {defineConfig, globalIgnores} from 'eslint/config';
|
import {defineConfig, globalIgnores} from 'eslint/config';
|
||||||
|
import type {ESLint} from 'eslint';
|
||||||
|
|
||||||
const jsExts = ['js', 'mjs', 'cjs'] as const;
|
const jsExts = ['js', 'mjs', 'cjs'] as const;
|
||||||
const tsExts = ['ts', 'mts', 'cts'] as const;
|
const tsExts = ['ts', 'mts', 'cts'] as const;
|
||||||
const restrictedSyntax = ['WithStatement', 'ForInStatement', 'LabeledStatement', 'SequenceExpression'];
|
|
||||||
|
const restrictedGlobals = [
|
||||||
|
{name: 'localStorage', message: 'Use `modules/user-settings.ts` instead.'},
|
||||||
|
{name: 'fetch', message: 'Use `modules/fetch.ts` instead.'},
|
||||||
|
];
|
||||||
|
|
||||||
|
const restrictedProperties = [
|
||||||
|
{object: 'window', property: 'localStorage', message: 'Use `modules/user-settings.ts` instead.'},
|
||||||
|
{object: 'globalThis', property: 'localStorage', message: 'Use `modules/user-settings.ts` instead.'},
|
||||||
|
{object: 'window', property: 'fetch', message: 'Use `modules/fetch.ts` instead.'},
|
||||||
|
{object: 'globalThis', property: 'fetch', message: 'Use `modules/fetch.ts` instead.'},
|
||||||
|
];
|
||||||
|
|
||||||
export default defineConfig([
|
export default defineConfig([
|
||||||
globalIgnores([
|
globalIgnores([
|
||||||
@@ -33,10 +45,6 @@ export default defineConfig([
|
|||||||
languageOptions: {
|
languageOptions: {
|
||||||
ecmaVersion: 'latest',
|
ecmaVersion: 'latest',
|
||||||
sourceType: 'module',
|
sourceType: 'module',
|
||||||
globals: {
|
|
||||||
...globals.browser,
|
|
||||||
...globals.node,
|
|
||||||
},
|
|
||||||
parser: typescriptParser,
|
parser: typescriptParser,
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
sourceType: 'module',
|
sourceType: 'module',
|
||||||
@@ -49,24 +57,19 @@ export default defineConfig([
|
|||||||
},
|
},
|
||||||
linterOptions: {
|
linterOptions: {
|
||||||
reportUnusedDisableDirectives: 2,
|
reportUnusedDisableDirectives: 2,
|
||||||
|
reportUnusedInlineConfigs: 2,
|
||||||
},
|
},
|
||||||
plugins: {
|
plugins: {
|
||||||
'@eslint-community/eslint-comments': comments,
|
'@eslint-community/eslint-comments': comments,
|
||||||
// @ts-expect-error
|
|
||||||
'@stylistic': stylistic,
|
'@stylistic': stylistic,
|
||||||
'@typescript-eslint': typescriptPlugin.plugin,
|
'@typescript-eslint': typescriptPlugin.plugin,
|
||||||
'array-func': arrayFunc,
|
'array-func': arrayFunc,
|
||||||
// @ts-expect-error -- https://github.com/un-ts/eslint-plugin-import-x/issues/203
|
'de-morgan': deMorgan,
|
||||||
'import-x': importPlugin,
|
'import-x': importPlugin as unknown as ESLint.Plugin, // https://github.com/un-ts/eslint-plugin-import-x/issues/203
|
||||||
'no-use-extend-native': noUseExtendNative,
|
|
||||||
// @ts-expect-error
|
|
||||||
regexp,
|
regexp,
|
||||||
// @ts-expect-error
|
|
||||||
sonarjs,
|
sonarjs,
|
||||||
// @ts-expect-error
|
|
||||||
unicorn,
|
unicorn,
|
||||||
github,
|
github,
|
||||||
// @ts-expect-error
|
|
||||||
wc,
|
wc,
|
||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
@@ -75,7 +78,7 @@ export default defineConfig([
|
|||||||
'import-x/resolver': {'typescript': true},
|
'import-x/resolver': {'typescript': true},
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
'@eslint-community/eslint-comments/disable-enable-pair': [2],
|
'@eslint-community/eslint-comments/disable-enable-pair': [0],
|
||||||
'@eslint-community/eslint-comments/no-aggregating-enable': [2],
|
'@eslint-community/eslint-comments/no-aggregating-enable': [2],
|
||||||
'@eslint-community/eslint-comments/no-duplicate-disable': [2],
|
'@eslint-community/eslint-comments/no-duplicate-disable': [2],
|
||||||
'@eslint-community/eslint-comments/no-restricted-disable': [0],
|
'@eslint-community/eslint-comments/no-restricted-disable': [0],
|
||||||
@@ -155,11 +158,11 @@ export default defineConfig([
|
|||||||
'@typescript-eslint/adjacent-overload-signatures': [0],
|
'@typescript-eslint/adjacent-overload-signatures': [0],
|
||||||
'@typescript-eslint/array-type': [0],
|
'@typescript-eslint/array-type': [0],
|
||||||
'@typescript-eslint/await-thenable': [2],
|
'@typescript-eslint/await-thenable': [2],
|
||||||
'@typescript-eslint/ban-ts-comment': [2, {'ts-expect-error': false, 'ts-ignore': true, 'ts-nocheck': false, 'ts-check': false}],
|
'@typescript-eslint/ban-ts-comment': [2, {'ts-expect-error': true, 'ts-ignore': true, 'ts-nocheck': false, 'ts-check': false}],
|
||||||
'@typescript-eslint/ban-tslint-comment': [0],
|
'@typescript-eslint/ban-tslint-comment': [0],
|
||||||
'@typescript-eslint/class-literal-property-style': [0],
|
'@typescript-eslint/class-literal-property-style': [0],
|
||||||
'@typescript-eslint/class-methods-use-this': [0],
|
'@typescript-eslint/class-methods-use-this': [0],
|
||||||
'@typescript-eslint/consistent-generic-constructors': [0],
|
'@typescript-eslint/consistent-generic-constructors': [2, 'constructor'],
|
||||||
'@typescript-eslint/consistent-indexed-object-style': [0],
|
'@typescript-eslint/consistent-indexed-object-style': [0],
|
||||||
'@typescript-eslint/consistent-return': [0],
|
'@typescript-eslint/consistent-return': [0],
|
||||||
'@typescript-eslint/consistent-type-assertions': [2, {assertionStyle: 'as', objectLiteralTypeAssertions: 'allow'}],
|
'@typescript-eslint/consistent-type-assertions': [2, {assertionStyle: 'as', objectLiteralTypeAssertions: 'allow'}],
|
||||||
@@ -178,7 +181,7 @@ export default defineConfig([
|
|||||||
'@typescript-eslint/naming-convention': [0],
|
'@typescript-eslint/naming-convention': [0],
|
||||||
'@typescript-eslint/no-array-constructor': [2],
|
'@typescript-eslint/no-array-constructor': [2],
|
||||||
'@typescript-eslint/no-array-delete': [2],
|
'@typescript-eslint/no-array-delete': [2],
|
||||||
'@typescript-eslint/no-base-to-string': [0],
|
'@typescript-eslint/no-base-to-string': [2],
|
||||||
'@typescript-eslint/no-confusing-non-null-assertion': [2],
|
'@typescript-eslint/no-confusing-non-null-assertion': [2],
|
||||||
'@typescript-eslint/no-confusing-void-expression': [0],
|
'@typescript-eslint/no-confusing-void-expression': [0],
|
||||||
'@typescript-eslint/no-deprecated': [2],
|
'@typescript-eslint/no-deprecated': [2],
|
||||||
@@ -210,7 +213,7 @@ export default defineConfig([
|
|||||||
'@typescript-eslint/no-non-null-asserted-nullish-coalescing': [0],
|
'@typescript-eslint/no-non-null-asserted-nullish-coalescing': [0],
|
||||||
'@typescript-eslint/no-non-null-asserted-optional-chain': [2],
|
'@typescript-eslint/no-non-null-asserted-optional-chain': [2],
|
||||||
'@typescript-eslint/no-non-null-assertion': [0],
|
'@typescript-eslint/no-non-null-assertion': [0],
|
||||||
'@typescript-eslint/no-redeclare': [0],
|
'@typescript-eslint/no-redeclare': [2],
|
||||||
'@typescript-eslint/no-redundant-type-constituents': [2],
|
'@typescript-eslint/no-redundant-type-constituents': [2],
|
||||||
'@typescript-eslint/no-require-imports': [2],
|
'@typescript-eslint/no-require-imports': [2],
|
||||||
'@typescript-eslint/no-restricted-imports': [0],
|
'@typescript-eslint/no-restricted-imports': [0],
|
||||||
@@ -221,7 +224,7 @@ export default defineConfig([
|
|||||||
'@typescript-eslint/no-unnecessary-condition': [0],
|
'@typescript-eslint/no-unnecessary-condition': [0],
|
||||||
'@typescript-eslint/no-unnecessary-qualifier': [0],
|
'@typescript-eslint/no-unnecessary-qualifier': [0],
|
||||||
'@typescript-eslint/no-unnecessary-template-expression': [0],
|
'@typescript-eslint/no-unnecessary-template-expression': [0],
|
||||||
'@typescript-eslint/no-unnecessary-type-arguments': [0],
|
'@typescript-eslint/no-unnecessary-type-arguments': [2],
|
||||||
'@typescript-eslint/no-unnecessary-type-assertion': [2],
|
'@typescript-eslint/no-unnecessary-type-assertion': [2],
|
||||||
'@typescript-eslint/no-unnecessary-type-constraint': [2],
|
'@typescript-eslint/no-unnecessary-type-constraint': [2],
|
||||||
'@typescript-eslint/no-unnecessary-type-conversion': [2],
|
'@typescript-eslint/no-unnecessary-type-conversion': [2],
|
||||||
@@ -234,10 +237,12 @@ export default defineConfig([
|
|||||||
'@typescript-eslint/no-unsafe-member-access': [0],
|
'@typescript-eslint/no-unsafe-member-access': [0],
|
||||||
'@typescript-eslint/no-unsafe-return': [0],
|
'@typescript-eslint/no-unsafe-return': [0],
|
||||||
'@typescript-eslint/no-unsafe-unary-minus': [2],
|
'@typescript-eslint/no-unsafe-unary-minus': [2],
|
||||||
'@typescript-eslint/no-unused-expressions': [0],
|
'@typescript-eslint/no-unused-expressions': [2],
|
||||||
|
'@typescript-eslint/no-unused-private-class-members': [2],
|
||||||
'@typescript-eslint/no-unused-vars': [2, {vars: 'all', args: 'all', caughtErrors: 'all', ignoreRestSiblings: false, argsIgnorePattern: '^_', varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_', destructuredArrayIgnorePattern: '^_'}],
|
'@typescript-eslint/no-unused-vars': [2, {vars: 'all', args: 'all', caughtErrors: 'all', ignoreRestSiblings: false, argsIgnorePattern: '^_', varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_', destructuredArrayIgnorePattern: '^_'}],
|
||||||
'@typescript-eslint/no-use-before-define': [2, {functions: false, classes: true, variables: true, allowNamedExports: true, typedefs: false, enums: false, ignoreTypeReferences: true}],
|
'@typescript-eslint/no-use-before-define': [2, {functions: false, classes: true, variables: true, allowNamedExports: true, typedefs: false, enums: false, ignoreTypeReferences: true}],
|
||||||
'@typescript-eslint/no-useless-constructor': [0],
|
'@typescript-eslint/no-useless-constructor': [0],
|
||||||
|
'@typescript-eslint/no-useless-default-assignment': [2],
|
||||||
'@typescript-eslint/no-useless-empty-export': [0],
|
'@typescript-eslint/no-useless-empty-export': [0],
|
||||||
'@typescript-eslint/no-wrapper-object-types': [2],
|
'@typescript-eslint/no-wrapper-object-types': [2],
|
||||||
'@typescript-eslint/non-nullable-type-assertion-style': [0],
|
'@typescript-eslint/non-nullable-type-assertion-style': [0],
|
||||||
@@ -251,10 +256,10 @@ export default defineConfig([
|
|||||||
'@typescript-eslint/prefer-function-type': [2],
|
'@typescript-eslint/prefer-function-type': [2],
|
||||||
'@typescript-eslint/prefer-includes': [2],
|
'@typescript-eslint/prefer-includes': [2],
|
||||||
'@typescript-eslint/prefer-literal-enum-member': [0],
|
'@typescript-eslint/prefer-literal-enum-member': [0],
|
||||||
'@typescript-eslint/prefer-namespace-keyword': [0],
|
'@typescript-eslint/prefer-namespace-keyword': [2],
|
||||||
'@typescript-eslint/prefer-nullish-coalescing': [0],
|
'@typescript-eslint/prefer-nullish-coalescing': [0],
|
||||||
'@typescript-eslint/prefer-optional-chain': [2, {requireNullish: true}],
|
'@typescript-eslint/prefer-optional-chain': [2, {requireNullish: true}],
|
||||||
'@typescript-eslint/prefer-promise-reject-errors': [0],
|
'@typescript-eslint/prefer-promise-reject-errors': [2],
|
||||||
'@typescript-eslint/prefer-readonly': [0],
|
'@typescript-eslint/prefer-readonly': [0],
|
||||||
'@typescript-eslint/prefer-readonly-parameter-types': [0],
|
'@typescript-eslint/prefer-readonly-parameter-types': [0],
|
||||||
'@typescript-eslint/prefer-reduce-type-parameter': [0],
|
'@typescript-eslint/prefer-reduce-type-parameter': [0],
|
||||||
@@ -265,9 +270,10 @@ export default defineConfig([
|
|||||||
'@typescript-eslint/require-array-sort-compare': [0],
|
'@typescript-eslint/require-array-sort-compare': [0],
|
||||||
'@typescript-eslint/require-await': [0],
|
'@typescript-eslint/require-await': [0],
|
||||||
'@typescript-eslint/restrict-plus-operands': [2],
|
'@typescript-eslint/restrict-plus-operands': [2],
|
||||||
'@typescript-eslint/restrict-template-expressions': [0],
|
'@typescript-eslint/restrict-template-expressions': [2],
|
||||||
'@typescript-eslint/return-await': [0],
|
'@typescript-eslint/return-await': [0],
|
||||||
'@typescript-eslint/strict-boolean-expressions': [0],
|
'@typescript-eslint/strict-boolean-expressions': [0],
|
||||||
|
'@typescript-eslint/strict-void-return': [0],
|
||||||
'@typescript-eslint/switch-exhaustiveness-check': [0],
|
'@typescript-eslint/switch-exhaustiveness-check': [0],
|
||||||
'@typescript-eslint/triple-slash-reference': [2],
|
'@typescript-eslint/triple-slash-reference': [2],
|
||||||
'@typescript-eslint/typedef': [0],
|
'@typescript-eslint/typedef': [0],
|
||||||
@@ -291,6 +297,8 @@ export default defineConfig([
|
|||||||
'consistent-this': [0],
|
'consistent-this': [0],
|
||||||
'constructor-super': [2],
|
'constructor-super': [2],
|
||||||
'curly': [0],
|
'curly': [0],
|
||||||
|
'de-morgan/no-negated-conjunction': [2],
|
||||||
|
'de-morgan/no-negated-disjunction': [2],
|
||||||
'default-case-last': [2],
|
'default-case-last': [2],
|
||||||
'default-case': [0],
|
'default-case': [0],
|
||||||
'default-param-last': [0],
|
'default-param-last': [0],
|
||||||
@@ -321,7 +329,7 @@ export default defineConfig([
|
|||||||
'github/no-innerText': [2],
|
'github/no-innerText': [2],
|
||||||
'github/no-then': [2],
|
'github/no-then': [2],
|
||||||
'github/no-useless-passive': [2],
|
'github/no-useless-passive': [2],
|
||||||
'github/prefer-observers': [2],
|
'github/prefer-observers': [0],
|
||||||
'github/require-passive-events': [2],
|
'github/require-passive-events': [2],
|
||||||
'github/unescaped-html-literal': [2],
|
'github/unescaped-html-literal': [2],
|
||||||
'grouped-accessor-pairs': [2],
|
'grouped-accessor-pairs': [2],
|
||||||
@@ -338,7 +346,7 @@ export default defineConfig([
|
|||||||
'import-x/first': [2],
|
'import-x/first': [2],
|
||||||
'import-x/group-exports': [0],
|
'import-x/group-exports': [0],
|
||||||
'import-x/max-dependencies': [0],
|
'import-x/max-dependencies': [0],
|
||||||
'import-x/named': [2],
|
'import-x/named': [0],
|
||||||
'import-x/namespace': [0],
|
'import-x/namespace': [0],
|
||||||
'import-x/newline-after-import': [0],
|
'import-x/newline-after-import': [0],
|
||||||
'import-x/no-absolute-path': [0],
|
'import-x/no-absolute-path': [0],
|
||||||
@@ -366,7 +374,7 @@ export default defineConfig([
|
|||||||
'import-x/no-self-import': [2],
|
'import-x/no-self-import': [2],
|
||||||
'import-x/no-unassigned-import': [0],
|
'import-x/no-unassigned-import': [0],
|
||||||
'import-x/no-unresolved': [2, {commonjs: true, ignore: ['\\?.+$']}],
|
'import-x/no-unresolved': [2, {commonjs: true, ignore: ['\\?.+$']}],
|
||||||
// 'import-x/no-unused-modules': [2, {unusedExports: true}], // not compatible with eslint 9
|
'import-x/no-unused-modules': [0], // incompatible with eslint 9
|
||||||
'import-x/no-useless-path-segments': [2, {commonjs: true}],
|
'import-x/no-useless-path-segments': [2, {commonjs: true}],
|
||||||
'import-x/no-webpack-loader-syntax': [2],
|
'import-x/no-webpack-loader-syntax': [2],
|
||||||
'import-x/order': [0],
|
'import-x/order': [0],
|
||||||
@@ -433,7 +441,7 @@ export default defineConfig([
|
|||||||
'no-import-assign': [2],
|
'no-import-assign': [2],
|
||||||
'no-inline-comments': [0],
|
'no-inline-comments': [0],
|
||||||
'no-inner-declarations': [2],
|
'no-inner-declarations': [2],
|
||||||
'no-invalid-regexp': [2],
|
'no-invalid-regexp': [0], // handled by regexp/no-invalid-regexp
|
||||||
'no-invalid-this': [0],
|
'no-invalid-this': [0],
|
||||||
'no-irregular-whitespace': [2],
|
'no-irregular-whitespace': [2],
|
||||||
'no-iterator': [2],
|
'no-iterator': [2],
|
||||||
@@ -547,7 +555,7 @@ export default defineConfig([
|
|||||||
'no-new-func': [0], // handled by @typescript-eslint/no-implied-eval
|
'no-new-func': [0], // handled by @typescript-eslint/no-implied-eval
|
||||||
'no-new-native-nonconstructor': [2],
|
'no-new-native-nonconstructor': [2],
|
||||||
'no-new-object': [2],
|
'no-new-object': [2],
|
||||||
'no-new-symbol': [2],
|
'no-new-symbol': [0], // handled by no-new-native-nonconstructor
|
||||||
'no-new-wrappers': [2],
|
'no-new-wrappers': [2],
|
||||||
'no-new': [0],
|
'no-new': [0],
|
||||||
'no-nonoctal-decimal-escape': [2],
|
'no-nonoctal-decimal-escape': [2],
|
||||||
@@ -562,9 +570,14 @@ export default defineConfig([
|
|||||||
'no-redeclare': [0], // must be disabled for typescript overloads
|
'no-redeclare': [0], // must be disabled for typescript overloads
|
||||||
'no-regex-spaces': [2],
|
'no-regex-spaces': [2],
|
||||||
'no-restricted-exports': [0],
|
'no-restricted-exports': [0],
|
||||||
'no-restricted-globals': [2, 'addEventListener', 'blur', 'close', 'closed', 'confirm', 'defaultStatus', 'defaultstatus', 'error', 'event', 'external', 'find', 'focus', 'frameElement', 'frames', 'history', 'innerHeight', 'innerWidth', 'isFinite', 'isNaN', 'length', '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'],
|
'no-restricted-globals': [2, ...restrictedGlobals],
|
||||||
'no-restricted-imports': [0],
|
'no-restricted-properties': [2, ...restrictedProperties],
|
||||||
'no-restricted-syntax': [2, ...restrictedSyntax, {selector: 'CallExpression[callee.name="fetch"]', message: 'use modules/fetch.ts instead'}],
|
'no-restricted-imports': [2, {paths: [
|
||||||
|
{name: 'jquery', message: 'Use the global $ instead', allowTypeImports: true},
|
||||||
|
{name: 'htmx.org', message: 'Use the global htmx instead', allowTypeImports: true},
|
||||||
|
{name: 'idiomorph/htmx', message: 'Loaded in globals.ts', allowTypeImports: true},
|
||||||
|
]}],
|
||||||
|
'no-restricted-syntax': [2, 'WithStatement', 'ForInStatement', 'LabeledStatement', 'SequenceExpression'],
|
||||||
'no-return-assign': [0],
|
'no-return-assign': [0],
|
||||||
'no-script-url': [2],
|
'no-script-url': [2],
|
||||||
'no-self-assign': [2, {props: true}],
|
'no-self-assign': [2, {props: true}],
|
||||||
@@ -577,10 +590,11 @@ export default defineConfig([
|
|||||||
'no-template-curly-in-string': [2],
|
'no-template-curly-in-string': [2],
|
||||||
'no-ternary': [0],
|
'no-ternary': [0],
|
||||||
'no-this-before-super': [2],
|
'no-this-before-super': [2],
|
||||||
'no-throw-literal': [2],
|
'no-throw-literal': [0], // handled by @typescript-eslint/only-throw-error
|
||||||
'no-undef-init': [2],
|
'no-undef-init': [2],
|
||||||
'no-undef': [2], // it is still needed by eslint & IDE to prompt undefined names in real time
|
'no-undef': [2], // it is still needed by eslint & IDE to prompt undefined names in real time
|
||||||
'no-undefined': [0],
|
'no-undefined': [0],
|
||||||
|
'no-unassigned-vars': [2],
|
||||||
'no-underscore-dangle': [0],
|
'no-underscore-dangle': [0],
|
||||||
'no-unexpected-multiline': [2],
|
'no-unexpected-multiline': [2],
|
||||||
'no-unmodified-loop-condition': [2],
|
'no-unmodified-loop-condition': [2],
|
||||||
@@ -589,13 +603,13 @@ export default defineConfig([
|
|||||||
'no-unreachable': [2],
|
'no-unreachable': [2],
|
||||||
'no-unsafe-finally': [2],
|
'no-unsafe-finally': [2],
|
||||||
'no-unsafe-negation': [2],
|
'no-unsafe-negation': [2],
|
||||||
'no-unused-expressions': [2],
|
'no-unused-expressions': [0], // handled by @typescript-eslint/no-unused-expressions
|
||||||
'no-unused-labels': [2],
|
'no-unused-labels': [2],
|
||||||
'no-unused-private-class-members': [2],
|
'no-unused-private-class-members': [0], // handled by @typescript-eslint/no-unused-private-class-members
|
||||||
'no-unused-vars': [0], // handled by @typescript-eslint/no-unused-vars
|
'no-unused-vars': [0], // handled by @typescript-eslint/no-unused-vars
|
||||||
'no-use-before-define': [0], // handled by @typescript-eslint/no-use-before-define
|
'no-use-before-define': [0], // handled by @typescript-eslint/no-use-before-define
|
||||||
'no-use-extend-native/no-use-extend-native': [2],
|
'no-useless-assignment': [2],
|
||||||
'no-useless-backreference': [2],
|
'no-useless-backreference': [0], // handled by regexp/no-useless-backreference
|
||||||
'no-useless-call': [2],
|
'no-useless-call': [2],
|
||||||
'no-useless-catch': [2],
|
'no-useless-catch': [2],
|
||||||
'no-useless-computed-key': [2],
|
'no-useless-computed-key': [2],
|
||||||
@@ -603,7 +617,7 @@ export default defineConfig([
|
|||||||
'no-useless-constructor': [2],
|
'no-useless-constructor': [2],
|
||||||
'no-useless-escape': [2],
|
'no-useless-escape': [2],
|
||||||
'no-useless-rename': [2],
|
'no-useless-rename': [2],
|
||||||
'no-useless-return': [2],
|
'no-useless-return': [0], // handled by sonarjs/no-redundant-jump
|
||||||
'no-var': [2],
|
'no-var': [2],
|
||||||
'no-void': [2],
|
'no-void': [2],
|
||||||
'no-warning-comments': [0],
|
'no-warning-comments': [0],
|
||||||
@@ -612,7 +626,7 @@ export default defineConfig([
|
|||||||
'one-var-declaration-per-line': [0],
|
'one-var-declaration-per-line': [0],
|
||||||
'one-var': [0],
|
'one-var': [0],
|
||||||
'operator-assignment': [2, 'always'],
|
'operator-assignment': [2, 'always'],
|
||||||
'operator-linebreak': [2, 'after'],
|
'operator-linebreak': [0], // handled by @stylistic/operator-linebreak
|
||||||
'prefer-arrow-callback': [2, {allowNamedFunctions: true, allowUnboundThis: true}],
|
'prefer-arrow-callback': [2, {allowNamedFunctions: true, allowUnboundThis: true}],
|
||||||
'prefer-const': [2, {destructuring: 'all', ignoreReadBeforeAssign: true}],
|
'prefer-const': [2, {destructuring: 'all', ignoreReadBeforeAssign: true}],
|
||||||
'prefer-destructuring': [0],
|
'prefer-destructuring': [0],
|
||||||
@@ -621,19 +635,20 @@ export default defineConfig([
|
|||||||
'prefer-numeric-literals': [2],
|
'prefer-numeric-literals': [2],
|
||||||
'prefer-object-has-own': [2],
|
'prefer-object-has-own': [2],
|
||||||
'prefer-object-spread': [2],
|
'prefer-object-spread': [2],
|
||||||
'prefer-promise-reject-errors': [2, {allowEmptyReject: false}],
|
'prefer-promise-reject-errors': [0], // handled by @typescript-eslint/prefer-promise-reject-errors
|
||||||
'prefer-regex-literals': [2],
|
'prefer-regex-literals': [2],
|
||||||
'prefer-rest-params': [2],
|
'prefer-rest-params': [2],
|
||||||
'prefer-spread': [2],
|
'prefer-spread': [2],
|
||||||
'prefer-template': [2],
|
'prefer-template': [2],
|
||||||
'radix': [2, 'as-needed'],
|
'preserve-caught-error': [0],
|
||||||
|
'radix': [0],
|
||||||
'regexp/confusing-quantifier': [2],
|
'regexp/confusing-quantifier': [2],
|
||||||
'regexp/control-character-escape': [2],
|
'regexp/control-character-escape': [2],
|
||||||
'regexp/hexadecimal-escape': [0],
|
'regexp/hexadecimal-escape': [0],
|
||||||
'regexp/letter-case': [0],
|
'regexp/letter-case': [0],
|
||||||
'regexp/match-any': [2],
|
'regexp/match-any': [2],
|
||||||
'regexp/negation': [2],
|
'regexp/negation': [2],
|
||||||
'regexp/no-contradiction-with-assertion': [0],
|
'regexp/no-contradiction-with-assertion': [2],
|
||||||
'regexp/no-control-character': [0],
|
'regexp/no-control-character': [0],
|
||||||
'regexp/no-dupe-characters-character-class': [2],
|
'regexp/no-dupe-characters-character-class': [2],
|
||||||
'regexp/no-dupe-disjunctions': [2],
|
'regexp/no-dupe-disjunctions': [2],
|
||||||
@@ -649,8 +664,8 @@ export default defineConfig([
|
|||||||
'regexp/no-invisible-character': [2],
|
'regexp/no-invisible-character': [2],
|
||||||
'regexp/no-lazy-ends': [2],
|
'regexp/no-lazy-ends': [2],
|
||||||
'regexp/no-legacy-features': [2],
|
'regexp/no-legacy-features': [2],
|
||||||
'regexp/no-misleading-capturing-group': [0],
|
'regexp/no-misleading-capturing-group': [2],
|
||||||
'regexp/no-misleading-unicode-character': [0],
|
'regexp/no-misleading-unicode-character': [2],
|
||||||
'regexp/no-missing-g-flag': [2],
|
'regexp/no-missing-g-flag': [2],
|
||||||
'regexp/no-non-standard-flag': [2],
|
'regexp/no-non-standard-flag': [2],
|
||||||
'regexp/no-obscure-range': [2],
|
'regexp/no-obscure-range': [2],
|
||||||
@@ -692,7 +707,7 @@ export default defineConfig([
|
|||||||
'regexp/prefer-question-quantifier': [2],
|
'regexp/prefer-question-quantifier': [2],
|
||||||
'regexp/prefer-range': [2],
|
'regexp/prefer-range': [2],
|
||||||
'regexp/prefer-regexp-exec': [2],
|
'regexp/prefer-regexp-exec': [2],
|
||||||
'regexp/prefer-regexp-test': [2],
|
'regexp/prefer-regexp-test': [0], // handled by unicorn/prefer-regexp-test
|
||||||
'regexp/prefer-result-array-groups': [0],
|
'regexp/prefer-result-array-groups': [0],
|
||||||
'regexp/prefer-set-operation': [2],
|
'regexp/prefer-set-operation': [2],
|
||||||
'regexp/prefer-star-quantifier': [2],
|
'regexp/prefer-star-quantifier': [2],
|
||||||
@@ -722,7 +737,7 @@ export default defineConfig([
|
|||||||
'sonarjs/no-empty-collection': [2],
|
'sonarjs/no-empty-collection': [2],
|
||||||
'sonarjs/no-extra-arguments': [2],
|
'sonarjs/no-extra-arguments': [2],
|
||||||
'sonarjs/no-gratuitous-expressions': [2],
|
'sonarjs/no-gratuitous-expressions': [2],
|
||||||
'sonarjs/no-identical-conditions': [2],
|
'sonarjs/no-identical-conditions': [0], // handled by no-dupe-else-if
|
||||||
'sonarjs/no-identical-expressions': [2],
|
'sonarjs/no-identical-expressions': [2],
|
||||||
'sonarjs/no-identical-functions': [2, 5],
|
'sonarjs/no-identical-functions': [2, 5],
|
||||||
'sonarjs/no-ignored-return': [2],
|
'sonarjs/no-ignored-return': [2],
|
||||||
@@ -735,7 +750,7 @@ export default defineConfig([
|
|||||||
'sonarjs/no-small-switch': [0],
|
'sonarjs/no-small-switch': [0],
|
||||||
'sonarjs/no-unused-collection': [2],
|
'sonarjs/no-unused-collection': [2],
|
||||||
'sonarjs/no-use-of-empty-return-value': [2],
|
'sonarjs/no-use-of-empty-return-value': [2],
|
||||||
'sonarjs/no-useless-catch': [2],
|
'sonarjs/no-useless-catch': [0], // handled by no-useless-catch
|
||||||
'sonarjs/non-existent-operator': [2],
|
'sonarjs/non-existent-operator': [2],
|
||||||
'sonarjs/prefer-immediate-return': [0],
|
'sonarjs/prefer-immediate-return': [0],
|
||||||
'sonarjs/prefer-object-literal': [0],
|
'sonarjs/prefer-object-literal': [0],
|
||||||
@@ -751,6 +766,7 @@ export default defineConfig([
|
|||||||
'unicorn/catch-error-name': [0],
|
'unicorn/catch-error-name': [0],
|
||||||
'unicorn/consistent-destructuring': [2],
|
'unicorn/consistent-destructuring': [2],
|
||||||
'unicorn/consistent-empty-array-spread': [2],
|
'unicorn/consistent-empty-array-spread': [2],
|
||||||
|
'unicorn/consistent-template-literal-escape': [2],
|
||||||
'unicorn/consistent-existence-index-check': [0],
|
'unicorn/consistent-existence-index-check': [0],
|
||||||
'unicorn/consistent-function-scoping': [0],
|
'unicorn/consistent-function-scoping': [0],
|
||||||
'unicorn/custom-error-definition': [0],
|
'unicorn/custom-error-definition': [0],
|
||||||
@@ -762,6 +778,7 @@ export default defineConfig([
|
|||||||
'unicorn/filename-case': [0],
|
'unicorn/filename-case': [0],
|
||||||
'unicorn/import-index': [0],
|
'unicorn/import-index': [0],
|
||||||
'unicorn/import-style': [0],
|
'unicorn/import-style': [0],
|
||||||
|
'unicorn/isolated-functions': [2, {functions: []}],
|
||||||
'unicorn/new-for-builtins': [2],
|
'unicorn/new-for-builtins': [2],
|
||||||
'unicorn/no-abusive-eslint-disable': [0],
|
'unicorn/no-abusive-eslint-disable': [0],
|
||||||
'unicorn/no-anonymous-default-export': [0],
|
'unicorn/no-anonymous-default-export': [0],
|
||||||
@@ -777,6 +794,7 @@ export default defineConfig([
|
|||||||
'unicorn/no-empty-file': [2],
|
'unicorn/no-empty-file': [2],
|
||||||
'unicorn/no-for-loop': [0],
|
'unicorn/no-for-loop': [0],
|
||||||
'unicorn/no-hex-escape': [0],
|
'unicorn/no-hex-escape': [0],
|
||||||
|
'unicorn/no-immediate-mutation': [0],
|
||||||
'unicorn/no-instanceof-array': [0],
|
'unicorn/no-instanceof-array': [0],
|
||||||
'unicorn/no-invalid-fetch-options': [2],
|
'unicorn/no-invalid-fetch-options': [2],
|
||||||
'unicorn/no-invalid-remove-event-listener': [2],
|
'unicorn/no-invalid-remove-event-listener': [2],
|
||||||
@@ -800,9 +818,11 @@ export default defineConfig([
|
|||||||
'unicorn/no-unnecessary-await': [2],
|
'unicorn/no-unnecessary-await': [2],
|
||||||
'unicorn/no-unnecessary-polyfills': [2],
|
'unicorn/no-unnecessary-polyfills': [2],
|
||||||
'unicorn/no-unreadable-array-destructuring': [0],
|
'unicorn/no-unreadable-array-destructuring': [0],
|
||||||
'unicorn/no-unreadable-iife': [2],
|
'unicorn/no-unreadable-iife': [0],
|
||||||
'unicorn/no-unused-properties': [2],
|
'unicorn/no-unused-properties': [2],
|
||||||
|
'unicorn/no-useless-collection-argument': [2],
|
||||||
'unicorn/no-useless-fallback-in-spread': [2],
|
'unicorn/no-useless-fallback-in-spread': [2],
|
||||||
|
'unicorn/no-useless-iterator-to-array': [2],
|
||||||
'unicorn/no-useless-length-check': [2],
|
'unicorn/no-useless-length-check': [2],
|
||||||
'unicorn/no-useless-promise-resolve-reject': [2],
|
'unicorn/no-useless-promise-resolve-reject': [2],
|
||||||
'unicorn/no-useless-spread': [2],
|
'unicorn/no-useless-spread': [2],
|
||||||
@@ -812,9 +832,9 @@ export default defineConfig([
|
|||||||
'unicorn/number-literal-case': [0],
|
'unicorn/number-literal-case': [0],
|
||||||
'unicorn/numeric-separators-style': [0],
|
'unicorn/numeric-separators-style': [0],
|
||||||
'unicorn/prefer-add-event-listener': [2],
|
'unicorn/prefer-add-event-listener': [2],
|
||||||
'unicorn/prefer-array-find': [2],
|
'unicorn/prefer-array-find': [0], // handled by @typescript-eslint/prefer-find
|
||||||
'unicorn/prefer-array-flat-map': [2],
|
|
||||||
'unicorn/prefer-array-flat': [2],
|
'unicorn/prefer-array-flat': [2],
|
||||||
|
'unicorn/prefer-array-flat-map': [2],
|
||||||
'unicorn/prefer-array-index-of': [2],
|
'unicorn/prefer-array-index-of': [2],
|
||||||
'unicorn/prefer-array-some': [2],
|
'unicorn/prefer-array-some': [2],
|
||||||
'unicorn/prefer-at': [0],
|
'unicorn/prefer-at': [0],
|
||||||
@@ -829,7 +849,7 @@ export default defineConfig([
|
|||||||
'unicorn/prefer-event-target': [2],
|
'unicorn/prefer-event-target': [2],
|
||||||
'unicorn/prefer-export-from': [0],
|
'unicorn/prefer-export-from': [0],
|
||||||
'unicorn/prefer-global-this': [0],
|
'unicorn/prefer-global-this': [0],
|
||||||
'unicorn/prefer-includes': [2],
|
'unicorn/prefer-includes': [0], // handled by @typescript-eslint/prefer-includes
|
||||||
'unicorn/prefer-json-parse-buffer': [0],
|
'unicorn/prefer-json-parse-buffer': [0],
|
||||||
'unicorn/prefer-keyboard-event-key': [2],
|
'unicorn/prefer-keyboard-event-key': [2],
|
||||||
'unicorn/prefer-logical-operator-over-ternary': [2],
|
'unicorn/prefer-logical-operator-over-ternary': [2],
|
||||||
@@ -849,13 +869,15 @@ export default defineConfig([
|
|||||||
'unicorn/prefer-query-selector': [2],
|
'unicorn/prefer-query-selector': [2],
|
||||||
'unicorn/prefer-reflect-apply': [0],
|
'unicorn/prefer-reflect-apply': [0],
|
||||||
'unicorn/prefer-regexp-test': [2],
|
'unicorn/prefer-regexp-test': [2],
|
||||||
|
'unicorn/prefer-response-static-json': [2],
|
||||||
'unicorn/prefer-set-has': [0],
|
'unicorn/prefer-set-has': [0],
|
||||||
'unicorn/prefer-set-size': [2],
|
'unicorn/prefer-set-size': [2],
|
||||||
|
'unicorn/prefer-simple-condition-first': [0],
|
||||||
'unicorn/prefer-spread': [0],
|
'unicorn/prefer-spread': [0],
|
||||||
'unicorn/prefer-string-raw': [0],
|
'unicorn/prefer-string-raw': [0],
|
||||||
'unicorn/prefer-string-replace-all': [0],
|
'unicorn/prefer-string-replace-all': [0],
|
||||||
'unicorn/prefer-string-slice': [0],
|
'unicorn/prefer-string-slice': [0],
|
||||||
'unicorn/prefer-string-starts-ends-with': [2],
|
'unicorn/prefer-string-starts-ends-with': [0], // handled by @typescript-eslint/prefer-string-starts-ends-with
|
||||||
'unicorn/prefer-string-trim-start-end': [2],
|
'unicorn/prefer-string-trim-start-end': [2],
|
||||||
'unicorn/prefer-structured-clone': [2],
|
'unicorn/prefer-structured-clone': [2],
|
||||||
'unicorn/prefer-switch': [0],
|
'unicorn/prefer-switch': [0],
|
||||||
@@ -869,6 +891,7 @@ export default defineConfig([
|
|||||||
'unicorn/require-post-message-target-origin': [0],
|
'unicorn/require-post-message-target-origin': [0],
|
||||||
'unicorn/string-content': [0],
|
'unicorn/string-content': [0],
|
||||||
'unicorn/switch-case-braces': [0],
|
'unicorn/switch-case-braces': [0],
|
||||||
|
'unicorn/switch-case-break-position': [2],
|
||||||
'unicorn/template-indent': [2],
|
'unicorn/template-indent': [2],
|
||||||
'unicorn/text-encoding-identifier-case': [0],
|
'unicorn/text-encoding-identifier-case': [0],
|
||||||
'unicorn/throw-new-error': [2],
|
'unicorn/throw-new-error': [2],
|
||||||
@@ -900,12 +923,13 @@ export default defineConfig([
|
|||||||
'yoda': [2, 'never'],
|
'yoda': [2, 'never'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// @ts-expect-error
|
|
||||||
{
|
{
|
||||||
...playwright.configs['flat/recommended'],
|
...playwright.configs['flat/recommended'],
|
||||||
files: ['tests/e2e/**'],
|
files: ['tests/e2e/**/*.test.ts'],
|
||||||
|
languageOptions: {globals: {...globals.nodeBuiltin, ...globals.browser}},
|
||||||
rules: {
|
rules: {
|
||||||
...playwright.configs['flat/recommended'].rules,
|
...playwright.configs['flat/recommended'].rules,
|
||||||
|
'playwright/expect-expect': [0],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -916,27 +940,19 @@ export default defineConfig([
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
extends: [
|
extends: [
|
||||||
// @ts-expect-error
|
|
||||||
vue.configs['flat/recommended'],
|
vue.configs['flat/recommended'],
|
||||||
// @ts-expect-error
|
vueScopedCss.configs.recommended as any,
|
||||||
vueScopedCss.configs['flat/recommended'],
|
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
'vue/attributes-order': [0],
|
'vue/attributes-order': [0],
|
||||||
'vue/html-closing-bracket-spacing': [2, {startTag: 'never', endTag: 'never', selfClosingTag: 'never'}],
|
'vue/html-closing-bracket-spacing': [2, {startTag: 'never', endTag: 'never', selfClosingTag: 'never'}],
|
||||||
'vue/max-attributes-per-line': [0],
|
'vue/max-attributes-per-line': [0],
|
||||||
'vue/singleline-html-element-content-newline': [0],
|
'vue/singleline-html-element-content-newline': [0],
|
||||||
},
|
'vue/require-typed-ref': [2],
|
||||||
},
|
|
||||||
{
|
|
||||||
files: ['web_src/js/modules/fetch.ts', 'web_src/js/standalone/**/*'],
|
|
||||||
rules: {
|
|
||||||
'no-restricted-syntax': [2, ...restrictedSyntax],
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
files: ['**/*.test.ts', 'web_src/js/test/setup.ts'],
|
files: ['**/*.test.ts', 'web_src/js/test/setup.ts'],
|
||||||
// @ts-expect-error - https://github.com/vitest-dev/eslint-plugin-vitest/issues/737
|
|
||||||
plugins: {vitest},
|
plugins: {vitest},
|
||||||
languageOptions: {globals: globals.vitest},
|
languageOptions: {globals: globals.vitest},
|
||||||
rules: {
|
rules: {
|
||||||
@@ -960,6 +976,7 @@ export default defineConfig([
|
|||||||
'vitest/no-interpolation-in-snapshots': [0],
|
'vitest/no-interpolation-in-snapshots': [0],
|
||||||
'vitest/no-large-snapshots': [0],
|
'vitest/no-large-snapshots': [0],
|
||||||
'vitest/no-mocks-import': [0],
|
'vitest/no-mocks-import': [0],
|
||||||
|
'vitest/no-importing-vitest-globals': [2],
|
||||||
'vitest/no-restricted-matchers': [0],
|
'vitest/no-restricted-matchers': [0],
|
||||||
'vitest/no-restricted-vi-methods': [0],
|
'vitest/no-restricted-vi-methods': [0],
|
||||||
'vitest/no-standalone-expect': [0],
|
'vitest/no-standalone-expect': [0],
|
||||||
@@ -988,42 +1005,24 @@ export default defineConfig([
|
|||||||
'vitest/require-to-throw-message': [0],
|
'vitest/require-to-throw-message': [0],
|
||||||
'vitest/require-top-level-describe': [0],
|
'vitest/require-top-level-describe': [0],
|
||||||
'vitest/valid-describe-callback': [2],
|
'vitest/valid-describe-callback': [2],
|
||||||
'vitest/valid-expect': [2],
|
'vitest/valid-expect': [2, {maxArgs: 2}],
|
||||||
|
'vitest/valid-expect-in-promise': [2],
|
||||||
'vitest/valid-title': [2],
|
'vitest/valid-title': [2],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
files: ['web_src/js/types.ts'],
|
|
||||||
rules: {
|
|
||||||
'import-x/no-unused-modules': [0],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
files: ['**/*.d.ts'],
|
files: ['**/*.d.ts'],
|
||||||
rules: {
|
rules: {
|
||||||
'import-x/no-unused-modules': [0],
|
|
||||||
'@typescript-eslint/consistent-type-definitions': [0],
|
'@typescript-eslint/consistent-type-definitions': [0],
|
||||||
'@typescript-eslint/consistent-type-imports': [0],
|
'@typescript-eslint/consistent-type-imports': [0],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
files: ['*.config.*'],
|
files: ['*', 'tools/**/*', 'tests/**/*'],
|
||||||
rules: {
|
languageOptions: {globals: globals.nodeBuiltin},
|
||||||
'import-x/no-unused-modules': [0],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
files: ['web_src/**/*', 'docs/**/*'],
|
|
||||||
languageOptions: {globals: globals.browser},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
files: ['web_src/**/*'],
|
files: ['web_src/**/*'],
|
||||||
languageOptions: {
|
languageOptions: {globals: {...globals.browser, ...globals.jquery, htmx: false}},
|
||||||
globals: {
|
|
||||||
...globals.browser,
|
|
||||||
__webpack_public_path__: true,
|
|
||||||
process: false, // https://github.com/webpack/webpack/issues/15833
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import {defineConfig, globalIgnores} from 'eslint/config';
|
||||||
|
import json from '@eslint/json';
|
||||||
|
|
||||||
|
export default defineConfig([
|
||||||
|
globalIgnores([
|
||||||
|
'**/.venv',
|
||||||
|
'**/node_modules',
|
||||||
|
'**/public',
|
||||||
|
]),
|
||||||
|
{
|
||||||
|
files: ['**/*.json'],
|
||||||
|
plugins: {json},
|
||||||
|
language: 'json/json',
|
||||||
|
extends: ['json/recommended'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: [
|
||||||
|
'tsconfig.json',
|
||||||
|
'.devcontainer/*.json',
|
||||||
|
'.vscode/*.json',
|
||||||
|
'contrib/ide/vscode/*.json',
|
||||||
|
],
|
||||||
|
plugins: {json},
|
||||||
|
language: 'json/jsonc',
|
||||||
|
languageOptions: {
|
||||||
|
allowTrailingCommas: true,
|
||||||
|
},
|
||||||
|
extends: ['json/recommended'],
|
||||||
|
},
|
||||||
|
]);
|
||||||
Generated
+3
-37
@@ -1,30 +1,12 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"flake-utils": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1731533236,
|
|
||||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1755186698,
|
"lastModified": 1775036866,
|
||||||
"narHash": "sha256-wNO3+Ks2jZJ4nTHMuks+cxAiVBGNuEBXsT29Bz6HASo=",
|
"narHash": "sha256-ZojAnPuCdy657PbTq5V0Y+AHKhZAIwSIT2cb8UgAz/U=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "fbcf476f790d8a217c3eab4e12033dc4a0f6d23c",
|
"rev": "6201e203d09599479a3b3450ed24fa81537ebc4e",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -36,24 +18,8 @@
|
|||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"systems": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": "root",
|
"root": "root",
|
||||||
|
|||||||
@@ -1,73 +1,94 @@
|
|||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
|
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
|
||||||
};
|
};
|
||||||
outputs =
|
outputs =
|
||||||
{ nixpkgs, flake-utils, ... }:
|
{ nixpkgs, ... }:
|
||||||
flake-utils.lib.eachDefaultSystem (
|
let
|
||||||
system:
|
supportedSystems = [
|
||||||
let
|
"aarch64-darwin"
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
"aarch64-linux"
|
||||||
in
|
"x86_64-darwin"
|
||||||
{
|
"x86_64-linux"
|
||||||
devShells.default =
|
];
|
||||||
with pkgs;
|
|
||||||
|
forEachSupportedSystem =
|
||||||
|
f:
|
||||||
|
nixpkgs.lib.genAttrs supportedSystems (
|
||||||
|
system:
|
||||||
let
|
let
|
||||||
# only bump toolchain versions here
|
pkgs = import nixpkgs {
|
||||||
go = go_1_25;
|
inherit system;
|
||||||
nodejs = nodejs_24;
|
|
||||||
python3 = python312;
|
|
||||||
pnpm = pnpm_10;
|
|
||||||
|
|
||||||
# Platform-specific dependencies
|
|
||||||
linuxOnlyInputs = lib.optionals pkgs.stdenv.isLinux [
|
|
||||||
glibc.static
|
|
||||||
];
|
|
||||||
|
|
||||||
linuxOnlyEnv = lib.optionalAttrs pkgs.stdenv.isLinux {
|
|
||||||
CFLAGS = "-I${glibc.static.dev}/include";
|
|
||||||
LDFLAGS = "-L ${glibc.static}/lib";
|
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
pkgs.mkShell (
|
f { inherit pkgs; }
|
||||||
{
|
);
|
||||||
buildInputs = [
|
in
|
||||||
# generic
|
{
|
||||||
git
|
devShells = forEachSupportedSystem (
|
||||||
git-lfs
|
{ pkgs, ... }:
|
||||||
gnumake
|
{
|
||||||
gnused
|
default =
|
||||||
gnutar
|
let
|
||||||
gzip
|
inherit (pkgs) lib;
|
||||||
zip
|
|
||||||
|
|
||||||
# frontend
|
# only bump toolchain versions here
|
||||||
nodejs
|
go = pkgs.go_1_26;
|
||||||
pnpm
|
nodejs = pkgs.nodejs_24;
|
||||||
cairo
|
python3 = pkgs.python314;
|
||||||
pixman
|
pnpm = pkgs.pnpm_10;
|
||||||
pkg-config
|
|
||||||
|
|
||||||
# linting
|
# Platform-specific dependencies
|
||||||
python3
|
linuxOnlyInputs = lib.optionals pkgs.stdenv.isLinux [
|
||||||
uv
|
pkgs.glibc.static
|
||||||
|
];
|
||||||
|
|
||||||
# backend
|
linuxOnlyEnv = lib.optionalAttrs pkgs.stdenv.isLinux {
|
||||||
go
|
CFLAGS = "-I${pkgs.glibc.static.dev}/include";
|
||||||
gofumpt
|
LDFLAGS = "-L ${pkgs.glibc.static}/lib";
|
||||||
sqlite
|
};
|
||||||
]
|
in
|
||||||
++ linuxOnlyInputs;
|
pkgs.mkShell {
|
||||||
|
packages =
|
||||||
|
with pkgs;
|
||||||
|
[
|
||||||
|
# generic
|
||||||
|
git
|
||||||
|
git-lfs
|
||||||
|
gnumake
|
||||||
|
gnused
|
||||||
|
gnutar
|
||||||
|
gzip
|
||||||
|
zip
|
||||||
|
|
||||||
GO = "${go}/bin/go";
|
# frontend
|
||||||
GOROOT = "${go}/share/go";
|
nodejs
|
||||||
|
pnpm
|
||||||
|
cairo
|
||||||
|
pixman
|
||||||
|
pkg-config
|
||||||
|
|
||||||
TAGS = "sqlite sqlite_unlock_notify";
|
# linting
|
||||||
STATIC = "true";
|
python3
|
||||||
}
|
uv
|
||||||
// linuxOnlyEnv
|
|
||||||
);
|
# backend
|
||||||
}
|
go
|
||||||
);
|
gofumpt
|
||||||
|
sqlite
|
||||||
|
]
|
||||||
|
++ linuxOnlyInputs;
|
||||||
|
|
||||||
|
env = {
|
||||||
|
GO = "${go}/bin/go";
|
||||||
|
GOROOT = "${go}/share/go";
|
||||||
|
|
||||||
|
TAGS = "sqlite sqlite_unlock_notify";
|
||||||
|
STATIC = "true";
|
||||||
|
}
|
||||||
|
// linuxOnlyEnv;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+140
-142
@@ -1,8 +1,6 @@
|
|||||||
module code.gitea.io/gitea
|
module code.gitea.io/gitea
|
||||||
|
|
||||||
go 1.25.0
|
go 1.26.3
|
||||||
|
|
||||||
toolchain go1.25.5
|
|
||||||
|
|
||||||
// rfc5280 said: "The serial number is an integer assigned by the CA to each certificate."
|
// rfc5280 said: "The serial number is an integer assigned by the CA to each certificate."
|
||||||
// But some CAs use negative serial number, just relax the check. related:
|
// But some CAs use negative serial number, just relax the check. related:
|
||||||
@@ -11,208 +9,201 @@ godebug x509negativeserial=1
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
code.gitea.io/actions-proto-go v0.4.1
|
code.gitea.io/actions-proto-go v0.4.1
|
||||||
code.gitea.io/gitea-vet v0.2.3
|
code.gitea.io/sdk/gitea v0.24.1
|
||||||
code.gitea.io/sdk/gitea v0.22.0
|
|
||||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
|
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
|
||||||
connectrpc.com/connect v1.18.1
|
connectrpc.com/connect v1.19.1
|
||||||
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed
|
gitea.com/go-chi/binding v0.0.0-20260414111559-654cea7ac60a
|
||||||
gitea.com/go-chi/cache v0.2.1
|
gitea.com/go-chi/cache v0.2.1
|
||||||
gitea.com/go-chi/captcha v0.0.0-20240315150714-fb487f629098
|
gitea.com/go-chi/captcha v0.0.0-20240315150714-fb487f629098
|
||||||
gitea.com/go-chi/session v0.0.0-20240316035857-16768d98ec96
|
gitea.com/go-chi/session v0.0.0-20251124165456-68e0254e989e
|
||||||
gitea.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96
|
gitea.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96
|
||||||
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4
|
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4
|
||||||
github.com/42wim/httpsig v1.2.3
|
github.com/42wim/httpsig v1.2.4
|
||||||
github.com/42wim/sshsig v0.0.0-20250502153856-5100632e8920
|
github.com/42wim/sshsig v0.0.0-20260317195500-b9f38cf0d432
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.0
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.0
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2
|
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
|
github.com/Azure/go-ntlmssp v0.1.0
|
||||||
github.com/ProtonMail/go-crypto v1.3.0
|
github.com/ProtonMail/go-crypto v1.4.1
|
||||||
github.com/PuerkitoBio/goquery v1.10.3
|
github.com/PuerkitoBio/goquery v1.12.0
|
||||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.8.0
|
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.8.0
|
||||||
github.com/alecthomas/chroma/v2 v2.20.0
|
github.com/alecthomas/chroma/v2 v2.23.1
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.18.10
|
github.com/aws/aws-sdk-go-v2/credentials v1.19.13
|
||||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.32.2
|
github.com/aws/aws-sdk-go-v2/service/codecommit v1.33.12
|
||||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
||||||
github.com/blevesearch/bleve/v2 v2.5.3
|
github.com/blevesearch/bleve/v2 v2.5.7
|
||||||
github.com/bohde/codel v0.2.0
|
github.com/bohde/codel v0.2.0
|
||||||
github.com/buildkite/terminal-to-html/v3 v3.16.8
|
github.com/buildkite/terminal-to-html/v3 v3.16.8
|
||||||
github.com/caddyserver/certmagic v0.24.0
|
github.com/caddyserver/certmagic v0.25.2
|
||||||
github.com/charmbracelet/git-lfs-transfer v0.1.1-0.20251013092601-6327009efd21
|
github.com/charmbracelet/git-lfs-transfer v0.1.1-0.20251013092601-6327009efd21
|
||||||
github.com/chi-middleware/proxy v1.1.1
|
github.com/chi-middleware/proxy v1.1.1
|
||||||
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21
|
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21
|
||||||
github.com/djherbis/buffer v1.2.0
|
github.com/dlclark/regexp2 v1.11.5
|
||||||
github.com/djherbis/nio/v3 v3.0.1
|
|
||||||
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707
|
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707
|
||||||
github.com/dustin/go-humanize v1.0.1
|
github.com/dustin/go-humanize v1.0.1
|
||||||
github.com/editorconfig/editorconfig-core-go/v2 v2.6.3
|
github.com/editorconfig/editorconfig-core-go/v2 v2.6.4
|
||||||
github.com/emersion/go-imap v1.2.1
|
github.com/emersion/go-imap v1.2.1
|
||||||
github.com/emirpasic/gods v1.18.1
|
github.com/emirpasic/gods v1.18.1
|
||||||
github.com/ethantkoenig/rupture v1.0.1
|
github.com/ethantkoenig/rupture v1.0.1
|
||||||
github.com/felixge/fgprof v0.9.5
|
github.com/felixge/fgprof v0.9.5
|
||||||
github.com/fsnotify/fsnotify v1.9.0
|
github.com/fsnotify/fsnotify v1.9.0
|
||||||
github.com/gliderlabs/ssh v0.3.8
|
github.com/gliderlabs/ssh v0.3.8
|
||||||
github.com/go-ap/activitypub v0.0.0-20250810115208-cb73b20a1742
|
github.com/go-chi/chi/v5 v5.2.5
|
||||||
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73
|
|
||||||
github.com/go-chi/chi/v5 v5.2.3
|
|
||||||
github.com/go-chi/cors v1.2.2
|
github.com/go-chi/cors v1.2.2
|
||||||
github.com/go-co-op/gocron v1.37.0
|
github.com/go-co-op/gocron/v2 v2.19.1
|
||||||
github.com/go-enry/go-enry/v2 v2.9.2
|
github.com/go-enry/go-enry/v2 v2.9.5
|
||||||
github.com/go-git/go-billy/v5 v5.6.2
|
github.com/go-git/go-billy/v5 v5.9.0
|
||||||
github.com/go-git/go-git/v5 v5.16.3
|
github.com/go-git/go-git/v5 v5.19.0
|
||||||
github.com/go-ldap/ldap/v3 v3.4.11
|
github.com/go-ldap/ldap/v3 v3.4.13
|
||||||
github.com/go-redsync/redsync/v4 v4.13.0
|
github.com/go-redsync/redsync/v4 v4.16.0
|
||||||
github.com/go-sql-driver/mysql v1.9.3
|
github.com/go-sql-driver/mysql v1.9.3
|
||||||
github.com/go-webauthn/webauthn v0.13.4
|
github.com/go-webauthn/webauthn v0.16.1
|
||||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
|
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
|
||||||
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
|
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
|
||||||
github.com/golang-jwt/jwt/v5 v5.3.0
|
github.com/golang-jwt/jwt/v5 v5.3.1
|
||||||
github.com/google/go-github/v74 v74.0.0
|
github.com/google/go-github/v84 v84.0.0
|
||||||
github.com/google/licenseclassifier/v2 v2.0.0
|
github.com/google/licenseclassifier/v2 v2.0.0
|
||||||
github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6
|
github.com/google/pprof v0.0.0-20260302011040-a15ffb7f9dcc
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/gorilla/feeds v1.2.0
|
github.com/gorilla/feeds v1.2.0
|
||||||
github.com/gorilla/sessions v1.4.0
|
github.com/gorilla/sessions v1.4.0
|
||||||
github.com/hashicorp/go-version v1.7.0
|
github.com/hashicorp/go-version v1.9.0
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7
|
github.com/hashicorp/golang-lru/v2 v2.0.7
|
||||||
github.com/huandu/xstrings v1.5.0
|
github.com/huandu/xstrings v1.5.0
|
||||||
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056
|
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056
|
||||||
github.com/jhillyerd/enmime v1.3.0
|
github.com/jhillyerd/enmime/v2 v2.3.0
|
||||||
github.com/json-iterator/go v1.1.12
|
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||||
github.com/klauspost/compress v1.18.0
|
github.com/klauspost/compress v1.18.5
|
||||||
github.com/klauspost/cpuid/v2 v2.3.0
|
github.com/klauspost/cpuid/v2 v2.3.0
|
||||||
github.com/lib/pq v1.10.9
|
github.com/lib/pq v1.12.1
|
||||||
github.com/markbates/goth v1.82.0
|
github.com/markbates/goth v1.82.0
|
||||||
github.com/mattn/go-isatty v0.0.20
|
github.com/mattn/go-isatty v0.0.20
|
||||||
github.com/mattn/go-sqlite3 v1.14.32
|
github.com/mattn/go-sqlite3 v1.14.38
|
||||||
github.com/meilisearch/meilisearch-go v0.33.2
|
github.com/meilisearch/meilisearch-go v0.36.1
|
||||||
github.com/mholt/archives v0.1.5-0.20251009205813-e30ac6010726
|
github.com/mholt/archives v0.1.5
|
||||||
github.com/microcosm-cc/bluemonday v1.0.27
|
github.com/microcosm-cc/bluemonday v1.0.27
|
||||||
github.com/microsoft/go-mssqldb v1.9.3
|
github.com/microsoft/go-mssqldb v1.9.6
|
||||||
github.com/minio/minio-go/v7 v7.0.95
|
github.com/minio/minio-go/v7 v7.0.99
|
||||||
github.com/msteinert/pam v1.2.0
|
github.com/msteinert/pam/v2 v2.1.0
|
||||||
github.com/nektos/act v0.2.63
|
github.com/nektos/act v0.2.63
|
||||||
github.com/niklasfasching/go-org v1.9.1
|
github.com/niklasfasching/go-org v1.9.1
|
||||||
github.com/olivere/elastic/v7 v7.0.32
|
github.com/olivere/elastic/v7 v7.0.32
|
||||||
github.com/opencontainers/go-digest v1.0.0
|
github.com/opencontainers/go-digest v1.0.0
|
||||||
github.com/opencontainers/image-spec v1.1.1
|
github.com/opencontainers/image-spec v1.1.1
|
||||||
github.com/pkg/errors v0.9.1
|
|
||||||
github.com/pquerna/otp v1.5.0
|
github.com/pquerna/otp v1.5.0
|
||||||
github.com/prometheus/client_golang v1.23.0
|
github.com/prometheus/client_golang v1.23.2
|
||||||
github.com/quasoft/websspi v1.1.2
|
github.com/quasoft/websspi v1.1.2
|
||||||
github.com/redis/go-redis/v9 v9.12.1
|
github.com/redis/go-redis/v9 v9.18.0
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
|
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2
|
||||||
github.com/sassoftware/go-rpmutils v0.4.0
|
github.com/sassoftware/go-rpmutils v0.4.0
|
||||||
github.com/sergi/go-diff v1.4.0
|
github.com/sergi/go-diff v1.4.0
|
||||||
github.com/stretchr/testify v1.11.1
|
github.com/stretchr/testify v1.11.1
|
||||||
github.com/syndtr/goleveldb v1.0.0
|
github.com/syndtr/goleveldb v1.0.0
|
||||||
github.com/tstranex/u2f v1.0.0
|
github.com/tstranex/u2f v1.0.0
|
||||||
github.com/ulikunitz/xz v0.5.15
|
github.com/ulikunitz/xz v0.5.15
|
||||||
github.com/urfave/cli-docs/v3 v3.0.0-alpha6
|
github.com/urfave/cli-docs/v3 v3.1.0
|
||||||
github.com/urfave/cli/v3 v3.4.1
|
github.com/urfave/cli/v3 v3.4.1
|
||||||
github.com/wneessen/go-mail v0.7.2
|
github.com/wneessen/go-mail v0.7.2
|
||||||
github.com/xeipuuv/gojsonschema v1.2.0
|
github.com/xeipuuv/gojsonschema v1.2.0
|
||||||
github.com/yohcop/openid-go v1.0.1
|
github.com/yohcop/openid-go v1.0.1
|
||||||
github.com/yuin/goldmark v1.7.13
|
github.com/yuin/goldmark v1.8.2
|
||||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
||||||
github.com/yuin/goldmark-meta v1.1.0
|
gitlab.com/gitlab-org/api/client-go v1.46.0
|
||||||
gitlab.com/gitlab-org/api/client-go v0.142.4
|
go.yaml.in/yaml/v4 v4.0.0-rc.3
|
||||||
golang.org/x/crypto v0.45.0
|
golang.org/x/crypto v0.50.0
|
||||||
golang.org/x/image v0.30.0
|
golang.org/x/image v0.38.0
|
||||||
golang.org/x/net v0.47.0
|
golang.org/x/net v0.53.0
|
||||||
golang.org/x/oauth2 v0.30.0
|
golang.org/x/oauth2 v0.36.0
|
||||||
golang.org/x/sync v0.18.0
|
golang.org/x/sync v0.20.0
|
||||||
golang.org/x/sys v0.38.0
|
golang.org/x/sys v0.44.0
|
||||||
golang.org/x/text v0.31.0
|
golang.org/x/text v0.36.0
|
||||||
google.golang.org/grpc v1.75.0
|
google.golang.org/grpc v1.79.3
|
||||||
google.golang.org/protobuf v1.36.8
|
google.golang.org/protobuf v1.36.11
|
||||||
gopkg.in/ini.v1 v1.67.0
|
gopkg.in/ini.v1 v1.67.1
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
mvdan.cc/xurls/v2 v2.6.0
|
mvdan.cc/xurls/v2 v2.6.0
|
||||||
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
|
strk.kbt.io/projects/go/libravatar v0.0.0-20260301104140-add494e31dab
|
||||||
xorm.io/builder v0.3.13
|
xorm.io/builder v0.3.13
|
||||||
xorm.io/xorm v1.3.10
|
xorm.io/xorm v1.3.11
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/compute/metadata v0.8.0 // indirect
|
cloud.google.com/go/compute/metadata v0.9.0 // indirect
|
||||||
|
code.gitea.io/gitea-vet v0.2.3 // indirect
|
||||||
dario.cat/mergo v1.0.2 // indirect
|
dario.cat/mergo v1.0.2 // indirect
|
||||||
filippo.io/edwards25519 v1.1.0 // indirect
|
filippo.io/edwards25519 v1.2.0 // indirect
|
||||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect
|
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect
|
||||||
github.com/DataDog/zstd v1.5.7 // indirect
|
github.com/DataDog/zstd v1.5.7 // indirect
|
||||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
github.com/RoaringBitmap/roaring/v2 v2.10.0 // indirect
|
github.com/RoaringBitmap/roaring/v2 v2.16.0 // indirect
|
||||||
github.com/STARRY-S/zip v0.2.3 // indirect
|
github.com/STARRY-S/zip v0.2.3 // indirect
|
||||||
github.com/andybalholm/brotli v1.2.0 // indirect
|
github.com/andybalholm/brotli v1.2.1 // indirect
|
||||||
github.com/andybalholm/cascadia v1.3.3 // indirect
|
github.com/andybalholm/cascadia v1.3.3 // indirect
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
|
||||||
github.com/aws/aws-sdk-go-v2 v1.38.3 // indirect
|
github.com/aws/aws-sdk-go-v2 v1.41.5 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.6 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.6 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 // indirect
|
||||||
github.com/aws/smithy-go v1.23.0 // indirect
|
github.com/aws/smithy-go v1.24.2 // indirect
|
||||||
github.com/aymerick/douceur v0.2.0 // indirect
|
github.com/aymerick/douceur v0.2.0 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bits-and-blooms/bitset v1.24.0 // indirect
|
github.com/bits-and-blooms/bitset v1.24.4 // indirect
|
||||||
github.com/blevesearch/bleve_index_api v1.2.9 // indirect
|
github.com/blevesearch/bleve_index_api v1.3.7 // indirect
|
||||||
github.com/blevesearch/geo v0.2.4 // indirect
|
github.com/blevesearch/geo v0.2.5 // indirect
|
||||||
github.com/blevesearch/go-faiss v1.0.25 // indirect
|
github.com/blevesearch/go-faiss v1.0.30 // indirect
|
||||||
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
|
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
|
||||||
github.com/blevesearch/gtreap v0.1.1 // indirect
|
github.com/blevesearch/gtreap v0.1.1 // indirect
|
||||||
github.com/blevesearch/mmap-go v1.0.4 // indirect
|
github.com/blevesearch/mmap-go v1.2.0 // indirect
|
||||||
github.com/blevesearch/scorch_segment_api/v2 v2.3.11 // indirect
|
github.com/blevesearch/scorch_segment_api/v2 v2.4.5 // indirect
|
||||||
github.com/blevesearch/segment v0.9.1 // indirect
|
github.com/blevesearch/segment v0.9.1 // indirect
|
||||||
github.com/blevesearch/snowballstem v0.9.0 // indirect
|
github.com/blevesearch/snowballstem v0.9.0 // indirect
|
||||||
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
|
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
|
||||||
github.com/blevesearch/vellum v1.1.0 // indirect
|
github.com/blevesearch/vellum v1.2.0 // indirect
|
||||||
github.com/blevesearch/zapx/v11 v11.4.2 // indirect
|
github.com/blevesearch/zapx/v11 v11.4.3 // indirect
|
||||||
github.com/blevesearch/zapx/v12 v12.4.2 // indirect
|
github.com/blevesearch/zapx/v12 v12.4.3 // indirect
|
||||||
github.com/blevesearch/zapx/v13 v13.4.2 // indirect
|
github.com/blevesearch/zapx/v13 v13.4.3 // indirect
|
||||||
github.com/blevesearch/zapx/v14 v14.4.2 // indirect
|
github.com/blevesearch/zapx/v14 v14.4.3 // indirect
|
||||||
github.com/blevesearch/zapx/v15 v15.4.2 // indirect
|
github.com/blevesearch/zapx/v15 v15.4.3 // indirect
|
||||||
github.com/blevesearch/zapx/v16 v16.2.4 // indirect
|
github.com/blevesearch/zapx/v16 v16.3.2 // indirect
|
||||||
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect
|
||||||
github.com/bodgit/plumbing v1.3.0 // indirect
|
github.com/bodgit/plumbing v1.3.0 // indirect
|
||||||
github.com/bodgit/sevenzip v1.6.1 // indirect
|
github.com/bodgit/sevenzip v1.6.1 // indirect
|
||||||
github.com/bodgit/windows v1.0.1 // indirect
|
github.com/bodgit/windows v1.0.1 // indirect
|
||||||
github.com/boombuler/barcode v1.1.0 // indirect
|
github.com/boombuler/barcode v1.1.0 // indirect
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf // indirect
|
github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf // indirect
|
||||||
github.com/caddyserver/zerossl v0.1.3 // indirect
|
github.com/caddyserver/zerossl v0.1.5 // indirect
|
||||||
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
|
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/cloudflare/circl v1.6.1 // indirect
|
github.com/clipperhouse/displaywidth v0.11.0 // indirect
|
||||||
|
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
|
||||||
|
github.com/cloudflare/circl v1.6.3 // indirect
|
||||||
github.com/couchbase/go-couchbase v0.1.1 // indirect
|
github.com/couchbase/go-couchbase v0.1.1 // indirect
|
||||||
github.com/couchbase/gomemcached v0.3.3 // indirect
|
github.com/couchbase/gomemcached v0.3.4 // indirect
|
||||||
github.com/couchbase/goutils v0.1.2 // indirect
|
github.com/couchbase/goutils v0.3.0 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
|
||||||
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
|
github.com/cyphar/filepath-securejoin v0.6.1 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
github.com/dlclark/regexp2 v1.11.5 // indirect
|
|
||||||
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 // indirect
|
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 // indirect
|
||||||
github.com/fatih/color v1.18.0 // indirect
|
github.com/fatih/color v1.19.0 // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
|
github.com/fxamacker/cbor/v2 v2.9.1 // indirect
|
||||||
github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1 // indirect
|
github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1 // indirect
|
||||||
github.com/go-ap/errors v0.0.0-20250527110557-c8db454e53fd // indirect
|
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
|
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
|
||||||
github.com/go-enry/go-oniguruma v1.2.1 // indirect
|
github.com/go-enry/go-oniguruma v1.2.1 // indirect
|
||||||
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e // indirect
|
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e // indirect
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||||
github.com/go-ini/ini v1.67.0 // indirect
|
github.com/go-ini/ini v1.67.0 // indirect
|
||||||
github.com/go-webauthn/x v0.1.24 // indirect
|
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
|
||||||
github.com/goccy/go-json v0.10.5 // indirect
|
github.com/go-webauthn/x v0.2.2 // indirect
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
github.com/goccy/go-json v0.10.6 // indirect
|
||||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
||||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||||
github.com/golang/protobuf v1.5.4 // indirect
|
|
||||||
github.com/golang/snappy v1.0.0 // indirect
|
github.com/golang/snappy v1.0.0 // indirect
|
||||||
github.com/google/btree v1.1.3 // indirect
|
github.com/google/btree v1.1.3 // indirect
|
||||||
github.com/google/flatbuffers v25.2.10+incompatible // indirect
|
github.com/google/flatbuffers v25.12.19+incompatible // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.2.0 // indirect
|
||||||
github.com/google/go-tpm v0.9.5 // indirect
|
github.com/google/go-tpm v0.9.8 // indirect
|
||||||
github.com/gorilla/css v1.0.1 // indirect
|
github.com/gorilla/css v1.0.1 // indirect
|
||||||
github.com/gorilla/mux v1.8.1 // indirect
|
github.com/gorilla/mux v1.8.1 // indirect
|
||||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||||
@@ -220,53 +211,56 @@ require (
|
|||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
|
github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
|
||||||
|
github.com/inbucket/html2text v1.0.0 // indirect
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||||
|
github.com/jonboulle/clockwork v0.5.0 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/kevinburke/ssh_config v1.4.0 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/kevinburke/ssh_config v1.6.0 // indirect
|
||||||
|
github.com/klauspost/crc32 v1.3.0 // indirect
|
||||||
github.com/klauspost/pgzip v1.2.6 // indirect
|
github.com/klauspost/pgzip v1.2.6 // indirect
|
||||||
github.com/libdns/libdns v1.1.1 // indirect
|
github.com/libdns/libdns v1.1.1 // indirect
|
||||||
github.com/mailru/easyjson v0.9.0 // indirect
|
github.com/mailru/easyjson v0.9.2 // indirect
|
||||||
github.com/markbates/going v1.0.3 // indirect
|
github.com/markbates/going v1.0.3 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
github.com/mattn/go-runewidth v0.0.21 // indirect
|
||||||
github.com/mattn/go-shellwords v1.0.12 // indirect
|
github.com/mattn/go-shellwords v1.0.12 // indirect
|
||||||
github.com/mholt/acmez/v3 v3.1.2 // indirect
|
github.com/mholt/acmez/v3 v3.1.6 // indirect
|
||||||
github.com/miekg/dns v1.1.68 // indirect
|
github.com/miekg/dns v1.1.72 // indirect
|
||||||
github.com/mikelolasagasti/xz v1.0.1 // indirect
|
github.com/mikelolasagasti/xz v1.0.1 // indirect
|
||||||
github.com/minio/crc64nvme v1.1.1 // indirect
|
github.com/minio/crc64nvme v1.1.1 // indirect
|
||||||
github.com/minio/md5-simd v1.1.2 // indirect
|
github.com/minio/md5-simd v1.1.2 // indirect
|
||||||
github.com/minio/minlz v1.0.1 // indirect
|
github.com/minio/minlz v1.1.0 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect
|
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect
|
||||||
github.com/mschoch/smat v0.2.0 // indirect
|
github.com/mschoch/smat v0.2.0 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/nwaples/rardecode/v2 v2.2.0 // indirect
|
github.com/nwaples/rardecode/v2 v2.2.2 // indirect
|
||||||
github.com/olekukonko/cat v0.0.0-20250817074551-3280053e4e00 // indirect
|
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect
|
||||||
github.com/olekukonko/errors v1.1.0 // indirect
|
github.com/olekukonko/errors v1.2.0 // indirect
|
||||||
github.com/olekukonko/ll v0.1.0 // indirect
|
github.com/olekukonko/ll v0.1.8 // indirect
|
||||||
github.com/olekukonko/tablewriter v1.0.9 // indirect
|
github.com/olekukonko/tablewriter v1.1.4 // indirect
|
||||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||||
github.com/philhofer/fwd v1.2.0 // indirect
|
github.com/philhofer/fwd v1.2.0 // indirect
|
||||||
github.com/pierrec/lz4/v4 v4.1.22 // indirect
|
github.com/pierrec/lz4/v4 v4.1.26 // indirect
|
||||||
github.com/pjbgf/sha1cd v0.4.0 // indirect
|
github.com/pjbgf/sha1cd v0.6.0 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
github.com/prometheus/client_model v0.6.2 // indirect
|
github.com/prometheus/client_model v0.6.2 // indirect
|
||||||
github.com/prometheus/common v0.65.0 // indirect
|
github.com/prometheus/common v0.67.5 // indirect
|
||||||
github.com/prometheus/procfs v0.17.0 // indirect
|
github.com/prometheus/procfs v0.20.1 // indirect
|
||||||
github.com/rhysd/actionlint v1.7.7 // indirect
|
github.com/rhysd/actionlint v1.7.12 // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
|
||||||
github.com/rs/xid v1.6.0 // indirect
|
github.com/rs/xid v1.6.0 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
github.com/shopspring/decimal v1.4.0 // indirect
|
||||||
github.com/skeema/knownhosts v1.3.1 // indirect
|
github.com/sirupsen/logrus v1.9.4 // indirect
|
||||||
|
github.com/skeema/knownhosts v1.3.2 // indirect
|
||||||
github.com/sorairolake/lzip-go v0.3.8 // indirect
|
github.com/sorairolake/lzip-go v0.3.8 // indirect
|
||||||
github.com/spf13/afero v1.15.0 // indirect
|
github.com/spf13/afero v1.15.0 // indirect
|
||||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
||||||
github.com/tinylib/msgp v1.4.0 // indirect
|
github.com/tinylib/msgp v1.6.3 // indirect
|
||||||
github.com/unknwon/com v1.0.1 // indirect
|
github.com/unknwon/com v1.0.1 // indirect
|
||||||
github.com/valyala/fastjson v1.6.4 // indirect
|
|
||||||
github.com/x448/float16 v0.8.4 // indirect
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||||
@@ -277,16 +271,16 @@ require (
|
|||||||
go.etcd.io/bbolt v1.4.3 // indirect
|
go.etcd.io/bbolt v1.4.3 // indirect
|
||||||
go.uber.org/atomic v1.11.0 // indirect
|
go.uber.org/atomic v1.11.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
go.uber.org/zap v1.27.1 // indirect
|
||||||
go.uber.org/zap/exp v0.3.0 // indirect
|
go.uber.org/zap/exp v0.3.0 // indirect
|
||||||
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
|
go.yaml.in/yaml/v2 v2.4.4 // indirect
|
||||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
|
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||||
golang.org/x/mod v0.29.0 // indirect
|
go4.org v0.0.0-20260112195520-a5071408f32f // indirect
|
||||||
golang.org/x/time v0.12.0 // indirect
|
golang.org/x/mod v0.35.0 // indirect
|
||||||
golang.org/x/tools v0.38.0 // indirect
|
golang.org/x/time v0.15.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1 // indirect
|
golang.org/x/tools v0.44.0 // indirect
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401020348-3a24fdc17823 // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
|
||||||
)
|
)
|
||||||
|
|
||||||
ignore (
|
ignore (
|
||||||
@@ -294,18 +288,22 @@ ignore (
|
|||||||
./node_modules
|
./node_modules
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/jaytaylor/html2text => github.com/Necoro/html2text v0.0.0-20250804200300-7bf1ce1c7347
|
// When doing "go get -u ./...", Golang will try to update all dependencies
|
||||||
|
// But not all latest versions of dependencies are compatible with other packages or our codebase, so we need to pin some dependencies to specific versions
|
||||||
|
// Need to regularly maintain this list to try to update them to latest versions, especially the TODO ones
|
||||||
|
|
||||||
replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1
|
replace github.com/jaytaylor/html2text => github.com/Necoro/html2text v0.0.0-20250804200300-7bf1ce1c7347 // jaytaylor/html2text is unmaintained
|
||||||
|
|
||||||
replace github.com/nektos/act => gitea.com/gitea/act v0.261.7-0.20251003180512-ac6e4b751763
|
replace github.com/nektos/act => gitea.com/gitea/act v0.261.10 // gitea maintains its own package
|
||||||
|
|
||||||
replace git.sr.ht/~mariusor/go-xsd-duration => gitea.com/gitea/go-xsd-duration v0.0.0-20220703122237-02e73435a078
|
replace github.com/urfave/cli/v3 => github.com/urfave/cli/v3 v3.4.1 // v3.6.2 breaks -c flag parsing in help commands
|
||||||
|
|
||||||
exclude github.com/gofrs/uuid v3.2.0+incompatible
|
replace go.yaml.in/yaml/v4 => go.yaml.in/yaml/v4 v4.0.0-rc.3 // rc.4 changes block scalar serialization, wait for stable release
|
||||||
|
|
||||||
exclude github.com/gofrs/uuid v4.0.0+incompatible
|
replace github.com/Azure/azure-sdk-for-go/sdk/azcore => github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.0 // v1.21.0+ uses API version unsupported by Azurite in CI
|
||||||
|
|
||||||
exclude github.com/goccy/go-json v0.4.11
|
replace github.com/Azure/azure-sdk-for-go/sdk/storage/azblob => github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.2 // v1.6.4+ uses API version unsupported by Azurite in CI
|
||||||
|
|
||||||
exclude github.com/satori/go.uuid v1.2.0
|
replace github.com/microsoft/go-mssqldb => github.com/microsoft/go-mssqldb v1.9.7 // downgraded with Azure SDK
|
||||||
|
|
||||||
|
tool code.gitea.io/gitea-vet
|
||||||
|
|||||||
+294
-472
File diff suppressed because it is too large
Load Diff
@@ -26,9 +26,8 @@ import (
|
|||||||
|
|
||||||
// these flags will be set by the build flags
|
// these flags will be set by the build flags
|
||||||
var (
|
var (
|
||||||
Version = "development" // program version for this build
|
Version = "development" // program version for this build
|
||||||
Tags = "" // the Golang build tags
|
Tags = "" // the Golang build tags
|
||||||
MakeVersion = "" // "make" program version if built with make
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -44,14 +43,12 @@ func main() {
|
|||||||
}
|
}
|
||||||
app := cmd.NewMainApp(cmd.AppVersion{Version: Version, Extra: formatBuiltWith()})
|
app := cmd.NewMainApp(cmd.AppVersion{Version: Version, Extra: formatBuiltWith()})
|
||||||
_ = cmd.RunMainApp(app, os.Args...) // all errors should have been handled by the RunMainApp
|
_ = cmd.RunMainApp(app, os.Args...) // all errors should have been handled by the RunMainApp
|
||||||
|
// flush the queued logs before exiting, it is a MUST, otherwise there will be log loss
|
||||||
log.GetManager().Close()
|
log.GetManager().Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatBuiltWith() string {
|
func formatBuiltWith() string {
|
||||||
version := runtime.Version()
|
version := runtime.Version()
|
||||||
if len(MakeVersion) > 0 {
|
|
||||||
version = MakeVersion + ", " + runtime.Version()
|
|
||||||
}
|
|
||||||
if len(Tags) == 0 {
|
if len(Tags) == 0 {
|
||||||
return " built with " + version
|
return " built with " + version
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,11 @@ func init() {
|
|||||||
db.RegisterModel(new(ActionArtifact))
|
db.RegisterModel(new(ActionArtifact))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
ContentEncodingV3Gzip = "gzip"
|
||||||
|
ContentTypeZip = "application/zip"
|
||||||
|
)
|
||||||
|
|
||||||
// ActionArtifact is a file that is stored in the artifact storage.
|
// ActionArtifact is a file that is stored in the artifact storage.
|
||||||
type ActionArtifact struct {
|
type ActionArtifact struct {
|
||||||
ID int64 `xorm:"pk autoincr"`
|
ID int64 `xorm:"pk autoincr"`
|
||||||
@@ -61,16 +66,26 @@ type ActionArtifact struct {
|
|||||||
RepoID int64 `xorm:"index"`
|
RepoID int64 `xorm:"index"`
|
||||||
OwnerID int64
|
OwnerID int64
|
||||||
CommitSHA string
|
CommitSHA string
|
||||||
StoragePath string // The path to the artifact in the storage
|
StoragePath string // The path to the artifact in the storage
|
||||||
FileSize int64 // The size of the artifact in bytes
|
FileSize int64 // The size of the artifact in bytes
|
||||||
FileCompressedSize int64 // The size of the artifact in bytes after gzip compression
|
FileCompressedSize int64 // The size of the artifact in bytes after gzip compression
|
||||||
ContentEncoding string // The content encoding of the artifact
|
|
||||||
ArtifactPath string `xorm:"index unique(runid_name_path)"` // The path to the artifact when runner uploads it
|
// The content encoding or content type of the artifact
|
||||||
ArtifactName string `xorm:"index unique(runid_name_path)"` // The name of the artifact when runner uploads it
|
// * empty or null: legacy (v3) uncompressed content
|
||||||
Status ArtifactStatus `xorm:"index"` // The status of the artifact, uploading, expired or need-delete
|
// * magic string "gzip" (ContentEncodingV3Gzip): v3 gzip compressed content
|
||||||
CreatedUnix timeutil.TimeStamp `xorm:"created"`
|
// * requires gzip decoding before storing in a zip for download
|
||||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated index"`
|
// * requires gzip content-encoding header when downloaded single files within a workflow
|
||||||
ExpiredUnix timeutil.TimeStamp `xorm:"index"` // The time when the artifact will be expired
|
// * mime type for "Content-Type":
|
||||||
|
// * "application/zip" (ContentTypeZip), seems to be an abuse, fortunately there is no conflict, and it won't cause problems?
|
||||||
|
// * "application/pdf", "text/html", etc.: real content type of the artifact
|
||||||
|
ContentEncodingOrType string `xorm:"content_encoding"`
|
||||||
|
|
||||||
|
ArtifactPath string `xorm:"index unique(runid_name_path)"` // The path to the artifact when runner uploads it
|
||||||
|
ArtifactName string `xorm:"index unique(runid_name_path)"` // The name of the artifact when runner uploads it
|
||||||
|
Status ArtifactStatus `xorm:"index"` // The status of the artifact, uploading, expired or need-delete
|
||||||
|
CreatedUnix timeutil.TimeStamp `xorm:"created"`
|
||||||
|
UpdatedUnix timeutil.TimeStamp `xorm:"updated index"`
|
||||||
|
ExpiredUnix timeutil.TimeStamp `xorm:"index"` // The time when the artifact will be expired
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateArtifact(ctx context.Context, t *ActionTask, artifactName, artifactPath string, expiredDays int64) (*ActionArtifact, error) {
|
func CreateArtifact(ctx context.Context, t *ActionTask, artifactName, artifactPath string, expiredDays int64) (*ActionArtifact, error) {
|
||||||
@@ -156,7 +171,8 @@ func (opts FindArtifactsOptions) ToConds() builder.Cond {
|
|||||||
}
|
}
|
||||||
if opts.FinalizedArtifactsV4 {
|
if opts.FinalizedArtifactsV4 {
|
||||||
cond = cond.And(builder.Eq{"status": ArtifactStatusUploadConfirmed}.Or(builder.Eq{"status": ArtifactStatusExpired}))
|
cond = cond.And(builder.Eq{"status": ArtifactStatusUploadConfirmed}.Or(builder.Eq{"status": ArtifactStatusExpired}))
|
||||||
cond = cond.And(builder.Eq{"content_encoding": "application/zip"})
|
// see the comment of ActionArtifact.ContentEncodingOrType: "*/*" means the field is a content type
|
||||||
|
cond = cond.And(builder.Like{"content_encoding", "%/%"})
|
||||||
}
|
}
|
||||||
|
|
||||||
return cond
|
return cond
|
||||||
@@ -170,10 +186,10 @@ type ActionArtifactMeta struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListUploadedArtifactsMeta returns all uploaded artifacts meta of a run
|
// ListUploadedArtifactsMeta returns all uploaded artifacts meta of a run
|
||||||
func ListUploadedArtifactsMeta(ctx context.Context, runID int64) ([]*ActionArtifactMeta, error) {
|
func ListUploadedArtifactsMeta(ctx context.Context, repoID, runID int64) ([]*ActionArtifactMeta, error) {
|
||||||
arts := make([]*ActionArtifactMeta, 0, 10)
|
arts := make([]*ActionArtifactMeta, 0, 10)
|
||||||
return arts, db.GetEngine(ctx).Table("action_artifact").
|
return arts, db.GetEngine(ctx).Table("action_artifact").
|
||||||
Where("run_id=? AND (status=? OR status=?)", runID, ArtifactStatusUploadConfirmed, ArtifactStatusExpired).
|
Where("repo_id=? AND run_id=? AND (status=? OR status=?)", repoID, runID, ArtifactStatusUploadConfirmed, ArtifactStatusExpired).
|
||||||
GroupBy("artifact_name").
|
GroupBy("artifact_name").
|
||||||
Select("artifact_name, sum(file_size) as file_size, max(status) as status").
|
Select("artifact_name, sum(file_size) as file_size, max(status) as status").
|
||||||
Find(&arts)
|
Find(&arts)
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package actions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/perm"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
"code.gitea.io/gitea/modules/json"
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
|
"xorm.io/xorm/convert"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OwnerActionsConfig defines the Actions configuration for a user or organization
|
||||||
|
type OwnerActionsConfig struct {
|
||||||
|
// TokenPermissionMode defines the default permission mode (permissive, restricted)
|
||||||
|
TokenPermissionMode repo_model.ActionsTokenPermissionMode `json:"token_permission_mode,omitempty"`
|
||||||
|
|
||||||
|
// MaxTokenPermissions defines the absolute maximum permissions any token can have in this context.
|
||||||
|
MaxTokenPermissions *repo_model.ActionsTokenPermissions `json:"max_token_permissions,omitempty"`
|
||||||
|
|
||||||
|
// AllowedCrossRepoIDs is a list of specific repo IDs that can be accessed cross-repo
|
||||||
|
AllowedCrossRepoIDs []int64 `json:"allowed_cross_repo_ids,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ convert.ConversionFrom = (*OwnerActionsConfig)(nil)
|
||||||
|
|
||||||
|
func (cfg *OwnerActionsConfig) FromDB(bytes []byte) error {
|
||||||
|
_ = json.Unmarshal(bytes, cfg)
|
||||||
|
cfg.TokenPermissionMode, _ = util.EnumValue(cfg.TokenPermissionMode)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOwnerActionsConfig loads the OwnerActionsConfig for a user or organization from user settings
|
||||||
|
// It returns a default config if no setting is found
|
||||||
|
func GetOwnerActionsConfig(ctx context.Context, userID int64) (ret OwnerActionsConfig, err error) {
|
||||||
|
return user_model.GetUserSettingJSON(ctx, userID, user_model.SettingsKeyActionsConfig, ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOwnerActionsConfig saves the OwnerActionsConfig for a user or organization to user settings
|
||||||
|
func SetOwnerActionsConfig(ctx context.Context, userID int64, cfg OwnerActionsConfig) error {
|
||||||
|
return user_model.SetUserSettingJSON(ctx, userID, user_model.SettingsKeyActionsConfig, cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDefaultTokenPermissions returns the default token permissions by its TokenPermissionMode.
|
||||||
|
func (cfg *OwnerActionsConfig) GetDefaultTokenPermissions() repo_model.ActionsTokenPermissions {
|
||||||
|
switch cfg.TokenPermissionMode {
|
||||||
|
case repo_model.ActionsTokenPermissionModeRestricted:
|
||||||
|
return repo_model.MakeRestrictedPermissions()
|
||||||
|
case repo_model.ActionsTokenPermissionModePermissive:
|
||||||
|
return repo_model.MakeActionsTokenPermissions(perm.AccessModeWrite)
|
||||||
|
default:
|
||||||
|
return repo_model.MakeActionsTokenPermissions(perm.AccessModeNone)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMaxTokenPermissions returns the maximum allowed permissions
|
||||||
|
func (cfg *OwnerActionsConfig) GetMaxTokenPermissions() repo_model.ActionsTokenPermissions {
|
||||||
|
if cfg.MaxTokenPermissions != nil {
|
||||||
|
return *cfg.MaxTokenPermissions
|
||||||
|
}
|
||||||
|
// Default max is write for everything
|
||||||
|
return repo_model.MakeActionsTokenPermissions(perm.AccessModeWrite)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClampPermissions ensures that the given permissions don't exceed the maximum
|
||||||
|
func (cfg *OwnerActionsConfig) ClampPermissions(perms repo_model.ActionsTokenPermissions) repo_model.ActionsTokenPermissions {
|
||||||
|
maxPerms := cfg.GetMaxTokenPermissions()
|
||||||
|
return repo_model.ClampActionsTokenPermissions(perms, maxPerms)
|
||||||
|
}
|
||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"slices"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -16,13 +15,13 @@ import (
|
|||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/json"
|
"code.gitea.io/gitea/modules/json"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
webhook_module "code.gitea.io/gitea/modules/webhook"
|
webhook_module "code.gitea.io/gitea/modules/webhook"
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/jobparser"
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -30,7 +29,7 @@ import (
|
|||||||
type ActionRun struct {
|
type ActionRun struct {
|
||||||
ID int64
|
ID int64
|
||||||
Title string
|
Title string
|
||||||
RepoID int64 `xorm:"index unique(repo_index)"`
|
RepoID int64 `xorm:"unique(repo_index) index(repo_concurrency)"`
|
||||||
Repo *repo_model.Repository `xorm:"-"`
|
Repo *repo_model.Repository `xorm:"-"`
|
||||||
OwnerID int64 `xorm:"index"`
|
OwnerID int64 `xorm:"index"`
|
||||||
WorkflowID string `xorm:"index"` // the name of workflow file
|
WorkflowID string `xorm:"index"` // the name of workflow file
|
||||||
@@ -49,6 +48,9 @@ type ActionRun struct {
|
|||||||
TriggerEvent string // the trigger event defined in the `on` configuration of the triggered workflow
|
TriggerEvent string // the trigger event defined in the `on` configuration of the triggered workflow
|
||||||
Status Status `xorm:"index"`
|
Status Status `xorm:"index"`
|
||||||
Version int `xorm:"version default 0"` // Status could be updated concomitantly, so an optimistic lock is needed
|
Version int `xorm:"version default 0"` // Status could be updated concomitantly, so an optimistic lock is needed
|
||||||
|
RawConcurrency string // raw concurrency
|
||||||
|
ConcurrencyGroup string `xorm:"index(repo_concurrency) NOT NULL DEFAULT ''"`
|
||||||
|
ConcurrencyCancel bool `xorm:"NOT NULL DEFAULT FALSE"`
|
||||||
// Started and Stopped is used for recording last run time, if rerun happened, they will be reset to 0
|
// Started and Stopped is used for recording last run time, if rerun happened, they will be reset to 0
|
||||||
Started timeutil.TimeStamp
|
Started timeutil.TimeStamp
|
||||||
Stopped timeutil.TimeStamp
|
Stopped timeutil.TimeStamp
|
||||||
@@ -67,14 +69,14 @@ func (run *ActionRun) HTMLURL() string {
|
|||||||
if run.Repo == nil {
|
if run.Repo == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s/actions/runs/%d", run.Repo.HTMLURL(), run.Index)
|
return fmt.Sprintf("%s/actions/runs/%d", run.Repo.HTMLURL(), run.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (run *ActionRun) Link() string {
|
func (run *ActionRun) Link() string {
|
||||||
if run.Repo == nil {
|
if run.Repo == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s/actions/runs/%d", run.Repo.Link(), run.Index)
|
return fmt.Sprintf("%s/actions/runs/%d", run.Repo.Link(), run.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (run *ActionRun) WorkflowLink() string {
|
func (run *ActionRun) WorkflowLink() string {
|
||||||
@@ -102,8 +104,17 @@ func (run *ActionRun) PrettyRef() string {
|
|||||||
return refName.ShortName()
|
return refName.ShortName()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RefTooltip return a tooltop of run's ref. For pull request, it's the title of the PR, otherwise it's the ShortName.
|
||||||
|
func (run *ActionRun) RefTooltip() string {
|
||||||
|
payload, err := run.GetPullRequestEventPayload()
|
||||||
|
if err == nil && payload != nil && payload.PullRequest != nil {
|
||||||
|
return payload.PullRequest.Title
|
||||||
|
}
|
||||||
|
return git.RefName(run.Ref).ShortName()
|
||||||
|
}
|
||||||
|
|
||||||
// LoadAttributes load Repo TriggerUser if not loaded
|
// LoadAttributes load Repo TriggerUser if not loaded
|
||||||
func (run *ActionRun) LoadAttributes(ctx context.Context) error {
|
func (run *ActionRun) LoadAttributes(ctx context.Context) (err error) {
|
||||||
if run == nil {
|
if run == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -117,11 +128,10 @@ func (run *ActionRun) LoadAttributes(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if run.TriggerUser == nil {
|
if run.TriggerUser == nil {
|
||||||
u, err := user_model.GetPossibleUserByID(ctx, run.TriggerUserID)
|
run.TriggerUserID, run.TriggerUser, err = user_model.GetPossibleUserByID(ctx, run.TriggerUserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
run.TriggerUser = u
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -141,7 +151,11 @@ func (run *ActionRun) LoadRepo(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (run *ActionRun) Duration() time.Duration {
|
func (run *ActionRun) Duration() time.Duration {
|
||||||
return calculateDuration(run.Started, run.Stopped, run.Status) + run.PreviousDuration
|
d := calculateDuration(run.Started, run.Stopped, run.Status, run.Updated) + run.PreviousDuration
|
||||||
|
if d < 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
func (run *ActionRun) GetPushEventPayload() (*api.PushPayload, error) {
|
func (run *ActionRun) GetPushEventPayload() (*api.PushPayload, error) {
|
||||||
@@ -156,7 +170,7 @@ func (run *ActionRun) GetPushEventPayload() (*api.PushPayload, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (run *ActionRun) GetPullRequestEventPayload() (*api.PullRequestPayload, error) {
|
func (run *ActionRun) GetPullRequestEventPayload() (*api.PullRequestPayload, error) {
|
||||||
if run.Event.IsPullRequest() {
|
if run.Event.IsPullRequest() || run.Event.IsPullRequestReview() {
|
||||||
var payload api.PullRequestPayload
|
var payload api.PullRequestPayload
|
||||||
if err := json.Unmarshal([]byte(run.EventPayload), &payload); err != nil {
|
if err := json.Unmarshal([]byte(run.EventPayload), &payload); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -181,30 +195,35 @@ func (run *ActionRun) IsSchedule() bool {
|
|||||||
return run.ScheduleID > 0
|
return run.ScheduleID > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) error {
|
// UpdateRepoRunsNumbers updates the number of runs and closed runs of a repository.
|
||||||
_, err := db.GetEngine(ctx).ID(repo.ID).
|
// Callers MUST invoke this from outside any transaction that has X-locked action_run rows for the same repo, otherwise, transaction deadlock
|
||||||
NoAutoTime().
|
func UpdateRepoRunsNumbers(ctx context.Context, repoID int64) {
|
||||||
Cols("num_action_runs", "num_closed_action_runs").
|
if db.InTransaction(ctx) {
|
||||||
SetExpr("num_action_runs",
|
setting.PanicInDevOrTesting("UpdateRepoRunsNumbers must not be called inside a transaction")
|
||||||
builder.Select("count(*)").From("action_run").
|
}
|
||||||
Where(builder.Eq{"repo_id": repo.ID}),
|
|
||||||
).
|
e := db.GetEngine(ctx)
|
||||||
SetExpr("num_closed_action_runs",
|
|
||||||
builder.Select("count(*)").From("action_run").
|
numActionRuns, err := e.Where("repo_id = ?", repoID).Count(new(ActionRun))
|
||||||
Where(builder.Eq{
|
if err != nil {
|
||||||
"repo_id": repo.ID,
|
log.Error("UpdateRepoRunsNumbers count num_action_runs for repo %d: %v", repoID, err)
|
||||||
}.And(
|
return
|
||||||
builder.In("status",
|
}
|
||||||
StatusSuccess,
|
|
||||||
StatusFailure,
|
numClosedActionRuns, err := e.Where("repo_id = ?", repoID).
|
||||||
StatusCancelled,
|
In("status", StatusSuccess, StatusFailure, StatusCancelled, StatusSkipped).
|
||||||
StatusSkipped,
|
Count(new(ActionRun))
|
||||||
),
|
if err != nil {
|
||||||
),
|
log.Error("UpdateRepoRunsNumbers count num_closed_action_runs for repo %d: %v", repoID, err)
|
||||||
),
|
return
|
||||||
).
|
}
|
||||||
Update(repo)
|
|
||||||
return err
|
if _, err := e.ID(repoID).Cols("num_action_runs", "num_closed_action_runs").NoAutoTime().Update(&repo_model.Repository{
|
||||||
|
NumActionRuns: int(numActionRuns),
|
||||||
|
NumClosedActionRuns: int(numClosedActionRuns),
|
||||||
|
}); err != nil {
|
||||||
|
log.Error("UpdateRepoRunsNumbers update repo %d: %v", repoID, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CancelPreviousJobs cancels all previous jobs of the same repository, reference, workflow, and event.
|
// CancelPreviousJobs cancels all previous jobs of the same repository, reference, workflow, and event.
|
||||||
@@ -239,116 +258,62 @@ func CancelPreviousJobs(ctx context.Context, repoID int64, ref, workflowID strin
|
|||||||
return cancelledJobs, err
|
return cancelledJobs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate over each job and attempt to cancel it.
|
cjs, err := CancelJobs(ctx, jobs)
|
||||||
for _, job := range jobs {
|
if err != nil {
|
||||||
// Skip jobs that are already in a terminal state (completed, cancelled, etc.).
|
return cancelledJobs, err
|
||||||
status := job.Status
|
|
||||||
if status.IsDone() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the job has no associated task (probably an error), set its status to 'Cancelled' and stop it.
|
|
||||||
if job.TaskID == 0 {
|
|
||||||
job.Status = StatusCancelled
|
|
||||||
job.Stopped = timeutil.TimeStampNow()
|
|
||||||
|
|
||||||
// Update the job's status and stopped time in the database.
|
|
||||||
n, err := UpdateRunJob(ctx, job, builder.Eq{"task_id": 0}, "status", "stopped")
|
|
||||||
if err != nil {
|
|
||||||
return cancelledJobs, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the update affected 0 rows, it means the job has changed in the meantime, so we need to try again.
|
|
||||||
if n == 0 {
|
|
||||||
return cancelledJobs, errors.New("job has changed, try again")
|
|
||||||
}
|
|
||||||
|
|
||||||
cancelledJobs = append(cancelledJobs, job)
|
|
||||||
// Continue with the next job.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the job has an associated task, try to stop the task, effectively cancelling the job.
|
|
||||||
if err := StopTask(ctx, job.TaskID, StatusCancelled); err != nil {
|
|
||||||
return cancelledJobs, err
|
|
||||||
}
|
|
||||||
cancelledJobs = append(cancelledJobs, job)
|
|
||||||
}
|
}
|
||||||
|
cancelledJobs = append(cancelledJobs, cjs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return nil to indicate successful cancellation of all running and waiting jobs.
|
// Return nil to indicate successful cancellation of all running and waiting jobs.
|
||||||
return cancelledJobs, nil
|
return cancelledJobs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// InsertRun inserts a run
|
func CancelJobs(ctx context.Context, jobs []*ActionRunJob) ([]*ActionRunJob, error) {
|
||||||
// The title will be cut off at 255 characters if it's longer than 255 characters.
|
cancelledJobs := make([]*ActionRunJob, 0, len(jobs))
|
||||||
func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWorkflow) error {
|
// Iterate over each job and attempt to cancel it.
|
||||||
return db.WithTx(ctx, func(ctx context.Context) error {
|
for _, job := range jobs {
|
||||||
index, err := db.GetNextResourceIndex(ctx, "action_run_index", run.RepoID)
|
// Skip jobs that are already in a terminal state (completed, cancelled, etc.).
|
||||||
if err != nil {
|
status := job.Status
|
||||||
return err
|
if status.IsDone() {
|
||||||
}
|
continue
|
||||||
run.Index = index
|
|
||||||
run.Title = util.EllipsisDisplayString(run.Title, 255)
|
|
||||||
|
|
||||||
if err := db.Insert(ctx, run); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if run.Repo == nil {
|
// If the job has no associated task (probably an error), set its status to 'Cancelled' and stop it.
|
||||||
repo, err := repo_model.GetRepositoryByID(ctx, run.RepoID)
|
if job.TaskID == 0 {
|
||||||
|
job.Status = StatusCancelled
|
||||||
|
job.Stopped = timeutil.TimeStampNow()
|
||||||
|
|
||||||
|
// Update the job's status and stopped time in the database.
|
||||||
|
n, err := UpdateRunJob(ctx, job, builder.Eq{"task_id": 0}, "status", "stopped")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return cancelledJobs, err
|
||||||
}
|
}
|
||||||
run.Repo = repo
|
|
||||||
|
// If the update affected 0 rows, it means the job has changed in the meantime
|
||||||
|
if n == 0 {
|
||||||
|
log.Error("Failed to cancel job %d because it has changed", job.ID)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelledJobs = append(cancelledJobs, job)
|
||||||
|
// Continue with the next job.
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := updateRepoRunsNumbers(ctx, run.Repo); err != nil {
|
// If the job has an associated task, try to stop the task, effectively cancelling the job.
|
||||||
return err
|
if err := StopTask(ctx, job.TaskID, StatusCancelled); err != nil {
|
||||||
|
return cancelledJobs, err
|
||||||
}
|
}
|
||||||
|
updatedJob, err := GetRunJobByRunAndID(ctx, job.RunID, job.ID)
|
||||||
|
if err != nil {
|
||||||
|
return cancelledJobs, fmt.Errorf("get job: %w", err)
|
||||||
|
}
|
||||||
|
cancelledJobs = append(cancelledJobs, updatedJob)
|
||||||
|
}
|
||||||
|
|
||||||
runJobs := make([]*ActionRunJob, 0, len(jobs))
|
// Return nil to indicate successful cancellation of all running and waiting jobs.
|
||||||
var hasWaiting bool
|
return cancelledJobs, nil
|
||||||
for _, v := range jobs {
|
|
||||||
id, job := v.Job()
|
|
||||||
needs := job.Needs()
|
|
||||||
if err := v.SetJob(id, job.EraseNeeds()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
payload, _ := v.Marshal()
|
|
||||||
status := StatusWaiting
|
|
||||||
if len(needs) > 0 || run.NeedApproval {
|
|
||||||
status = StatusBlocked
|
|
||||||
} else {
|
|
||||||
hasWaiting = true
|
|
||||||
}
|
|
||||||
job.Name = util.EllipsisDisplayString(job.Name, 255)
|
|
||||||
runJobs = append(runJobs, &ActionRunJob{
|
|
||||||
RunID: run.ID,
|
|
||||||
RepoID: run.RepoID,
|
|
||||||
OwnerID: run.OwnerID,
|
|
||||||
CommitSHA: run.CommitSHA,
|
|
||||||
IsForkPullRequest: run.IsForkPullRequest,
|
|
||||||
Name: job.Name,
|
|
||||||
WorkflowPayload: payload,
|
|
||||||
JobID: id,
|
|
||||||
Needs: needs,
|
|
||||||
RunsOn: job.RunsOn(),
|
|
||||||
Status: status,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if err := db.Insert(ctx, runJobs); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// if there is a job in the waiting status, increase tasks version.
|
|
||||||
if hasWaiting {
|
|
||||||
if err := IncreaseTaskVersion(ctx, run.OwnerID, run.RepoID); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetRunByRepoAndID(ctx context.Context, repoID, runID int64) (*ActionRun, error) {
|
func GetRunByRepoAndID(ctx context.Context, repoID, runID int64) (*ActionRun, error) {
|
||||||
@@ -363,16 +328,16 @@ func GetRunByRepoAndID(ctx context.Context, repoID, runID int64) (*ActionRun, er
|
|||||||
return &run, nil
|
return &run, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetRunByIndex(ctx context.Context, repoID, index int64) (*ActionRun, error) {
|
func GetRunByRepoAndIndex(ctx context.Context, repoID, runIndex int64) (*ActionRun, error) {
|
||||||
run := &ActionRun{
|
run := &ActionRun{
|
||||||
RepoID: repoID,
|
RepoID: repoID,
|
||||||
Index: index,
|
Index: runIndex,
|
||||||
}
|
}
|
||||||
has, err := db.GetEngine(ctx).Get(run)
|
has, err := db.GetEngine(ctx).Get(run)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if !has {
|
} else if !has {
|
||||||
return nil, fmt.Errorf("run with index %d %d: %w", repoID, index, util.ErrNotExist)
|
return nil, fmt.Errorf("run with repo_id %d and index %d: %w", repoID, runIndex, util.ErrNotExist)
|
||||||
}
|
}
|
||||||
|
|
||||||
return run, nil
|
return run, nil
|
||||||
@@ -426,19 +391,63 @@ func UpdateRun(ctx context.Context, run *ActionRun, cols ...string) error {
|
|||||||
// It's impossible that the run is not found, since Gitea never deletes runs.
|
// It's impossible that the run is not found, since Gitea never deletes runs.
|
||||||
}
|
}
|
||||||
|
|
||||||
if run.Status != 0 || slices.Contains(cols, "status") {
|
|
||||||
if run.RepoID == 0 {
|
|
||||||
setting.PanicInDevOrTesting("RepoID should not be 0")
|
|
||||||
}
|
|
||||||
if err = run.LoadRepo(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := updateRepoRunsNumbers(ctx, run.Repo); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ActionRunIndex db.ResourceIndex
|
type ActionRunIndex db.ResourceIndex
|
||||||
|
|
||||||
|
func GetConcurrentRunsAndJobs(ctx context.Context, repoID int64, concurrencyGroup string, status []Status) ([]*ActionRun, []*ActionRunJob, error) {
|
||||||
|
runs, err := db.Find[ActionRun](ctx, &FindRunOptions{
|
||||||
|
RepoID: repoID,
|
||||||
|
ConcurrencyGroup: concurrencyGroup,
|
||||||
|
Status: status,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("find runs: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
jobs, err := db.Find[ActionRunJob](ctx, &FindRunJobOptions{
|
||||||
|
RepoID: repoID,
|
||||||
|
ConcurrencyGroup: concurrencyGroup,
|
||||||
|
Statuses: status,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("find jobs: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return runs, jobs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CancelPreviousJobsByRunConcurrency(ctx context.Context, actionRun *ActionRun) ([]*ActionRunJob, error) {
|
||||||
|
if actionRun.ConcurrencyGroup == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var jobsToCancel []*ActionRunJob
|
||||||
|
|
||||||
|
statusFindOption := []Status{StatusWaiting, StatusBlocked}
|
||||||
|
if actionRun.ConcurrencyCancel {
|
||||||
|
statusFindOption = append(statusFindOption, StatusRunning)
|
||||||
|
}
|
||||||
|
runs, jobs, err := GetConcurrentRunsAndJobs(ctx, actionRun.RepoID, actionRun.ConcurrencyGroup, statusFindOption)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("find concurrent runs and jobs: %w", err)
|
||||||
|
}
|
||||||
|
jobsToCancel = append(jobsToCancel, jobs...)
|
||||||
|
|
||||||
|
// cancel runs in the same concurrency group
|
||||||
|
for _, run := range runs {
|
||||||
|
if run.ID == actionRun.ID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
jobs, err := db.Find[ActionRunJob](ctx, FindRunJobOptions{
|
||||||
|
RunID: run.ID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("find run %d jobs: %w", run.ID, err)
|
||||||
|
}
|
||||||
|
jobsToCancel = append(jobsToCancel, jobs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return CancelJobs(ctx, jobsToCancel)
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,34 +11,60 @@ import (
|
|||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
"code.gitea.io/gitea/modules/actions/jobparser"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MaxJobNumPerRun is the maximum number of jobs in a single run.
|
||||||
|
// https://docs.github.com/en/actions/reference/limits#existing-system-limits
|
||||||
|
// TODO: check this limit when creating jobs
|
||||||
|
const MaxJobNumPerRun = 256
|
||||||
|
|
||||||
// ActionRunJob represents a job of a run
|
// ActionRunJob represents a job of a run
|
||||||
type ActionRunJob struct {
|
type ActionRunJob struct {
|
||||||
ID int64
|
ID int64
|
||||||
RunID int64 `xorm:"index"`
|
RunID int64 `xorm:"index"`
|
||||||
Run *ActionRun `xorm:"-"`
|
Run *ActionRun `xorm:"-"`
|
||||||
RepoID int64 `xorm:"index"`
|
RepoID int64 `xorm:"index(repo_concurrency)"`
|
||||||
Repo *repo_model.Repository `xorm:"-"`
|
Repo *repo_model.Repository `xorm:"-"`
|
||||||
OwnerID int64 `xorm:"index"`
|
OwnerID int64 `xorm:"index"`
|
||||||
CommitSHA string `xorm:"index"`
|
CommitSHA string `xorm:"index"`
|
||||||
IsForkPullRequest bool
|
IsForkPullRequest bool
|
||||||
Name string `xorm:"VARCHAR(255)"`
|
Name string `xorm:"VARCHAR(255)"`
|
||||||
Attempt int64
|
Attempt int64
|
||||||
WorkflowPayload []byte
|
|
||||||
JobID string `xorm:"VARCHAR(255)"` // job id in workflow, not job's id
|
// WorkflowPayload is act/jobparser.SingleWorkflow for act/jobparser.Parse
|
||||||
Needs []string `xorm:"JSON TEXT"`
|
// it should contain exactly one job with global workflow fields for this model
|
||||||
RunsOn []string `xorm:"JSON TEXT"`
|
WorkflowPayload []byte
|
||||||
TaskID int64 // the latest task of the job
|
|
||||||
Status Status `xorm:"index"`
|
JobID string `xorm:"VARCHAR(255)"` // job id in workflow, not job's id
|
||||||
Started timeutil.TimeStamp
|
Needs []string `xorm:"JSON TEXT"`
|
||||||
Stopped timeutil.TimeStamp
|
RunsOn []string `xorm:"JSON TEXT"`
|
||||||
Created timeutil.TimeStamp `xorm:"created"`
|
TaskID int64 // the latest task of the job
|
||||||
Updated timeutil.TimeStamp `xorm:"updated index"`
|
Status Status `xorm:"index"`
|
||||||
|
|
||||||
|
RawConcurrency string // raw concurrency from job YAML's "concurrency" section
|
||||||
|
|
||||||
|
// IsConcurrencyEvaluated is only valid/needed when this job's RawConcurrency is not empty.
|
||||||
|
// If RawConcurrency can't be evaluated (e.g. depend on other job's outputs or have errors), this field will be false.
|
||||||
|
// If RawConcurrency has been successfully evaluated, this field will be true, ConcurrencyGroup and ConcurrencyCancel are also set.
|
||||||
|
IsConcurrencyEvaluated bool
|
||||||
|
|
||||||
|
ConcurrencyGroup string `xorm:"index(repo_concurrency) NOT NULL DEFAULT ''"` // evaluated concurrency.group
|
||||||
|
ConcurrencyCancel bool `xorm:"NOT NULL DEFAULT FALSE"` // evaluated concurrency.cancel-in-progress
|
||||||
|
|
||||||
|
// TokenPermissions stores the explicit permissions from workflow/job YAML (no org/repo clamps applied).
|
||||||
|
// Org/repo clamps are enforced when the token is used at runtime.
|
||||||
|
// It is JSON-encoded repo_model.ActionsTokenPermissions and may be empty if not specified.
|
||||||
|
TokenPermissions *repo_model.ActionsTokenPermissions `xorm:"JSON TEXT"`
|
||||||
|
|
||||||
|
Started timeutil.TimeStamp
|
||||||
|
Stopped timeutil.TimeStamp
|
||||||
|
Created timeutil.TimeStamp `xorm:"created"`
|
||||||
|
Updated timeutil.TimeStamp `xorm:"updated index"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -46,7 +72,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (job *ActionRunJob) Duration() time.Duration {
|
func (job *ActionRunJob) Duration() time.Duration {
|
||||||
return calculateDuration(job.Started, job.Stopped, job.Status)
|
return calculateDuration(job.Started, job.Stopped, job.Status, job.Updated)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (job *ActionRunJob) LoadRun(ctx context.Context) error {
|
func (job *ActionRunJob) LoadRun(ctx context.Context) error {
|
||||||
@@ -84,13 +110,43 @@ func (job *ActionRunJob) LoadAttributes(ctx context.Context) error {
|
|||||||
return job.Run.LoadAttributes(ctx)
|
return job.Run.LoadAttributes(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetRunJobByID(ctx context.Context, id int64) (*ActionRunJob, error) {
|
// ParseJob parses the job structure from the ActionRunJob.WorkflowPayload
|
||||||
|
func (job *ActionRunJob) ParseJob() (*jobparser.Job, error) {
|
||||||
|
// job.WorkflowPayload is a SingleWorkflow created from an ActionRun's workflow, which exactly contains this job's YAML definition.
|
||||||
|
// Ideally it shouldn't be called "Workflow", it is just a job with global workflow fields + trigger
|
||||||
|
parsedWorkflows, err := jobparser.Parse(job.WorkflowPayload)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("job %d single workflow: unable to parse: %w", job.ID, err)
|
||||||
|
} else if len(parsedWorkflows) != 1 {
|
||||||
|
return nil, fmt.Errorf("job %d single workflow: not single workflow", job.ID)
|
||||||
|
}
|
||||||
|
_, workflowJob := parsedWorkflows[0].Job()
|
||||||
|
if workflowJob == nil {
|
||||||
|
// it shouldn't happen, and since the callers don't check nil, so return an error instead of nil
|
||||||
|
return nil, util.ErrorWrap(util.ErrNotExist, "job %d single workflow: payload doesn't contain a job", job.ID)
|
||||||
|
}
|
||||||
|
return workflowJob, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRunJobByRepoAndID(ctx context.Context, repoID, jobID int64) (*ActionRunJob, error) {
|
||||||
var job ActionRunJob
|
var job ActionRunJob
|
||||||
has, err := db.GetEngine(ctx).Where("id=?", id).Get(&job)
|
has, err := db.GetEngine(ctx).Where("id=? AND repo_id=?", jobID, repoID).Get(&job)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if !has {
|
} else if !has {
|
||||||
return nil, fmt.Errorf("run job with id %d: %w", id, util.ErrNotExist)
|
return nil, fmt.Errorf("run job with id %d: %w", jobID, util.ErrNotExist)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &job, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRunJobByRunAndID(ctx context.Context, runID, jobID int64) (*ActionRunJob, error) {
|
||||||
|
var job ActionRunJob
|
||||||
|
has, err := db.GetEngine(ctx).Where("id=? AND run_id=?", jobID, runID).Get(&job)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if !has {
|
||||||
|
return nil, fmt.Errorf("run job with id %d: %w", jobID, util.ErrNotExist)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &job, nil
|
return &job, nil
|
||||||
@@ -125,7 +181,7 @@ func UpdateRunJob(ctx context.Context, job *ActionRunJob, cond builder.Cond, col
|
|||||||
return affected, nil
|
return affected, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if affected != 0 && slices.Contains(cols, "status") && job.Status.IsWaiting() {
|
if slices.Contains(cols, "status") && job.Status.IsWaiting() {
|
||||||
// if the status of job changes to waiting again, increase tasks version.
|
// if the status of job changes to waiting again, increase tasks version.
|
||||||
if err := IncreaseTaskVersion(ctx, job.OwnerID, job.RepoID); err != nil {
|
if err := IncreaseTaskVersion(ctx, job.OwnerID, job.RepoID); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -134,7 +190,7 @@ func UpdateRunJob(ctx context.Context, job *ActionRunJob, cond builder.Cond, col
|
|||||||
|
|
||||||
if job.RunID == 0 {
|
if job.RunID == 0 {
|
||||||
var err error
|
var err error
|
||||||
if job, err = GetRunJobByID(ctx, job.ID); err != nil {
|
if job, err = GetRunJobByRepoAndID(ctx, job.RepoID, job.ID); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,3 +253,39 @@ func AggregateJobStatus(jobs []*ActionRunJob) Status {
|
|||||||
return StatusUnknown // it shouldn't happen
|
return StatusUnknown // it shouldn't happen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CancelPreviousJobsByJobConcurrency(ctx context.Context, job *ActionRunJob) (jobsToCancel []*ActionRunJob, _ error) {
|
||||||
|
if job.RawConcurrency == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
if !job.IsConcurrencyEvaluated {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
if job.ConcurrencyGroup == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
statusFindOption := []Status{StatusWaiting, StatusBlocked}
|
||||||
|
if job.ConcurrencyCancel {
|
||||||
|
statusFindOption = append(statusFindOption, StatusRunning)
|
||||||
|
}
|
||||||
|
runs, jobs, err := GetConcurrentRunsAndJobs(ctx, job.RepoID, job.ConcurrencyGroup, statusFindOption)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("find concurrent runs and jobs: %w", err)
|
||||||
|
}
|
||||||
|
jobs = slices.DeleteFunc(jobs, func(j *ActionRunJob) bool { return j.ID == job.ID })
|
||||||
|
jobsToCancel = append(jobsToCancel, jobs...)
|
||||||
|
|
||||||
|
// cancel runs in the same concurrency group
|
||||||
|
for _, run := range runs {
|
||||||
|
jobs, err := db.Find[ActionRunJob](ctx, FindRunJobOptions{
|
||||||
|
RunID: run.ID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("find run %d jobs: %w", run.ID, err)
|
||||||
|
}
|
||||||
|
jobsToCancel = append(jobsToCancel, jobs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return CancelJobs(ctx, jobsToCancel)
|
||||||
|
}
|
||||||
|
|||||||
@@ -69,12 +69,13 @@ func (jobs ActionJobList) LoadAttributes(ctx context.Context, withRepo bool) err
|
|||||||
|
|
||||||
type FindRunJobOptions struct {
|
type FindRunJobOptions struct {
|
||||||
db.ListOptions
|
db.ListOptions
|
||||||
RunID int64
|
RunID int64
|
||||||
RepoID int64
|
RepoID int64
|
||||||
OwnerID int64
|
OwnerID int64
|
||||||
CommitSHA string
|
CommitSHA string
|
||||||
Statuses []Status
|
Statuses []Status
|
||||||
UpdatedBefore timeutil.TimeStamp
|
UpdatedBefore timeutil.TimeStamp
|
||||||
|
ConcurrencyGroup string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (opts FindRunJobOptions) ToConds() builder.Cond {
|
func (opts FindRunJobOptions) ToConds() builder.Cond {
|
||||||
@@ -94,6 +95,12 @@ func (opts FindRunJobOptions) ToConds() builder.Cond {
|
|||||||
if opts.UpdatedBefore > 0 {
|
if opts.UpdatedBefore > 0 {
|
||||||
cond = cond.And(builder.Lt{"`action_run_job`.updated": opts.UpdatedBefore})
|
cond = cond.And(builder.Lt{"`action_run_job`.updated": opts.UpdatedBefore})
|
||||||
}
|
}
|
||||||
|
if opts.ConcurrencyGroup != "" {
|
||||||
|
if opts.RepoID == 0 {
|
||||||
|
panic("Invalid FindRunJobOptions: repo_id is required")
|
||||||
|
}
|
||||||
|
cond = cond.And(builder.Eq{"`action_run_job`.concurrency_group": opts.ConcurrencyGroup})
|
||||||
|
}
|
||||||
return cond
|
return cond
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,15 +64,16 @@ func (runs RunList) LoadRepos(ctx context.Context) error {
|
|||||||
|
|
||||||
type FindRunOptions struct {
|
type FindRunOptions struct {
|
||||||
db.ListOptions
|
db.ListOptions
|
||||||
RepoID int64
|
RepoID int64
|
||||||
OwnerID int64
|
OwnerID int64
|
||||||
WorkflowID string
|
WorkflowID string
|
||||||
Ref string // the commit/tag/… that caused this workflow
|
Ref string // the commit/tag/… that caused this workflow
|
||||||
TriggerUserID int64
|
TriggerUserID int64
|
||||||
TriggerEvent webhook_module.HookEventType
|
TriggerEvent webhook_module.HookEventType
|
||||||
Approved bool // not util.OptionalBool, it works only when it's true
|
Approved bool // not util.OptionalBool, it works only when it's true
|
||||||
Status []Status
|
Status []Status
|
||||||
CommitSHA string
|
ConcurrencyGroup string
|
||||||
|
CommitSHA string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (opts FindRunOptions) ToConds() builder.Cond {
|
func (opts FindRunOptions) ToConds() builder.Cond {
|
||||||
@@ -101,6 +102,12 @@ func (opts FindRunOptions) ToConds() builder.Cond {
|
|||||||
if opts.CommitSHA != "" {
|
if opts.CommitSHA != "" {
|
||||||
cond = cond.And(builder.Eq{"`action_run`.commit_sha": opts.CommitSHA})
|
cond = cond.And(builder.Eq{"`action_run`.commit_sha": opts.CommitSHA})
|
||||||
}
|
}
|
||||||
|
if len(opts.ConcurrencyGroup) > 0 {
|
||||||
|
if opts.RepoID == 0 {
|
||||||
|
panic("Invalid FindRunOptions: repo_id is required")
|
||||||
|
}
|
||||||
|
cond = cond.And(builder.Eq{"`action_run`.concurrency_group": opts.ConcurrencyGroup})
|
||||||
|
}
|
||||||
return cond
|
return cond
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,12 @@ package actions
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
@@ -27,9 +29,18 @@ func TestUpdateRepoRunsNumbers(t *testing.T) {
|
|||||||
assert.Equal(t, 2, repo.NumClosedActionRuns)
|
assert.Equal(t, 2, repo.NumClosedActionRuns)
|
||||||
|
|
||||||
// now update will correct them, only num_actionr_runs and num_closed_action_runs should be updated
|
// now update will correct them, only num_actionr_runs and num_closed_action_runs should be updated
|
||||||
err = updateRepoRunsNumbers(t.Context(), repo)
|
UpdateRepoRunsNumbers(t.Context(), repo.ID)
|
||||||
assert.NoError(t, err)
|
|
||||||
repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
|
repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
|
||||||
assert.Equal(t, 5, repo.NumActionRuns)
|
assert.Equal(t, 5, repo.NumActionRuns)
|
||||||
assert.Equal(t, 3, repo.NumClosedActionRuns)
|
assert.Equal(t, 3, repo.NumClosedActionRuns)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestActionRun_Duration_NonNegative(t *testing.T) {
|
||||||
|
run := &ActionRun{
|
||||||
|
Started: timeutil.TimeStamp(100),
|
||||||
|
Stopped: timeutil.TimeStamp(200),
|
||||||
|
Status: StatusSuccess,
|
||||||
|
PreviousDuration: -time.Hour,
|
||||||
|
}
|
||||||
|
assert.Equal(t, time.Duration(0), run.Duration())
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/shared/types"
|
"code.gitea.io/gitea/models/shared/types"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
"code.gitea.io/gitea/modules/container"
|
||||||
"code.gitea.io/gitea/modules/optional"
|
"code.gitea.io/gitea/modules/optional"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
@@ -61,6 +62,8 @@ type ActionRunner struct {
|
|||||||
AgentLabels []string `xorm:"TEXT"`
|
AgentLabels []string `xorm:"TEXT"`
|
||||||
// Store if this is a runner that only ever get one single job assigned
|
// Store if this is a runner that only ever get one single job assigned
|
||||||
Ephemeral bool `xorm:"ephemeral NOT NULL DEFAULT false"`
|
Ephemeral bool `xorm:"ephemeral NOT NULL DEFAULT false"`
|
||||||
|
// Store if this runner is disabled and should not pick up new jobs
|
||||||
|
IsDisabled bool `xorm:"is_disabled NOT NULL DEFAULT false"`
|
||||||
|
|
||||||
Created timeutil.TimeStamp `xorm:"created"`
|
Created timeutil.TimeStamp `xorm:"created"`
|
||||||
Updated timeutil.TimeStamp `xorm:"updated"`
|
Updated timeutil.TimeStamp `xorm:"updated"`
|
||||||
@@ -173,6 +176,13 @@ func (r *ActionRunner) GenerateToken() (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CanMatchLabels checks whether the runner's labels can match a job's "runs-on"
|
||||||
|
// See https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_idruns-on
|
||||||
|
func (r *ActionRunner) CanMatchLabels(jobRunsOn []string) bool {
|
||||||
|
runnerLabelSet := container.SetOf(r.AgentLabels...)
|
||||||
|
return runnerLabelSet.Contains(jobRunsOn...) // match all labels
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
db.RegisterModel(&ActionRunner{})
|
db.RegisterModel(&ActionRunner{})
|
||||||
}
|
}
|
||||||
@@ -191,6 +201,7 @@ type FindRunnerOptions struct {
|
|||||||
Sort string
|
Sort string
|
||||||
Filter string
|
Filter string
|
||||||
IsOnline optional.Option[bool]
|
IsOnline optional.Option[bool]
|
||||||
|
IsDisabled optional.Option[bool]
|
||||||
WithAvailable bool // not only runners belong to, but also runners can be used
|
WithAvailable bool // not only runners belong to, but also runners can be used
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,6 +242,10 @@ func (opts FindRunnerOptions) ToConds() builder.Cond {
|
|||||||
cond = cond.And(builder.Lte{"last_online": time.Now().Add(-RunnerOfflineTime).Unix()})
|
cond = cond.And(builder.Lte{"last_online": time.Now().Add(-RunnerOfflineTime).Unix()})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opts.IsDisabled.Has() {
|
||||||
|
cond = cond.And(builder.Eq{"is_disabled": opts.IsDisabled.Value()})
|
||||||
|
}
|
||||||
return cond
|
return cond
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,6 +304,20 @@ func UpdateRunner(ctx context.Context, r *ActionRunner, cols ...string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetRunnerDisabled(ctx context.Context, runner *ActionRunner, isDisabled bool) error {
|
||||||
|
if runner.IsDisabled == isDisabled {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return db.WithTx(ctx, func(ctx context.Context) error {
|
||||||
|
runner.IsDisabled = isDisabled
|
||||||
|
if err := UpdateRunner(ctx, runner, "is_disabled"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return IncreaseTaskVersion(ctx, runner.OwnerID, runner.RepoID)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteRunner deletes a runner by given ID.
|
// DeleteRunner deletes a runner by given ID.
|
||||||
func DeleteRunner(ctx context.Context, id int64) error {
|
func DeleteRunner(ctx context.Context, id int64) error {
|
||||||
if _, err := GetRunnerByID(ctx, id); err != nil {
|
if _, err := GetRunnerByID(ctx, id); err != nil {
|
||||||
|
|||||||
@@ -8,12 +8,13 @@ import (
|
|||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
auth_model "code.gitea.io/gitea/models/auth"
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
"code.gitea.io/gitea/modules/container"
|
"code.gitea.io/gitea/modules/actions/jobparser"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
@@ -21,7 +22,6 @@ import (
|
|||||||
|
|
||||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||||
lru "github.com/hashicorp/golang-lru/v2"
|
lru "github.com/hashicorp/golang-lru/v2"
|
||||||
"github.com/nektos/act/pkg/jobparser"
|
|
||||||
"google.golang.org/protobuf/types/known/timestamppb"
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
@@ -77,7 +77,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (task *ActionTask) Duration() time.Duration {
|
func (task *ActionTask) Duration() time.Duration {
|
||||||
return calculateDuration(task.Started, task.Stopped, task.Status)
|
return calculateDuration(task.Started, task.Stopped, task.Status, task.Updated)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (task *ActionTask) IsStopped() bool {
|
func (task *ActionTask) IsStopped() bool {
|
||||||
@@ -114,7 +114,7 @@ func (task *ActionTask) GetRepoLink() string {
|
|||||||
|
|
||||||
func (task *ActionTask) LoadJob(ctx context.Context) error {
|
func (task *ActionTask) LoadJob(ctx context.Context) error {
|
||||||
if task.Job == nil {
|
if task.Job == nil {
|
||||||
job, err := GetRunJobByID(ctx, task.JobID)
|
job, err := GetRunJobByRepoAndID(ctx, task.RepoID, task.JobID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -216,6 +216,20 @@ func GetRunningTaskByToken(ctx context.Context, token string) (*ActionTask, erro
|
|||||||
return nil, errNotExist
|
return nil, errNotExist
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeTaskStepDisplayName(step *jobparser.Step, limit int) (name string) {
|
||||||
|
if step.Name != "" {
|
||||||
|
name = step.Name // the step has an explicit name
|
||||||
|
} else {
|
||||||
|
// for unnamed step, its "String()" method tries to get a display name by its "name", "uses",
|
||||||
|
// "run" or "id" (last fallback), we add the "Run " prefix for unnamed steps for better display
|
||||||
|
// for multi-line "run" scripts, only use the first line to match GitHub's behavior
|
||||||
|
// https://github.com/actions/runner/blob/66800900843747f37591b077091dd2c8cf2c1796/src/Runner.Worker/Handlers/ScriptHandler.cs#L45-L58
|
||||||
|
runStr, _, _ := strings.Cut(strings.TrimSpace(step.Run), "\n")
|
||||||
|
name = "Run " + util.IfZero(strings.TrimSpace(runStr), step.String())
|
||||||
|
}
|
||||||
|
return util.EllipsisDisplayString(name, limit) // database column has a length limit
|
||||||
|
}
|
||||||
|
|
||||||
func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask, bool, error) {
|
func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask, bool, error) {
|
||||||
ctx, committer, err := db.TxContext(ctx)
|
ctx, committer, err := db.TxContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -246,7 +260,7 @@ func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask
|
|||||||
var job *ActionRunJob
|
var job *ActionRunJob
|
||||||
log.Trace("runner labels: %v", runner.AgentLabels)
|
log.Trace("runner labels: %v", runner.AgentLabels)
|
||||||
for _, v := range jobs {
|
for _, v := range jobs {
|
||||||
if isSubset(runner.AgentLabels, v.RunsOn) {
|
if runner.CanMatchLabels(v.RunsOn) {
|
||||||
job = v
|
job = v
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -278,13 +292,10 @@ func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask
|
|||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedWorkflows, err := jobparser.Parse(job.WorkflowPayload)
|
workflowJob, err := job.ParseJob()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, fmt.Errorf("parse workflow of job %d: %w", job.ID, err)
|
return nil, false, fmt.Errorf("load job %d: %w", job.ID, err)
|
||||||
} else if len(parsedWorkflows) != 1 {
|
|
||||||
return nil, false, fmt.Errorf("workflow of job %d: not single workflow", job.ID)
|
|
||||||
}
|
}
|
||||||
_, workflowJob := parsedWorkflows[0].Job()
|
|
||||||
|
|
||||||
if _, err := e.Insert(task); err != nil {
|
if _, err := e.Insert(task); err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
@@ -298,9 +309,8 @@ func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask
|
|||||||
if len(workflowJob.Steps) > 0 {
|
if len(workflowJob.Steps) > 0 {
|
||||||
steps := make([]*ActionTaskStep, len(workflowJob.Steps))
|
steps := make([]*ActionTaskStep, len(workflowJob.Steps))
|
||||||
for i, v := range workflowJob.Steps {
|
for i, v := range workflowJob.Steps {
|
||||||
name := util.EllipsisDisplayString(v.String(), 255)
|
|
||||||
steps[i] = &ActionTaskStep{
|
steps[i] = &ActionTaskStep{
|
||||||
Name: name,
|
Name: makeTaskStepDisplayName(v, 255),
|
||||||
TaskID: task.ID,
|
TaskID: task.ID,
|
||||||
Index: int64(i),
|
Index: int64(i),
|
||||||
RepoID: task.RepoID,
|
RepoID: task.RepoID,
|
||||||
@@ -378,6 +388,7 @@ func UpdateTaskByState(ctx context.Context, runnerID int64, state *runnerv1.Task
|
|||||||
}
|
}
|
||||||
if _, err := UpdateRunJob(ctx, &ActionRunJob{
|
if _, err := UpdateRunJob(ctx, &ActionRunJob{
|
||||||
ID: task.JobID,
|
ID: task.JobID,
|
||||||
|
RepoID: task.RepoID,
|
||||||
Status: task.Status,
|
Status: task.Status,
|
||||||
Stopped: task.Stopped,
|
Stopped: task.Stopped,
|
||||||
}, nil); err != nil {
|
}, nil); err != nil {
|
||||||
@@ -439,6 +450,7 @@ func StopTask(ctx context.Context, taskID int64, status Status) error {
|
|||||||
task.Stopped = now
|
task.Stopped = now
|
||||||
if _, err := UpdateRunJob(ctx, &ActionRunJob{
|
if _, err := UpdateRunJob(ctx, &ActionRunJob{
|
||||||
ID: task.JobID,
|
ID: task.JobID,
|
||||||
|
RepoID: task.RepoID,
|
||||||
Status: task.Status,
|
Status: task.Status,
|
||||||
Stopped: task.Stopped,
|
Stopped: task.Stopped,
|
||||||
}, nil); err != nil {
|
}, nil); err != nil {
|
||||||
@@ -479,20 +491,6 @@ func FindOldTasksToExpire(ctx context.Context, olderThan timeutil.TimeStamp, lim
|
|||||||
Find(&tasks)
|
Find(&tasks)
|
||||||
}
|
}
|
||||||
|
|
||||||
func isSubset(set, subset []string) bool {
|
|
||||||
m := make(container.Set[string], len(set))
|
|
||||||
for _, v := range set {
|
|
||||||
m.Add(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, v := range subset {
|
|
||||||
if !m.Contains(v) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func convertTimestamp(timestamp *timestamppb.Timestamp) timeutil.TimeStamp {
|
func convertTimestamp(timestamp *timestamppb.Timestamp) timeutil.TimeStamp {
|
||||||
if timestamp.GetSeconds() == 0 && timestamp.GetNanos() == 0 {
|
if timestamp.GetSeconds() == 0 && timestamp.GetNanos() == 0 {
|
||||||
return timeutil.TimeStamp(0)
|
return timeutil.TimeStamp(0)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
// ActionTaskStep represents a step of ActionTask
|
// ActionTaskStep represents a step of ActionTask
|
||||||
type ActionTaskStep struct {
|
type ActionTaskStep struct {
|
||||||
ID int64
|
ID int64
|
||||||
Name string `xorm:"VARCHAR(255)"`
|
Name string `xorm:"VARCHAR(255)"` // the step name, for display purpose only, it will be truncated if it is too long
|
||||||
TaskID int64 `xorm:"index unique(task_index)"`
|
TaskID int64 `xorm:"index unique(task_index)"`
|
||||||
Index int64 `xorm:"index unique(task_index)"`
|
Index int64 `xorm:"index unique(task_index)"`
|
||||||
RepoID int64 `xorm:"index"`
|
RepoID int64 `xorm:"index"`
|
||||||
@@ -28,7 +28,7 @@ type ActionTaskStep struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (step *ActionTaskStep) Duration() time.Duration {
|
func (step *ActionTaskStep) Duration() time.Duration {
|
||||||
return calculateDuration(step.Started, step.Stopped, step.Status)
|
return calculateDuration(step.Started, step.Stopped, step.Status, step.Updated)
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user