mirror of
https://github.com/go-gitea/gitea.git
synced 2026-09-23 04:38:56 +02:00
Merge branch 'main' into add-matrix-dynamic-job-input-support
This commit is contained in:
@@ -129,7 +129,7 @@ jobs:
|
||||
ports:
|
||||
- "7700:7700"
|
||||
redis:
|
||||
image: redis:latest@sha256:94ea4f5ccdaa6b154df99a792986ecb3ffbb3fe7722a197220477f1f3e65f9fe
|
||||
image: redis:latest@sha256:48e78eb9d1e1adcfb10184b2cc3c7fc5ed21e5a3be08875f239257d194bab8c9
|
||||
options: >- # wait until redis has started
|
||||
--health-cmd "redis-cli ping"
|
||||
--health-interval 5s
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
name: labeler
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened]
|
||||
# pull_request_target is required to label PRs from forks; jobs only use pinned
|
||||
# actions or base-branch checkout, never PR-head code.
|
||||
pull_request_target: # zizmor: ignore[dangerous-triggers]
|
||||
types: [opened, synchronize, reopened, edited, ready_for_review]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
@@ -18,3 +20,28 @@ jobs:
|
||||
- uses: actions/labeler@f27b608878404679385c85cfa523b85ccb86e213 # v6.1.0
|
||||
with:
|
||||
sync-labels: true
|
||||
|
||||
pr-title:
|
||||
if: github.event.pull_request.draft == false
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
# Base-branch checkout only: pull_request_target runs with elevated token; never run PR-head code here.
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.base.sha }}
|
||||
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
with:
|
||||
node-version: 24
|
||||
# Labels are only synced after the title lints, so an invalid title never reaches the label diff.
|
||||
- run: node ./tools/ci-tools.ts lint-pr-title
|
||||
env:
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
- run: node ./tools/ci-tools.ts set-pr-labels
|
||||
env:
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
name: pr-title
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- reopened
|
||||
- synchronize
|
||||
- ready_for_review
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
lint-pr-title:
|
||||
if: github.event.pull_request.draft == false
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
with:
|
||||
node-version: 24
|
||||
- run: make lint-pr-title
|
||||
env:
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
@@ -7,7 +7,7 @@
|
||||
- Run single playwright e2e test files with `GITEA_TEST_E2E_FLAGS='<filepath>' make test-e2e`
|
||||
- Add the current year into the copyright header of new `.go` files
|
||||
- Ensure no trailing whitespace in edited files
|
||||
- Use Conventional Commits format for commit messages and PR titles (for example `type(scope): subject`; place `!` immediately before the colon when the change is breaking)
|
||||
- Use Conventional Commits for commit messages and PR titles, e.g. `type(scope): subject`; `!` before the colon if breaking. Use `test` type for test-only changes.
|
||||
- Never force-push, amend, or squash unless asked. Use new commits and normal push for pull request updates
|
||||
- Preserve existing code comments, do not remove or rewrite comments that are still relevant
|
||||
- Keep comments short, prefer same-line, explain why, never narrate code
|
||||
|
||||
@@ -11,7 +11,7 @@ COMMA := ,
|
||||
|
||||
XGO_VERSION := go-1.26.x
|
||||
|
||||
AIR_PACKAGE ?= github.com/air-verse/air@v1.65.1 # renovate: datasource=go
|
||||
AIR_PACKAGE ?= github.com/air-verse/air@v1.65.2 # renovate: datasource=go
|
||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.6.1 # renovate: datasource=go
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.12.2 # renovate: datasource=go
|
||||
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.15 # renovate: datasource=go
|
||||
@@ -321,10 +321,6 @@ lint-md: node_modules ## lint markdown files
|
||||
lint-md-fix: node_modules ## lint markdown files and fix issues
|
||||
pnpm exec markdownlint --fix *.md
|
||||
|
||||
.PHONY: lint-pr-title
|
||||
lint-pr-title: ## lint PR title against Conventional Commits (set PR_TITLE=...)
|
||||
@node ./tools/lint-pr-title.ts
|
||||
|
||||
.PHONY: lint-spell
|
||||
lint-spell: ## lint spelling
|
||||
@git ls-files $(SPELLCHECK_FILES) | xargs go run $(MISSPELL_PACKAGE) -dict assets/misspellings.csv -error
|
||||
|
||||
Generated
+7
-7
File diff suppressed because one or more lines are too long
@@ -56,3 +56,8 @@ Endpoints returning lists must
|
||||
|
||||
- support pagination (`page` & `limit` options in query)
|
||||
- set `X-Total-Count` header via **SetTotalCountHeader** ([example](https://github.com/go-gitea/gitea/blob/7aae98cc5d4113f1e9918b7ee7dd09f67c189e3e/routers/api/v1/repo/issue.go#L444))
|
||||
|
||||
### Knowledge
|
||||
|
||||
- Partially database table migration must use `SyncWithOptions(IgnoreDrop...)`
|
||||
- Template variables with "camelCase" or "snake_case" are used for restoring the form values from a submitted form
|
||||
|
||||
@@ -11,8 +11,8 @@ require (
|
||||
code.gitea.io/actions-proto-go v0.4.1
|
||||
code.gitea.io/sdk/gitea v0.25.1
|
||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
|
||||
connectrpc.com/connect v1.19.2
|
||||
gitea.com/gitea/runner v1.0.3
|
||||
connectrpc.com/connect v1.20.0
|
||||
gitea.com/gitea/runner v1.0.5
|
||||
gitea.com/go-chi/binding v0.0.0-20260414111559-654cea7ac60a
|
||||
gitea.com/go-chi/cache v0.2.1
|
||||
gitea.com/go-chi/captcha v0.0.0-20240315150714-fb487f629098
|
||||
@@ -24,9 +24,10 @@ require (
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.3
|
||||
github.com/Azure/go-ntlmssp v0.1.1
|
||||
github.com/Necoro/html2text v0.0.0-20250804200300-7bf1ce1c7347
|
||||
github.com/ProtonMail/go-crypto v1.4.1
|
||||
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.3
|
||||
github.com/alecthomas/chroma/v2 v2.24.1
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.16
|
||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.33.14
|
||||
@@ -62,7 +63,7 @@ require (
|
||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
|
||||
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1
|
||||
github.com/google/go-github/v86 v86.0.0
|
||||
github.com/google/go-github/v87 v87.0.0
|
||||
github.com/google/licenseclassifier/v2 v2.0.0
|
||||
github.com/google/pprof v0.0.0-20260507013755-92041b743c96
|
||||
github.com/google/uuid v1.6.0
|
||||
@@ -71,8 +72,7 @@ require (
|
||||
github.com/hashicorp/go-version v1.9.0
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7
|
||||
github.com/huandu/xstrings v1.5.0
|
||||
github.com/jaytaylor/html2text v0.0.0-20260303211410-1a4bdc82ecec
|
||||
github.com/jhillyerd/enmime/v2 v2.3.0
|
||||
github.com/jhillyerd/enmime/v2 v2.4.0
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||
github.com/klauspost/compress v1.18.6
|
||||
github.com/klauspost/cpuid/v2 v2.3.0
|
||||
@@ -107,7 +107,7 @@ require (
|
||||
github.com/yohcop/openid-go v1.0.1
|
||||
github.com/yuin/goldmark v1.8.2
|
||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
||||
gitlab.com/gitlab-org/api/client-go/v2 v2.26.0
|
||||
gitlab.com/gitlab-org/api/client-go/v2 v2.30.0
|
||||
go.yaml.in/yaml/v4 v4.0.0-rc.3
|
||||
golang.org/x/crypto v0.52.0
|
||||
golang.org/x/image v0.40.0
|
||||
@@ -224,7 +224,7 @@ require (
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/markbates/going v1.0.3 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.21 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.23 // indirect
|
||||
github.com/mattn/go-shellwords v1.0.12 // indirect
|
||||
github.com/mholt/acmez/v3 v3.1.6 // indirect
|
||||
github.com/miekg/dns v1.1.72 // indirect
|
||||
@@ -243,7 +243,7 @@ require (
|
||||
github.com/oasdiff/yaml v0.0.9 // indirect
|
||||
github.com/oasdiff/yaml3 v0.0.12 // indirect
|
||||
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect
|
||||
github.com/olekukonko/errors v1.2.0 // indirect
|
||||
github.com/olekukonko/errors v1.3.0 // indirect
|
||||
github.com/olekukonko/ll v0.1.8 // indirect
|
||||
github.com/olekukonko/tablewriter v1.1.4 // indirect
|
||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||
@@ -301,8 +301,6 @@ ignore (
|
||||
// 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/jaytaylor/html2text => github.com/Necoro/html2text v0.0.0-20250804200300-7bf1ce1c7347 // jaytaylor/html2text is unmaintained
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
@@ -8,14 +8,14 @@ code.pfad.fr/check v1.1.0 h1:GWvjdzhSEgHvEHe2uJujDcpmZoySKuHQNrZMfzfO0bE=
|
||||
code.pfad.fr/check v1.1.0/go.mod h1:NiUH13DtYsb7xp5wll0U4SXx7KhXQVCtRgdC96IPfoM=
|
||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570 h1:TXbikPqa7YRtfU9vS6QJBg77pUvbEb6StRdZO8t1bEY=
|
||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570/go.mod h1:IIAjsijsd8q1isWX8MACefDEgTQslQ4stk2AeeTt3kM=
|
||||
connectrpc.com/connect v1.19.2 h1:McQ83FGdzL+t60peksi0gXC7MQ/iLKgLduAnThbM0mo=
|
||||
connectrpc.com/connect v1.19.2/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w=
|
||||
connectrpc.com/connect v1.20.0 h1:6TNDAB+WeNd2uolWNlYczB5E0KNNaVMNUEx8JEUsPmQ=
|
||||
connectrpc.com/connect v1.20.0/go.mod h1:A2ygJrukXwWy32vkCAAHNVguZrqZ+jeZ9rGRnGR4dN4=
|
||||
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
||||
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
||||
filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo=
|
||||
filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc=
|
||||
gitea.com/gitea/runner v1.0.3 h1:jwwXPj2UKSrbFCfyAcqoiXcbaTNQTWlozRb1kikiquw=
|
||||
gitea.com/gitea/runner v1.0.3/go.mod h1:0xR69LP2GwVJT9QnbLHok/87YIFDmpKnJVLkRKKJbSM=
|
||||
gitea.com/gitea/runner v1.0.5 h1:9Idm8XXxXp4aHoLp0Ba0AEwv87YUblp9gk4qbih+DlE=
|
||||
gitea.com/gitea/runner v1.0.5/go.mod h1:ff8SKVat/6FywBGpN4dKi2x3AlHZUfLOA/vVWHf7+Cw=
|
||||
gitea.com/go-chi/binding v0.0.0-20260414111559-654cea7ac60a h1:JHoBrfuTSF9Ke9aNfSYj1XRPBHjKPgCApVprnt2Am0M=
|
||||
gitea.com/go-chi/binding v0.0.0-20260414111559-654cea7ac60a/go.mod h1:FOsLJIMdpiHzBp3Vby6Wfkdw2ppGscrjgU1IC7E4/zQ=
|
||||
gitea.com/go-chi/cache v0.2.1 h1:bfAPkvXlbcZxPCpcmDVCWoHgiBSBmZN/QosnZvEC0+g=
|
||||
@@ -71,8 +71,8 @@ github.com/RoaringBitmap/roaring/v2 v2.16.0 h1:Kys1UNf49d5W8Tq3bpuAhIr/Z8/yPB+59
|
||||
github.com/RoaringBitmap/roaring/v2 v2.16.0/go.mod h1:eq4wdNXxtJIS/oikeCzdX1rBzek7ANzbth041hrU8Q4=
|
||||
github.com/STARRY-S/zip v0.2.3 h1:luE4dMvRPDOWQdeDdUxUoZkzUIpTccdKdhHHsQJ1fm4=
|
||||
github.com/STARRY-S/zip v0.2.3/go.mod h1:lqJ9JdeRipyOQJrYSOtpNAiaesFO6zVDsE8GIGFaoSk=
|
||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.8.0 h1:tgjwQrDH5m6jIYB7kac5IQZmfUzQNseac/e3H4VoCNE=
|
||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.8.0/go.mod h1:1HmmMEVsr+0R1QWahSeMJkjSkq6CYAZu1aIbYSpfJ4o=
|
||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.8.3 h1:ikrUPushSxbpr9mmDhSgz1KyUTChjwkDrxY/jzv2OTQ=
|
||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.8.3/go.mod h1:bnXbvnI9Mfqdj4L3Y9aCsB1A/ztuYLNRzgVKsJFgR/U=
|
||||
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
|
||||
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
|
||||
@@ -381,8 +381,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-github/v86 v86.0.0 h1:S/6aANJhwRm8EQmGKVML3j41yq0h2BsTP8FnDkO7kcA=
|
||||
github.com/google/go-github/v86 v86.0.0/go.mod h1:zKv1l4SwDXNFMGByi2FWkq71KwSXqj/eQRZuqtmcot8=
|
||||
github.com/google/go-github/v87 v87.0.0 h1:9Ck3dcOxWJyfsN8tzdah4YvmqB/7ZsstMglv/PkOsl0=
|
||||
github.com/google/go-github/v87 v87.0.0/go.mod h1:hGUoT5pwm/ck5uLL+wroSVQfg8mpe+buxllCcGV4VaM=
|
||||
github.com/google/go-querystring v1.2.0 h1:yhqkPbu2/OH+V9BfpCVPZkNmUXhb2gBxJArfhIxNtP0=
|
||||
github.com/google/go-querystring v1.2.0/go.mod h1:8IFJqpSRITyJ8QhQ13bmbeMBDfmeEJZD5A0egEOmkqU=
|
||||
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
|
||||
@@ -461,8 +461,8 @@ github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh6
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
|
||||
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
|
||||
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
|
||||
github.com/jhillyerd/enmime/v2 v2.3.0 h1:Y/pzQanyU8nkSgB2npXX8Dha5OItJE/QwbDJM4sf/kU=
|
||||
github.com/jhillyerd/enmime/v2 v2.3.0/go.mod h1:mGKXAP45l6pF6HZiaLhgSYsgteJskaSIYmEZXpw6ZpI=
|
||||
github.com/jhillyerd/enmime/v2 v2.4.0 h1:6bPyyg2OPXEK1fKsLT89DntZf05LqaL2cIx+cvkEXTo=
|
||||
github.com/jhillyerd/enmime/v2 v2.4.0/go.mod h1:TLpvqImPiumRecsJK5TYseRw2bPg3g0EtWc+SfU7cMs=
|
||||
github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=
|
||||
github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
@@ -517,8 +517,8 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4=
|
||||
github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
|
||||
github.com/mattn/go-runewidth v0.0.21 h1:jJKAZiQH+2mIinzCJIaIG9Be1+0NR+5sz/lYEEjdM8w=
|
||||
github.com/mattn/go-runewidth v0.0.21/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||
github.com/mattn/go-runewidth v0.0.23 h1:7ykA0T0jkPpzSvMS5i9uoNn2Xy3R383f9HDx3RybWcw=
|
||||
github.com/mattn/go-runewidth v0.0.23/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
|
||||
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.44 h1:3VSe+xafpbzsLbdr2AWlAZk9yRHiBhTBakioXaCKTF8=
|
||||
@@ -578,8 +578,8 @@ github.com/oasdiff/yaml3 v0.0.12 h1:75urAtPeDg2/iDEWwzNrLOWxI9N/dCh81nTTJtokt2M=
|
||||
github.com/oasdiff/yaml3 v0.0.12/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o=
|
||||
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 h1:zrbMGy9YXpIeTnGj4EljqMiZsIcE09mmF8XsD5AYOJc=
|
||||
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0=
|
||||
github.com/olekukonko/errors v1.2.0 h1:10Zcn4GeV59t/EGqJc8fUjtFT/FuUh5bTMzZ1XwmCRo=
|
||||
github.com/olekukonko/errors v1.2.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
|
||||
github.com/olekukonko/errors v1.3.0 h1:teJvgLGUEqMzBUms+Dj3/3szNqCG/Jdw9iDbum8fR6U=
|
||||
github.com/olekukonko/errors v1.3.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
|
||||
github.com/olekukonko/ll v0.1.8 h1:ysHCJRGHYKzmBSdz9w5AySztx7lG8SQY+naTGYUbsz8=
|
||||
github.com/olekukonko/ll v0.1.8/go.mod h1:RPRC6UcscfFZgjo1nulkfMH5IM0QAYim0LfnMvUuozw=
|
||||
github.com/olekukonko/tablewriter v1.1.4 h1:ORUMI3dXbMnRlRggJX3+q7OzQFDdvgbN9nVWj1drm6I=
|
||||
@@ -753,8 +753,8 @@ github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
|
||||
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
|
||||
github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs=
|
||||
github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s=
|
||||
gitlab.com/gitlab-org/api/client-go/v2 v2.26.0 h1:1E35d1GRLb22Yq7Jr4gWptjW1+Vg7ZDGogK/SZ6ijV8=
|
||||
gitlab.com/gitlab-org/api/client-go/v2 v2.26.0/go.mod h1:wx4w52UDENs3jolsL9cYT4byPNN9Pc6UpfGtCcHEIWY=
|
||||
gitlab.com/gitlab-org/api/client-go/v2 v2.30.0 h1:guXC+uOA325P1FIwUVesPoDcnogHnbPrhV8c+wMHZPE=
|
||||
gitlab.com/gitlab-org/api/client-go/v2 v2.30.0/go.mod h1:0upZTKi9YMMvhavTlKJ3YgQUZE/GJkcLmXT/+6knTXU=
|
||||
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
|
||||
go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
|
||||
|
||||
@@ -132,6 +132,32 @@ func GetStatusInfoList(ctx context.Context, lang translation.Locale) []StatusInf
|
||||
return statusInfoList
|
||||
}
|
||||
|
||||
// GetRunBranches returns branch names for the run-list "Branch" filter.
|
||||
// Sourced from the `branch` table (indexed by repo_id) rather than DISTINCT-ing
|
||||
// `action_run.ref`, which is wildcard-matched and slow on large repos; as a side
|
||||
// effect the list reflects existing branches, not only ones that produced a run.
|
||||
func GetRunBranches(ctx context.Context, repoID int64) ([]string, error) {
|
||||
branches := make([]string, 0, 10)
|
||||
return branches, db.GetEngine(ctx).Table("branch").
|
||||
Where("repo_id = ?", repoID).
|
||||
And("is_deleted = ?", false).
|
||||
Cols("name").
|
||||
OrderBy("name ASC").
|
||||
Find(&branches)
|
||||
}
|
||||
|
||||
// GetRunWorkflowIDs returns all distinct WorkflowIDs that have at least
|
||||
// one ActionRun in the given repo.
|
||||
func GetRunWorkflowIDs(ctx context.Context, repoID int64) ([]string, error) {
|
||||
ids := make([]string, 0, 10)
|
||||
return ids, db.GetEngine(ctx).Table("action_run").
|
||||
Where(builder.Eq{"repo_id": repoID}).
|
||||
Distinct("workflow_id").
|
||||
Cols("workflow_id").
|
||||
Asc("workflow_id").
|
||||
Find(&ids)
|
||||
}
|
||||
|
||||
// GetActors returns a slice of Actors
|
||||
func GetActors(ctx context.Context, repoID int64) ([]*user_model.User, error) {
|
||||
actors := make([]*user_model.User, 0, 10)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package actions
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetRunWorkflowIDs(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
ids, err := GetRunWorkflowIDs(t.Context(), 4)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{"artifact.yaml", "test.yaml"}, ids)
|
||||
|
||||
ids, err = GetRunWorkflowIDs(t.Context(), 999999)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, ids)
|
||||
}
|
||||
@@ -299,7 +299,7 @@ func TestIssue_ResolveMentions(t *testing.T) {
|
||||
func TestResourceIndex(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
var wg sync.WaitGroup
|
||||
for i := range 25 {
|
||||
for i := range 10 {
|
||||
wg.Go(func() {
|
||||
testInsertIssue(t, fmt.Sprintf("issue %d", i+1), "my issue", 0)
|
||||
})
|
||||
|
||||
@@ -207,7 +207,7 @@ type FixturesOptions struct {
|
||||
|
||||
// CreateTestEngine creates a test database and loads the fixture data from fixturesDir
|
||||
func CreateTestEngine(testSQLiteFile string, opts FixturesOptions) error {
|
||||
driver, connStr, err := db.ConnStr(db.ConnOptions{Type: setting.DatabaseTypeSQLite3, SQLitePath: testSQLiteFile, SQLiteBusyTimeout: 5000})
|
||||
driver, connStr, err := db.ConnStr(db.ConnOptions{Type: setting.DatabaseTypeSQLite3, SQLitePath: testSQLiteFile, SQLiteBusyTimeout: setting.DefaultSQLiteBusyTimeout})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ func TestFile(t *testing.T) {
|
||||
{
|
||||
name: "tags.py",
|
||||
code: "<>",
|
||||
want: lines(`<span class="o"><</span><span class="o">></span>`),
|
||||
want: lines(`<span class="o"><></span>`),
|
||||
lexerName: "Python",
|
||||
},
|
||||
{
|
||||
@@ -102,7 +102,7 @@ c=2
|
||||
<span class="n">def</span><span class="p">:</span>\n
|
||||
<span class="n">a</span><span class="o">=</span><span class="mi">1</span>\n
|
||||
\n
|
||||
<span class="n">b</span><span class="o">=</span><span class="sa"></span><span class="s1">'</span><span class="s1">'</span>\n
|
||||
<span class="n">b</span><span class="o">=</span><span class="s1">''</span>\n
|
||||
\n
|
||||
<span class="n">c</span><span class="o">=</span><span class="mi">2</span>`,
|
||||
),
|
||||
@@ -114,6 +114,18 @@ c=2
|
||||
want: []template.HTML{"<span class=\"c1\">--\n</span>", `<span class="k">SELECT</span>`},
|
||||
lexerName: "SQL",
|
||||
},
|
||||
{
|
||||
name: "test.http",
|
||||
code: `HTTP/1.0 400 Bad request
|
||||
Content-Type: text/html
|
||||
|
||||
<html></html>`,
|
||||
want: lines(`<span class="kr">HTTP</span><span class="o">/</span><span class="m">1.0</span> <span class="m">400</span> <span class="ne">Bad request</span>\n
|
||||
<span class="n">Content-Type</span><span class="o">:</span> <span class="l">text/html</span>\n
|
||||
\n
|
||||
<span class="p"><</span><span class="nt">html</span><span class="p">></</span><span class="nt">html</span><span class="p">></span>`),
|
||||
lexerName: "HTTP",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
@@ -289,24 +289,24 @@ func detectChromaLexerWithAnalyze(fileName, lang string, code []byte) chroma.Lex
|
||||
|
||||
// if lang is provided, and it matches a lexer, use it directly
|
||||
if byLang {
|
||||
return lexer
|
||||
return chroma.Coalesce(lexer)
|
||||
}
|
||||
|
||||
// if a lexer is detected and there is no conflict for the file extension, use it directly
|
||||
fileExt := path.Ext(fileName)
|
||||
_, hasConflicts := chromaLexers().conflictingExtLangMap[fileExt]
|
||||
if !hasConflicts && lexer != lexers.Fallback {
|
||||
return lexer
|
||||
return chroma.Coalesce(lexer)
|
||||
}
|
||||
|
||||
// try to detect language by content, for best guessing for the language
|
||||
// when using "code" to detect, analyze.GetCodeLanguage is slow, it iterates many rules to detect language from content
|
||||
analyzedLanguage := analyze.GetCodeLanguage(fileName, code)
|
||||
lexer = DetectChromaLexerByFileName(fileName, analyzedLanguage)
|
||||
lexer, _ = detectChromaLexerByFileName(fileName, analyzedLanguage)
|
||||
if lexer == lexers.Fallback {
|
||||
if analyzedLanguage != enry.OtherLanguage {
|
||||
log.Warn("No chroma lexer found for enry detected language: %s (file: %s), need to fix the language mapping between enry and chroma.", analyzedLanguage, fileName)
|
||||
}
|
||||
}
|
||||
return lexer
|
||||
return chroma.Coalesce(lexer)
|
||||
}
|
||||
|
||||
@@ -181,10 +181,11 @@ func (u *User) UnmarshalJSON(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Repository https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md#version
|
||||
// Repository https://docs.npmjs.com/cli/v11/configuring-npm/package-json#repository
|
||||
type Repository struct {
|
||||
Type string `json:"type"`
|
||||
URL string `json:"url"`
|
||||
Type string `json:"type"`
|
||||
URL string `json:"url"`
|
||||
Directory string `json:"directory,omitempty"`
|
||||
}
|
||||
|
||||
// PackageAttachment https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md#package
|
||||
|
||||
@@ -28,8 +28,9 @@ func TestParsePackage(t *testing.T) {
|
||||
data := "H4sIAAAAAAAA/ytITM5OTE/VL4DQelnF+XkMVAYGBgZmJiYK2MRBwNDcSIHB2NTMwNDQzMwAqA7IMDUxA9LUdgg2UFpcklgEdAql5kD8ogCnhwio5lJQUMpLzE1VslJQcihOzi9I1S9JLS7RhSYIJR2QgrLUouLM/DyQGkM9Az1D3YIiqExKanFyUWZBCVQ2BKhVwQVJDKwosbQkI78IJO/tZ+LsbRykxFXLNdA+HwWjYBSMgpENACgAbtAACAAA"
|
||||
integrity := "sha512-yA4FJsVhetynGfOC1jFf79BuS+jrHbm0fhh+aHzCQkOaOBXKf9oBnC4a6DnLLnEsHQDRLYd00cwj8sCXpC+wIg=="
|
||||
repository := Repository{
|
||||
Type: "gitea",
|
||||
URL: "http://localhost:3000/gitea/test.git",
|
||||
Type: "gitea",
|
||||
URL: "http://localhost:3000/gitea/test.git",
|
||||
Directory: "packages/test-package",
|
||||
}
|
||||
|
||||
t.Run("InvalidUpload", func(t *testing.T) {
|
||||
@@ -298,6 +299,7 @@ func TestParsePackage(t *testing.T) {
|
||||
assert.Equal(t, "1.2.0", p.Metadata.Dependencies["package"])
|
||||
assert.Equal(t, repository.Type, p.Metadata.Repository.Type)
|
||||
assert.Equal(t, repository.URL, p.Metadata.Repository.URL)
|
||||
assert.Equal(t, repository.Directory, p.Metadata.Repository.Directory)
|
||||
})
|
||||
|
||||
t.Run("ValidLicenseMap", func(t *testing.T) {
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const defaultSQLiteBusyTimeout = 20 * 1000
|
||||
const DefaultSQLiteBusyTimeout = 20 * 1000
|
||||
|
||||
var (
|
||||
// SupportedDatabaseTypes includes all XORM supported databases type, sqlite3 maybe added by the tag-controlled drivers
|
||||
@@ -66,11 +66,11 @@ func loadDBSetting(rootCfg ConfigProvider) {
|
||||
|
||||
Database.Path = sec.Key("PATH").MustString(filepath.Join(AppDataPath, "gitea.db"))
|
||||
|
||||
Database.SQLiteBusyTimeout = sec.Key("SQLITE_TIMEOUT").MustInt(defaultSQLiteBusyTimeout)
|
||||
Database.SQLiteBusyTimeout = sec.Key("SQLITE_TIMEOUT").MustInt(DefaultSQLiteBusyTimeout)
|
||||
// mattn driver isn't really affected by this timeout, but other drivers are affected
|
||||
// the default value was 500 (0.5s), to avoid breaking existing users, make sure the timeout is long enough (at least, 5 seconds)
|
||||
if Database.SQLiteBusyTimeout < 5000 {
|
||||
Database.SQLiteBusyTimeout = defaultSQLiteBusyTimeout
|
||||
Database.SQLiteBusyTimeout = DefaultSQLiteBusyTimeout
|
||||
}
|
||||
Database.SQLiteJournalMode = sec.Key("SQLITE_JOURNAL_MODE").MustString("")
|
||||
|
||||
|
||||
@@ -434,6 +434,10 @@ type ChangesPayload struct {
|
||||
type PullRequestPayload struct {
|
||||
// The action performed on the pull request
|
||||
Action HookIssueAction `json:"action"`
|
||||
// The SHA of the most recent commit on the PR head branch before the push
|
||||
Before string `json:"before,omitempty"`
|
||||
// The SHA of the most recent commit on the PR head branch after the push
|
||||
After string `json:"after,omitempty"`
|
||||
// The index number of the pull request
|
||||
Index int64 `json:"number"`
|
||||
// Changes made to the pull request (for edit actions)
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package structs
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPullRequestPayloadSynchronizeBeforeAfter(t *testing.T) {
|
||||
payload := &PullRequestPayload{
|
||||
Action: HookIssueSynchronized,
|
||||
Before: "1111111111111111111111111111111111111111",
|
||||
After: "2222222222222222222222222222222222222222",
|
||||
Index: 12,
|
||||
}
|
||||
|
||||
data, err := json.Marshal(payload)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.JSONEq(t, `{
|
||||
"action": "synchronized",
|
||||
"before": "1111111111111111111111111111111111111111",
|
||||
"after": "2222222222222222222222222222222222222222",
|
||||
"number": 12,
|
||||
"commit_id": "",
|
||||
"pull_request": null,
|
||||
"repository": null,
|
||||
"requested_reviewer": null,
|
||||
"review": null,
|
||||
"sender": null
|
||||
}`, string(data))
|
||||
}
|
||||
|
||||
func TestPullRequestPayloadNonSynchronizeOmitsBeforeAfter(t *testing.T) {
|
||||
payload := &PullRequestPayload{
|
||||
Action: HookIssueOpened,
|
||||
Index: 12,
|
||||
}
|
||||
|
||||
data, err := json.Marshal(payload)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.JSONEq(t, `{
|
||||
"action": "opened",
|
||||
"number": 12,
|
||||
"commit_id": "",
|
||||
"pull_request": null,
|
||||
"repository": null,
|
||||
"requested_reviewer": null,
|
||||
"review": null,
|
||||
"sender": null
|
||||
}`, string(data))
|
||||
}
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/modules/charset"
|
||||
"code.gitea.io/gitea/modules/emoji"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/htmlutil"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/markup"
|
||||
@@ -223,6 +224,25 @@ func (ut *RenderUtils) MarkdownToHtml(input string) template.HTML { //nolint:rev
|
||||
return output
|
||||
}
|
||||
|
||||
// RenderPackageMarkdown renders package page Markdown so relative links resolve against the
|
||||
// linked repository's default branch instead of the site root, falling back to plain rendering
|
||||
// when there is no linked repository. pkgTreePath optionally roots links in a subdirectory
|
||||
// (e.g. npm's repository.directory for monorepo packages).
|
||||
func (ut *RenderUtils) RenderPackageMarkdown(input string, linkedRepo *repo.Repository, pkgTreePath ...string) template.HTML {
|
||||
if linkedRepo == nil {
|
||||
return `<div class="markup markdown">` + ut.MarkdownToHtml(input) + `</div>`
|
||||
}
|
||||
rctx := renderhelper.NewRenderContextRepoFile(ut.ctx, linkedRepo, renderhelper.RepoFileOptions{
|
||||
CurrentRefSubURL: git.RefNameFromBranch(linkedRepo.DefaultBranch).RefWebLinkPath(),
|
||||
CurrentTreePath: util.OptionalArg(pkgTreePath),
|
||||
})
|
||||
output, err := markdown.RenderString(rctx, input)
|
||||
if err != nil {
|
||||
log.Error("RenderString: %v", err)
|
||||
}
|
||||
return `<div class="markup markdown">` + output + `</div>`
|
||||
}
|
||||
|
||||
func (ut *RenderUtils) RenderLabels(labels []*issues_model.Label, repoLink string, issue *issues_model.Issue) template.HTML {
|
||||
isPullRequest := issue != nil && issue.IsPull
|
||||
baseLink := fmt.Sprintf("%s/%s", repoLink, util.Iif(isPullRequest, "pulls", "issues"))
|
||||
|
||||
@@ -194,6 +194,38 @@ space</p>
|
||||
assert.Equal(t, expected, string(newTestRenderUtils(t).MarkdownToHtml(testInput())))
|
||||
}
|
||||
|
||||
func TestRenderPackageMarkdown(t *testing.T) {
|
||||
defer test.MockVariableValue(&markup.RenderBehaviorForTesting.DisableAdditionalAttributes, true)()
|
||||
mockRepo := &repo.Repository{
|
||||
ID: 1, OwnerName: "user13", Name: "repo11", DefaultBranch: "main",
|
||||
Owner: &user_model.User{ID: 13, Name: "user13"},
|
||||
Units: []*repo.RepoUnit{},
|
||||
}
|
||||
ut := newTestRenderUtils(t)
|
||||
|
||||
t.Run("LinkedRepoWithDirectory", func(t *testing.T) {
|
||||
rendered := ut.RenderPackageMarkdown("[docs](docs/getting-started.md)\n", mockRepo, "pkg-subdir")
|
||||
expected := `<div class="markup markdown"><p><a href="/user13/repo11/src/branch/main/pkg-subdir/docs/getting-started.md" rel="nofollow">docs</a>
|
||||
<a href="/user13/repo11/src/branch/main/pkg-subdir/logo.png" target="_blank" rel="nofollow noopener"><img src="/user13/repo11/media/branch/main/pkg-subdir/logo.png" alt="logo"/></a></p>
|
||||
</div>`
|
||||
assert.Equal(t, expected, strings.TrimSpace(string(rendered)))
|
||||
})
|
||||
|
||||
t.Run("LinkedRepoWithEmptyDirectory", func(t *testing.T) {
|
||||
rendered := ut.RenderPackageMarkdown("[docs](docs/getting-started.md)", mockRepo, "")
|
||||
expected := `<div class="markup markdown"><p><a href="/user13/repo11/src/branch/main/docs/getting-started.md" rel="nofollow">docs</a></p>
|
||||
</div>`
|
||||
assert.Equal(t, expected, strings.TrimSpace(string(rendered)))
|
||||
})
|
||||
|
||||
t.Run("UnlinkedRepo", func(t *testing.T) {
|
||||
rendered := ut.RenderPackageMarkdown("[docs](docs/getting-started.md)", nil, "pkg-subdir")
|
||||
expected := `<div class="markup markdown"><p><a href="/docs/getting-started.md" rel="nofollow">docs</a></p>
|
||||
</div>`
|
||||
assert.Equal(t, expected, strings.TrimSpace(string(rendered)))
|
||||
})
|
||||
}
|
||||
|
||||
func TestRenderLabels(t *testing.T) {
|
||||
ut := newTestRenderUtils(t)
|
||||
label := &issues.Label{ID: 123, Name: "label-name", Color: "label-color"}
|
||||
|
||||
@@ -3759,6 +3759,8 @@
|
||||
"actions.runners.reset_registration_token_confirm": "Would you like to invalidate the current token and generate a new one?",
|
||||
"actions.runners.reset_registration_token_success": "Runner registration token reset successfully",
|
||||
"actions.runs.all_workflows": "All Workflows",
|
||||
"actions.runs.other_workflows": "Other workflows",
|
||||
"actions.runs.other_workflows_tooltip": "Workflows that were executed in this repository but do not exist on the default branch.",
|
||||
"actions.runs.workflow_run_count_1": "%d workflow run",
|
||||
"actions.runs.workflow_run_count_n": "%d workflow runs",
|
||||
"actions.runs.commit": "Commit",
|
||||
@@ -3774,6 +3776,8 @@
|
||||
"actions.runs.status": "Status",
|
||||
"actions.runs.actors_no_select": "All actors",
|
||||
"actions.runs.status_no_select": "All status",
|
||||
"actions.runs.branch": "Branch",
|
||||
"actions.runs.branches_no_select": "All branches",
|
||||
"actions.runs.no_results": "No results matched.",
|
||||
"actions.runs.no_workflows": "There are no workflows yet.",
|
||||
"actions.runs.no_workflows.quick_start": "Don't know how to start with Gitea Actions? See <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"%s\">the quick start guide</a>.",
|
||||
|
||||
@@ -81,9 +81,11 @@
|
||||
"retry": "再試行",
|
||||
"rerun": "再実行",
|
||||
"rerun_all": "すべてのジョブを再実行",
|
||||
"rerun_failed": "失敗したジョブを再実行",
|
||||
"save": "保存",
|
||||
"add": "追加",
|
||||
"add_all": "すべて追加",
|
||||
"dismiss": "閉じる",
|
||||
"remove": "除去",
|
||||
"remove_all": "すべて除去",
|
||||
"remove_label_str": "アイテム「%s」を削除",
|
||||
@@ -103,6 +105,7 @@
|
||||
"copy_error": "コピーに失敗しました",
|
||||
"copy_type_unsupported": "このファイルタイプはコピーできません",
|
||||
"copy_filename": "ファイル名をコピー",
|
||||
"copy_output": "出力をコピー",
|
||||
"write": "書き込み",
|
||||
"preview": "プレビュー",
|
||||
"loading": "読み込み中…",
|
||||
@@ -120,6 +123,7 @@
|
||||
"unpin": "ピン留め解除",
|
||||
"artifacts": "成果物",
|
||||
"expired": "期限切れ",
|
||||
"artifact_expires_at": "保存期限 %s",
|
||||
"confirm_delete_artifact": "アーティファクト '%s' を削除してよろしいですか?",
|
||||
"archived": "アーカイブ",
|
||||
"concept_system_global": "グローバル",
|
||||
@@ -167,9 +171,12 @@
|
||||
"search.exact_tooltip": "検索語と完全に一致する結果だけを含めます",
|
||||
"search.repo_kind": "リポジトリを検索…",
|
||||
"search.user_kind": "ユーザーを検索…",
|
||||
"search.badge_kind": "バッジを検索…",
|
||||
"search.org_kind": "組織を検索…",
|
||||
"search.team_kind": "チームを検索…",
|
||||
"search.code_kind": "コードを検索…",
|
||||
"search.code_empty": "コード検索を開始。",
|
||||
"search.code_empty_description": "コード全体から検索するキーワードを入力してください。",
|
||||
"search.code_search_unavailable": "コード検索は現在利用できません。 サイト管理者にお問い合わせください。",
|
||||
"search.code_search_by_git_grep": "現在のコード検索は \"git grep\" によって行われています。 サイト管理者がリポジトリインデクサーを有効にすれば、より優れた結果が得られる可能性があります。",
|
||||
"search.package_kind": "パッケージを検索…",
|
||||
@@ -210,11 +217,15 @@
|
||||
"editor.buttons.switch_to_legacy.tooltip": "レガシーエディタを使用する",
|
||||
"editor.buttons.enable_monospace_font": "等幅フォントを有効にする",
|
||||
"editor.buttons.disable_monospace_font": "等幅フォントを無効にする",
|
||||
"editor.code_editor.command_palette": "コマンドパレット",
|
||||
"editor.code_editor.find": "検索",
|
||||
"editor.code_editor.placeholder": "ファイルの内容をここに入力",
|
||||
"filter.string.asc": "A–Z",
|
||||
"filter.string.desc": "Z–A",
|
||||
"error.occurred": "エラーが発生しました",
|
||||
"error.report_message": "Gitea のバグが疑われる場合は、<a href=\"%s\" target=\"_blank\">GitHub</a>でIssueを検索して、見つからなければ新しいIssueを作成してください。",
|
||||
"error.not_found": "ターゲットが見つかりませんでした。",
|
||||
"error.permission_denied": "権限がありません。",
|
||||
"error.network_error": "ネットワークエラー",
|
||||
"startpage.app_desc": "自分で立てる、超簡単 Git サービス",
|
||||
"startpage.install": "簡単インストール",
|
||||
@@ -261,7 +272,7 @@
|
||||
"install.lfs_path": "Git LFSルートパス",
|
||||
"install.lfs_path_helper": "Git LFSで管理するファイルが、このディレクトリに保存されます。 空欄にするとGit LFSを無効にします。",
|
||||
"install.run_user": "実行ユーザー名",
|
||||
"install.run_user_helper": "オペレーティングシステム上のユーザー名です。 Giteaをこのユーザーとして実行します。 このユーザーはリポジトリルートパスへのアクセス権を持っている必要があります。",
|
||||
"install.run_user_helper": "Giteaを実行しているオペレーティングシステム上のユーザー名です。 このユーザーにはデータパスへの書き込み権限が必要です。 この値は自動的に検出されたもので、ここでは変更できません。 別のユーザーを使用するには、そのアカウントからGiteaを再起動してください。",
|
||||
"install.domain": "サーバードメイン",
|
||||
"install.domain_helper": "サーバーのドメインまたはホストアドレス。",
|
||||
"install.ssh_port": "SSHサーバーのポート",
|
||||
@@ -284,12 +295,6 @@
|
||||
"install.register_confirm": "登録にはメールによる確認が必要",
|
||||
"install.mail_notify": "メール通知を有効にする",
|
||||
"install.server_service_title": "サーバーと外部サービスの設定",
|
||||
"install.offline_mode": "ローカルモードを有効にする",
|
||||
"install.offline_mode_popup": "外のCDNサービスを使わず、すべてのリソースを自前で提供します。",
|
||||
"install.disable_gravatar": "Gravatarを無効にする",
|
||||
"install.disable_gravatar_popup": "Gravatarと外のアバターソースを無効にします。 アバターをローカルにアップロードしていないユーザーには、デフォルトのアバターが使用されます。",
|
||||
"install.federated_avatar_lookup": "フェデレーテッド・アバターを有効にする",
|
||||
"install.federated_avatar_lookup_popup": "Libravatarを使用したフェデレーテッド・アバター検索を有効にします。",
|
||||
"install.disable_registration": "セルフ登録を無効にする",
|
||||
"install.disable_registration_popup": "ユーザーのセルフ登録を無効にします。 新しいユーザーアカウントを作成できるのは管理者だけとなります。",
|
||||
"install.allow_only_external_registration_popup": "外部サービスを使用した登録のみを許可",
|
||||
@@ -309,12 +314,10 @@
|
||||
"install.admin_email": "メールアドレス",
|
||||
"install.install_btn_confirm": "Giteaをインストール",
|
||||
"install.test_git_failed": "'git'コマンドが確認できません: %v",
|
||||
"install.sqlite3_not_available": "GiteaのこのバージョンはSQLite3をサポートしていません。 公式のバイナリ版を %s からダウンロードしてください。 ('gobuild'版でないもの)",
|
||||
"install.invalid_db_setting": "データベース設定が無効です: %v",
|
||||
"install.invalid_db_table": "データベーステーブルの \"%s\" が無効です: %v",
|
||||
"install.invalid_repo_path": "リポジトリのルートパスが無効です: %v",
|
||||
"install.invalid_app_data_path": "アプリのデータパス (APP_DATA_PATH) が無効です: %v",
|
||||
"install.run_user_not_match": "実行ユーザー名が、現在のユーザー名ではありません: %s -> %s",
|
||||
"install.internal_token_failed": "内部トークンの生成に失敗しました: %v",
|
||||
"install.secret_key_failed": "シークレットキーの生成に失敗しました: %v",
|
||||
"install.save_config_failed": "設定ファイルの保存に失敗しました: %v",
|
||||
@@ -547,6 +550,7 @@
|
||||
"form.glob_pattern_error": "のglobパターンが不正です: %s.",
|
||||
"form.regex_pattern_error": "の正規表現パターンが不正です: %s.",
|
||||
"form.username_error": "は、英数字('0-9','a-z','A-Z')、ダッシュ('-')、アンダースコア('_')、ドット('.')だけを含めることができます。 先頭と末尾は英数字以外の文字にはできません。 また、連続した英数字以外の文字も許されません。",
|
||||
"form.invalid_slug_error": " は無効です。",
|
||||
"form.invalid_group_team_map_error": "のマッピングが無効です: %s",
|
||||
"form.unknown_error": "不明なエラー:",
|
||||
"form.captcha_incorrect": "CAPTCHAコードが正しくありません。",
|
||||
@@ -635,14 +639,8 @@
|
||||
"user.block.unblock.failure": "ユーザーのブロック解除に失敗しました: %s",
|
||||
"user.block.blocked": "あなたはこのユーザーをブロックしています。",
|
||||
"user.block.title": "ユーザーをブロックする",
|
||||
"user.block.info": "ユーザーをブロックすると、そのユーザーは、プルリクエストやイシューの作成、コメントの投稿など、リポジトリに対する操作ができなくなります。 ユーザーのブロックについてはよく確認してください。",
|
||||
"user.block.info_1": "ユーザーをブロックすることで、あなたのアカウントとあなたのリポジトリに対する以下の行為を阻止します:",
|
||||
"user.block.info_2": "あなたのアカウントのフォロー",
|
||||
"user.block.info_3": "あなたのユーザー名で@メンションして通知を送ること",
|
||||
"user.block.info_4": "そのユーザーのリポジトリに、あなたを共同作業者として招待すること",
|
||||
"user.block.info_5": "リポジトリへの、スター、フォーク、ウォッチ",
|
||||
"user.block.info_6": "イシューやプルリクエストの作成、コメント投稿",
|
||||
"user.block.info_7": "イシューやプルリクエストでの、あなたのコメントに対するリアクションの送信",
|
||||
"user.block.info": "ユーザーをブロックすると、そのユーザーは、プルリクエストやイシューの作成、コメントの投稿など、リポジトリに対する操作ができなくなります。",
|
||||
"user.block.info.docs": "ユーザーのブロックについて詳しくはこちらをご覧ください。",
|
||||
"user.block.user_to_block": "ブロックするユーザー",
|
||||
"user.block.note": "メモ",
|
||||
"user.block.note.title": "メモ(任意):",
|
||||
@@ -650,6 +648,7 @@
|
||||
"user.block.note.edit": "メモを編集",
|
||||
"user.block.list": "ブロックしたユーザー",
|
||||
"user.block.list.none": "ブロックしているユーザーはいません。",
|
||||
"settings.general": "一般",
|
||||
"settings.profile": "プロフィール",
|
||||
"settings.account": "アカウント",
|
||||
"settings.appearance": "外観",
|
||||
@@ -970,7 +969,6 @@
|
||||
"repo.visibility_description": "オーナー、または権限を持つ組織のメンバーだけが、リポジトリを見ることができます。",
|
||||
"repo.visibility_helper": "リポジトリをプライベートにする",
|
||||
"repo.visibility_helper_forced": "サイト管理者の設定により、新しいリポジトリは強制的にプライベートになります。",
|
||||
"repo.visibility_fork_helper": "(この変更はすべてのフォークに適用されます)",
|
||||
"repo.clone_helper": "クローンに関してお困りであれば<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"%s\">ヘルプ</a>を参照しましょう。",
|
||||
"repo.fork_repo": "リポジトリをフォーク",
|
||||
"repo.fork_from": "フォーク元",
|
||||
@@ -1042,6 +1040,7 @@
|
||||
"repo.forks": "フォーク",
|
||||
"repo.stars": "スター",
|
||||
"repo.reactions_more": "さらに %d 件",
|
||||
"repo.reactions": "リアクション",
|
||||
"repo.unit_disabled": "サイト管理者がこのリポジトリセクションを無効にしています。",
|
||||
"repo.language_other": "その他",
|
||||
"repo.adopt_search": "未登録リポジトリを探すユーザー名を入力… (空ですべてを探索)",
|
||||
@@ -1062,8 +1061,8 @@
|
||||
"repo.transfer.accept_desc": "\"%s\" に移転",
|
||||
"repo.transfer.reject": "移転を拒否",
|
||||
"repo.transfer.reject_desc": "\"%s\" への移転をキャンセル",
|
||||
"repo.transfer.no_permission_to_accept": "この移転を承認する権限がありません。",
|
||||
"repo.transfer.no_permission_to_reject": "この移転を拒否する権限がありません。",
|
||||
"repo.transfer.is_transferring": "移転処理中…",
|
||||
"repo.transfer.is_transferring_prompt": "リポジトリは %s に移転処理中です",
|
||||
"repo.desc.private": "プライベート",
|
||||
"repo.desc.public": "公開",
|
||||
"repo.desc.public_access": "公開アクセス",
|
||||
@@ -1214,7 +1213,7 @@
|
||||
"repo.ambiguous_runes_description": "このファイルには、他の文字と見間違える可能性があるUnicode文字が含まれています。 それが意図的なものと考えられる場合は、この警告を無視して構いません。 それらの文字を表示するにはエスケープボタンを使用します。",
|
||||
"repo.invisible_runes_line": "この行には不可視のUnicode文字があります",
|
||||
"repo.ambiguous_runes_line": "この行には曖昧(ambiguous)なUnicode文字があります",
|
||||
"repo.ambiguous_character": "%[1]c [U+%04[1]X] は %[2]c [U+%04[2]X] と混同するおそれがあります",
|
||||
"repo.ambiguous_character": "%[1]s は %[2]s と混同するおそれがあります",
|
||||
"repo.escape_control_characters": "エスケープ",
|
||||
"repo.unescape_control_characters": "エスケープ解除",
|
||||
"repo.file_copy_permalink": "パーマリンクをコピー",
|
||||
@@ -1307,9 +1306,9 @@
|
||||
"repo.editor.upload_file_is_locked": "ファイル \"%s\" は %s がロックしています。",
|
||||
"repo.editor.upload_files_to_dir": "\"%s\" にファイルをアップロード",
|
||||
"repo.editor.cannot_commit_to_protected_branch": "保護されたブランチ \"%s\" にコミットすることはできません。",
|
||||
"repo.editor.no_commit_to_branch": "ブランチに直接コミットすることはできません、なぜなら:",
|
||||
"repo.editor.no_commit_to_branch": "ブランチに直接コミットすることは許可されません、なぜなら:",
|
||||
"repo.editor.user_no_push_to_branch": "ユーザーはブランチにプッシュできません",
|
||||
"repo.editor.require_signed_commit": "ブランチでは署名されたコミットが必須です",
|
||||
"repo.editor.require_signed_commit": "ブランチには署名済みコミットが必要です",
|
||||
"repo.editor.cherry_pick": "チェリーピック %s:",
|
||||
"repo.editor.revert": "リバート %s:",
|
||||
"repo.editor.failed_to_commit": "変更のコミットに失敗しました。",
|
||||
@@ -1323,7 +1322,7 @@
|
||||
"repo.commits.desc": "ソースコードの変更履歴を参照します。",
|
||||
"repo.commits.commits": "コミット",
|
||||
"repo.commits.no_commits": "共通のコミットはありません。 \"%s\" と \"%s\" の履歴はすべて異なっています。",
|
||||
"repo.commits.nothing_to_compare": "二つのブランチは同じ内容です。",
|
||||
"repo.commits.nothing_to_compare": "差分はありません。",
|
||||
"repo.commits.search.tooltip": "キーワード \"author:\"、\"committer:\"、\"after:\"、\"before:\" を付けて指定できます。 例 \"revert author:Alice before:2019-01-13\"",
|
||||
"repo.commits.search_branch": "このブランチ",
|
||||
"repo.commits.search_all": "すべてのブランチ",
|
||||
@@ -1355,10 +1354,13 @@
|
||||
"repo.projects.desc": "プロジェクトでイシューとプルリクエストを管理します。",
|
||||
"repo.projects.description": "説明 (オプション)",
|
||||
"repo.projects.description_placeholder": "説明",
|
||||
"repo.projects.empty": "プロジェクトはまだありません。",
|
||||
"repo.projects.empty_description": "イシューとプルリクエストを整理するために、プロジェクトを作成してください。",
|
||||
"repo.projects.create": "プロジェクトを作成",
|
||||
"repo.projects.title": "タイトル",
|
||||
"repo.projects.new": "新しいプロジェクト",
|
||||
"repo.projects.new_subheader": "作業の調整・追跡・更新をひとつの場所で行い、プロジェクトの透明性と良好な進捗を維持します。",
|
||||
"repo.projects.no_results": "検索条件に一致するプロジェクトはありません。",
|
||||
"repo.projects.create_success": "プロジェクト \"%s\" を作成しました。",
|
||||
"repo.projects.deletion": "プロジェクトの削除",
|
||||
"repo.projects.deletion_desc": "プロジェクトを削除し、関連するすべてのイシューから除去します。続行しますか?",
|
||||
@@ -1383,6 +1385,7 @@
|
||||
"repo.projects.column.delete": "列を削除",
|
||||
"repo.projects.column.deletion_desc": "プロジェクト列を削除すると、関連するすべてのイシューがデフォルトの列に移動します。 続行しますか?",
|
||||
"repo.projects.column.color": "カラー",
|
||||
"repo.projects.column": "列",
|
||||
"repo.projects.open": "オープン",
|
||||
"repo.projects.close": "クローズ",
|
||||
"repo.projects.column.assigned_to": "担当",
|
||||
@@ -1400,11 +1403,12 @@
|
||||
"repo.issues.new": "新しいイシュー",
|
||||
"repo.issues.new.title_empty": "タイトルは空にできません",
|
||||
"repo.issues.new.labels": "ラベル",
|
||||
"repo.issues.new.no_label": "ラベルなし",
|
||||
"repo.issues.new.no_labels": "ラベルなし",
|
||||
"repo.issues.new.clear_labels": "ラベルをクリア",
|
||||
"repo.issues.new.projects": "プロジェクト",
|
||||
"repo.issues.new.clear_projects": "プロジェクトをクリア",
|
||||
"repo.issues.new.no_projects": "プロジェクトなし",
|
||||
"repo.issues.new.no_column": "列なし",
|
||||
"repo.issues.new.open_projects": "オープン中のプロジェクト",
|
||||
"repo.issues.new.closed_projects": "クローズ済みプロジェクト",
|
||||
"repo.issues.new.no_items": "項目なし",
|
||||
@@ -1524,16 +1528,18 @@
|
||||
"repo.issues.commented_at": "がコメント <a href=\"#%s\">%s</a>",
|
||||
"repo.issues.delete_comment_confirm": "このコメントを削除してよろしいですか?",
|
||||
"repo.issues.context.copy_link": "リンクをコピー",
|
||||
"repo.issues.context.copy_source": "ソースをコピー",
|
||||
"repo.issues.context.quote_reply": "引用して返信",
|
||||
"repo.issues.context.reference_issue": "新しいイシューから参照",
|
||||
"repo.issues.context.edit": "編集",
|
||||
"repo.issues.context.delete": "削除",
|
||||
"repo.issues.no_content": "説明はありません。",
|
||||
"repo.issues.comment_no_content": "コメントはありません。",
|
||||
"repo.issues.close": "イシューをクローズ",
|
||||
"repo.issues.comment_pull_merged_at": "がコミット %[1]s を %[2]s にマージ %[3]s",
|
||||
"repo.issues.comment_manually_pull_merged_at": "がコミット %[1]s を %[2]s に手動マージ %[3]s",
|
||||
"repo.issues.close_comment_issue": "コメントしてクローズ",
|
||||
"repo.issues.reopen_issue": "再オープンする",
|
||||
"repo.issues.reopen_issue": "イシューを再オープン",
|
||||
"repo.issues.reopen_comment_issue": "コメントして再オープン",
|
||||
"repo.issues.create_comment": "コメントする",
|
||||
"repo.issues.comment.blocked_user": "投稿者またはリポジトリのオーナーがあなたをブロックしているため、コメントの作成や編集はできません。",
|
||||
@@ -1778,8 +1784,9 @@
|
||||
"repo.pulls.select_commit_hold_shift_for_range": "コミットを選択。シフトを押しながらクリックで範囲選択。",
|
||||
"repo.pulls.review_only_possible_for_full_diff": "すべての差分を表示しているときだけレビューが可能です",
|
||||
"repo.pulls.filter_changes_by_commit": "コミットで絞り込み",
|
||||
"repo.pulls.nothing_to_compare": "同じブランチ同士のため、 プルリクエストを作成する必要がありません。",
|
||||
"repo.pulls.nothing_to_compare_have_tag": "選択したブランチ/タグは同一のものです。",
|
||||
"repo.pulls.nothing_to_compare": "差分がないため、 プルリクエストを作成する必要はありません。",
|
||||
"repo.pulls.no_common_history": "これらのブランチには共通のマージベースがありません。 別のベースブランチまたは比較ブランチを選択してください。",
|
||||
"repo.pulls.nothing_to_compare_have_tag": "選択したブランチ/タグの間で差分がありません。",
|
||||
"repo.pulls.nothing_to_compare_and_allow_empty_pr": "これらのブランチは内容が同じです。 空のプルリクエストになります。",
|
||||
"repo.pulls.has_pull_request": "同じブランチのプルリクエストはすでに存在します: <a href=\"%[1]s\">%[2]s#%[3]d</a>",
|
||||
"repo.pulls.create": "プルリクエストを作成",
|
||||
@@ -1813,6 +1820,7 @@
|
||||
"repo.pulls.required_status_check_failed": "いくつかの必要なステータスチェックが成功していません。",
|
||||
"repo.pulls.required_status_check_missing": "必要なチェックがいくつか抜けています。",
|
||||
"repo.pulls.required_status_check_administrator": "管理者であるため、このプルリクエストをマージすることは可能です。",
|
||||
"repo.pulls.required_status_check_bypass_allowlist": "あなたには、このマージでブランチ保護ルールのバイパスが許可されています。",
|
||||
"repo.pulls.blocked_by_approvals": "このプルリクエストはまだ必要な承認数を満たしていません。 公式の承認を %[1]d / %[2]d 得ています。",
|
||||
"repo.pulls.blocked_by_approvals_whitelisted": "このプルリクエストはまだ必要な承認数を満たしていません。 許可リストのユーザーまたはチームからの承認を %[1]d / %[2]d 得ています。",
|
||||
"repo.pulls.blocked_by_rejection": "このプルリクエストは公式レビューアにより変更要請されています。",
|
||||
@@ -1844,7 +1852,8 @@
|
||||
"repo.pulls.fast_forward_only_merge_pull_request": "ファストフォワードのみ",
|
||||
"repo.pulls.merge_manually": "手動マージ済みにする",
|
||||
"repo.pulls.merge_commit_id": "マージコミットID",
|
||||
"repo.pulls.require_signed_wont_sign": "ブランチでは署名されたコミットが必須ですが、このマージでは署名がされません",
|
||||
"repo.pulls.require_signed_wont_sign": "ブランチには署名済みコミットが必要ですが、このマージでは署名がされません",
|
||||
"repo.pulls.require_signed_head_commits_unverified": "ブランチには署名済みコミットが必要ですが、このプルリクエストに対する 1つ以上のコミットは検証されていません",
|
||||
"repo.pulls.invalid_merge_option": "このプルリクエストでは、指定したマージ方法は使えません。",
|
||||
"repo.pulls.merge_conflict": "マージ失敗: マージ中にコンフリクトがありました。 ヒント: 別のストラテジーを試してみてください。",
|
||||
"repo.pulls.merge_conflict_summary": "エラーメッセージ",
|
||||
@@ -1877,6 +1886,7 @@
|
||||
"repo.pulls.update_not_allowed": "ブランチを更新する権限がありません",
|
||||
"repo.pulls.outdated_with_base_branch": "このブランチはベースブランチに対して最新ではありません",
|
||||
"repo.pulls.close": "プルリクエストをクローズ",
|
||||
"repo.pulls.reopen": "プルリクエストを再オープン",
|
||||
"repo.pulls.closed_at": "がプルリクエストをクローズ <a id=\"%[1]s\" href=\"#%[1]s\">%[2]s</a>",
|
||||
"repo.pulls.reopened_at": "がプルリクエストを再オープン <a id=\"%[1]s\" href=\"#%[1]s\">%[2]s</a>",
|
||||
"repo.pulls.cmd_instruction_hint": "コマンドラインの手順を表示",
|
||||
@@ -1949,7 +1959,6 @@
|
||||
"repo.signing.wont_sign.headsigned": "HEADコミットが署名されていないため、マージは署名されません。",
|
||||
"repo.signing.wont_sign.commitssigned": "関連するコミットすべてが署名されていないため、マージは署名されません。",
|
||||
"repo.signing.wont_sign.approved": "PRが未承認のため、マージは署名されません。",
|
||||
"repo.signing.wont_sign.not_signed_in": "サインインしていません。",
|
||||
"repo.ext_wiki": "外部Wikiへのアクセス",
|
||||
"repo.ext_wiki.desc": "外部Wikiへのリンク。",
|
||||
"repo.wiki": "Wiki",
|
||||
@@ -2131,7 +2140,9 @@
|
||||
"repo.settings.pulls_desc": "プルリクエストを有効にする",
|
||||
"repo.settings.pulls.ignore_whitespace": "空白文字のコンフリクトを無視する",
|
||||
"repo.settings.pulls.enable_autodetect_manual_merge": "手動マージの自動検出を有効にする (注意: 特殊なケースでは判定ミスが発生する場合があります)",
|
||||
"repo.settings.pulls.allow_merge_update": "マージでプルリクエストのブランチの更新を可能にする",
|
||||
"repo.settings.pulls.allow_rebase_update": "リベースでプルリクエストのブランチの更新を可能にする",
|
||||
"repo.settings.pulls.default_update_style": "デフォルトのブランチ更新スタイル",
|
||||
"repo.settings.pulls.default_target_branch": "新しいプルリクエストのデフォルトのターゲットブランチ",
|
||||
"repo.settings.pulls.default_target_branch_default": "デフォルトブランチ (%s)",
|
||||
"repo.settings.pulls.default_delete_branch_after_merge": "デフォルトでプルリクエストのブランチをマージ後に削除する",
|
||||
@@ -2173,7 +2184,8 @@
|
||||
"repo.settings.transfer_abort_invalid": "存在しないリポジトリの移転はキャンセルできません。",
|
||||
"repo.settings.transfer_abort_success": "%s へのリポジトリ移転は正常にキャンセルされました。",
|
||||
"repo.settings.transfer_desc": "別のユーザーやあなたが管理者権限を持っている組織にリポジトリを移転します。",
|
||||
"repo.settings.transfer_form_title": "確認のためリポジトリ名を入力:",
|
||||
"repo.settings.enter_repo_name_to_confirm": "確認のためリポジトリ名を入力:",
|
||||
"repo.settings.enter_repo_full_name_to_confirm": "確認のため完全なリポジトリ名(owner/name形式)を入力:",
|
||||
"repo.settings.transfer_in_progress": "現在進行中の移転があります。このリポジトリを別のユーザーに移転したい場合はキャンセルしてください。",
|
||||
"repo.settings.transfer_notices_1": "- 個人ユーザーに移転すると、あなたはリポジトリへのアクセス権を失います。",
|
||||
"repo.settings.transfer_notices_2": "- あなたが所有(または共同で所有)している組織に移転すると、リポジトリへのアクセス権は維持されます。",
|
||||
@@ -2249,13 +2261,14 @@
|
||||
"repo.settings.webhook.delivery.success": "イベントを配信キューに追加しました。 配信履歴に表示されるまで数秒かかります。",
|
||||
"repo.settings.githooks_desc": "GitのフックはGit自体が提供する仕組みです。 以下のフックファイルを編集するとカスタム処理を設定できます。",
|
||||
"repo.settings.githook_edit_desc": "もしフックがアクティブではない場合はサンプルの内容が表示されます。 内容を空にするとフックが無効になります。",
|
||||
"repo.settings.githook_name": "フックの名称",
|
||||
"repo.settings.githook_content": "フックの内容",
|
||||
"repo.settings.update_githook": "フックを更新",
|
||||
"repo.settings.add_webhook_desc": "GiteaはターゲットURLに、指定したContent Typeで<code>POST</code>リクエストを送ります。 詳細は<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"%s\">Webhookガイド</a>へ。",
|
||||
"repo.settings.payload_url": "ターゲットURL",
|
||||
"repo.settings.http_method": "HTTPメソッド",
|
||||
"repo.settings.content_type": "POST Content Type",
|
||||
"repo.settings.webhook.name": "Webhook名",
|
||||
"repo.settings.webhook.name_helper": "任意で、このWebhookにわかりやすい名前をつける",
|
||||
"repo.settings.webhook.name_empty": "無名のWebhook",
|
||||
"repo.settings.secret": "シークレット",
|
||||
"repo.settings.webhook_secret_desc": "Webhookサーバーがsecretの使用をサポートしている場合は、webhookのマニュアルに従いここにsecretを入力できます。",
|
||||
"repo.settings.slack_username": "ユーザー名",
|
||||
@@ -2404,6 +2417,11 @@
|
||||
"repo.settings.protect_merge_whitelist_committers_desc": "許可リストに登録したユーザーまたはチームにのみ、このブランチへのプルリクエストのマージを許可します。",
|
||||
"repo.settings.protect_merge_whitelist_users": "マージ許可リストに含むユーザー:",
|
||||
"repo.settings.protect_merge_whitelist_teams": "マージ許可リストに含むチーム:",
|
||||
"repo.settings.protect_bypass_allowlist": "ブランチ保護のバイパス",
|
||||
"repo.settings.protect_enable_bypass_allowlist": "選択されたユーザーまたはチームにブランチ保護のバイパスを許可",
|
||||
"repo.settings.protect_enable_bypass_allowlist_desc": "許可リストに指定したユーザーまたはチームは、必要な承認、ステータスチェック、保護ファイルのルールにより通常であればブロックされる場合でも、マージやプッシュを行うことができます。",
|
||||
"repo.settings.protect_bypass_allowlist_users": "保護のバイパスを許可するユーザー:",
|
||||
"repo.settings.protect_bypass_allowlist_teams": "保護のバイパスを許可するチーム:",
|
||||
"repo.settings.protect_check_status_contexts": "ステータスチェックを有効にする",
|
||||
"repo.settings.protect_status_check_patterns": "ステータスチェック パターン:",
|
||||
"repo.settings.protect_status_check_patterns_desc": "このルールの対象ブランチがマージ可能になる前に、どのステータスチェックがパスしなければならないかを、パターンで入力します。 各行にパターンを指定します。 この設定は空にできません。",
|
||||
@@ -2445,7 +2463,7 @@
|
||||
"repo.settings.block_outdated_branch": "遅れているプルリクエストのマージをブロック",
|
||||
"repo.settings.block_outdated_branch_desc": "baseブランチがheadブランチより進んでいる場合、マージできないようにします。",
|
||||
"repo.settings.block_admin_merge_override": "管理者もブランチ保護のルールに従う",
|
||||
"repo.settings.block_admin_merge_override_desc": "管理者はブランチ保護のルールに従う必要があり、回避することはできません。",
|
||||
"repo.settings.block_admin_merge_override_desc": "管理者はブランチ保護のルールに従う必要があり、回避することはできません。 バイパス許可リストを有効にしている場合、許可リストに含まれるユーザーやチームは、引き続きルールのバイパスが可能です。",
|
||||
"repo.settings.default_branch_desc": "コミット表示のデフォルトのブランチを選択します。",
|
||||
"repo.settings.default_target_branch_desc": "プルリクエストでは、リポジトリ拡張設定の「プルリクエスト」セクションで設定することで、別のデフォルトターゲットブランチを使用できます。",
|
||||
"repo.settings.merge_style_desc": "マージ スタイル",
|
||||
@@ -2476,7 +2494,10 @@
|
||||
"repo.settings.visibility.private.text": "プライベートに変更することで、リポジトリは許可されたメンバーにのみ表示されるようになり、既存のフォーク、ウォッチャー、スターとの関係は解除される可能性があります。",
|
||||
"repo.settings.visibility.private.bullet_title": "<strong>プライベートに変更すると:</strong>",
|
||||
"repo.settings.visibility.private.bullet_one": "許可されたメンバーにのみリポジトリを表示します。",
|
||||
"repo.settings.visibility.private.bullet_two": "<strong>フォーク</strong>、<strong>ウォッチャー</strong>、<strong>スター</strong>との関係を解除する可能性があります。",
|
||||
"repo.settings.visibility.private.bullet_two": "非公開設定はフォークにも適用し、<strong>ウォッチャー</strong>と<strong>スター</strong>は削除します。",
|
||||
"repo.settings.visibility.private.stats_stars": "このリポジトリには、失われるおそれのあるスターが <strong>%d</strong> 個あります。",
|
||||
"repo.settings.visibility.private.stats_watchers": "このリポジトリには、失われるおそれのあるウォッチャーが <strong>%d</strong> 件あります。",
|
||||
"repo.settings.visibility.private.stats_forks": "このリポジトリには、関連するフォークが <strong>%d</strong> 件あります。",
|
||||
"repo.settings.visibility.public.button": "公開する",
|
||||
"repo.settings.visibility.public.text": "公開に変更すると、リポジトリを誰でも閲覧できるようにします。",
|
||||
"repo.settings.visibility.public.bullet_title": "<strong>公開に変更すると:</strong>",
|
||||
@@ -2712,6 +2733,8 @@
|
||||
"org.members": "メンバー",
|
||||
"org.teams": "チーム",
|
||||
"org.code": "コード",
|
||||
"org.repos.empty": "リポジトリはまだありません。",
|
||||
"org.repos.empty_description": "コードを組織内で共有するため、リポジトリを作成してください。",
|
||||
"org.lower_members": "メンバー",
|
||||
"org.lower_repositories": "リポジトリ",
|
||||
"org.create_new_team": "新しいチーム",
|
||||
@@ -2804,7 +2827,10 @@
|
||||
"org.teams.no_desc": "このチームには説明がありません。",
|
||||
"org.teams.settings": "設定",
|
||||
"org.teams.owners_permission_desc": "オーナーは<strong>すべてのリポジトリ</strong>へのフルアクセス権と、組織への<strong>管理者アクセス権</strong>を持ちます。",
|
||||
"org.teams.owners_permission_suggestion": "メンバーのアクセス権限を細かく管理するため、新しくチームを作成することもできます。",
|
||||
"org.teams.members": "チームメンバー",
|
||||
"org.teams.manage_team_member": "チームとメンバーを管理",
|
||||
"org.teams.manage_team_member_prompt": "メンバーの管理はチームを使って行います。 ユーザーをこの組織に招待するには、チームに追加してください。",
|
||||
"org.teams.update_settings": "設定の更新",
|
||||
"org.teams.delete_team": "チームを削除",
|
||||
"org.teams.add_team_member": "チームメンバーを追加",
|
||||
@@ -2845,6 +2871,8 @@
|
||||
"org.worktime.date_range_end": "期間 (至)",
|
||||
"org.worktime.query": "集計",
|
||||
"org.worktime.time": "時間",
|
||||
"org.worktime.empty": "作業時間のデータはまだありません。",
|
||||
"org.worktime.empty_description": "記録された作業時間を表示するには、日付範囲を調整してください。",
|
||||
"org.worktime.by_repositories": "リポジトリ別",
|
||||
"org.worktime.by_milestones": "マイルストーン別",
|
||||
"org.worktime.by_members": "メンバー別",
|
||||
@@ -2859,6 +2887,30 @@
|
||||
"admin.hooks": "Webhook",
|
||||
"admin.integrations": "連携",
|
||||
"admin.authentication": "認証ソース",
|
||||
"admin.badges": "バッジ",
|
||||
"admin.badges.badges_manage_panel": "バッジ管理",
|
||||
"admin.badges.details": "バッジ詳細",
|
||||
"admin.badges.new_badge": "新しいバッジを作成",
|
||||
"admin.badges.slug": "スラッグ",
|
||||
"admin.badges.slug_been_taken": "スラッグが既に使用されています。",
|
||||
"admin.badges.description": "説明",
|
||||
"admin.badges.image_url": "画像URL",
|
||||
"admin.badges.new_success": "バッジ \"%s\" を作成しました。",
|
||||
"admin.badges.update_success": "バッジを更新しました。",
|
||||
"admin.badges.deletion_success": "バッジを削除しました。",
|
||||
"admin.badges.edit_badge": "バッジを編集",
|
||||
"admin.badges.update_badge": "バッジを更新",
|
||||
"admin.badges.delete_badge": "バッジを削除",
|
||||
"admin.badges.delete_badge_desc": "このバッジを完全に削除してよろしいですか?",
|
||||
"admin.badges.users_with_badge": "バッジ保持者: %s",
|
||||
"admin.badges.not_found": "バッジが見つかりません。",
|
||||
"admin.badges.user_already_has": "ユーザーは既にこのバッジを保有しています。",
|
||||
"admin.badges.user_add_success": "ユーザーにバッジを付与しました。",
|
||||
"admin.badges.user_remove_success": "ユーザーのバッジを取り消しました。",
|
||||
"admin.badges.manage_users": "ユーザーを管理",
|
||||
"admin.badges.add_user": "ユーザーを追加",
|
||||
"admin.badges.remove_user": "ユーザーを削除",
|
||||
"admin.badges.delete_user_desc": "このユーザーのバッジを取り消してもよろしいですか?",
|
||||
"admin.emails": "ユーザーメールアドレス",
|
||||
"admin.config": "設定",
|
||||
"admin.config_summary": "サマリー",
|
||||
@@ -3135,6 +3187,8 @@
|
||||
"admin.auths.oauth2_required_claim_name_helper": "このClaim名を設定すると、このソースからのログインを、指定したClaim名を持つユーザーに限定します。",
|
||||
"admin.auths.oauth2_required_claim_value": "必須Claim値",
|
||||
"admin.auths.oauth2_required_claim_value_helper": "この値を設定すると、このソースからのログインを、指定したClaim名とClaim値を持つユーザーに限定します。",
|
||||
"admin.auths.open_id_connect_external_id_claim": "外部ID Claim名 (オプション)",
|
||||
"admin.auths.open_id_connect_external_id_claim_helper": "ユーザーの外部IDに使用するClaim名。 デフォルトは \"sub\" です。 Azure AD / Entra IDについては、Azure AD V2 プロバイダーから移行したときに継続性を維持するため、この値を \"oid\" にしてください。 注: \"oid\" Claimを使う場合は、上にあるスコープ設定に \"profile\" スコープを含める必要があります。",
|
||||
"admin.auths.oauth2_group_claim_name": "このソースでグループ名を提供するClaim名 (オプション)",
|
||||
"admin.auths.oauth2_full_name_claim_name": "フルネームのClaim名。 (オプション — 設定すると、ユーザーのフルネームは常にこのClaimに同期します)",
|
||||
"admin.auths.oauth2_ssh_public_key_claim_name": "SSH公開鍵のClaim名",
|
||||
@@ -3187,11 +3241,8 @@
|
||||
"admin.config.server_config": "サーバー設定",
|
||||
"admin.config.app_name": "サイトのタイトル",
|
||||
"admin.config.app_ver": "Giteaのバージョン",
|
||||
"admin.config.app_url": "GiteaのベースURL",
|
||||
"admin.config.custom_conf": "設定ファイルのパス",
|
||||
"admin.config.custom_file_root_path": "カスタムファイルのルートパス",
|
||||
"admin.config.domain": "サーバードメイン",
|
||||
"admin.config.offline_mode": "ローカルモード",
|
||||
"admin.config.disable_router_log": "ルーターのログが無効",
|
||||
"admin.config.run_user": "実行ユーザー名",
|
||||
"admin.config.run_mode": "実行モード",
|
||||
@@ -3271,15 +3322,20 @@
|
||||
"admin.config.cache_config": "キャッシュ設定",
|
||||
"admin.config.cache_adapter": "キャッシュ アダプター",
|
||||
"admin.config.cache_interval": "キャッシュ間隔",
|
||||
"admin.config.cache_conn": "キャッシュ接続",
|
||||
"admin.config.cache_item_ttl": "キャッシュアイテムのTTL",
|
||||
"admin.config.cache_test": "キャッシュのテスト",
|
||||
"admin.config.cache_test_failed": "キャッシュの調査に失敗しました: %v.",
|
||||
"admin.config.cache_test_slow": "キャッシュのテストは成功しましたが、応答が遅いです: %s",
|
||||
"admin.config.cache_test_succeeded": "キャッシュのテストは成功し、応答時間は %s でした。",
|
||||
"admin.config.common.start_time": "開始時刻",
|
||||
"admin.config.common.end_time": "終了時刻",
|
||||
"admin.config.common.skip_time_check": "時刻を空に(入力欄をクリア)すると時刻チェックをスキップします",
|
||||
"admin.config.instance_maintenance": "インスタンスのメンテナンス",
|
||||
"admin.config.instance_maintenance_mode.admin_web_access_only": "管理者にのみWeb UIへのアクセスを許可",
|
||||
"admin.config.instance_web_banner.enabled": "バナーを表示",
|
||||
"admin.config.instance_web_banner.message_placeholder": "バナーメッセージ (Markdownをサポート)",
|
||||
"admin.config.session_config": "セッション設定",
|
||||
"admin.config.session_provider": "セッション プロバイダー",
|
||||
"admin.config.provider_config": "プロバイダーの設定",
|
||||
"admin.config.cookie_name": "Cookieの名称",
|
||||
"admin.config.gc_interval_time": "GCの間隔",
|
||||
"admin.config.session_life_time": "セッションの有効期間",
|
||||
@@ -3287,7 +3343,7 @@
|
||||
"admin.config.cookie_life_time": "Cookieの有効期間",
|
||||
"admin.config.picture_config": "画像とアバターの設定",
|
||||
"admin.config.picture_service": "画像サービス",
|
||||
"admin.config.disable_gravatar": "Gravatarが無効",
|
||||
"admin.config.enable_gravatar": "Gravatar有効",
|
||||
"admin.config.enable_federated_avatar": "フェデレーテッド・アバター有効",
|
||||
"admin.config.open_with_editor_app_help": "クローンメニューの「~で開く」に表示するエディタ。 空白のままにするとデフォルトが使用されます。 展開するとデフォルトを確認できます。",
|
||||
"admin.config.git_guide_remote_name": "操作説明内のgitコマンドで使うリポジトリリモート名",
|
||||
@@ -3465,6 +3521,7 @@
|
||||
"packages.dependencies": "依存関係",
|
||||
"packages.keywords": "キーワード",
|
||||
"packages.details": "詳細",
|
||||
"packages.name": "パッケージ名",
|
||||
"packages.details.author": "著作者",
|
||||
"packages.details.project_site": "プロジェクトサイト",
|
||||
"packages.details.repository_site": "リポジトリサイト",
|
||||
@@ -3560,9 +3617,27 @@
|
||||
"packages.swift.registry": "このレジストリをコマンドラインからセットアップします:",
|
||||
"packages.swift.install": "あなたの <code>Package.swift</code> ファイルにパッケージを追加します:",
|
||||
"packages.swift.install2": "そして次のコマンドを実行します:",
|
||||
"packages.terraform.install": "HTTPバックエンドを使用するよう状態を設定します",
|
||||
"packages.terraform.install2": "そして次のコマンドを実行します:",
|
||||
"packages.terraform.lock_status": "ロック状態",
|
||||
"packages.terraform.locked_by": "%s がロックしています",
|
||||
"packages.terraform.unlocked": "アンロックされています",
|
||||
"packages.terraform.lock": "ロック",
|
||||
"packages.terraform.unlock": "アンロック",
|
||||
"packages.terraform.lock.success": "Terraform状態は正常にロックされました。",
|
||||
"packages.terraform.unlock.success": "Terraform状態は正常にアンロックされました。",
|
||||
"packages.terraform.lock.error.already_locked": "Terraform状態は既にロックされています。",
|
||||
"packages.terraform.delete.locked": "Terraform状態はロックされているため削除できません。",
|
||||
"packages.terraform.delete.latest": "Terraform状態の最新バージョンは削除できません。",
|
||||
"packages.vagrant.install": "Vagrant ボックスを追加するには、次のコマンドを実行します。",
|
||||
"packages.settings.link": "このパッケージをリポジトリにリンク",
|
||||
"packages.settings.link.description": "パッケージをリポジトリにリンクすると、リポジトリのパッケージ一覧にそのパッケージが表示されます。 リンクできるのは、同じオーナーが所有するリポジトリのみです。 入力欄を空にするとリンクを削除します。",
|
||||
"packages.settings.link.description": "パッケージをリポジトリにリンクすると、リポジトリのパッケージ一覧に表示されるようになります。",
|
||||
"packages.settings.link.notice1": "同じオーナーが所有するリポジトリにだけリンクできます。",
|
||||
"packages.settings.link.notice2": "リポジトリにリンクしてもパッケージの公開範囲は変わりません。",
|
||||
"packages.settings.link.notice3": "入力欄を空にするとリンクを削除します。",
|
||||
"packages.settings.visibility": "パッケージの公開範囲",
|
||||
"packages.settings.visibility.inherit": "パッケージの公開範囲は所有者から継承されており、ここで個別に変更することはできません。 変更するには、このパッケージを所有するユーザーまたは組織の公開設定を変更してください。",
|
||||
"packages.settings.visibility.button": "所有者の公開範囲を変更",
|
||||
"packages.settings.link.select": "リポジトリを選択",
|
||||
"packages.settings.link.button": "リポジトリのリンクを更新",
|
||||
"packages.settings.link.success": "リポジトリのリンクを更新しました。",
|
||||
@@ -3573,8 +3648,13 @@
|
||||
"packages.settings.delete": "パッケージ削除",
|
||||
"packages.settings.delete.description": "パッケージの削除は恒久的で元に戻すことはできません。",
|
||||
"packages.settings.delete.notice": "%s (%s) を削除しようとしています。この操作は元に戻せません。よろしいですか?",
|
||||
"packages.settings.delete.notice.package": "%s とその全てのバージョンを削除しようとしています。この操作は元に戻せません。よろしいですか?",
|
||||
"packages.settings.delete.success": "パッケージを削除しました。",
|
||||
"packages.settings.delete.version.success": "パッケージバージョンを削除しました。",
|
||||
"packages.settings.delete.error": "パッケージの削除に失敗しました。",
|
||||
"packages.settings.delete.version": "バージョンを削除",
|
||||
"packages.settings.delete.confirm": "確認のためパッケージ名を入力してください",
|
||||
"packages.settings.delete.invalid_package_name": "入力したパッケージ名が間違っています。",
|
||||
"packages.owner.settings.cargo.title": "Cargoレジストリ インデックス",
|
||||
"packages.owner.settings.cargo.initialize": "インデックスを初期化",
|
||||
"packages.owner.settings.cargo.initialize.description": "Cargoレジストリを使用するには、インデックス用の特別なgitリポジトリが必要です。 このオプションを使用するとそのリポジトリを(再)作成し、自動的に構成します。",
|
||||
@@ -3630,9 +3710,10 @@
|
||||
"actions.status.running": "実行中",
|
||||
"actions.status.success": "成功",
|
||||
"actions.status.failure": "失敗",
|
||||
"actions.status.cancelled": "キャンセル",
|
||||
"actions.status.skipped": "スキップ",
|
||||
"actions.status.blocked": "ブロックされた",
|
||||
"actions.status.cancelled": "キャンセルされました",
|
||||
"actions.status.cancelling": "キャンセル中",
|
||||
"actions.status.skipped": "スキップされました",
|
||||
"actions.status.blocked": "ブロックされました",
|
||||
"actions.runners": "ランナー",
|
||||
"actions.runners.runner_manage_panel": "ランナーの管理",
|
||||
"actions.runners.new": "新しいランナーを作成",
|
||||
@@ -3641,6 +3722,7 @@
|
||||
"actions.runners.id": "ID",
|
||||
"actions.runners.name": "名称",
|
||||
"actions.runners.owner_type": "タイプ",
|
||||
"actions.runners.availability": "利用可否",
|
||||
"actions.runners.description": "説明",
|
||||
"actions.runners.labels": "ラベル",
|
||||
"actions.runners.last_online": "最終オンライン時刻",
|
||||
@@ -3656,6 +3738,12 @@
|
||||
"actions.runners.update_runner": "変更を保存",
|
||||
"actions.runners.update_runner_success": "ランナーを更新しました",
|
||||
"actions.runners.update_runner_failed": "ランナーの更新に失敗しました",
|
||||
"actions.runners.enable_runner": "このランナーを有効化",
|
||||
"actions.runners.enable_runner_success": "ランナーを有効化しました",
|
||||
"actions.runners.enable_runner_failed": "ランナーの有効化に失敗しました",
|
||||
"actions.runners.disable_runner": "このランナーを無効化",
|
||||
"actions.runners.disable_runner_success": "ランナーを無効化しました",
|
||||
"actions.runners.disable_runner_failed": "ランナーの無効化に失敗しました",
|
||||
"actions.runners.delete_runner": "このランナーを削除",
|
||||
"actions.runners.delete_runner_success": "ランナーを削除しました",
|
||||
"actions.runners.delete_runner_failed": "ランナーの削除に失敗しました",
|
||||
@@ -3671,7 +3759,11 @@
|
||||
"actions.runners.reset_registration_token_confirm": "現在のトークンを無効にして、新しいトークンを生成しますか?",
|
||||
"actions.runners.reset_registration_token_success": "ランナー登録トークンをリセットしました",
|
||||
"actions.runs.all_workflows": "すべてのワークフロー",
|
||||
"actions.runs.workflow_run_count_1": "%d 件のワークフロー実行",
|
||||
"actions.runs.workflow_run_count_n": "%d 件のワークフロー実行",
|
||||
"actions.runs.commit": "コミット",
|
||||
"actions.runs.run_details": "実行の詳細",
|
||||
"actions.runs.workflow_file": "ワークフローのファイル",
|
||||
"actions.runs.scheduled": "スケジュール済み",
|
||||
"actions.runs.pushed_by": "pushed by",
|
||||
"actions.runs.invalid_workflow_helper": "ワークフロー設定ファイルは無効です。あなたの設定ファイルを確認してください: %s",
|
||||
@@ -3694,6 +3786,13 @@
|
||||
"actions.runs.delete.description": "このワークフローを完全に削除してもよろしいですか?この操作は元に戻せません。",
|
||||
"actions.runs.not_done": "このワークフローの実行は完了していません。",
|
||||
"actions.runs.view_workflow_file": "ワークフローファイルを表示",
|
||||
"actions.runs.summary": "サマリー",
|
||||
"actions.runs.all_jobs": "すべてのジョブ",
|
||||
"actions.runs.attempt": "試行",
|
||||
"actions.runs.latest": "最新",
|
||||
"actions.runs.latest_attempt": "最新 試行",
|
||||
"actions.runs.triggered_via": "%s によりトリガー",
|
||||
"actions.runs.total_duration": "総所要時間:",
|
||||
"actions.workflow.disable": "ワークフローを無効にする",
|
||||
"actions.workflow.disable_success": "ワークフロー '%s' が無効になりました。",
|
||||
"actions.workflow.enable": "ワークフローを有効にする",
|
||||
@@ -3743,5 +3842,24 @@
|
||||
"git.filemode.normal_file": "ノーマルファイル",
|
||||
"git.filemode.executable_file": "実行可能ファイル",
|
||||
"git.filemode.symbolic_link": "シンボリックリンク",
|
||||
"git.filemode.submodule": "サブモジュール"
|
||||
"git.filemode.submodule": "サブモジュール",
|
||||
"org.repos.none": "リポジトリはありません。",
|
||||
"actions.general.permissions": "Actionsトークンの権限",
|
||||
"actions.general.token_permissions.mode": "トークンのデフォルトの権限",
|
||||
"actions.general.token_permissions.mode.desc": "ワークフローファイルでActionsジョブに権限(permissions)を指定していない場合、デフォルトの権限が使用されます。",
|
||||
"actions.general.token_permissions.mode.permissive": "許可",
|
||||
"actions.general.token_permissions.mode.permissive.desc": "ジョブの対象リポジトリについて、読み取りと書き込みを許可。",
|
||||
"actions.general.token_permissions.mode.restricted": "制限あり",
|
||||
"actions.general.token_permissions.mode.restricted.desc": "ジョブの対象リポジトリのコンテンツ・ユニット(コード、リリース)について、読み取りのみ許可。",
|
||||
"actions.general.token_permissions.override_owner": "オーナーレベルの設定を上書きする",
|
||||
"actions.general.token_permissions.override_owner_desc": "有効にすると、このリポジトリは(ユーザーまたは組織の)オーナーのActions設定に従うのではなく、独自の設定を使用します。",
|
||||
"actions.general.token_permissions.maximum": "トークン権限の上限",
|
||||
"actions.general.token_permissions.maximum.description": "Actionsジョブの実効権限はこの上限によって制限されます。",
|
||||
"actions.general.token_permissions.fork_pr_note": "フォークからのプルリクエストによってジョブが開始された場合は、実効権限は読み取り専用までとなります。",
|
||||
"actions.general.token_permissions.customize_max_permissions": "権限の上限をカスタマイズする",
|
||||
"actions.general.cross_repo": "クロスリポジトリ アクセス",
|
||||
"actions.general.cross_repo_desc": "Actionsジョブの実行時に、このオーナーのすべてのリポジトリから選択したリポジトリへ、GITEA_TOKENを使用して(読み取り専用で)アクセスすることを許可します。",
|
||||
"actions.general.cross_repo_selected": "選択したリポジトリ",
|
||||
"actions.general.cross_repo_target_repos": "対象リポジトリ",
|
||||
"actions.general.cross_repo_add": "対象リポジトリの追加"
|
||||
}
|
||||
|
||||
+21
-21
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"type": "module",
|
||||
"packageManager": "pnpm@11.1.1",
|
||||
"packageManager": "pnpm@11.2.1",
|
||||
"engines": {
|
||||
"node": ">= 22.18.0",
|
||||
"pnpm": ">= 11.0.0"
|
||||
@@ -16,11 +16,11 @@
|
||||
"@codemirror/lang-markdown": "6.5.0",
|
||||
"@codemirror/language": "6.12.3",
|
||||
"@codemirror/language-data": "6.5.2",
|
||||
"@codemirror/legacy-modes": "6.5.2",
|
||||
"@codemirror/legacy-modes": "6.5.3",
|
||||
"@codemirror/lint": "6.9.6",
|
||||
"@codemirror/search": "6.7.0",
|
||||
"@codemirror/state": "6.6.0",
|
||||
"@codemirror/view": "6.42.1",
|
||||
"@codemirror/view": "6.43.0",
|
||||
"@deltablot/dropzone": "7.4.3",
|
||||
"@github/markdown-toolbar-element": "2.2.3",
|
||||
"@github/paste-markdown": "1.5.3",
|
||||
@@ -28,19 +28,19 @@
|
||||
"@lezer/highlight": "1.2.3",
|
||||
"@mcaptcha/vanilla-glue": "0.1.0-rc2",
|
||||
"@mermaid-js/layout-elk": "0.2.1",
|
||||
"@primer/octicons": "19.25.0",
|
||||
"@primer/octicons": "19.26.0",
|
||||
"@replit/codemirror-indentation-markers": "6.5.3",
|
||||
"@replit/codemirror-lang-nix": "6.0.1",
|
||||
"@replit/codemirror-lang-svelte": "6.0.0",
|
||||
"@replit/codemirror-vscode-keymap": "6.0.2",
|
||||
"@resvg/resvg-wasm": "2.6.2",
|
||||
"@vitejs/plugin-vue": "6.0.6",
|
||||
"@vitejs/plugin-vue": "6.0.7",
|
||||
"ansi_up": "6.0.6",
|
||||
"asciinema-player": "3.15.1",
|
||||
"chart.js": "4.5.1",
|
||||
"chartjs-adapter-dayjs-4": "1.0.4",
|
||||
"chartjs-plugin-zoom": "2.2.0",
|
||||
"clippie": "4.1.15",
|
||||
"clippie": "4.2.0",
|
||||
"codemirror-lang-elixir": "4.0.1",
|
||||
"colord": "2.9.3",
|
||||
"compare-versions": "6.1.1",
|
||||
@@ -51,13 +51,13 @@
|
||||
"idiomorph": "0.7.4",
|
||||
"jquery": "4.0.0",
|
||||
"js-yaml": "4.1.1",
|
||||
"katex": "0.16.46",
|
||||
"katex": "0.16.47",
|
||||
"mermaid": "11.15.0",
|
||||
"online-3d-viewer": "0.18.0",
|
||||
"pdfobject": "2.3.1",
|
||||
"perfect-debounce": "2.1.0",
|
||||
"postcss": "8.5.14",
|
||||
"rolldown-license-plugin": "3.0.5",
|
||||
"postcss": "8.5.15",
|
||||
"rolldown-license-plugin": "3.0.7",
|
||||
"sortablejs": "1.15.7",
|
||||
"swagger-ui-dist": "5.32.6",
|
||||
"tailwindcss": "3.4.19",
|
||||
@@ -67,7 +67,7 @@
|
||||
"tributejs": "5.1.3",
|
||||
"uint8-to-base64": "0.2.1",
|
||||
"vanilla-colorful": "0.7.2",
|
||||
"vite": "8.0.12",
|
||||
"vite": "8.0.13",
|
||||
"vite-string-plugin": "2.0.4",
|
||||
"vue": "3.5.34",
|
||||
"vue-bar-graph": "2.2.0",
|
||||
@@ -78,27 +78,27 @@
|
||||
"@eslint/json": "1.2.0",
|
||||
"@playwright/test": "1.60.0",
|
||||
"@stylistic/eslint-plugin": "5.10.0",
|
||||
"@stylistic/stylelint-plugin": "5.1.0",
|
||||
"@stylistic/stylelint-plugin": "5.2.0",
|
||||
"@types/codemirror": "5.60.17",
|
||||
"@types/jquery": "4.0.0",
|
||||
"@types/js-yaml": "4.0.9",
|
||||
"@types/katex": "0.16.8",
|
||||
"@types/node": "25.7.0",
|
||||
"@types/node": "25.9.1",
|
||||
"@types/pdfobject": "2.2.5",
|
||||
"@types/sortablejs": "1.15.9",
|
||||
"@types/swagger-ui-dist": "3.30.6",
|
||||
"@types/throttle-debounce": "5.0.2",
|
||||
"@types/toastify-js": "1.12.4",
|
||||
"@typescript-eslint/parser": "8.59.3",
|
||||
"@vitejs/plugin-vue": "6.0.6",
|
||||
"@typescript-eslint/parser": "8.59.4",
|
||||
"@vitejs/plugin-vue": "6.0.7",
|
||||
"@vitest/eslint-plugin": "1.6.17",
|
||||
"eslint": "10.3.0",
|
||||
"eslint": "10.4.0",
|
||||
"eslint-import-resolver-typescript": "4.4.4",
|
||||
"eslint-plugin-array-func": "5.1.1",
|
||||
"eslint-plugin-de-morgan": "2.1.2",
|
||||
"eslint-plugin-github": "6.0.0",
|
||||
"eslint-plugin-import-x": "4.16.2",
|
||||
"eslint-plugin-playwright": "2.10.2",
|
||||
"eslint-plugin-playwright": "2.10.4",
|
||||
"eslint-plugin-regexp": "3.1.0",
|
||||
"eslint-plugin-sonarjs": "4.0.3",
|
||||
"eslint-plugin-unicorn": "64.0.0",
|
||||
@@ -113,16 +113,16 @@
|
||||
"nolyfill": "1.0.44",
|
||||
"postcss-html": "1.8.1",
|
||||
"spectral-cli-bundle": "1.0.8",
|
||||
"stylelint": "17.11.0",
|
||||
"stylelint": "17.12.0",
|
||||
"stylelint-config-recommended": "18.0.0",
|
||||
"stylelint-declaration-block-no-ignored-properties": "3.0.0",
|
||||
"stylelint-declaration-strict-value": "1.11.1",
|
||||
"stylelint-value-no-unknown-custom-properties": "6.1.1",
|
||||
"svgo": "4.0.1",
|
||||
"typescript": "6.0.3",
|
||||
"typescript-eslint": "8.59.3",
|
||||
"updates": "17.16.11",
|
||||
"vitest": "4.1.6",
|
||||
"vue-tsc": "3.2.9"
|
||||
"typescript-eslint": "8.59.4",
|
||||
"updates": "17.16.13",
|
||||
"vitest": "4.1.7",
|
||||
"vue-tsc": "3.3.1"
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+512
-525
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" class="svg octicon-repo-forked-locked" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M9 10.167V9a3 3 0 1 1 6 0v1.167c.591.281 1 .884 1 1.583v2.5A1.75 1.75 0 0 1 14.25 16h-4.5A1.75 1.75 0 0 1 8 14.25v-2.5c0-.699.409-1.302 1-1.583M13.5 10h-3V9a1.5 1.5 0 0 1 3 0z"/><path fill-rule="evenodd" d="M3.25 1a2.247 2.247 0 0 1 1.938 3.388 2.25 2.25 0 0 1-1.189.982v.881a.746.746 0 0 0 .75.748h3.095c-.052.428-.008.986.051 1.499H7.75v1.748c-.315.418-.5.938-.5 1.502v.294a1 1 0 0 0-.256-.041.75.75 0 0 0-.53.22.79.79 0 0 0-.22.547.746.746 0 0 0 .75.748.8.8 0 0 0 .25-.042v.796q.002.376.107.72-.177.03-.357.031a2.247 2.247 0 0 1-1.938-3.388c.268-.456.69-.805 1.19-.983V8.5h-2.5a2.23 2.23 0 0 1-1.586-.66 2.25 2.25 0 0 1-.66-1.591v-.881A2.255 2.255 0 0 1 .03 2.867c.088-.523.36-.998.768-1.34C1.205 1.187 1.72 1 2.25 1zm0 1.499a.75.75 0 0 0-.53.22.8.8 0 0 0-.22.547.75.75 0 0 0 1.5 0 .8.8 0 0 0-.22-.547.75.75 0 0 0-.53-.22m7.5.75a2.247 2.247 0 0 1 1.938 3.388 2.25 2.25 0 0 1-1.189.982V8.96c0 .414.336.75.75.75h.5a.75.75 0 0 1 0 1.5h-.5a3 3 0 0 1-3-3v.54a.746.746 0 0 1 .75-.748h1.01V5a1.5 1.5 0 0 1 1.5-1.5zm0 1.499a.75.75 0 0 0-.53.22.8.8 0 0 0-.22.547.75.75 0 0 0 1.5 0 .8.8 0 0 0-.22-.547.75.75 0 0 0-.53-.22"/><path d="M8.63 7.749a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0"/></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
+1
-1
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 16 16" class="svg octicon-sandbox" width="16" height="16" aria-hidden="true"><g clip-path="url(#octicon-sandbox__a)"><path fill="#010409" d="M7.72 8.97a.75.75 0 1 1 1.06 1.06L7.31 11.5l1.47 1.47a.75.75 0 1 1-1.06 1.06l-2-2a.75.75 0 0 1 0-1.06zm3.5 0a.75.75 0 0 1 1.06 0l2 2a.75.75 0 0 1 0 1.06l-2 2a.75.75 0 1 1-1.06-1.06l1.47-1.47-1.47-1.47a.75.75 0 0 1 0-1.06M14.5 8V1.75a.25.25 0 0 0-.25-.25H1.75a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25H3.5a.75.75 0 0 1 0 1.5H1.75A1.75 1.75 0 0 1 0 14.25V1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75V8a.75.75 0 0 1-1.5 0"/></g><defs><clipPath id="octicon-sandbox__a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" class="svg octicon-sandbox" width="16" height="16" aria-hidden="true"><path d="M7.72 8.97a.75.75 0 1 1 1.06 1.06L7.31 11.5l1.47 1.47a.75.75 0 1 1-1.06 1.06l-2-2a.75.75 0 0 1 0-1.06zm3.5 0a.75.75 0 0 1 1.06 0l2 2a.75.75 0 0 1 0 1.06l-2 2a.75.75 0 1 1-1.06-1.06l1.47-1.47-1.47-1.47a.75.75 0 0 1 0-1.06M14.5 8V1.75a.25.25 0 0 0-.25-.25H1.75a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25H3.5a.75.75 0 0 1 0 1.5H1.75A1.75 1.75 0 0 1 0 14.25V1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75V8a.75.75 0 0 1-1.5 0"/></svg>
|
||||
|
Before Width: | Height: | Size: 745 B After Width: | Height: | Size: 579 B |
+1
-1
@@ -7,7 +7,7 @@ requires-python = ">=3.10"
|
||||
dev = [
|
||||
"djlint==1.36.4",
|
||||
"yamllint==1.38.0",
|
||||
"zizmor==1.25.1",
|
||||
"zizmor==1.25.2",
|
||||
]
|
||||
|
||||
[tool.djlint]
|
||||
|
||||
@@ -7,7 +7,9 @@ import (
|
||||
"bytes"
|
||||
stdCtx "context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
@@ -44,6 +46,14 @@ type WorkflowInfo struct {
|
||||
Workflow *act_model.Workflow
|
||||
}
|
||||
|
||||
// DisplayName returns the workflow name from the YAML file if present, otherwise the filename.
|
||||
func (w WorkflowInfo) DisplayName() string {
|
||||
if w.Workflow != nil && w.Workflow.Name != "" {
|
||||
return w.Workflow.Name
|
||||
}
|
||||
return w.Entry.Name()
|
||||
}
|
||||
|
||||
// MustEnableActions check if actions are enabled in settings
|
||||
func MustEnableActions(ctx *context.Context) {
|
||||
if !setting.Actions.Enabled {
|
||||
@@ -82,12 +92,16 @@ func List(ctx *context.Context) {
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
otherWorkflows := prepareOtherWorkflows(ctx, workflows, curWorkflowID)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
prepareWorkflowDispatchTemplate(ctx, workflows, curWorkflowID)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
prepareWorkflowList(ctx, workflows)
|
||||
prepareWorkflowList(ctx, workflows, otherWorkflows)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
@@ -95,6 +109,31 @@ func List(ctx *context.Context) {
|
||||
ctx.HTML(http.StatusOK, tplListActions)
|
||||
}
|
||||
|
||||
// prepareOtherWorkflows surfaces historical runs whose workflow file no longer
|
||||
// exists on the default branch (renamed, removed, or only on other branches).
|
||||
func prepareOtherWorkflows(ctx *context.Context, workflows []WorkflowInfo, curWorkflowID string) []string {
|
||||
listed := make(container.Set[string], len(workflows))
|
||||
for _, w := range workflows {
|
||||
listed.Add(w.Entry.Name())
|
||||
}
|
||||
|
||||
var other []string
|
||||
if ctx.Repo.Repository.NumActionRuns > 0 {
|
||||
ids, err := actions_model.GetRunWorkflowIDs(ctx, ctx.Repo.Repository.ID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetRunWorkflowIDs", err)
|
||||
return nil
|
||||
}
|
||||
other = container.FilterSlice(ids, func(id string) (string, bool) {
|
||||
return id, id != "" && !listed.Contains(id)
|
||||
})
|
||||
}
|
||||
|
||||
ctx.Data["OtherWorkflows"] = other
|
||||
ctx.Data["CurWorkflowIsListed"] = curWorkflowID == "" || listed.Contains(curWorkflowID)
|
||||
return other
|
||||
}
|
||||
|
||||
func WorkflowDispatchInputs(ctx *context.Context) {
|
||||
ref := ctx.FormString("ref")
|
||||
if ref == "" {
|
||||
@@ -245,10 +284,11 @@ func prepareWorkflowDispatchTemplate(ctx *context.Context, workflowInfos []Workf
|
||||
ctx.Data["Tags"] = tags
|
||||
}
|
||||
|
||||
func prepareWorkflowList(ctx *context.Context, workflows []WorkflowInfo) {
|
||||
func prepareWorkflowList(ctx *context.Context, workflows []WorkflowInfo, otherWorkflows []string) {
|
||||
actorID := ctx.FormInt64("actor")
|
||||
status := ctx.FormInt("status")
|
||||
workflowID := ctx.FormString("workflow")
|
||||
branch := ctx.FormString("branch")
|
||||
page := ctx.FormInt("page")
|
||||
if page <= 0 {
|
||||
page = 1
|
||||
@@ -258,7 +298,8 @@ func prepareWorkflowList(ctx *context.Context, workflows []WorkflowInfo) {
|
||||
// they will be 0 by default, which indicates get all status or actors
|
||||
ctx.Data["CurActor"] = actorID
|
||||
ctx.Data["CurStatus"] = status
|
||||
if actorID > 0 || status > int(actions_model.StatusUnknown) {
|
||||
ctx.Data["CurBranch"] = branch
|
||||
if actorID > 0 || status > int(actions_model.StatusUnknown) || branch != "" {
|
||||
ctx.Data["IsFiltered"] = true
|
||||
}
|
||||
|
||||
@@ -276,6 +317,9 @@ func prepareWorkflowList(ctx *context.Context, workflows []WorkflowInfo) {
|
||||
if actions_model.Status(status) != actions_model.StatusUnknown {
|
||||
opts.Status = []actions_model.Status{actions_model.Status(status)}
|
||||
}
|
||||
if branch != "" {
|
||||
opts.Ref = string(git.RefNameFromBranch(branch))
|
||||
}
|
||||
|
||||
runs, total, err := db.FindAndCount[actions_model.ActionRun](ctx, opts)
|
||||
if err != nil {
|
||||
@@ -341,6 +385,12 @@ func prepareWorkflowList(ctx *context.Context, workflows []WorkflowInfo) {
|
||||
|
||||
ctx.Data["Runs"] = runs
|
||||
|
||||
workflowNames := make(map[string]string, len(workflows))
|
||||
for _, wf := range workflows {
|
||||
workflowNames[wf.Entry.Name()] = wf.DisplayName()
|
||||
}
|
||||
ctx.Data["WorkflowNames"] = workflowNames
|
||||
|
||||
actors, err := actions_model.GetActors(ctx, ctx.Repo.Repository.ID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetActors", err)
|
||||
@@ -350,10 +400,17 @@ func prepareWorkflowList(ctx *context.Context, workflows []WorkflowInfo) {
|
||||
|
||||
ctx.Data["StatusInfoList"] = actions_model.GetStatusInfoList(ctx, ctx.Locale)
|
||||
|
||||
runBranches, err := actions_model.GetRunBranches(ctx, ctx.Repo.Repository.ID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetRunBranches", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["RunBranches"] = runBranches
|
||||
|
||||
pager := context.NewPagination(total, opts.PageSize, opts.Page, 5)
|
||||
pager.AddParamFromRequest(ctx.Req)
|
||||
ctx.Data["Page"] = pager
|
||||
ctx.Data["HasWorkflowsOrRuns"] = len(workflows) > 0 || len(runs) > 0
|
||||
ctx.Data["HasWorkflowsOrRuns"] = len(workflows) > 0 || len(otherWorkflows) > 0 || len(runs) > 0
|
||||
|
||||
ctx.Data["CanWriteRepoUnitActions"] = ctx.Repo.Permission.CanWrite(unit.TypeActions)
|
||||
}
|
||||
@@ -466,3 +523,13 @@ func decodeNode(node yaml.Node, out any) bool {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func actionsListRedirectURL(repoLink, workflow, actor, status, branch string) string {
|
||||
return fmt.Sprintf("%s/actions?workflow=%s&actor=%s&status=%s&branch=%s",
|
||||
repoLink,
|
||||
url.QueryEscape(workflow),
|
||||
url.QueryEscape(actor),
|
||||
url.QueryEscape(status),
|
||||
url.QueryEscape(branch),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1103,14 +1103,14 @@ func disableOrEnableWorkflowFile(ctx *context_module.Context, isEnable bool) {
|
||||
ctx.Flash.Success(ctx.Tr("actions.workflow.disable_success", workflow))
|
||||
}
|
||||
|
||||
redirectURL := fmt.Sprintf("%s/actions?workflow=%s&actor=%s&status=%s", ctx.Repo.RepoLink, url.QueryEscape(workflow),
|
||||
url.QueryEscape(ctx.FormString("actor")), url.QueryEscape(ctx.FormString("status")))
|
||||
redirectURL := actionsListRedirectURL(ctx.Repo.RepoLink, workflow,
|
||||
ctx.FormString("actor"), ctx.FormString("status"), ctx.FormString("branch"))
|
||||
ctx.JSONRedirect(redirectURL)
|
||||
}
|
||||
|
||||
func Run(ctx *context_module.Context) {
|
||||
redirectURL := fmt.Sprintf("%s/actions?workflow=%s&actor=%s&status=%s", ctx.Repo.RepoLink, url.QueryEscape(ctx.FormString("workflow")),
|
||||
url.QueryEscape(ctx.FormString("actor")), url.QueryEscape(ctx.FormString("status")))
|
||||
redirectURL := actionsListRedirectURL(ctx.Repo.RepoLink, ctx.FormString("workflow"),
|
||||
ctx.FormString("actor"), ctx.FormString("status"), ctx.FormString("branch"))
|
||||
|
||||
workflowID := ctx.FormString("workflow")
|
||||
if len(workflowID) == 0 {
|
||||
|
||||
@@ -687,7 +687,7 @@ func (n *actionsNotifier) AutoMergePullRequest(ctx context.Context, doer *user_m
|
||||
n.MergePullRequest(ctx, doer, pr)
|
||||
}
|
||||
|
||||
func (n *actionsNotifier) PullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) {
|
||||
func (n *actionsNotifier) PullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, before, after string) {
|
||||
ctx = withMethod(ctx, "PullRequestSynchronized")
|
||||
|
||||
if err := pr.LoadIssue(ctx); err != nil {
|
||||
@@ -703,6 +703,8 @@ func (n *actionsNotifier) PullRequestSynchronized(ctx context.Context, doer *use
|
||||
newNotifyInput(pr.Issue.Repo, doer, webhook_module.HookEventPullRequestSync).
|
||||
WithPayload(&api.PullRequestPayload{
|
||||
Action: api.HookIssueSynchronized,
|
||||
Before: before,
|
||||
After: after,
|
||||
Index: pr.Issue.Index,
|
||||
PullRequest: convert.ToAPIPullRequest(ctx, pr, nil),
|
||||
Repository: convert.ToRepo(ctx, pr.Issue.Repo, access_model.Permission{AccessMode: perm_model.AccessModeNone}),
|
||||
|
||||
@@ -286,7 +286,7 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.
|
||||
} else if commentCreated {
|
||||
notify_service.PullRequestPushCommits(ctx, pusher, pr, comment)
|
||||
}
|
||||
notify_service.PullRequestSynchronized(ctx, pusher, pr)
|
||||
notify_service.PullRequestSynchronized(ctx, pusher, pr, oldCommitID, opts.NewCommitIDs[i])
|
||||
|
||||
results = append(results, private.HookProcReceiveRefResult{
|
||||
OldOID: oldCommitID,
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/jaytaylor/html2text"
|
||||
"github.com/Necoro/html2text"
|
||||
gomail "github.com/wneessen/go-mail"
|
||||
)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ package migrations
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/google/go-github/v86/github"
|
||||
"github.com/google/go-github/v87/github"
|
||||
)
|
||||
|
||||
// ErrRepoNotCreated returns the error that repository not created
|
||||
|
||||
@@ -43,7 +43,7 @@ func (f *GitBucketDownloaderFactory) New(ctx context.Context, opts base.MigrateO
|
||||
oldName := strings.TrimSuffix(fields[len(fields)-1], ".git")
|
||||
|
||||
log.Trace("Create GitBucket downloader. BaseURL: %s RepoOwner: %s RepoName: %s", baseURL, oldOwner, oldName)
|
||||
return NewGitBucketDownloader(ctx, baseURL, opts.AuthUsername, opts.AuthPassword, opts.AuthToken, oldOwner, oldName), nil
|
||||
return NewGitBucketDownloader(ctx, baseURL, opts.AuthUsername, opts.AuthPassword, opts.AuthToken, oldOwner, oldName)
|
||||
}
|
||||
|
||||
// GitServiceType returns the type of git service
|
||||
@@ -70,8 +70,11 @@ func (g *GitBucketDownloader) LogString() string {
|
||||
}
|
||||
|
||||
// NewGitBucketDownloader creates a GitBucket downloader
|
||||
func NewGitBucketDownloader(ctx context.Context, baseURL, userName, password, token, repoOwner, repoName string) *GitBucketDownloader {
|
||||
githubDownloader := NewGithubDownloaderV3(ctx, baseURL, userName, password, token, repoOwner, repoName)
|
||||
func NewGitBucketDownloader(ctx context.Context, baseURL, userName, password, token, repoOwner, repoName string) (*GitBucketDownloader, error) {
|
||||
githubDownloader, err := NewGithubDownloaderV3(ctx, baseURL, userName, password, token, repoOwner, repoName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Gitbucket 4.40 uses different internal hard-coded perPage values.
|
||||
// Issues, PRs, and other major parts use 25. Release page uses 10.
|
||||
// Some API doesn't support paging yet. Sounds difficult, but using
|
||||
@@ -81,7 +84,7 @@ func NewGitBucketDownloader(ctx context.Context, baseURL, userName, password, to
|
||||
githubDownloader.SkipReviews = true
|
||||
return &GitBucketDownloader{
|
||||
githubDownloader,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SupportGetRepoComments return true if it supports get repo comments
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
repo_service "code.gitea.io/gitea/services/repository"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGiteaUploadRepo(t *testing.T) {
|
||||
@@ -31,14 +32,15 @@ func TestGiteaUploadRepo(t *testing.T) {
|
||||
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
|
||||
ctx := t.Context()
|
||||
downloader, err := NewGithubDownloaderV3(ctx, "https://github.com", "", "", "", "go-xorm", "builder")
|
||||
require.NoError(t, err)
|
||||
var (
|
||||
ctx = t.Context()
|
||||
downloader = NewGithubDownloaderV3(ctx, "https://github.com", "", "", "", "go-xorm", "builder")
|
||||
repoName = "builder-" + time.Now().Format("2006-01-02-15-04-05")
|
||||
uploader = NewGiteaLocalUploader(graceful.GetManager().HammerContext(), user, user.Name, repoName)
|
||||
repoName = "builder-" + time.Now().Format("2006-01-02-15-04-05")
|
||||
uploader = NewGiteaLocalUploader(graceful.GetManager().HammerContext(), user, user.Name, repoName)
|
||||
)
|
||||
|
||||
err := migrateRepository(t.Context(), user, downloader, uploader, base.MigrateOptions{
|
||||
err = migrateRepository(t.Context(), user, downloader, uploader, base.MigrateOptions{
|
||||
CloneAddr: "https://github.com/go-xorm/builder",
|
||||
RepoName: repoName,
|
||||
AuthUsername: "",
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/proxy"
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
|
||||
"github.com/google/go-github/v86/github"
|
||||
"github.com/google/go-github/v87/github"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
@@ -52,7 +52,7 @@ func (f *GithubDownloaderV3Factory) New(ctx context.Context, opts base.MigrateOp
|
||||
|
||||
log.Trace("Create github downloader BaseURL: %s %s/%s", baseURL, oldOwner, oldName)
|
||||
|
||||
return NewGithubDownloaderV3(ctx, baseURL, opts.AuthUsername, opts.AuthPassword, opts.AuthToken, oldOwner, oldName), nil
|
||||
return NewGithubDownloaderV3(ctx, baseURL, opts.AuthUsername, opts.AuthPassword, opts.AuthToken, oldOwner, oldName)
|
||||
}
|
||||
|
||||
// GitServiceType returns the type of git service
|
||||
@@ -78,7 +78,7 @@ type GithubDownloaderV3 struct {
|
||||
}
|
||||
|
||||
// NewGithubDownloaderV3 creates a github Downloader via github v3 API
|
||||
func NewGithubDownloaderV3(_ context.Context, baseURL, userName, password, token, repoOwner, repoName string) *GithubDownloaderV3 {
|
||||
func NewGithubDownloaderV3(_ context.Context, baseURL, userName, password, token, repoOwner, repoName string) (*GithubDownloaderV3, error) {
|
||||
downloader := GithubDownloaderV3{
|
||||
userName: userName,
|
||||
baseURL: baseURL,
|
||||
@@ -102,7 +102,9 @@ func NewGithubDownloaderV3(_ context.Context, baseURL, userName, password, token
|
||||
},
|
||||
}
|
||||
|
||||
downloader.addClient(client, baseURL)
|
||||
if err := downloader.addClient(client, baseURL); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
transport := NewMigrationHTTPTransport()
|
||||
@@ -113,9 +115,11 @@ func NewGithubDownloaderV3(_ context.Context, baseURL, userName, password, token
|
||||
client := &http.Client{
|
||||
Transport: transport,
|
||||
}
|
||||
downloader.addClient(client, baseURL)
|
||||
if err := downloader.addClient(client, baseURL); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &downloader
|
||||
return &downloader, nil
|
||||
}
|
||||
|
||||
// String implements Stringer
|
||||
@@ -130,13 +134,18 @@ func (g *GithubDownloaderV3) LogString() string {
|
||||
return fmt.Sprintf("<GithubDownloaderV3 %s %s/%s>", g.baseURL, g.repoOwner, g.repoName)
|
||||
}
|
||||
|
||||
func (g *GithubDownloaderV3) addClient(client *http.Client, baseURL string) {
|
||||
githubClient := github.NewClient(client)
|
||||
func (g *GithubDownloaderV3) addClient(client *http.Client, baseURL string) error {
|
||||
opts := []github.ClientOptionsFunc{github.WithHTTPClient(client)}
|
||||
if baseURL != "https://github.com" {
|
||||
githubClient, _ = githubClient.WithEnterpriseURLs(baseURL, baseURL)
|
||||
opts = append(opts, github.WithEnterpriseURLs(baseURL, baseURL))
|
||||
}
|
||||
githubClient, err := github.NewClient(opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.clients = append(g.clients, githubClient)
|
||||
g.rates = append(g.rates, nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *GithubDownloaderV3) waitAndPickClient(ctx context.Context) {
|
||||
|
||||
@@ -30,8 +30,9 @@ func TestGitHubDownloadRepo(t *testing.T) {
|
||||
|
||||
GithubLimitRateRemaining = 3 // Wait at 3 remaining since we could have 3 CI in //
|
||||
ctx := t.Context()
|
||||
downloader := NewGithubDownloaderV3(ctx, mockServer.URL, "", "", token, "go-gitea", "test_repo")
|
||||
err := downloader.RefreshRate(ctx)
|
||||
downloader, err := NewGithubDownloaderV3(ctx, mockServer.URL, "", "", token, "go-gitea", "test_repo")
|
||||
require.NoError(t, err)
|
||||
err = downloader.RefreshRate(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
repo, err := downloader.GetRepoInfo(ctx)
|
||||
|
||||
@@ -45,7 +45,7 @@ type Notifier interface {
|
||||
NewPullRequest(ctx context.Context, pr *issues_model.PullRequest, mentions []*user_model.User)
|
||||
MergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest)
|
||||
AutoMergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest)
|
||||
PullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest)
|
||||
PullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, before, after string)
|
||||
PullRequestReview(ctx context.Context, pr *issues_model.PullRequest, review *issues_model.Review, comment *issues_model.Comment, mentions []*user_model.User)
|
||||
PullRequestCodeComment(ctx context.Context, pr *issues_model.PullRequest, comment *issues_model.Comment, mentions []*user_model.User)
|
||||
PullRequestChangeTargetBranch(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, oldBranch string)
|
||||
|
||||
@@ -120,9 +120,9 @@ func NewPullRequest(ctx context.Context, pr *issues_model.PullRequest, mentions
|
||||
}
|
||||
|
||||
// PullRequestSynchronized notifies Synchronized pull request
|
||||
func PullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) {
|
||||
func PullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, before, after string) {
|
||||
for _, notifier := range notifiers {
|
||||
notifier.PullRequestSynchronized(ctx, doer, pr)
|
||||
notifier.PullRequestSynchronized(ctx, doer, pr, before, after)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ func (*NullNotifier) AutoMergePullRequest(ctx context.Context, doer *user_model.
|
||||
}
|
||||
|
||||
// PullRequestSynchronized places a place holder function
|
||||
func (*NullNotifier) PullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) {
|
||||
func (*NullNotifier) PullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, before, after string) {
|
||||
}
|
||||
|
||||
// PullRequestChangeTargetBranch places a place holder function
|
||||
|
||||
@@ -479,7 +479,7 @@ func AddTestPullRequestTask(opts TestPullRequestOptions) {
|
||||
}
|
||||
}
|
||||
|
||||
notify_service.PullRequestSynchronized(ctx, opts.Doer, pr)
|
||||
notify_service.PullRequestSynchronized(ctx, opts.Doer, pr, opts.OldCommitID, opts.NewCommitID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -818,7 +818,7 @@ func (m *webhookNotifier) CreateRef(ctx context.Context, pusher *user_model.User
|
||||
}
|
||||
}
|
||||
|
||||
func (m *webhookNotifier) PullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) {
|
||||
func (m *webhookNotifier) PullRequestSynchronized(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest, before, after string) {
|
||||
if err := pr.LoadIssue(ctx); err != nil {
|
||||
log.Error("LoadIssue: %v", err)
|
||||
return
|
||||
@@ -830,6 +830,8 @@ func (m *webhookNotifier) PullRequestSynchronized(ctx context.Context, doer *use
|
||||
|
||||
if err := PrepareWebhooks(ctx, EventSource{Repository: pr.Issue.Repo}, webhook_module.HookEventPullRequestSync, &api.PullRequestPayload{
|
||||
Action: api.HookIssueSynchronized,
|
||||
Before: before,
|
||||
After: after,
|
||||
Index: pr.Issue.Index,
|
||||
PullRequest: convert.ToAPIPullRequest(ctx, pr, doer),
|
||||
Repository: convert.ToRepo(ctx, pr.Issue.Repo, access_model.Permission{AccessMode: perm.AccessModeOwner}),
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="ui fluid vertical menu">
|
||||
<div class="header item">{{ctx.Locale.Tr "admin.settings"}}</div>
|
||||
|
||||
<details class="item toggleable-item" {{if or .PageIsAdminDashboard .PageIsAdminSelfCheck}}open{{end}}>
|
||||
<details class="item" {{if or .PageIsAdminDashboard .PageIsAdminSelfCheck}}open{{end}}>
|
||||
<summary>{{ctx.Locale.Tr "admin.maintenance"}}</summary>
|
||||
<div class="menu">
|
||||
<a class="{{if .PageIsAdminDashboard}}active {{end}}item" href="{{AppSubUrl}}/-/admin">
|
||||
@@ -13,7 +13,7 @@
|
||||
</a>
|
||||
</div>
|
||||
</details>
|
||||
<details class="item toggleable-item" {{if or .PageIsAdminUsers .PageIsAdminBadges .PageIsAdminEmails .PageIsAdminOrganizations .PageIsAdminAuthentications}}open{{end}}>
|
||||
<details class="item" {{if or .PageIsAdminUsers .PageIsAdminBadges .PageIsAdminEmails .PageIsAdminOrganizations .PageIsAdminAuthentications}}open{{end}}>
|
||||
<summary>{{ctx.Locale.Tr "admin.identity_access"}}</summary>
|
||||
<div class="menu">
|
||||
<a class="{{if .PageIsAdminAuthentications}}active {{end}}item" href="{{AppSubUrl}}/-/admin/auths">
|
||||
@@ -33,7 +33,7 @@
|
||||
</a>
|
||||
</div>
|
||||
</details>
|
||||
<details class="item toggleable-item" {{if or .PageIsAdminRepositories (and .EnablePackages .PageIsAdminPackages)}}open{{end}}>
|
||||
<details class="item" {{if or .PageIsAdminRepositories (and .EnablePackages .PageIsAdminPackages)}}open{{end}}>
|
||||
<summary>{{ctx.Locale.Tr "admin.assets"}}</summary>
|
||||
<div class="menu">
|
||||
{{if .EnablePackages}}
|
||||
@@ -48,7 +48,7 @@
|
||||
</details>
|
||||
<!-- Webhooks and OAuth can be both disabled here, so add this if statement to display different ui -->
|
||||
{{if and (not DisableWebhooks) .EnableOAuth2}}
|
||||
<details class="item toggleable-item" {{if or .PageIsAdminDefaultHooks .PageIsAdminSystemHooks .PageIsAdminApplications}}open{{end}}>
|
||||
<details class="item" {{if or .PageIsAdminDefaultHooks .PageIsAdminSystemHooks .PageIsAdminApplications}}open{{end}}>
|
||||
<summary>{{ctx.Locale.Tr "admin.integrations"}}</summary>
|
||||
<div class="menu">
|
||||
<a class="{{if .PageIsAdminApplications}}active {{end}}item" href="{{AppSubUrl}}/-/admin/applications">
|
||||
@@ -72,7 +72,7 @@
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if .EnableActions}}
|
||||
<details class="item toggleable-item" {{if or .PageIsSharedSettingsRunners .PageIsSharedSettingsVariables}}open{{end}}>
|
||||
<details class="item" {{if or .PageIsSharedSettingsRunners .PageIsSharedSettingsVariables}}open{{end}}>
|
||||
<summary>{{ctx.Locale.Tr "actions.actions"}}</summary>
|
||||
<div class="menu">
|
||||
<a class="{{if .PageIsSharedSettingsRunners}}active {{end}}item" href="{{AppSubUrl}}/-/admin/actions/runners">
|
||||
@@ -84,7 +84,7 @@
|
||||
</div>
|
||||
</details>
|
||||
{{end}}
|
||||
<details class="item toggleable-item" {{if or .PageIsAdminConfig}}open{{end}}>
|
||||
<details class="item" {{if or .PageIsAdminConfig}}open{{end}}>
|
||||
<summary>{{ctx.Locale.Tr "admin.config"}}</summary>
|
||||
<div class="menu">
|
||||
<a class="{{if .PageIsAdminConfigSummary}}active {{end}}item" href="{{AppSubUrl}}/-/admin/config">
|
||||
@@ -98,7 +98,7 @@
|
||||
<a class="{{if .PageIsAdminNotices}}active {{end}}item" href="{{AppSubUrl}}/-/admin/notices">
|
||||
{{ctx.Locale.Tr "admin.notices"}}
|
||||
</a>
|
||||
<details class="item toggleable-item" {{if or .PageIsAdminMonitorStats .PageIsAdminMonitorCron .PageIsAdminMonitorQueue .PageIsAdminMonitorTrace}}open{{end}}>
|
||||
<details class="item" {{if or .PageIsAdminMonitorStats .PageIsAdminMonitorCron .PageIsAdminMonitorQueue .PageIsAdminMonitorTrace}}open{{end}}>
|
||||
<summary>{{ctx.Locale.Tr "admin.monitor"}}</summary>
|
||||
<div class="menu">
|
||||
<a class="{{if .PageIsAdminMonitorStats}}active {{end}}item" href="{{AppSubUrl}}/-/admin/monitor/stats">
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
</a>
|
||||
{{end}}
|
||||
{{if .EnableActions}}
|
||||
<details class="item toggleable-item" {{if or .PageIsOrgSettingsActionsGeneral .PageIsSharedSettingsRunners .PageIsSharedSettingsSecrets .PageIsSharedSettingsVariables}}open{{end}}>
|
||||
<details class="item" {{if or .PageIsOrgSettingsActionsGeneral .PageIsSharedSettingsRunners .PageIsSharedSettingsSecrets .PageIsSharedSettingsVariables}}open{{end}}>
|
||||
<summary>{{ctx.Locale.Tr "actions.actions"}}</summary>
|
||||
<div class="menu">
|
||||
<a class="{{if .PageIsOrgSettingsActionsGeneral}}active {{end}}item" href="{{.OrgLink}}/settings/actions">
|
||||
|
||||
@@ -27,7 +27,7 @@ git-fetch-with-cli = true</code></pre></div>
|
||||
{{if or .PackageDescriptor.Metadata.Description .PackageDescriptor.Metadata.Readme}}
|
||||
<h4 class="ui top attached header">{{ctx.Locale.Tr "packages.about"}}</h4>
|
||||
{{if .PackageDescriptor.Metadata.Description}}<div class="ui attached segment">{{.PackageDescriptor.Metadata.Description}}</div>{{end}}
|
||||
{{if .PackageDescriptor.Metadata.Readme}}<div class="ui attached segment">{{ctx.RenderUtils.MarkdownToHtml .PackageDescriptor.Metadata.Readme}}</div>{{end}}
|
||||
{{if .PackageDescriptor.Metadata.Readme}}<div class="ui attached segment">{{ctx.RenderUtils.RenderPackageMarkdown .PackageDescriptor.Metadata.Readme .PackageDescriptor.Repository}}</div>{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if .PackageDescriptor.Metadata.Dependencies}}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<h4 class="ui top attached header">{{ctx.Locale.Tr "packages.about"}}</h4>
|
||||
<div class="ui attached segment">
|
||||
{{if .PackageDescriptor.Metadata.Description}}<p>{{.PackageDescriptor.Metadata.Description}}</p>{{end}}
|
||||
{{if .PackageDescriptor.Metadata.LongDescription}}{{ctx.RenderUtils.MarkdownToHtml .PackageDescriptor.Metadata.LongDescription}}{{end}}
|
||||
{{if .PackageDescriptor.Metadata.LongDescription}}{{ctx.RenderUtils.RenderPackageMarkdown .PackageDescriptor.Metadata.LongDescription .PackageDescriptor.Repository}}{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
{{if or .PackageDescriptor.Metadata.Description .PackageDescriptor.Metadata.Comments}}
|
||||
<h4 class="ui top attached header">{{ctx.Locale.Tr "packages.about"}}</h4>
|
||||
{{if .PackageDescriptor.Metadata.Description}}<div class="ui attached segment">{{.PackageDescriptor.Metadata.Description}}</div>{{end}}
|
||||
{{if .PackageDescriptor.Metadata.Readme}}<div class="ui attached segment markup markdown">{{ctx.RenderUtils.MarkdownToHtml .PackageDescriptor.Metadata.Readme}}</div>{{end}}
|
||||
{{if .PackageDescriptor.Metadata.Readme}}<div class="ui attached segment">{{ctx.RenderUtils.RenderPackageMarkdown .PackageDescriptor.Metadata.Readme .PackageDescriptor.Repository}}</div>{{end}}
|
||||
{{if .PackageDescriptor.Metadata.Comments}}<div class="ui attached segment">{{StringUtils.Join .PackageDescriptor.Metadata.Comments " "}}</div>{{end}}
|
||||
{{end}}
|
||||
|
||||
|
||||
@@ -22,15 +22,8 @@
|
||||
|
||||
{{if or .PackageDescriptor.Metadata.Description .PackageDescriptor.Metadata.Readme}}
|
||||
<h4 class="ui top attached header">{{ctx.Locale.Tr "packages.about"}}</h4>
|
||||
<div class="ui attached segment">
|
||||
{{if .PackageDescriptor.Metadata.Readme}}
|
||||
<div class="markup markdown">
|
||||
{{ctx.RenderUtils.MarkdownToHtml .PackageDescriptor.Metadata.Readme}}
|
||||
</div>
|
||||
{{else if .PackageDescriptor.Metadata.Description}}
|
||||
{{.PackageDescriptor.Metadata.Description}}
|
||||
{{end}}
|
||||
</div>
|
||||
{{if .PackageDescriptor.Metadata.Description}}<div class="ui attached segment">{{.PackageDescriptor.Metadata.Description}}</div>{{end}}
|
||||
{{if .PackageDescriptor.Metadata.Readme}}<div class="ui attached segment">{{ctx.RenderUtils.RenderPackageMarkdown .PackageDescriptor.Metadata.Readme .PackageDescriptor.Repository .PackageDescriptor.Metadata.Repository.Directory}}</div>{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if or .PackageDescriptor.Metadata.Dependencies .PackageDescriptor.Metadata.DevelopmentDependencies .PackageDescriptor.Metadata.PeerDependencies .PackageDescriptor.Metadata.OptionalDependencies}}
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
|
||||
{{if or .PackageDescriptor.Metadata.Description .PackageDescriptor.Metadata.ReleaseNotes .PackageDescriptor.Metadata.Readme}}
|
||||
<h4 class="ui top attached header">{{ctx.Locale.Tr "packages.about"}}</h4>
|
||||
{{if .PackageDescriptor.Metadata.Description}}<div class="ui attached segment">{{ctx.RenderUtils.MarkdownToHtml .PackageDescriptor.Metadata.Description}}</div>{{end}}
|
||||
{{if .PackageDescriptor.Metadata.Readme}}<div class="ui attached segment markup markdown">{{ctx.RenderUtils.MarkdownToHtml .PackageDescriptor.Metadata.Readme}}</div>{{end}}
|
||||
{{if .PackageDescriptor.Metadata.ReleaseNotes}}<div class="ui attached segment">{{ctx.RenderUtils.MarkdownToHtml .PackageDescriptor.Metadata.ReleaseNotes}}</div>{{end}}
|
||||
{{if .PackageDescriptor.Metadata.Description}}<div class="ui attached segment">{{ctx.RenderUtils.RenderPackageMarkdown .PackageDescriptor.Metadata.Description .PackageDescriptor.Repository}}</div>{{end}}
|
||||
{{if .PackageDescriptor.Metadata.Readme}}<div class="ui attached segment">{{ctx.RenderUtils.RenderPackageMarkdown .PackageDescriptor.Metadata.Readme .PackageDescriptor.Repository}}</div>{{end}}
|
||||
{{if .PackageDescriptor.Metadata.ReleaseNotes}}<div class="ui attached segment">{{ctx.RenderUtils.RenderPackageMarkdown .PackageDescriptor.Metadata.ReleaseNotes .PackageDescriptor.Repository}}</div>{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if .PackageDescriptor.Metadata.Dependencies}}
|
||||
|
||||
@@ -14,6 +14,6 @@
|
||||
{{if or .PackageDescriptor.Metadata.Description .PackageDescriptor.Metadata.Readme}}
|
||||
<h4 class="ui top attached header">{{ctx.Locale.Tr "packages.about"}}</h4>
|
||||
{{if .PackageDescriptor.Metadata.Description}}<div class="ui attached segment">{{.PackageDescriptor.Metadata.Description}}</div>{{end}}
|
||||
{{if .PackageDescriptor.Metadata.Readme}}<div class="ui attached segment">{{ctx.RenderUtils.MarkdownToHtml .PackageDescriptor.Metadata.Readme}}</div>{{end}}
|
||||
{{if .PackageDescriptor.Metadata.Readme}}<div class="ui attached segment">{{ctx.RenderUtils.RenderPackageMarkdown .PackageDescriptor.Metadata.Readme .PackageDescriptor.Repository}}</div>{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
<div class="ui attached segment">
|
||||
<p>{{if .PackageDescriptor.Metadata.Summary}}{{.PackageDescriptor.Metadata.Summary}}{{end}}</p>
|
||||
{{if .PackageDescriptor.Metadata.LongDescription}}
|
||||
{{ctx.RenderUtils.MarkdownToHtml .PackageDescriptor.Metadata.LongDescription}}
|
||||
{{ctx.RenderUtils.RenderPackageMarkdown .PackageDescriptor.Metadata.LongDescription .PackageDescriptor.Repository}}
|
||||
{{else if .PackageDescriptor.Metadata.Description}}
|
||||
{{ctx.RenderUtils.MarkdownToHtml .PackageDescriptor.Metadata.Description}}
|
||||
{{ctx.RenderUtils.RenderPackageMarkdown .PackageDescriptor.Metadata.Description .PackageDescriptor.Repository}}
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
{{if .HasWorkflowsOrRuns}}
|
||||
<div class="flex-container">
|
||||
<div class="flex-container-nav">
|
||||
<div class="ui fluid vertical menu flex-items-block">
|
||||
<a class="item {{if not $.CurWorkflow}}active{{end}}" href="?actor={{$.CurActor}}&status={{$.CurStatus}}">{{ctx.Locale.Tr "actions.runs.all_workflows"}}</a>
|
||||
<div class="ui fluid vertical menu">
|
||||
<a class="item {{if not $.CurWorkflow}}active{{end}}" href="?actor={{$.CurActor}}&status={{$.CurStatus}}&branch={{$.CurBranch}}">{{ctx.Locale.Tr "actions.runs.all_workflows"}}</a>
|
||||
{{range .workflows}}
|
||||
<a class="item {{if eq .Entry.Name $.CurWorkflow}}active{{end}}" href="?workflow={{.Entry.Name}}&actor={{$.CurActor}}&status={{$.CurStatus}}">
|
||||
<span class="gt-ellipsis">{{.Entry.Name}}</span>
|
||||
<a class="item flex-text-block {{if eq .Entry.Name $.CurWorkflow}}active{{end}}" href="?workflow={{.Entry.Name}}&actor={{$.CurActor}}&status={{$.CurStatus}}&branch={{$.CurBranch}}">
|
||||
<span class="gt-ellipsis">{{.DisplayName}}</span>
|
||||
|
||||
{{if .ErrMsg}}
|
||||
<span class="flex-text-inline" data-tooltip-content="{{.ErrMsg}}">{{svg "octicon-alert" 16 "tw-text-red"}}</span>
|
||||
@@ -22,6 +22,23 @@
|
||||
{{end}}
|
||||
</a>
|
||||
{{end}}
|
||||
{{if .OtherWorkflows}}
|
||||
<details class="item"{{if not $.CurWorkflowIsListed}} open{{end}}>
|
||||
<summary data-tooltip-content="{{ctx.Locale.Tr "actions.runs.other_workflows_tooltip"}}">
|
||||
<span class="flex-text-block">
|
||||
{{ctx.Locale.Tr "actions.runs.other_workflows"}}
|
||||
<span class="ui label">{{len .OtherWorkflows}}</span>
|
||||
</span>
|
||||
</summary>
|
||||
<div class="menu items-full-width">
|
||||
{{range .OtherWorkflows}}
|
||||
<a class="item {{if eq . $.CurWorkflow}}active{{end}}" href="?workflow={{.}}&actor={{$.CurActor}}&status={{$.CurStatus}}">
|
||||
<span class="gt-ellipsis">{{.}}</span>
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</details>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-container-main">
|
||||
@@ -37,11 +54,11 @@
|
||||
<i class="icon">{{svg "octicon-search"}}</i>
|
||||
<input type="text" placeholder="{{ctx.Locale.Tr "actions.runs.actor"}}">
|
||||
</div>
|
||||
<a class="item{{if not $.CurActor}} active{{end}}" href="?workflow={{$.CurWorkflow}}&status={{$.CurStatus}}&actor=0">
|
||||
<a class="item{{if not $.CurActor}} selected{{end}}" href="?workflow={{$.CurWorkflow}}&status={{$.CurStatus}}&branch={{$.CurBranch}}&actor=0">
|
||||
{{ctx.Locale.Tr "actions.runs.actors_no_select"}}
|
||||
</a>
|
||||
{{range .Actors}}
|
||||
<a class="item{{if eq .ID $.CurActor}} active{{end}}" href="?workflow={{$.CurWorkflow}}&actor={{.ID}}&status={{$.CurStatus}}">
|
||||
<a class="item{{if eq .ID $.CurActor}} selected{{end}}" href="?workflow={{$.CurWorkflow}}&actor={{.ID}}&status={{$.CurStatus}}&branch={{$.CurBranch}}">
|
||||
{{ctx.AvatarUtils.Avatar . 20}} {{.GetDisplayName}}
|
||||
</a>
|
||||
{{end}}
|
||||
@@ -56,22 +73,41 @@
|
||||
<i class="icon">{{svg "octicon-search"}}</i>
|
||||
<input type="text" placeholder="{{ctx.Locale.Tr "actions.runs.status"}}">
|
||||
</div>
|
||||
<a class="item{{if not $.CurStatus}} active{{end}}" href="?workflow={{$.CurWorkflow}}&actor={{$.CurActor}}&status=0">
|
||||
<a class="item{{if not $.CurStatus}} selected{{end}}" href="?workflow={{$.CurWorkflow}}&actor={{$.CurActor}}&branch={{$.CurBranch}}&status=0">
|
||||
{{ctx.Locale.Tr "actions.runs.status_no_select"}}
|
||||
</a>
|
||||
{{range .StatusInfoList}}
|
||||
<a class="item{{if eq .Status $.CurStatus}} active{{end}}" href="?workflow={{$.CurWorkflow}}&actor={{$.CurActor}}&status={{.Status}}">
|
||||
<a class="item{{if eq .Status $.CurStatus}} selected{{end}}" href="?workflow={{$.CurWorkflow}}&actor={{$.CurActor}}&status={{.Status}}&branch={{$.CurBranch}}">
|
||||
{{.DisplayedStatus}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<!-- Branch -->
|
||||
<div class="ui{{if not .RunBranches}} disabled{{end}} dropdown jump item" data-test-id="filter-branch">
|
||||
<span class="text">{{ctx.Locale.Tr "actions.runs.branch"}}</span>
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
<div class="menu">
|
||||
<div class="ui icon search input">
|
||||
<i class="icon">{{svg "octicon-search"}}</i>
|
||||
<input type="text" placeholder="{{ctx.Locale.Tr "actions.runs.branch"}}">
|
||||
</div>
|
||||
<a class="item{{if not $.CurBranch}} selected{{end}}" href="?workflow={{$.CurWorkflow}}&actor={{$.CurActor}}&status={{$.CurStatus}}">
|
||||
{{ctx.Locale.Tr "actions.runs.branches_no_select"}}
|
||||
</a>
|
||||
{{range .RunBranches}}
|
||||
<a class="item{{if eq . $.CurBranch}} selected{{end}}" href="?workflow={{$.CurWorkflow}}&actor={{$.CurActor}}&status={{$.CurStatus}}&branch={{.}}">
|
||||
{{.}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if .AllowDisableOrEnableWorkflow}}
|
||||
{{if and .AllowDisableOrEnableWorkflow .CurWorkflowIsListed $.CurWorkflow}}
|
||||
<button class="ui jump dropdown btn interact-bg tw-p-2">
|
||||
{{svg "octicon-kebab-horizontal"}}
|
||||
<div class="menu">
|
||||
<a class="item link-action" data-url="{{$.Link}}/{{if .CurWorkflowDisabled}}enable{{else}}disable{{end}}?workflow={{$.CurWorkflow}}&actor={{.CurActor}}&status={{$.CurStatus}}">
|
||||
<a class="item link-action" data-url="{{$.Link}}/{{if .CurWorkflowDisabled}}enable{{else}}disable{{end}}?workflow={{$.CurWorkflow}}&actor={{.CurActor}}&status={{$.CurStatus}}&branch={{$.CurBranch}}">
|
||||
{{if .CurWorkflowDisabled}}{{ctx.Locale.Tr "actions.workflow.enable"}}{{else}}{{ctx.Locale.Tr "actions.workflow.disable"}}{{end}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
{{end}}
|
||||
</span>
|
||||
<div class="item-body">
|
||||
<span><b>{{if not $.CurWorkflow}}{{$run.WorkflowID}} {{end}}#{{$run.Index}}</b>:</span>
|
||||
{{$workflowName := index $.WorkflowNames $run.WorkflowID}}
|
||||
<span><b>{{if not $.CurWorkflow}}{{if $workflowName}}{{$workflowName}}{{else}}{{$run.WorkflowID}}{{end}} {{end}}#{{$run.Index}}</b>:</span>
|
||||
|
||||
{{- if $run.ScheduleID -}}
|
||||
{{ctx.Locale.Tr "actions.runs.scheduled"}}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</div>
|
||||
<div id="runWorkflowDispatchModal" class="ui tiny modal">
|
||||
<div class="content">
|
||||
<form id="runWorkflowDispatchForm" class="ui form ignore-dirty" action="{{$.Link}}/run?workflow={{$.CurWorkflow}}&actor={{$.CurActor}}&status={{.Status}}" method="post">
|
||||
<form id="runWorkflowDispatchForm" class="ui form ignore-dirty" action="{{$.Link}}/run?workflow={{$.CurWorkflow}}&actor={{$.CurActor}}&status={{$.CurStatus}}&branch={{$.CurBranch}}" method="post">
|
||||
<div class="ui inline field required tw-flex tw-items-center">
|
||||
<span class="ui inline required field">
|
||||
<label>{{ctx.Locale.Tr "actions.workflow.from_ref"}}:</label>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
</a>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<details class="item toggleable-item" {{if or .PageIsSharedSettingsRunners .PageIsSharedSettingsSecrets .PageIsSharedSettingsVariables .PageIsActionsSettingsGeneral}}open{{end}}>
|
||||
<details class="item" {{if or .PageIsSharedSettingsRunners .PageIsSharedSettingsSecrets .PageIsSharedSettingsVariables .PageIsActionsSettingsGeneral}}open{{end}}>
|
||||
<summary>{{ctx.Locale.Tr "actions.actions"}}</summary>
|
||||
<div class="menu">
|
||||
<a class="{{if .PageIsActionsSettingsGeneral}}active {{end}}item" href="{{.RepoLink}}/settings/actions/general">
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
</a>
|
||||
{{end}}
|
||||
{{if .EnableActions}}
|
||||
<details class="item toggleable-item" {{if or .PageIsUserSettingsActionsGeneral .PageIsSharedSettingsRunners .PageIsSharedSettingsSecrets .PageIsSharedSettingsVariables}}open{{end}}>
|
||||
<details class="item" {{if or .PageIsUserSettingsActionsGeneral .PageIsSharedSettingsRunners .PageIsSharedSettingsSecrets .PageIsSharedSettingsVariables}}open{{end}}>
|
||||
<summary>{{ctx.Locale.Tr "actions.actions"}}</summary>
|
||||
<div class="menu">
|
||||
<a class="{{if .PageIsUserSettingsActionsGeneral}}active {{end}}item" href="{{AppSubUrl}}/user/settings/actions/general">
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestActionsListFilters(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
user5 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
|
||||
session := loginUser(t, user5.Name)
|
||||
actionsURL := fmt.Sprintf("/%s/%s/actions", user5.Name, repo.Name)
|
||||
|
||||
t.Run("BranchDropdownListsBranches", func(t *testing.T) {
|
||||
req := NewRequest(t, "GET", actionsURL)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
var labels []string
|
||||
htmlDoc.doc.Find(`[data-test-id="filter-branch"] .menu a.item`).Each(func(_ int, a *goquery.Selection) {
|
||||
labels = append(labels, strings.TrimSpace(a.Text()))
|
||||
})
|
||||
assert.Contains(t, labels, "master")
|
||||
})
|
||||
|
||||
t.Run("FilterByBranch", func(t *testing.T) {
|
||||
req := NewRequest(t, "GET", actionsURL+"?branch=master")
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
refs := htmlDoc.doc.Find(".run-list .run-list-ref")
|
||||
assert.Positive(t, refs.Length(), "filtered run list should not be empty")
|
||||
refs.Each(func(_ int, sel *goquery.Selection) {
|
||||
assert.Equal(t, "master", strings.TrimSpace(sel.Text()))
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("PaginationPreservesFilters", func(t *testing.T) {
|
||||
req := NewRequest(t, "GET", actionsURL+"?branch=master&limit=1")
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
pageLinks := htmlDoc.doc.Find(".pagination a[href]")
|
||||
assert.Positive(t, pageLinks.Length(), "pagination should be rendered")
|
||||
pageLinks.Each(func(_ int, a *goquery.Selection) {
|
||||
u, err := url.Parse(a.AttrOr("href", ""))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "master", u.Query().Get("branch"), "pagination link must preserve branch filter")
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/packages"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/packages/npm"
|
||||
@@ -20,6 +21,7 @@ import (
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPackageNpm(t *testing.T) {
|
||||
@@ -39,6 +41,7 @@ func TestPackageNpm(t *testing.T) {
|
||||
packageBinPath := "./cli.sh"
|
||||
repoType := "gitea"
|
||||
repoURL := "http://localhost:3000/gitea/test.git"
|
||||
repoDirectory := "package-subdir"
|
||||
|
||||
data := "H4sIAAAAAAAA/ytITM5OTE/VL4DQelnF+XkMVAYGBgZmJiYK2MRBwNDcSIHB2NTMwNDQzMwAqA7IMDUxA9LUdgg2UFpcklgEdAql5kD8ogCnhwio5lJQUMpLzE1VslJQcihOzi9I1S9JLS7RhSYIJR2QgrLUouLM/DyQGkM9Az1D3YIiqExKanFyUWZBCVQ2BKhVwQVJDKwosbQkI78IJO/tZ+LsbRykxFXLNdA+HwWjYBSMgpENACgAbtAACAAA"
|
||||
|
||||
@@ -67,8 +70,10 @@ func TestPackageNpm(t *testing.T) {
|
||||
},
|
||||
"repository": {
|
||||
"type": "` + repoType + `",
|
||||
"url": "` + repoURL + `"
|
||||
"url": "` + repoURL + `",
|
||||
"directory": "` + repoDirectory + `"
|
||||
},
|
||||
"readme": "[docs](docs/usage.md)\n",
|
||||
"peerDependencies": {
|
||||
"tea": "2.x",
|
||||
"soy-milk": "1.2"
|
||||
@@ -282,6 +287,28 @@ func TestPackageNpm(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("WebViewReadmeRepoLinks", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
pvs, err := packages.GetVersionsByPackageType(t.Context(), user.ID, packages.TypeNpm)
|
||||
assert.NoError(t, err)
|
||||
require.Len(t, pvs, 1)
|
||||
|
||||
// link the package to a repository so README relative links resolve against
|
||||
// repository files instead of the site root
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
assert.NoError(t, packages.SetRepositoryLink(t.Context(), pvs[0].PackageID, repo.ID))
|
||||
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/%s/-/packages/npm/%s/%s", user.Name, url.PathEscape(packageName), packageVersion)).
|
||||
AddBasicAuth(user.Name)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
doc := NewHTMLParser(t, resp.Body)
|
||||
rendered, _ := doc.Find(".markup.markdown").Html()
|
||||
assert.Equal(t, `<p dir="auto"><a href="/user2/repo1/src/branch/master/package-subdir/docs/usage.md" rel="nofollow">docs</a>
|
||||
<a href="/user2/repo1/src/branch/master/package-subdir/logo.png" rel="nofollow noopener" target="_blank"><img src="/user2/repo1/media/branch/master/package-subdir/logo.png" alt="logo" loading="lazy"/></a></p>
|
||||
`, rendered)
|
||||
})
|
||||
|
||||
t.Run("Delete", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
|
||||
@@ -351,48 +351,52 @@ func TestAPIGetRepoByIDUnauthorized(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAPIRepoMigrate(t *testing.T) {
|
||||
testCases := []struct {
|
||||
ctxUserID, userID int64
|
||||
cloneURL, repoName string
|
||||
expectedStatus int
|
||||
}{
|
||||
{ctxUserID: 1, userID: 2, cloneURL: "https://github.com/go-gitea/test_repo.git", repoName: "git-admin", expectedStatus: http.StatusCreated},
|
||||
{ctxUserID: 2, userID: 2, cloneURL: "https://github.com/go-gitea/test_repo.git", repoName: "git-own", expectedStatus: http.StatusCreated},
|
||||
{ctxUserID: 2, userID: 1, cloneURL: "https://github.com/go-gitea/test_repo.git", repoName: "git-bad", expectedStatus: http.StatusForbidden},
|
||||
{ctxUserID: 2, userID: 3, cloneURL: "https://github.com/go-gitea/test_repo.git", repoName: "git-org", expectedStatus: http.StatusCreated},
|
||||
{ctxUserID: 2, userID: 6, cloneURL: "https://github.com/go-gitea/test_repo.git", repoName: "git-bad-org", expectedStatus: http.StatusForbidden},
|
||||
{ctxUserID: 2, userID: 3, cloneURL: "https://localhost:3000/user/test_repo.git", repoName: "private-ip", expectedStatus: http.StatusUnprocessableEntity},
|
||||
{ctxUserID: 2, userID: 3, cloneURL: "https://10.0.0.1/user/test_repo.git", repoName: "private-ip", expectedStatus: http.StatusUnprocessableEntity},
|
||||
}
|
||||
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
||||
// migrate from a local fixture repo (user2/repo1) via the live listener so the test runs offline
|
||||
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
cloneAddr := fmt.Sprintf("%s%s/%s.git", u.String(), repo1.OwnerName, repo1.Name)
|
||||
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
defer test.MockVariableValue(&setting.Migrations.AllowLocalNetworks, false)()
|
||||
require.NoError(t, migrations.Init())
|
||||
|
||||
for _, testCase := range testCases {
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: testCase.ctxUserID})
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/migrate", &api.MigrateRepoOptions{
|
||||
CloneAddr: testCase.cloneURL,
|
||||
RepoOwnerID: testCase.userID,
|
||||
RepoName: testCase.repoName,
|
||||
}).AddTokenAuth(token)
|
||||
resp := MakeRequest(t, req, NoExpectedStatus)
|
||||
if resp.Code == http.StatusUnprocessableEntity {
|
||||
respJSON := DecodeJSON(t, resp, map[string]string{})
|
||||
switch respJSON["message"] {
|
||||
case "Remote visit addressed rate limitation.":
|
||||
t.Log("test hit github rate limitation")
|
||||
case "You can not import from disallowed hosts.":
|
||||
assert.Equal(t, "private-ip", testCase.repoName)
|
||||
default:
|
||||
assert.FailNow(t, "unexpected error", "unexpected error '%v' on url '%s'", respJSON["message"], testCase.cloneURL)
|
||||
t.Run("Permitted", func(t *testing.T) {
|
||||
// migrations.Init builds the host allowlist from AllowLocalNetworks, so set it first
|
||||
defer test.MockVariableValue(&setting.Migrations.AllowLocalNetworks, true)()
|
||||
require.NoError(t, migrations.Init())
|
||||
for _, testCase := range []struct {
|
||||
ctxUserID, ownerID int64
|
||||
repoName string
|
||||
expectedStatus int
|
||||
}{
|
||||
{ctxUserID: 1, ownerID: 2, repoName: "git-admin", expectedStatus: http.StatusCreated},
|
||||
{ctxUserID: 2, ownerID: 2, repoName: "git-own", expectedStatus: http.StatusCreated},
|
||||
{ctxUserID: 2, ownerID: 1, repoName: "git-bad", expectedStatus: http.StatusForbidden},
|
||||
{ctxUserID: 2, ownerID: 3, repoName: "git-org", expectedStatus: http.StatusCreated},
|
||||
{ctxUserID: 2, ownerID: 6, repoName: "git-bad-org", expectedStatus: http.StatusForbidden},
|
||||
} {
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: testCase.ctxUserID})
|
||||
token := getTokenForLoggedInUser(t, loginUser(t, user.Name), auth_model.AccessTokenScopeWriteRepository)
|
||||
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/migrate", &api.MigrateRepoOptions{
|
||||
CloneAddr: cloneAddr,
|
||||
RepoOwnerID: testCase.ownerID,
|
||||
RepoName: testCase.repoName,
|
||||
}).AddTokenAuth(token)
|
||||
MakeRequest(t, req, testCase.expectedStatus)
|
||||
}
|
||||
} else {
|
||||
assert.Equal(t, testCase.expectedStatus, resp.Code)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("DisallowedHost", func(t *testing.T) {
|
||||
defer test.MockVariableValue(&setting.Migrations.AllowLocalNetworks, false)()
|
||||
require.NoError(t, migrations.Init())
|
||||
token := getTokenForLoggedInUser(t, loginUser(t, "user2"), auth_model.AccessTokenScopeWriteRepository)
|
||||
for _, cloneURL := range []string{"https://localhost:3000/user/test_repo.git", "https://10.0.0.1/user/test_repo.git"} {
|
||||
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/migrate", &api.MigrateRepoOptions{
|
||||
CloneAddr: cloneURL,
|
||||
RepoOwnerID: 3,
|
||||
RepoName: "private-ip",
|
||||
}).AddTokenAuth(token)
|
||||
resp := MakeRequest(t, req, http.StatusUnprocessableEntity)
|
||||
assert.Equal(t, "You can not import from disallowed hosts.", DecodeJSON(t, resp, map[string]string{})["message"])
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestAPIRepoMigrateConflict(t *testing.T) {
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
#!/usr/bin/env node
|
||||
import {argv, env, exit} from 'node:process';
|
||||
|
||||
const allowedTypes = [
|
||||
'build',
|
||||
'chore',
|
||||
'ci',
|
||||
'docs',
|
||||
'enhance',
|
||||
'feat',
|
||||
'fix',
|
||||
'perf',
|
||||
'refactor',
|
||||
'revert',
|
||||
'style',
|
||||
'test',
|
||||
] as const;
|
||||
type CommitType = typeof allowedTypes[number];
|
||||
|
||||
const allowedTypesList = allowedTypes.join(', ');
|
||||
const titlePattern = new RegExp(`^(${allowedTypes.join('|')})(\\([\\w/.-]+\\))?(!)?: .+$`);
|
||||
|
||||
function parsePrTitle(title: string): {type: CommitType; breaking: boolean} | null {
|
||||
const match = titlePattern.exec(title);
|
||||
return match ? {type: match[1] as CommitType, breaking: Boolean(match[3])} : null;
|
||||
}
|
||||
|
||||
const breakingLabel = 'pr/breaking';
|
||||
|
||||
// Mutually exclusive type labels, fully synced with the title type (added and removed).
|
||||
const typeLabels: Partial<Record<CommitType, string>> = {
|
||||
feat: 'type/feature',
|
||||
enhance: 'type/enhancement',
|
||||
fix: 'type/bug',
|
||||
docs: 'type/docs',
|
||||
test: 'type/testing',
|
||||
};
|
||||
|
||||
// Non-type labels, only added, never auto-removed, so manual labeling is not clobbered.
|
||||
const extraLabels: Partial<Record<CommitType, string>> = {
|
||||
chore: 'skip-changelog',
|
||||
ci: 'skip-changelog',
|
||||
build: 'topic/build',
|
||||
};
|
||||
|
||||
// Labels this tool may remove when the title no longer implies them.
|
||||
const removableLabels = [...Object.values(typeLabels), breakingLabel];
|
||||
|
||||
function labelsForPrTitle(title: string): string[] {
|
||||
const parsed = parsePrTitle(title);
|
||||
if (!parsed) return [];
|
||||
return [typeLabels[parsed.type], extraLabels[parsed.type], parsed.breaking ? breakingLabel : undefined]
|
||||
.filter((label): label is string => label !== undefined);
|
||||
}
|
||||
|
||||
// Command: validate PR_TITLE against the allowed Conventional Commits format.
|
||||
function lintPrTitle(): void {
|
||||
if (!env.PR_TITLE) {
|
||||
console.error('Missing PR_TITLE');
|
||||
exit(1);
|
||||
}
|
||||
if (!parsePrTitle(env.PR_TITLE)) {
|
||||
console.error(`Invalid PR title: ${env.PR_TITLE}`);
|
||||
console.error('Expected format: type(scope): subject (scope optional, append "!" for breaking changes)');
|
||||
console.error(`Allowed types: ${allowedTypesList}`);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Command: sync the title-derived labels onto the PR via the GitHub API.
|
||||
async function setPrLabels(): Promise<void> {
|
||||
if (!env.PR_TITLE || !env.GITHUB_TOKEN || !env.GITHUB_REPOSITORY || !env.PR_NUMBER) {
|
||||
console.error('set-pr-labels requires PR_TITLE, GITHUB_TOKEN, GITHUB_REPOSITORY and PR_NUMBER');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const labelsUrl = `https://api.github.com/repos/${env.GITHUB_REPOSITORY}/issues/${env.PR_NUMBER}/labels`;
|
||||
|
||||
async function request(url: string, method = 'GET', body?: unknown): Promise<Response> {
|
||||
const response = await fetch(url, {
|
||||
method,
|
||||
headers: {
|
||||
Accept: 'application/vnd.github+json',
|
||||
Authorization: `Bearer ${env.GITHUB_TOKEN}`,
|
||||
'X-GitHub-Api-Version': '2022-11-28',
|
||||
...(body ? {'Content-Type': 'application/json'} : {}),
|
||||
},
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`GitHub API ${method} ${url} failed (${response.status}): ${await response.text()}`);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
const desired = labelsForPrTitle(env.PR_TITLE);
|
||||
const response = await request(`${labelsUrl}?per_page=100`);
|
||||
const current = ((await response.json()) as Array<{name: string}>).map((label) => label.name);
|
||||
|
||||
const toAdd = desired.filter((name) => !current.includes(name));
|
||||
const toRemove = removableLabels.filter((name) => current.includes(name) && !desired.includes(name));
|
||||
|
||||
if (toAdd.length) {
|
||||
await request(labelsUrl, 'POST', {labels: toAdd});
|
||||
console.info(`Added labels: ${toAdd.join(', ')}`);
|
||||
}
|
||||
for (const name of toRemove) {
|
||||
await request(`${labelsUrl}/${encodeURIComponent(name)}`, 'DELETE');
|
||||
console.info(`Removed label: ${name}`);
|
||||
}
|
||||
if (!toAdd.length && !toRemove.length) {
|
||||
console.info('PR labels already in sync');
|
||||
}
|
||||
}
|
||||
|
||||
const commands: Record<string, () => void | Promise<void>> = {
|
||||
'lint-pr-title': lintPrTitle,
|
||||
'set-pr-labels': setPrLabels,
|
||||
};
|
||||
|
||||
const command = argv[2];
|
||||
const handler = commands[command];
|
||||
if (!handler) {
|
||||
console.error(`Usage: ci-tools.ts <${Object.keys(commands).join('|')}>`);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
await handler();
|
||||
} catch (error) {
|
||||
console.error(error instanceof Error ? error.message : error);
|
||||
exit(1);
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
import {env, exit} from 'node:process';
|
||||
|
||||
const allowedTypes = 'build, chore, ci, docs, enhance, feat, fix, perf, refactor, revert, style, test';
|
||||
const title = env.PR_TITLE;
|
||||
|
||||
if (!title) {
|
||||
console.error('Missing PR_TITLE');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const validTitlePattern = new RegExp(`^(${allowedTypes.replaceAll(', ', '|')})(\\([\\w.-]+\\))?(!)?: .+$`);
|
||||
|
||||
if (!validTitlePattern.test(title)) {
|
||||
console.error(`Invalid PR title: ${title}`);
|
||||
console.error('Expected format: type(scope): subject');
|
||||
console.error(`Allowed types: ${allowedTypes}`);
|
||||
exit(1);
|
||||
}
|
||||
@@ -102,7 +102,7 @@ dev = [
|
||||
dev = [
|
||||
{ name = "djlint", specifier = "==1.36.4" },
|
||||
{ name = "yamllint", specifier = "==1.38.0" },
|
||||
{ name = "zizmor", specifier = "==1.25.1" },
|
||||
{ name = "zizmor", specifier = "==1.25.2" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -420,18 +420,18 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "zizmor"
|
||||
version = "1.25.1"
|
||||
version = "1.25.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/28/16/6fb78c89586bfbd6e2aec21999891e3281ed104d29b65654b0112b6f804f/zizmor-1.25.1.tar.gz", hash = "sha256:f7849ce53371178338bd0302c7ee16fd274354e1f46490b49a76da37a1a1e7a1", size = 517745, upload-time = "2026-05-15T20:08:49.258Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b3/41/8987d546e3101cc76748b2f1b0ccda58e244773ef5124d39e7e749e3d6e4/zizmor-1.25.2.tar.gz", hash = "sha256:f26ffeb16659c8922c7b08203ca5a4f8bf5e1a7e8d190734961c40877cf778ea", size = 517794, upload-time = "2026-05-16T06:28:43.816Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/64/e4/a8971c6a350150485309ead9a09dc38268057d0b07a423f75bc30ef5ac5c/zizmor-1.25.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:afb2e483beb7245d9216ed62ccaf7bef4b59387126521f2b5a47677eda3fade1", size = 9152995, upload-time = "2026-05-15T20:08:50.815Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/d2/281b579c8cbb5d9f52f70a53db67bf9162ce1f260312d783b415d99b78c6/zizmor-1.25.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:172ff167f4d3616c7af972a5ddcd9e26b6fe4bf39d33bcfbb424da54f667e80b", size = 8682011, upload-time = "2026-05-15T20:08:59.54Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/05/c6e16b705452a80aae1d532a64f05b2f672665eb04f9f155d14a81fa62cc/zizmor-1.25.1-py3-none-manylinux_2_24_aarch64.whl", hash = "sha256:3eabb625b4e9814754c77f6a79092cd57ce05a1693ef0f2a16362b841c7268db", size = 8849676, upload-time = "2026-05-15T20:08:55.354Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/06/b5588059bd05d4e61203e3d3dfb34fc5c0930d4b5446c79154cfe0c71c60/zizmor-1.25.1-py3-none-manylinux_2_28_armv7l.whl", hash = "sha256:e25e9167d549df0a21a857165b7c57e3d60fd2984f934fa07d1f5e06c9a59f4a", size = 8463314, upload-time = "2026-05-15T20:08:47.413Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/5b/a5dd5cb75d4b0cb148d0d395abfd6e9b335244f22372367b5d82fb6d5d60/zizmor-1.25.1-py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:917c86ff8f91706e6d6f2e24a3472f64e75397e2dd50c19fda5b117ab1b9f26d", size = 9286826, upload-time = "2026-05-15T20:09:03.528Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/db/ad/0d41eb3dd09625f824545590e02b3e5be4fef2fba716b5466a7269dac8bd/zizmor-1.25.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4db178b1d6671abb78aca64295c7b3081375c3ab9303e966e91cfae20b1604e2", size = 8870771, upload-time = "2026-05-15T20:08:45.237Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/65/f3/e9703dcc60fbc91849cbdedff438a8c47fb962e429811d0200ac370f5e13/zizmor-1.25.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:025ff2ae568513af2ca8e5f8da7077920ade7f4454086b0ba32ccfe1b3e9d3c0", size = 8419481, upload-time = "2026-05-15T20:08:57.336Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/93/857a412ac097a9a887d01994ba7154daf9c9ef160b9ee22a8305914901cb/zizmor-1.25.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5b727f9dd5bee4138638bcc3a90471326b33dd8aa7cfdd48e9da1513030b75e5", size = 9373062, upload-time = "2026-05-15T20:08:53.123Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/f0/79c5f3d13a07a85f8fc77be7dfc619e89dbc721ccb9482d894d14d7dff50/zizmor-1.25.1-py3-none-win32.whl", hash = "sha256:6ebb21f7c1f3a6288b70dae899a3850cf4705443a7a0d8a3976508536a867f48", size = 7547943, upload-time = "2026-05-15T20:09:01.844Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/90/61/50ceb009e10d9a6dfff176b1c14cf5178c53b50820113b170b43f405a3f1/zizmor-1.25.1-py3-none-win_amd64.whl", hash = "sha256:d3113404fe529751b983f0282373e1c66c755f114ef5078aa6e59cf5f9c3fea9", size = 8622930, upload-time = "2026-05-15T20:08:43.151Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/bd/84108a92ccbfda0d28efc11f382997c7a767b58863bf4a550634b8cf0211/zizmor-1.25.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:17cc8cfd9d472e8b11945a869c198d25cfdf4a33f36fa7a1f9674099f5fb509d", size = 9115548, upload-time = "2026-05-16T06:28:33.591Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/c0/66453a2553a66286a96ca32d75e3e6bcc94ce7f907cd5f8c2c3fce55315e/zizmor-1.25.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d3e301eb4465e2da77857cf01ab4ef0184cf3818e826800b270ab01ae7338977", size = 8665071, upload-time = "2026-05-16T06:28:30.861Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/3e/d60939d1cc4907c0d021a7c46362aab5e8045550bb09157d56c070e43568/zizmor-1.25.2-py3-none-manylinux_2_24_aarch64.whl", hash = "sha256:cf64374149b567c9373228b76c8e77a389b4071899f84b82c36ee50fab894e79", size = 8842884, upload-time = "2026-05-16T06:28:26.041Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/82/f3e8d9b6d941194f2558591b449c106d46a16ea566b95eccff3a83bf6acc/zizmor-1.25.2-py3-none-manylinux_2_28_armv7l.whl", hash = "sha256:0beba1601be08bd00c9277e6ed4b026e125b26b379d86d6d98eb708409b3050d", size = 8449741, upload-time = "2026-05-16T06:28:45.424Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/13/445bc98acc2c976d6b8f8ca59b9c09f055adb5ffb3445d99af8ff7efcb4f/zizmor-1.25.2-py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:c4246f1344d8dbeffc044d7bb11b131773a7db7eb57d9073c45942dfd3543a1f", size = 9285184, upload-time = "2026-05-16T06:28:39.21Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cf/78/fc7717c706bde7531b2fde12003994fbc04c47ab4f91aa6ca9b3b24b30fd/zizmor-1.25.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:dbb1b5c85b8de8eaa0227c6620f06c8e4fbd0a4da2086e218bc225c0bef0923d", size = 8886579, upload-time = "2026-05-16T06:28:51.384Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/bc/a46f11377cdc145c625d62d88c30fead56f9d29bc31652069a1a0eaed6c2/zizmor-1.25.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d670a1e2f00b3cd56febd145bc1a0b2c4caf1cbe5dad8128721843fa877e2d2e", size = 8413576, upload-time = "2026-05-16T06:28:36.376Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/3b/0fd93b77171c8f229e8e1304eecc9931bf3009f722c57967d545d9f151b6/zizmor-1.25.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b75c84d7387389f95edadbe859fb2aaf0a360c5b080932cc53e92ae1db6f09ef", size = 9378162, upload-time = "2026-05-16T06:28:41.999Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/3f/dcb85fb9a0d87794847f9043f9db9bb4d274cf4b8077604bc13850c8fdb4/zizmor-1.25.2-py3-none-win32.whl", hash = "sha256:aa9f4c43b499c55339c3ef2e885133c5017cd9a18d76d9335541203cfa5ae1e7", size = 7548509, upload-time = "2026-05-16T06:28:28.828Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/81/1cb088098bd53f9b910098b0c19d06dc587acf328a170ef8afd1cd93b482/zizmor-1.25.2-py3-none-win_amd64.whl", hash = "sha256:af55bd9bd119ea8cbce2a7addc3922503019de32c1fe31106d70b3dc77d77908", size = 8609822, upload-time = "2026-05-16T06:28:48.078Z" },
|
||||
]
|
||||
|
||||
@@ -311,6 +311,7 @@
|
||||
.ui.vertical.menu .item > .menu {
|
||||
margin: 0.5em -1.14285714em 0;
|
||||
}
|
||||
|
||||
.ui.vertical.menu .menu .item {
|
||||
background: none;
|
||||
padding: 0.5em 1.33333333em;
|
||||
|
||||
@@ -1,25 +1,21 @@
|
||||
details.toggleable-item {
|
||||
user-select: none !important;
|
||||
padding: 0 !important;
|
||||
.ui.vertical.menu > details.item {
|
||||
user-select: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
details.toggleable-item .menu {
|
||||
margin: 4px 0 10px !important;
|
||||
}
|
||||
|
||||
details.toggleable-item summary {
|
||||
.ui.vertical.menu > details.item summary {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
justify-content: space-between; /* make the "::after" right-aligned */
|
||||
align-items: center;
|
||||
padding: 0.92857143em 1.14285714em;
|
||||
padding: 16px 13px; /* match Fomantic menu item padding */
|
||||
}
|
||||
|
||||
details.toggleable-item summary::marker, /* Chrome, Edge, Firefox */
|
||||
details.toggleable-item summary::-webkit-details-marker /* Safari */ {
|
||||
.ui.vertical.menu > details.item > summary::marker, /* Chrome, Edge, Firefox */
|
||||
.ui.vertical.menu > details.item > summary::-webkit-details-marker /* Safari */ {
|
||||
display: none;
|
||||
}
|
||||
|
||||
details.toggleable-item summary::after {
|
||||
.ui.vertical.menu > details.item > summary::after {
|
||||
transition: transform 0.25s ease;
|
||||
content: "";
|
||||
width: 14px;
|
||||
@@ -32,6 +28,28 @@ details.toggleable-item summary::after {
|
||||
border: 1px solid var(--color-body); /* workaround https://bugzilla.mozilla.org/show_bug.cgi?id=1671784 */
|
||||
}
|
||||
|
||||
details.toggleable-item[open] summary::after {
|
||||
.ui.vertical.menu > details.item[open] > summary::after {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
/* default toggleable details menu: items don't have menu item padding, don't change background color on hover or active */
|
||||
.ui.vertical.menu > details.item > .menu {
|
||||
margin: 0 0 10px; /* only need the space between the current details menu and next item */
|
||||
}
|
||||
|
||||
/* full width toggleable details menu: items have menu item padding, change background color on hover and active */
|
||||
.ui.vertical.menu > details.item > .menu.items-full-width {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.ui.vertical.menu > details.item > .menu.items-full-width > .item {
|
||||
padding: 16px 13px; /* match Fomantic menu item padding */
|
||||
}
|
||||
|
||||
.ui.vertical.menu > details.item > .menu.items-full-width > .item.active {
|
||||
background: var(--color-active);
|
||||
}
|
||||
|
||||
.ui.vertical.menu > details.item > .menu.items-full-width > .item:hover {
|
||||
background: var(--color-hover); /* ".ui.vertical.menu .menu .item" resets the hover background, so we need to add it again */
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user