diff --git a/.github/workflows/cron-licenses.yml b/.github/workflows/cron-licenses.yml
index c34066d318..12f52289b6 100644
--- a/.github/workflows/cron-licenses.yml
+++ b/.github/workflows/cron-licenses.yml
@@ -10,8 +10,8 @@ jobs:
runs-on: ubuntu-latest
if: github.repository == 'go-gitea/gitea'
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
+ - uses: actions/checkout@v5
+ - uses: actions/setup-go@v6
with:
go-version-file: go.mod
check-latest: true
diff --git a/.github/workflows/cron-translations.yml b/.github/workflows/cron-translations.yml
index f1b51debf1..ae2238ad2d 100644
--- a/.github/workflows/cron-translations.yml
+++ b/.github/workflows/cron-translations.yml
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
if: github.repository == 'go-gitea/gitea'
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: crowdin/github-action@v1
with:
upload_sources: true
diff --git a/.github/workflows/files-changed.yml b/.github/workflows/files-changed.yml
index edceef0092..b21341a277 100644
--- a/.github/workflows/files-changed.yml
+++ b/.github/workflows/files-changed.yml
@@ -34,7 +34,7 @@ jobs:
swagger: ${{ steps.changes.outputs.swagger }}
yaml: ${{ steps.changes.outputs.yaml }}
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: dorny/paths-filter@v3
id: changes
with:
diff --git a/.github/workflows/pull-compliance.yml b/.github/workflows/pull-compliance.yml
index 6f8991ed4e..f73772e934 100644
--- a/.github/workflows/pull-compliance.yml
+++ b/.github/workflows/pull-compliance.yml
@@ -16,8 +16,8 @@ jobs:
needs: files-changed
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
+ - uses: actions/checkout@v5
+ - uses: actions/setup-go@v6
with:
go-version-file: go.mod
check-latest: true
@@ -31,7 +31,7 @@ jobs:
needs: files-changed
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: astral-sh/setup-uv@v6
- run: uv python install 3.12
- uses: pnpm/action-setup@v4
@@ -47,7 +47,7 @@ jobs:
needs: files-changed
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: astral-sh/setup-uv@v6
- run: uv python install 3.12
- run: make deps-py
@@ -58,7 +58,7 @@ jobs:
needs: files-changed
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v5
with:
@@ -71,8 +71,8 @@ jobs:
needs: files-changed
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
+ - uses: actions/checkout@v5
+ - uses: actions/setup-go@v6
with:
go-version-file: go.mod
check-latest: true
@@ -83,8 +83,8 @@ jobs:
needs: files-changed
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
+ - uses: actions/checkout@v5
+ - uses: actions/setup-go@v6
with:
go-version-file: go.mod
check-latest: true
@@ -100,8 +100,8 @@ jobs:
needs: files-changed
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
+ - uses: actions/checkout@v5
+ - uses: actions/setup-go@v6
with:
go-version-file: go.mod
check-latest: true
@@ -115,8 +115,8 @@ jobs:
needs: files-changed
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
+ - uses: actions/checkout@v5
+ - uses: actions/setup-go@v6
with:
go-version-file: go.mod
check-latest: true
@@ -128,7 +128,7 @@ jobs:
needs: files-changed
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v5
with:
@@ -144,8 +144,8 @@ jobs:
needs: files-changed
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
+ - uses: actions/checkout@v5
+ - uses: actions/setup-go@v6
with:
go-version-file: go.mod
check-latest: true
@@ -176,7 +176,7 @@ jobs:
needs: files-changed
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v5
with:
@@ -189,8 +189,8 @@ jobs:
needs: files-changed
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
+ - uses: actions/checkout@v5
+ - uses: actions/setup-go@v6
with:
go-version-file: go.mod
check-latest: true
diff --git a/.github/workflows/pull-db-tests.yml b/.github/workflows/pull-db-tests.yml
index a7ad7ed5c3..21ec76b48e 100644
--- a/.github/workflows/pull-db-tests.yml
+++ b/.github/workflows/pull-db-tests.yml
@@ -38,8 +38,8 @@ jobs:
ports:
- "9000:9000"
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
+ - uses: actions/checkout@v5
+ - uses: actions/setup-go@v6
with:
go-version-file: go.mod
check-latest: true
@@ -66,8 +66,8 @@ jobs:
needs: files-changed
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
+ - uses: actions/checkout@v5
+ - uses: actions/setup-go@v6
with:
go-version-file: go.mod
check-latest: true
@@ -124,8 +124,8 @@ jobs:
ports:
- 10000:10000
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
+ - uses: actions/checkout@v5
+ - uses: actions/setup-go@v6
with:
go-version-file: go.mod
check-latest: true
@@ -177,8 +177,8 @@ jobs:
- "587:587"
- "993:993"
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
+ - uses: actions/checkout@v5
+ - uses: actions/setup-go@v6
with:
go-version-file: go.mod
check-latest: true
@@ -217,8 +217,8 @@ jobs:
ports:
- 10000:10000
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
+ - uses: actions/checkout@v5
+ - uses: actions/setup-go@v6
with:
go-version-file: go.mod
check-latest: true
diff --git a/.github/workflows/pull-e2e-tests.yml b/.github/workflows/pull-e2e-tests.yml
index 89b32260ca..4f806e93bd 100644
--- a/.github/workflows/pull-e2e-tests.yml
+++ b/.github/workflows/pull-e2e-tests.yml
@@ -18,8 +18,8 @@ jobs:
needs: files-changed
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-go@v5
+ - uses: actions/checkout@v5
+ - uses: actions/setup-go@v6
with:
go-version-file: go.mod
check-latest: true
diff --git a/.github/workflows/pull-labeler.yml b/.github/workflows/pull-labeler.yml
index 812819b599..d05483e56c 100644
--- a/.github/workflows/pull-labeler.yml
+++ b/.github/workflows/pull-labeler.yml
@@ -15,6 +15,6 @@ jobs:
contents: read
pull-requests: write
steps:
- - uses: actions/labeler@v5
+ - uses: actions/labeler@v6
with:
sync-labels: true
diff --git a/.github/workflows/release-nightly.yml b/.github/workflows/release-nightly.yml
index 3d652e4ad8..16ce0fd643 100644
--- a/.github/workflows/release-nightly.yml
+++ b/.github/workflows/release-nightly.yml
@@ -12,11 +12,11 @@ jobs:
nightly-binary:
runs-on: namespace-profile-gitea-release-binary
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
- run: git fetch --unshallow --quiet --tags --force
- - uses: actions/setup-go@v5
+ - uses: actions/setup-go@v6
with:
go-version-file: go.mod
check-latest: true
@@ -61,11 +61,11 @@ jobs:
permissions:
packages: write # to publish to ghcr.io
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
- run: git fetch --unshallow --quiet --tags --force
- - uses: actions/setup-go@v5
+ - uses: actions/setup-go@v6
with:
go-version-file: go.mod
check-latest: true
@@ -103,11 +103,11 @@ jobs:
permissions:
packages: write # to publish to ghcr.io
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
- run: git fetch --unshallow --quiet --tags --force
- - uses: actions/setup-go@v5
+ - uses: actions/setup-go@v6
with:
go-version-file: go.mod
check-latest: true
diff --git a/.github/workflows/release-tag-rc.yml b/.github/workflows/release-tag-rc.yml
index f4776a9ed8..c239ff392b 100644
--- a/.github/workflows/release-tag-rc.yml
+++ b/.github/workflows/release-tag-rc.yml
@@ -13,11 +13,11 @@ jobs:
binary:
runs-on: namespace-profile-gitea-release-binary
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
- run: git fetch --unshallow --quiet --tags --force
- - uses: actions/setup-go@v5
+ - uses: actions/setup-go@v6
with:
go-version-file: go.mod
check-latest: true
@@ -71,7 +71,7 @@ jobs:
permissions:
packages: write # to publish to ghcr.io
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
- run: git fetch --unshallow --quiet --tags --force
@@ -112,7 +112,7 @@ jobs:
permissions:
packages: write # to publish to ghcr.io
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
- run: git fetch --unshallow --quiet --tags --force
diff --git a/.github/workflows/release-tag-version.yml b/.github/workflows/release-tag-version.yml
index ad0820f31f..289b0e9d9c 100644
--- a/.github/workflows/release-tag-version.yml
+++ b/.github/workflows/release-tag-version.yml
@@ -17,11 +17,11 @@ jobs:
permissions:
packages: write # to publish to ghcr.io
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
- run: git fetch --unshallow --quiet --tags --force
- - uses: actions/setup-go@v5
+ - uses: actions/setup-go@v6
with:
go-version-file: go.mod
check-latest: true
@@ -75,7 +75,7 @@ jobs:
permissions:
packages: write # to publish to ghcr.io
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
- run: git fetch --unshallow --quiet --tags --force
@@ -118,7 +118,7 @@ jobs:
docker-rootless:
runs-on: namespace-profile-gitea-release-docker
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
- run: git fetch --unshallow --quiet --tags --force
diff --git a/assets/go-licenses.json b/assets/go-licenses.json
index 9c19080e24..b105757683 100644
--- a/assets/go-licenses.json
+++ b/assets/go-licenses.json
@@ -1096,8 +1096,13 @@
},
{
"name": "github.com/sorairolake/lzip-go",
- "path": "github.com/sorairolake/lzip-go/LICENSE",
- "licenseText": " Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright [yyyy] [name of copyright owner]\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n---\n\nMIT License\n\nCopyright (c) 2024 Shun Sakai\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
+ "path": "github.com/sorairolake/lzip-go/LICENSE-APACHE",
+ "licenseText": " Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright [yyyy] [name of copyright owner]\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n"
+ },
+ {
+ "name": "github.com/spf13/afero",
+ "path": "github.com/spf13/afero/LICENSE.txt",
+ "licenseText": " Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n"
},
{
"name": "github.com/ssor/bom",
@@ -1225,8 +1230,8 @@
"licenseText": "Copyright (c) 2016-2024 Uber Technologies, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
},
{
- "name": "go4.org",
- "path": "go4.org/LICENSE",
+ "name": "go4.org/readerutil",
+ "path": "go4.org/readerutil/LICENSE",
"licenseText": " Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"{}\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright {yyyy} {name of copyright owner}\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n"
},
{
diff --git a/eslint.config.ts b/eslint.config.ts
index 678a49647c..02aacefca2 100644
--- a/eslint.config.ts
+++ b/eslint.config.ts
@@ -52,21 +52,16 @@ export default defineConfig([
},
plugins: {
'@eslint-community/eslint-comments': comments,
- // @ts-expect-error
'@stylistic': stylistic,
'@typescript-eslint': typescriptPlugin.plugin,
'array-func': arrayFunc,
// @ts-expect-error -- https://github.com/un-ts/eslint-plugin-import-x/issues/203
'import-x': importPlugin,
'no-use-extend-native': noUseExtendNative,
- // @ts-expect-error
regexp,
- // @ts-expect-error
sonarjs,
- // @ts-expect-error
unicorn,
github,
- // @ts-expect-error
wc,
},
settings: {
@@ -595,6 +590,7 @@ export default defineConfig([
'no-unused-vars': [0], // handled by @typescript-eslint/no-unused-vars
'no-use-before-define': [0], // handled by @typescript-eslint/no-use-before-define
'no-use-extend-native/no-use-extend-native': [2],
+ 'no-useless-assignment': [2],
'no-useless-backreference': [2],
'no-useless-call': [2],
'no-useless-catch': [2],
@@ -900,7 +896,6 @@ export default defineConfig([
'yoda': [2, 'never'],
},
},
- // @ts-expect-error
{
...playwright.configs['flat/recommended'],
files: ['tests/e2e/**'],
@@ -916,7 +911,6 @@ export default defineConfig([
},
},
extends: [
- // @ts-expect-error
vue.configs['flat/recommended'],
// @ts-expect-error
vueScopedCss.configs['flat/recommended'],
diff --git a/flake.lock b/flake.lock
index 16a487ba13..5cb95c1aed 100644
--- a/flake.lock
+++ b/flake.lock
@@ -20,11 +20,11 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1755186698,
- "narHash": "sha256-wNO3+Ks2jZJ4nTHMuks+cxAiVBGNuEBXsT29Bz6HASo=",
+ "lastModified": 1760038930,
+ "narHash": "sha256-Oncbh0UmHjSlxO7ErQDM3KM0A5/Znfofj2BSzlHLeVw=",
"owner": "nixos",
"repo": "nixpkgs",
- "rev": "fbcf476f790d8a217c3eab4e12033dc4a0f6d23c",
+ "rev": "0b4defa2584313f3b781240b29d61f6f9f7e0df3",
"type": "github"
},
"original": {
diff --git a/go.mod b/go.mod
index 64a7dcc708..cf4774801e 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
module code.gitea.io/gitea
-go 1.25.1
+go 1.25.3
// rfc5280 said: "The serial number is an integer assigned by the CA to each certificate."
// But some CAs use negative serial number, just relax the check. related:
@@ -35,7 +35,7 @@ require (
github.com/bohde/codel v0.2.0
github.com/buildkite/terminal-to-html/v3 v3.16.8
github.com/caddyserver/certmagic v0.24.0
- github.com/charmbracelet/git-lfs-transfer v0.2.0
+ github.com/charmbracelet/git-lfs-transfer v0.1.1-0.20251013092601-6327009efd21
github.com/chi-middleware/proxy v1.1.1
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21
github.com/djherbis/buffer v1.2.0
@@ -56,7 +56,7 @@ require (
github.com/go-co-op/gocron v1.37.0
github.com/go-enry/go-enry/v2 v2.9.2
github.com/go-git/go-billy/v5 v5.6.2
- github.com/go-git/go-git/v5 v5.16.2
+ github.com/go-git/go-git/v5 v5.16.3
github.com/go-ldap/ldap/v3 v3.4.11
github.com/go-redsync/redsync/v4 v4.13.0
github.com/go-sql-driver/mysql v1.9.3
@@ -84,7 +84,7 @@ require (
github.com/mattn/go-isatty v0.0.20
github.com/mattn/go-sqlite3 v1.14.32
github.com/meilisearch/meilisearch-go v0.33.2
- github.com/mholt/archives v0.1.3
+ github.com/mholt/archives v0.0.0-20251009205813-e30ac6010726
github.com/microcosm-cc/bluemonday v1.0.27
github.com/microsoft/go-mssqldb v1.9.3
github.com/minio/minio-go/v7 v7.0.95
@@ -116,13 +116,13 @@ require (
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
github.com/yuin/goldmark-meta v1.1.0
gitlab.com/gitlab-org/api/client-go v0.142.4
- golang.org/x/crypto v0.41.0
+ golang.org/x/crypto v0.42.0
golang.org/x/image v0.30.0
- golang.org/x/net v0.43.0
+ golang.org/x/net v0.44.0
golang.org/x/oauth2 v0.30.0
golang.org/x/sync v0.17.0
- golang.org/x/sys v0.35.0
- golang.org/x/text v0.29.0
+ golang.org/x/sys v0.37.0
+ golang.org/x/text v0.30.0
google.golang.org/grpc v1.75.0
google.golang.org/protobuf v1.36.8
gopkg.in/ini.v1 v1.67.0
@@ -142,7 +142,7 @@ require (
github.com/DataDog/zstd v1.5.7 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/RoaringBitmap/roaring/v2 v2.10.0 // indirect
- github.com/STARRY-S/zip v0.2.1 // indirect
+ github.com/STARRY-S/zip v0.2.3 // indirect
github.com/andybalholm/brotli v1.2.0 // indirect
github.com/andybalholm/cascadia v1.3.3 // indirect
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
@@ -172,7 +172,7 @@ require (
github.com/blevesearch/zapx/v16 v16.2.4 // indirect
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
github.com/bodgit/plumbing v1.3.0 // indirect
- github.com/bodgit/sevenzip v1.6.0 // indirect
+ github.com/bodgit/sevenzip v1.6.1 // indirect
github.com/bodgit/windows v1.0.1 // indirect
github.com/boombuler/barcode v1.1.0 // indirect
github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf // indirect
@@ -233,14 +233,14 @@ require (
github.com/mikelolasagasti/xz v1.0.1 // indirect
github.com/minio/crc64nvme v1.1.1 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
- github.com/minio/minlz v1.0.0 // indirect
+ github.com/minio/minlz v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect
github.com/mschoch/smat v0.2.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
- github.com/nwaples/rardecode/v2 v2.1.0 // indirect
+ github.com/nwaples/rardecode/v2 v2.2.0 // indirect
github.com/olekukonko/cat v0.0.0-20250817074551-3280053e4e00 // indirect
github.com/olekukonko/errors v1.1.0 // indirect
github.com/olekukonko/ll v0.1.0 // indirect
@@ -259,7 +259,8 @@ require (
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/skeema/knownhosts v1.3.1 // indirect
- github.com/sorairolake/lzip-go v0.3.5 // indirect
+ github.com/sorairolake/lzip-go v0.3.8 // indirect
+ github.com/spf13/afero v1.15.0 // indirect
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
github.com/tinylib/msgp v1.4.0 // indirect
github.com/unknwon/com v1.0.1 // indirect
@@ -278,9 +279,9 @@ require (
go.uber.org/zap/exp v0.3.0 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b // indirect
- golang.org/x/mod v0.27.0 // indirect
+ golang.org/x/mod v0.28.0 // indirect
golang.org/x/time v0.12.0 // indirect
- golang.org/x/tools v0.36.0 // indirect
+ golang.org/x/tools v0.37.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
@@ -297,9 +298,6 @@ replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1
replace github.com/nektos/act => gitea.com/gitea/act v0.261.7-0.20251003180512-ac6e4b751763
-// TODO: the only difference is in `PutObject`: the fork doesn't use `NewVerifyingReader(r, sha256.New(), oid, expectedSize)`, need to figure out why
-replace github.com/charmbracelet/git-lfs-transfer => gitea.com/gitea/git-lfs-transfer v0.2.0
-
replace git.sr.ht/~mariusor/go-xsd-duration => gitea.com/gitea/go-xsd-duration v0.0.0-20220703122237-02e73435a078
exclude github.com/gofrs/uuid v3.2.0+incompatible
diff --git a/go.sum b/go.sum
index 3e9d75c3b8..9acef3b977 100644
--- a/go.sum
+++ b/go.sum
@@ -33,8 +33,6 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
gitea.com/gitea/act v0.261.7-0.20251003180512-ac6e4b751763 h1:ohdxegvslDEllZmRNDqpKun6L4Oq81jNdEDtGgHEV2c=
gitea.com/gitea/act v0.261.7-0.20251003180512-ac6e4b751763/go.mod h1:Pg5C9kQY1CEA3QjthjhlrqOC/QOT5NyWNjOjRHw23Ok=
-gitea.com/gitea/git-lfs-transfer v0.2.0 h1:baHaNoBSRaeq/xKayEXwiDQtlIjps4Ac/Ll4KqLMB40=
-gitea.com/gitea/git-lfs-transfer v0.2.0/go.mod h1:UrXUCm3xLQkq15fu7qlXHUMlrhdlXHoi13KH2Dfiits=
gitea.com/gitea/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:BAFmdZpRW7zMQZQDClaCWobRj9uL1MR3MzpCVJvc5s4=
gitea.com/gitea/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed h1:EZZBtilMLSZNWtHHcgq2mt6NSGhJSZBuduAlinMEmso=
@@ -93,8 +91,8 @@ github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06
github.com/RoaringBitmap/roaring v0.7.1/go.mod h1:jdT9ykXwHFNdJbEtxePexlFYH9LXucApeS0/+/g+p1I=
github.com/RoaringBitmap/roaring/v2 v2.10.0 h1:HbJ8Cs71lfCJyvmSptxeMX2PtvOC8yonlU0GQcy2Ak0=
github.com/RoaringBitmap/roaring/v2 v2.10.0/go.mod h1:FiJcsfkGje/nZBZgCu0ZxCPOKD/hVXDS2dXi7/eUFE0=
-github.com/STARRY-S/zip v0.2.1 h1:pWBd4tuSGm3wtpoqRZZ2EAwOmcHK6XFf7bU9qcJXyFg=
-github.com/STARRY-S/zip v0.2.1/go.mod h1:xNvshLODWtC4EJ702g7cTYn13G53o1+X9BWnPFpcWV4=
+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/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
@@ -193,8 +191,8 @@ github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTS
github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q=
github.com/bodgit/plumbing v1.3.0 h1:pf9Itz1JOQgn7vEOE7v7nlEfBykYqvUYioC61TwWCFU=
github.com/bodgit/plumbing v1.3.0/go.mod h1:JOTb4XiRu5xfnmdnDJo6GmSbSbtSyufrsyZFByMtKEs=
-github.com/bodgit/sevenzip v1.6.0 h1:a4R0Wu6/P1o1pP/3VV++aEOcyeBxeO/xE2Y9NSTrr6A=
-github.com/bodgit/sevenzip v1.6.0/go.mod h1:zOBh9nJUof7tcrlqJFv1koWRrhz3LbDbUNngkuZxLMc=
+github.com/bodgit/sevenzip v1.6.1 h1:kikg2pUMYC9ljU7W9SaqHXhym5HyKm8/M/jd31fYan4=
+github.com/bodgit/sevenzip v1.6.1/go.mod h1:GVoYQbEVbOGT8n2pfqCIMRUaRjQ8F9oSqoBEqZh5fQ8=
github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4=
github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM=
github.com/bohde/codel v0.2.0 h1:fzF7ibgKmCfQbOzQCblmQcwzDRmV7WO7VMLm/hDvD3E=
@@ -219,6 +217,8 @@ github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a h1:MISbI8sU/PSK/
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a/go.mod h1:2GxOXOlEPAMFPfp014mK1SWq8G8BN8o7/dfYqJrVGn8=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/charmbracelet/git-lfs-transfer v0.1.1-0.20251013092601-6327009efd21 h1:2d64+4Jek9vjYwhY93AjbleiVH+AeWvPwPmDi1mfKFQ=
+github.com/charmbracelet/git-lfs-transfer v0.1.1-0.20251013092601-6327009efd21/go.mod h1:fNlYtCHWTRC8MofQERZkVUNUWaOvZeTBqHn/amSbKZI=
github.com/chi-middleware/proxy v1.1.1 h1:4HaXUp8o2+bhHr1OhVy+VjN0+L7/07JDcn6v7YrTjrQ=
github.com/chi-middleware/proxy v1.1.1/go.mod h1:jQwMEJct2tz9VmtCELxvnXoMfa+SOdikvbVJVHv/M+0=
github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
@@ -339,8 +339,8 @@ github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UN
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
-github.com/go-git/go-git/v5 v5.16.2 h1:fT6ZIOjE5iEnkzKyxTHK1W4HGAsPhqEqiSAssSO77hM=
-github.com/go-git/go-git/v5 v5.16.2/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
+github.com/go-git/go-git/v5 v5.16.3 h1:Z8BtvxZ09bYm/yYNgPKCzgWtaRqDTgIKRgIRHBfU6Z8=
+github.com/go-git/go-git/v5 v5.16.3/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
@@ -572,8 +572,8 @@ github.com/meilisearch/meilisearch-go v0.33.2 h1:YgsQSLYhAkRN2ias6I1KNRTjdYCN5w2
github.com/meilisearch/meilisearch-go v0.33.2/go.mod h1:6eOPcQ+OAuwXvnONlfSgfgvr7TIAWM/6OdhcVHg8cF0=
github.com/mholt/acmez/v3 v3.1.2 h1:auob8J/0FhmdClQicvJvuDavgd5ezwLBfKuYmynhYzc=
github.com/mholt/acmez/v3 v3.1.2/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ=
-github.com/mholt/archives v0.1.3 h1:aEAaOtNra78G+TvV5ohmXrJOAzf++dIlYeDW3N9q458=
-github.com/mholt/archives v0.1.3/go.mod h1:LUCGp++/IbV/I0Xq4SzcIR6uwgeh2yjnQWamjRQfLTU=
+github.com/mholt/archives v0.0.0-20251009205813-e30ac6010726 h1:narluFTg20M5KBwKxedpFiSMkdjQRRNUlpY4uAsKMwk=
+github.com/mholt/archives v0.0.0-20251009205813-e30ac6010726/go.mod h1:3TPMmBLPsgszL+1As5zECTuKwKvIfj6YcwWPpeTAXF4=
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
github.com/microsoft/go-mssqldb v1.9.3 h1:hy4p+LDC8LIGvI3JATnLVmBOLMJbmn5X400mr5j0lPs=
@@ -588,8 +588,8 @@ github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
github.com/minio/minio-go/v7 v7.0.95 h1:ywOUPg+PebTMTzn9VDsoFJy32ZuARN9zhB+K3IYEvYU=
github.com/minio/minio-go/v7 v7.0.95/go.mod h1:wOOX3uxS334vImCNRVyIDdXX9OsXDm89ToynKgqUKlo=
-github.com/minio/minlz v1.0.0 h1:Kj7aJZ1//LlTP1DM8Jm7lNKvvJS2m74gyyXXn3+uJWQ=
-github.com/minio/minlz v1.0.0/go.mod h1:qT0aEB35q79LLornSzeDH75LBf3aH1MV+jB5w9Wasec=
+github.com/minio/minlz v1.0.1 h1:OUZUzXcib8diiX+JYxyRLIdomyZYzHct6EShOKtQY2A=
+github.com/minio/minlz v1.0.1/go.mod h1:qT0aEB35q79LLornSzeDH75LBf3aH1MV+jB5w9Wasec=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
@@ -610,8 +610,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/niklasfasching/go-org v1.9.1 h1:/3s4uTPOF06pImGa2Yvlp24yKXZoTYM+nsIlMzfpg/0=
github.com/niklasfasching/go-org v1.9.1/go.mod h1:ZAGFFkWvUQcpazmi/8nHqwvARpr1xpb+Es67oUGX/48=
-github.com/nwaples/rardecode/v2 v2.1.0 h1:JQl9ZoBPDy+nIZGb1mx8+anfHp/LV3NE2MjMiv0ct/U=
-github.com/nwaples/rardecode/v2 v2.1.0/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw=
+github.com/nwaples/rardecode/v2 v2.2.0 h1:4ufPGHiNe1rYJxYfehALLjup4Ls3ck42CWwjKiOqu0A=
+github.com/nwaples/rardecode/v2 v2.2.0/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
@@ -714,9 +714,11 @@ github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYl
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8=
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
-github.com/sorairolake/lzip-go v0.3.5 h1:ms5Xri9o1JBIWvOFAorYtUNik6HI3HgBTkISiqu0Cwg=
-github.com/sorairolake/lzip-go v0.3.5/go.mod h1:N0KYq5iWrMXI0ZEXKXaS9hCyOjZUQdBDEIbXfoUwbdk=
+github.com/sorairolake/lzip-go v0.3.8 h1:j5Q2313INdTA80ureWYRhX+1K78mUXfMoPZCw/ivWik=
+github.com/sorairolake/lzip-go v0.3.8/go.mod h1:JcBqGMV0frlxwrsE9sMWXDjqn3EeVf0/54YPsw66qkU=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
+github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
+github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
@@ -729,6 +731,7 @@ github.com/steveyen/gtreap v0.1.0/go.mod h1:kl/5J7XbrOmlIbYIXdRHDDE5QxHqpk0cmkT7
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@@ -837,8 +840,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
-golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
-golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
+golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
+golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -875,8 +878,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
-golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
+golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
+golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -905,8 +908,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
-golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
-golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
+golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
+golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -972,8 +975,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
-golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
+golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -984,8 +987,8 @@ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
-golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
-golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
+golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
+golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -999,8 +1002,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
-golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
-golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
+golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
+golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
@@ -1036,8 +1039,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
-golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
-golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
+golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
+golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/models/actions/run.go b/models/actions/run.go
index f5ccba06c2..4da6958e2d 100644
--- a/models/actions/run.go
+++ b/models/actions/run.go
@@ -16,13 +16,13 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
+ "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
webhook_module "code.gitea.io/gitea/modules/webhook"
- "github.com/nektos/act/pkg/jobparser"
"xorm.io/builder"
)
@@ -30,7 +30,7 @@ import (
type ActionRun struct {
ID int64
Title string
- RepoID int64 `xorm:"index unique(repo_index)"`
+ RepoID int64 `xorm:"unique(repo_index) index(repo_concurrency)"`
Repo *repo_model.Repository `xorm:"-"`
OwnerID int64 `xorm:"index"`
WorkflowID string `xorm:"index"` // the name of workflow file
@@ -49,6 +49,9 @@ type ActionRun struct {
TriggerEvent string // the trigger event defined in the `on` configuration of the triggered workflow
Status Status `xorm:"index"`
Version int `xorm:"version default 0"` // Status could be updated concomitantly, so an optimistic lock is needed
+ RawConcurrency string // raw concurrency
+ ConcurrencyGroup string `xorm:"index(repo_concurrency) NOT NULL DEFAULT ''"`
+ ConcurrencyCancel bool `xorm:"NOT NULL DEFAULT FALSE"`
// Started and Stopped is used for recording last run time, if rerun happened, they will be reset to 0
Started timeutil.TimeStamp
Stopped timeutil.TimeStamp
@@ -102,6 +105,15 @@ func (run *ActionRun) PrettyRef() string {
return refName.ShortName()
}
+// RefTooltip return a tooltop of run's ref. For pull request, it's the title of the PR, otherwise it's the ShortName.
+func (run *ActionRun) RefTooltip() string {
+ payload, err := run.GetPullRequestEventPayload()
+ if err == nil && payload != nil && payload.PullRequest != nil {
+ return payload.PullRequest.Title
+ }
+ return git.RefName(run.Ref).ShortName()
+}
+
// LoadAttributes load Repo TriggerUser if not loaded
func (run *ActionRun) LoadAttributes(ctx context.Context) error {
if run == nil {
@@ -181,7 +193,7 @@ func (run *ActionRun) IsSchedule() bool {
return run.ScheduleID > 0
}
-func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) error {
+func UpdateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) error {
_, err := db.GetEngine(ctx).ID(repo.ID).
NoAutoTime().
SetExpr("num_action_runs",
@@ -238,116 +250,62 @@ func CancelPreviousJobs(ctx context.Context, repoID int64, ref, workflowID strin
return cancelledJobs, err
}
- // Iterate over each job and attempt to cancel it.
- for _, job := range jobs {
- // Skip jobs that are already in a terminal state (completed, cancelled, etc.).
- status := job.Status
- if status.IsDone() {
- continue
- }
-
- // If the job has no associated task (probably an error), set its status to 'Cancelled' and stop it.
- if job.TaskID == 0 {
- job.Status = StatusCancelled
- job.Stopped = timeutil.TimeStampNow()
-
- // Update the job's status and stopped time in the database.
- n, err := UpdateRunJob(ctx, job, builder.Eq{"task_id": 0}, "status", "stopped")
- if err != nil {
- return cancelledJobs, err
- }
-
- // If the update affected 0 rows, it means the job has changed in the meantime, so we need to try again.
- if n == 0 {
- return cancelledJobs, errors.New("job has changed, try again")
- }
-
- cancelledJobs = append(cancelledJobs, job)
- // Continue with the next job.
- continue
- }
-
- // If the job has an associated task, try to stop the task, effectively cancelling the job.
- if err := StopTask(ctx, job.TaskID, StatusCancelled); err != nil {
- return cancelledJobs, err
- }
- cancelledJobs = append(cancelledJobs, job)
+ cjs, err := CancelJobs(ctx, jobs)
+ if err != nil {
+ return cancelledJobs, err
}
+ cancelledJobs = append(cancelledJobs, cjs...)
}
// Return nil to indicate successful cancellation of all running and waiting jobs.
return cancelledJobs, nil
}
-// InsertRun inserts a run
-// The title will be cut off at 255 characters if it's longer than 255 characters.
-func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWorkflow) error {
- return db.WithTx(ctx, func(ctx context.Context) error {
- index, err := db.GetNextResourceIndex(ctx, "action_run_index", run.RepoID)
- if err != nil {
- return err
- }
- run.Index = index
- run.Title = util.EllipsisDisplayString(run.Title, 255)
-
- if err := db.Insert(ctx, run); err != nil {
- return err
+func CancelJobs(ctx context.Context, jobs []*ActionRunJob) ([]*ActionRunJob, error) {
+ cancelledJobs := make([]*ActionRunJob, 0, len(jobs))
+ // Iterate over each job and attempt to cancel it.
+ for _, job := range jobs {
+ // Skip jobs that are already in a terminal state (completed, cancelled, etc.).
+ status := job.Status
+ if status.IsDone() {
+ continue
}
- if run.Repo == nil {
- repo, err := repo_model.GetRepositoryByID(ctx, run.RepoID)
+ // If the job has no associated task (probably an error), set its status to 'Cancelled' and stop it.
+ if job.TaskID == 0 {
+ job.Status = StatusCancelled
+ job.Stopped = timeutil.TimeStampNow()
+
+ // Update the job's status and stopped time in the database.
+ n, err := UpdateRunJob(ctx, job, builder.Eq{"task_id": 0}, "status", "stopped")
if err != nil {
- return err
+ return cancelledJobs, err
}
- run.Repo = repo
+
+ // If the update affected 0 rows, it means the job has changed in the meantime
+ if n == 0 {
+ log.Error("Failed to cancel job %d because it has changed", job.ID)
+ continue
+ }
+
+ cancelledJobs = append(cancelledJobs, job)
+ // Continue with the next job.
+ continue
}
- if err := updateRepoRunsNumbers(ctx, run.Repo); err != nil {
- return err
+ // If the job has an associated task, try to stop the task, effectively cancelling the job.
+ if err := StopTask(ctx, job.TaskID, StatusCancelled); err != nil {
+ return cancelledJobs, err
}
+ updatedJob, err := GetRunJobByID(ctx, job.ID)
+ if err != nil {
+ return cancelledJobs, fmt.Errorf("get job: %w", err)
+ }
+ cancelledJobs = append(cancelledJobs, updatedJob)
+ }
- runJobs := make([]*ActionRunJob, 0, len(jobs))
- var hasWaiting bool
- for _, v := range jobs {
- id, job := v.Job()
- needs := job.Needs()
- if err := v.SetJob(id, job.EraseNeeds()); err != nil {
- return err
- }
- payload, _ := v.Marshal()
- status := StatusWaiting
- if len(needs) > 0 || run.NeedApproval {
- status = StatusBlocked
- } else {
- hasWaiting = true
- }
- job.Name = util.EllipsisDisplayString(job.Name, 255)
- runJobs = append(runJobs, &ActionRunJob{
- RunID: run.ID,
- RepoID: run.RepoID,
- OwnerID: run.OwnerID,
- CommitSHA: run.CommitSHA,
- IsForkPullRequest: run.IsForkPullRequest,
- Name: job.Name,
- WorkflowPayload: payload,
- JobID: id,
- Needs: needs,
- RunsOn: job.RunsOn(),
- Status: status,
- })
- }
- if err := db.Insert(ctx, runJobs); err != nil {
- return err
- }
-
- // if there is a job in the waiting status, increase tasks version.
- if hasWaiting {
- if err := IncreaseTaskVersion(ctx, run.OwnerID, run.RepoID); err != nil {
- return err
- }
- }
- return nil
- })
+ // Return nil to indicate successful cancellation of all running and waiting jobs.
+ return cancelledJobs, nil
}
func GetRunByRepoAndID(ctx context.Context, repoID, runID int64) (*ActionRun, error) {
@@ -432,7 +390,7 @@ func UpdateRun(ctx context.Context, run *ActionRun, cols ...string) error {
if err = run.LoadRepo(ctx); err != nil {
return err
}
- if err := updateRepoRunsNumbers(ctx, run.Repo); err != nil {
+ if err := UpdateRepoRunsNumbers(ctx, run.Repo); err != nil {
return err
}
}
@@ -441,3 +399,59 @@ func UpdateRun(ctx context.Context, run *ActionRun, cols ...string) error {
}
type ActionRunIndex db.ResourceIndex
+
+func GetConcurrentRunsAndJobs(ctx context.Context, repoID int64, concurrencyGroup string, status []Status) ([]*ActionRun, []*ActionRunJob, error) {
+ runs, err := db.Find[ActionRun](ctx, &FindRunOptions{
+ RepoID: repoID,
+ ConcurrencyGroup: concurrencyGroup,
+ Status: status,
+ })
+ if err != nil {
+ return nil, nil, fmt.Errorf("find runs: %w", err)
+ }
+
+ jobs, err := db.Find[ActionRunJob](ctx, &FindRunJobOptions{
+ RepoID: repoID,
+ ConcurrencyGroup: concurrencyGroup,
+ Statuses: status,
+ })
+ if err != nil {
+ return nil, nil, fmt.Errorf("find jobs: %w", err)
+ }
+
+ return runs, jobs, nil
+}
+
+func CancelPreviousJobsByRunConcurrency(ctx context.Context, actionRun *ActionRun) ([]*ActionRunJob, error) {
+ if actionRun.ConcurrencyGroup == "" {
+ return nil, nil
+ }
+
+ var jobsToCancel []*ActionRunJob
+
+ statusFindOption := []Status{StatusWaiting, StatusBlocked}
+ if actionRun.ConcurrencyCancel {
+ statusFindOption = append(statusFindOption, StatusRunning)
+ }
+ runs, jobs, err := GetConcurrentRunsAndJobs(ctx, actionRun.RepoID, actionRun.ConcurrencyGroup, statusFindOption)
+ if err != nil {
+ return nil, fmt.Errorf("find concurrent runs and jobs: %w", err)
+ }
+ jobsToCancel = append(jobsToCancel, jobs...)
+
+ // cancel runs in the same concurrency group
+ for _, run := range runs {
+ if run.ID == actionRun.ID {
+ continue
+ }
+ jobs, err := db.Find[ActionRunJob](ctx, FindRunJobOptions{
+ RunID: run.ID,
+ })
+ if err != nil {
+ return nil, fmt.Errorf("find run %d jobs: %w", run.ID, err)
+ }
+ jobsToCancel = append(jobsToCancel, jobs...)
+ }
+
+ return CancelJobs(ctx, jobsToCancel)
+}
diff --git a/models/actions/run_job.go b/models/actions/run_job.go
index e7fa21270c..f72a7040e3 100644
--- a/models/actions/run_job.go
+++ b/models/actions/run_job.go
@@ -14,6 +14,7 @@ import (
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
+ "github.com/nektos/act/pkg/jobparser"
"xorm.io/builder"
)
@@ -22,23 +23,38 @@ type ActionRunJob struct {
ID int64
RunID int64 `xorm:"index"`
Run *ActionRun `xorm:"-"`
- RepoID int64 `xorm:"index"`
+ RepoID int64 `xorm:"index(repo_concurrency)"`
Repo *repo_model.Repository `xorm:"-"`
OwnerID int64 `xorm:"index"`
CommitSHA string `xorm:"index"`
IsForkPullRequest bool
Name string `xorm:"VARCHAR(255)"`
Attempt int64
- WorkflowPayload []byte
- JobID string `xorm:"VARCHAR(255)"` // job id in workflow, not job's id
- Needs []string `xorm:"JSON TEXT"`
- RunsOn []string `xorm:"JSON TEXT"`
- TaskID int64 // the latest task of the job
- Status Status `xorm:"index"`
- Started timeutil.TimeStamp
- Stopped timeutil.TimeStamp
- Created timeutil.TimeStamp `xorm:"created"`
- Updated timeutil.TimeStamp `xorm:"updated index"`
+
+ // WorkflowPayload is act/jobparser.SingleWorkflow for act/jobparser.Parse
+ // it should contain exactly one job with global workflow fields for this model
+ WorkflowPayload []byte
+
+ JobID string `xorm:"VARCHAR(255)"` // job id in workflow, not job's id
+ Needs []string `xorm:"JSON TEXT"`
+ RunsOn []string `xorm:"JSON TEXT"`
+ TaskID int64 // the latest task of the job
+ Status Status `xorm:"index"`
+
+ RawConcurrency string // raw concurrency from job YAML's "concurrency" section
+
+ // IsConcurrencyEvaluated is only valid/needed when this job's RawConcurrency is not empty.
+ // If RawConcurrency can't be evaluated (e.g. depend on other job's outputs or have errors), this field will be false.
+ // If RawConcurrency has been successfully evaluated, this field will be true, ConcurrencyGroup and ConcurrencyCancel are also set.
+ IsConcurrencyEvaluated bool
+
+ ConcurrencyGroup string `xorm:"index(repo_concurrency) NOT NULL DEFAULT ''"` // evaluated concurrency.group
+ ConcurrencyCancel bool `xorm:"NOT NULL DEFAULT FALSE"` // evaluated concurrency.cancel-in-progress
+
+ Started timeutil.TimeStamp
+ Stopped timeutil.TimeStamp
+ Created timeutil.TimeStamp `xorm:"created"`
+ Updated timeutil.TimeStamp `xorm:"updated index"`
}
func init() {
@@ -84,6 +100,24 @@ func (job *ActionRunJob) LoadAttributes(ctx context.Context) error {
return job.Run.LoadAttributes(ctx)
}
+// ParseJob parses the job structure from the ActionRunJob.WorkflowPayload
+func (job *ActionRunJob) ParseJob() (*jobparser.Job, error) {
+ // job.WorkflowPayload is a SingleWorkflow created from an ActionRun's workflow, which exactly contains this job's YAML definition.
+ // Ideally it shouldn't be called "Workflow", it is just a job with global workflow fields + trigger
+ parsedWorkflows, err := jobparser.Parse(job.WorkflowPayload)
+ if err != nil {
+ return nil, fmt.Errorf("job %d single workflow: unable to parse: %w", job.ID, err)
+ } else if len(parsedWorkflows) != 1 {
+ return nil, fmt.Errorf("job %d single workflow: not single workflow", job.ID)
+ }
+ _, workflowJob := parsedWorkflows[0].Job()
+ if workflowJob == nil {
+ // it shouldn't happen, and since the callers don't check nil, so return an error instead of nil
+ return nil, util.ErrorWrap(util.ErrNotExist, "job %d single workflow: payload doesn't contain a job", job.ID)
+ }
+ return workflowJob, nil
+}
+
func GetRunJobByID(ctx context.Context, id int64) (*ActionRunJob, error) {
var job ActionRunJob
has, err := db.GetEngine(ctx).Where("id=?", id).Get(&job)
@@ -125,7 +159,7 @@ func UpdateRunJob(ctx context.Context, job *ActionRunJob, cond builder.Cond, col
return affected, nil
}
- if affected != 0 && slices.Contains(cols, "status") && job.Status.IsWaiting() {
+ if slices.Contains(cols, "status") && job.Status.IsWaiting() {
// if the status of job changes to waiting again, increase tasks version.
if err := IncreaseTaskVersion(ctx, job.OwnerID, job.RepoID); err != nil {
return 0, err
@@ -197,3 +231,39 @@ func AggregateJobStatus(jobs []*ActionRunJob) Status {
return StatusUnknown // it shouldn't happen
}
}
+
+func CancelPreviousJobsByJobConcurrency(ctx context.Context, job *ActionRunJob) (jobsToCancel []*ActionRunJob, _ error) {
+ if job.RawConcurrency == "" {
+ return nil, nil
+ }
+ if !job.IsConcurrencyEvaluated {
+ return nil, nil
+ }
+ if job.ConcurrencyGroup == "" {
+ return nil, nil
+ }
+
+ statusFindOption := []Status{StatusWaiting, StatusBlocked}
+ if job.ConcurrencyCancel {
+ statusFindOption = append(statusFindOption, StatusRunning)
+ }
+ runs, jobs, err := GetConcurrentRunsAndJobs(ctx, job.RepoID, job.ConcurrencyGroup, statusFindOption)
+ if err != nil {
+ return nil, fmt.Errorf("find concurrent runs and jobs: %w", err)
+ }
+ jobs = slices.DeleteFunc(jobs, func(j *ActionRunJob) bool { return j.ID == job.ID })
+ jobsToCancel = append(jobsToCancel, jobs...)
+
+ // cancel runs in the same concurrency group
+ for _, run := range runs {
+ jobs, err := db.Find[ActionRunJob](ctx, FindRunJobOptions{
+ RunID: run.ID,
+ })
+ if err != nil {
+ return nil, fmt.Errorf("find run %d jobs: %w", run.ID, err)
+ }
+ jobsToCancel = append(jobsToCancel, jobs...)
+ }
+
+ return CancelJobs(ctx, jobsToCancel)
+}
diff --git a/models/actions/run_job_list.go b/models/actions/run_job_list.go
index 5f7bb62878..10f76d3641 100644
--- a/models/actions/run_job_list.go
+++ b/models/actions/run_job_list.go
@@ -69,12 +69,13 @@ func (jobs ActionJobList) LoadAttributes(ctx context.Context, withRepo bool) err
type FindRunJobOptions struct {
db.ListOptions
- RunID int64
- RepoID int64
- OwnerID int64
- CommitSHA string
- Statuses []Status
- UpdatedBefore timeutil.TimeStamp
+ RunID int64
+ RepoID int64
+ OwnerID int64
+ CommitSHA string
+ Statuses []Status
+ UpdatedBefore timeutil.TimeStamp
+ ConcurrencyGroup string
}
func (opts FindRunJobOptions) ToConds() builder.Cond {
@@ -94,6 +95,12 @@ func (opts FindRunJobOptions) ToConds() builder.Cond {
if opts.UpdatedBefore > 0 {
cond = cond.And(builder.Lt{"`action_run_job`.updated": opts.UpdatedBefore})
}
+ if opts.ConcurrencyGroup != "" {
+ if opts.RepoID == 0 {
+ panic("Invalid FindRunJobOptions: repo_id is required")
+ }
+ cond = cond.And(builder.Eq{"`action_run_job`.concurrency_group": opts.ConcurrencyGroup})
+ }
return cond
}
diff --git a/models/actions/run_list.go b/models/actions/run_list.go
index 12c55e538e..2628c4712f 100644
--- a/models/actions/run_list.go
+++ b/models/actions/run_list.go
@@ -64,15 +64,16 @@ func (runs RunList) LoadRepos(ctx context.Context) error {
type FindRunOptions struct {
db.ListOptions
- RepoID int64
- OwnerID int64
- WorkflowID string
- Ref string // the commit/tag/… that caused this workflow
- TriggerUserID int64
- TriggerEvent webhook_module.HookEventType
- Approved bool // not util.OptionalBool, it works only when it's true
- Status []Status
- CommitSHA string
+ RepoID int64
+ OwnerID int64
+ WorkflowID string
+ Ref string // the commit/tag/… that caused this workflow
+ TriggerUserID int64
+ TriggerEvent webhook_module.HookEventType
+ Approved bool // not util.OptionalBool, it works only when it's true
+ Status []Status
+ ConcurrencyGroup string
+ CommitSHA string
}
func (opts FindRunOptions) ToConds() builder.Cond {
@@ -101,6 +102,12 @@ func (opts FindRunOptions) ToConds() builder.Cond {
if opts.CommitSHA != "" {
cond = cond.And(builder.Eq{"`action_run`.commit_sha": opts.CommitSHA})
}
+ if len(opts.ConcurrencyGroup) > 0 {
+ if opts.RepoID == 0 {
+ panic("Invalid FindRunOptions: repo_id is required")
+ }
+ cond = cond.And(builder.Eq{"`action_run`.concurrency_group": opts.ConcurrencyGroup})
+ }
return cond
}
diff --git a/models/actions/task.go b/models/actions/task.go
index c1306a8418..7417af8b45 100644
--- a/models/actions/task.go
+++ b/models/actions/task.go
@@ -21,7 +21,6 @@ import (
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
lru "github.com/hashicorp/golang-lru/v2"
- "github.com/nektos/act/pkg/jobparser"
"google.golang.org/protobuf/types/known/timestamppb"
"xorm.io/builder"
)
@@ -278,13 +277,10 @@ func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask
return nil, false, err
}
- parsedWorkflows, err := jobparser.Parse(job.WorkflowPayload)
+ workflowJob, err := job.ParseJob()
if err != nil {
- return nil, false, fmt.Errorf("parse workflow of job %d: %w", job.ID, err)
- } else if len(parsedWorkflows) != 1 {
- return nil, false, fmt.Errorf("workflow of job %d: not single workflow", job.ID)
+ return nil, false, fmt.Errorf("load job %d: %w", job.ID, err)
}
- _, workflowJob := parsedWorkflows[0].Job()
if _, err := e.Insert(task); err != nil {
return nil, false, err
diff --git a/models/issues/review_list.go b/models/issues/review_list.go
index bbb8c489fa..86b1a2e76e 100644
--- a/models/issues/review_list.go
+++ b/models/issues/review_list.go
@@ -173,7 +173,7 @@ func GetReviewsByIssueID(ctx context.Context, issueID int64) (latestReviews, mig
reviewersMap := make(map[int64][]*Review) // key is reviewer id
originalReviewersMap := make(map[int64][]*Review) // key is original author id
reviewTeamsMap := make(map[int64][]*Review) // key is reviewer team id
- countedReivewTypes := []ReviewType{ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest}
+ countedReivewTypes := []ReviewType{ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest, ReviewTypeComment}
for _, review := range reviews {
if review.ReviewerTeamID == 0 && slices.Contains(countedReivewTypes, review.Type) && !review.Dismissed {
if review.OriginalAuthorID != 0 {
diff --git a/models/issues/review_test.go b/models/issues/review_test.go
index 7b8537cc7d..6795ea8e66 100644
--- a/models/issues/review_test.go
+++ b/models/issues/review_test.go
@@ -122,6 +122,7 @@ func TestGetReviewersByIssueID(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 3})
+ user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
org3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3})
user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
@@ -129,6 +130,12 @@ func TestGetReviewersByIssueID(t *testing.T) {
expectedReviews := []*issues_model.Review{}
expectedReviews = append(expectedReviews,
+ &issues_model.Review{
+ ID: 5,
+ Reviewer: user1,
+ Type: issues_model.ReviewTypeComment,
+ UpdatedUnix: 946684810,
+ },
&issues_model.Review{
ID: 7,
Reviewer: org3,
@@ -167,8 +174,9 @@ func TestGetReviewersByIssueID(t *testing.T) {
for _, review := range allReviews {
assert.NoError(t, review.LoadReviewer(t.Context()))
}
- if assert.Len(t, allReviews, 5) {
+ if assert.Len(t, allReviews, 6) {
for i, review := range allReviews {
+ assert.Equal(t, expectedReviews[i].ID, review.ID)
assert.Equal(t, expectedReviews[i].Reviewer, review.Reviewer)
assert.Equal(t, expectedReviews[i].Type, review.Type)
assert.Equal(t, expectedReviews[i].UpdatedUnix, review.UpdatedUnix)
diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go
index 1b1558f39d..8fb10e84cf 100644
--- a/models/migrations/migrations.go
+++ b/models/migrations/migrations.go
@@ -394,6 +394,7 @@ func prepareMigrationTasks() []*migration {
// Gitea 1.24.0 ends at database version 321
newMigration(321, "Use LONGTEXT for some columns and fix review_state.updated_files column", v1_25.UseLongTextInSomeColumnsAndFixBugs),
newMigration(322, "Extend comment tree_path length limit", v1_25.ExtendCommentTreePathLength),
+ newMigration(323, "Add support for actions concurrency", v1_25.AddActionsConcurrency),
}
return preparedMigrations
}
diff --git a/models/migrations/v1_25/v323.go b/models/migrations/v1_25/v323.go
new file mode 100644
index 0000000000..5f38ea8545
--- /dev/null
+++ b/models/migrations/v1_25/v323.go
@@ -0,0 +1,43 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_25
+
+import (
+ "xorm.io/xorm"
+)
+
+func AddActionsConcurrency(x *xorm.Engine) error {
+ type ActionRun struct {
+ RepoID int64 `xorm:"index(repo_concurrency)"`
+ RawConcurrency string
+ ConcurrencyGroup string `xorm:"index(repo_concurrency) NOT NULL DEFAULT ''"`
+ ConcurrencyCancel bool `xorm:"NOT NULL DEFAULT FALSE"`
+ }
+
+ if _, err := x.SyncWithOptions(xorm.SyncOptions{
+ IgnoreDropIndices: true,
+ }, new(ActionRun)); err != nil {
+ return err
+ }
+
+ if err := x.Sync(new(ActionRun)); err != nil {
+ return err
+ }
+
+ type ActionRunJob struct {
+ RepoID int64 `xorm:"index(repo_concurrency)"`
+ RawConcurrency string
+ IsConcurrencyEvaluated bool
+ ConcurrencyGroup string `xorm:"index(repo_concurrency) NOT NULL DEFAULT ''"`
+ ConcurrencyCancel bool `xorm:"NOT NULL DEFAULT FALSE"`
+ }
+
+ if _, err := x.SyncWithOptions(xorm.SyncOptions{
+ IgnoreDropIndices: true,
+ }, new(ActionRunJob)); err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/models/repo/repo.go b/models/repo/repo.go
index 401775047b..819356dfad 100644
--- a/models/repo/repo.go
+++ b/models/repo/repo.go
@@ -229,10 +229,6 @@ func RelativePath(ownerName, repoName string) string {
return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".git"
}
-func RelativeWikiPath(ownerName, repoName string) string {
- return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".wiki.git"
-}
-
// RelativePath should be an unix style path like username/reponame.git
func (repo *Repository) RelativePath() string {
return RelativePath(repo.OwnerName, repo.Name)
@@ -245,12 +241,6 @@ func (sr StorageRepo) RelativePath() string {
return string(sr)
}
-// WikiStorageRepo returns the storage repo for the wiki
-// The wiki repository should have the same object format as the code repository
-func (repo *Repository) WikiStorageRepo() StorageRepo {
- return StorageRepo(RelativeWikiPath(repo.OwnerName, repo.Name))
-}
-
// SanitizedOriginalURL returns a sanitized OriginalURL
func (repo *Repository) SanitizedOriginalURL() string {
if repo.OriginalURL == "" {
diff --git a/models/repo/wiki.go b/models/repo/wiki.go
index 9f41445bf8..47c8fa43ab 100644
--- a/models/repo/wiki.go
+++ b/models/repo/wiki.go
@@ -7,7 +7,6 @@ package repo
import (
"context"
"fmt"
- "path/filepath"
"strings"
user_model "code.gitea.io/gitea/models/user"
@@ -76,12 +75,12 @@ func (repo *Repository) WikiCloneLink(ctx context.Context, doer *user_model.User
return repo.cloneLink(ctx, doer, repo.Name+".wiki")
}
-// WikiPath returns wiki data path by given user and repository name.
-func WikiPath(userName, repoName string) string {
- return filepath.Join(user_model.UserPath(userName), strings.ToLower(repoName)+".wiki.git")
+func RelativeWikiPath(ownerName, repoName string) string {
+ return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".wiki.git"
}
-// WikiPath returns wiki data path for given repository.
-func (repo *Repository) WikiPath() string {
- return WikiPath(repo.OwnerName, repo.Name)
+// WikiStorageRepo returns the storage repo for the wiki
+// The wiki repository should have the same object format as the code repository
+func (repo *Repository) WikiStorageRepo() StorageRepo {
+ return StorageRepo(RelativeWikiPath(repo.OwnerName, repo.Name))
}
diff --git a/models/repo/wiki_test.go b/models/repo/wiki_test.go
index 41e53d93d9..636c78009b 100644
--- a/models/repo/wiki_test.go
+++ b/models/repo/wiki_test.go
@@ -4,12 +4,10 @@
package repo_test
import (
- "path/filepath"
"testing"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
- "code.gitea.io/gitea/modules/setting"
"github.com/stretchr/testify/assert"
)
@@ -23,15 +21,10 @@ func TestRepository_WikiCloneLink(t *testing.T) {
assert.Equal(t, "https://try.gitea.io/user2/repo1.wiki.git", cloneLink.HTTPS)
}
-func TestWikiPath(t *testing.T) {
+func TestRepository_RelativeWikiPath(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- expected := filepath.Join(setting.RepoRootPath, "user2/repo1.wiki.git")
- assert.Equal(t, expected, repo_model.WikiPath("user2", "repo1"))
-}
-func TestRepository_WikiPath(t *testing.T) {
- assert.NoError(t, unittest.PrepareTestDatabase())
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
- expected := filepath.Join(setting.RepoRootPath, "user2/repo1.wiki.git")
- assert.Equal(t, expected, repo.WikiPath())
+ assert.Equal(t, "user2/repo1.wiki.git", repo_model.RelativeWikiPath(repo.OwnerName, repo.Name))
+ assert.Equal(t, "user2/repo1.wiki.git", repo.WikiStorageRepo().RelativePath())
}
diff --git a/modules/git/key.go b/modules/git/key.go
index 8c14742f34..39e79ddbe0 100644
--- a/modules/git/key.go
+++ b/modules/git/key.go
@@ -3,7 +3,13 @@
package git
-import "code.gitea.io/gitea/modules/setting"
+import (
+ "context"
+ "strings"
+
+ "code.gitea.io/gitea/modules/git/gitcmd"
+ "code.gitea.io/gitea/modules/setting"
+)
// Based on https://git-scm.com/docs/git-config#Documentation/git-config.txt-gpgformat
const (
@@ -24,3 +30,48 @@ func (s *SigningKey) String() string {
setting.PanicInDevOrTesting("don't call SigningKey.String() - it exposes the KeyID which might be a local file path")
return "SigningKey:" + s.Format
}
+
+// GetSigningKey returns the KeyID and git Signature for the repo
+func GetSigningKey(ctx context.Context, repoPath string) (*SigningKey, *Signature) {
+ if setting.Repository.Signing.SigningKey == "none" {
+ return nil, nil
+ }
+
+ if setting.Repository.Signing.SigningKey == "default" || setting.Repository.Signing.SigningKey == "" {
+ // Can ignore the error here as it means that commit.gpgsign is not set
+ value, _, _ := gitcmd.NewCommand("config", "--get", "commit.gpgsign").WithDir(repoPath).RunStdString(ctx)
+ sign, valid := ParseBool(strings.TrimSpace(value))
+ if !sign || !valid {
+ return nil, nil
+ }
+
+ format, _, _ := gitcmd.NewCommand("config", "--default", SigningKeyFormatOpenPGP, "--get", "gpg.format").WithDir(repoPath).RunStdString(ctx)
+ signingKey, _, _ := gitcmd.NewCommand("config", "--get", "user.signingkey").WithDir(repoPath).RunStdString(ctx)
+ signingName, _, _ := gitcmd.NewCommand("config", "--get", "user.name").WithDir(repoPath).RunStdString(ctx)
+ signingEmail, _, _ := gitcmd.NewCommand("config", "--get", "user.email").WithDir(repoPath).RunStdString(ctx)
+
+ if strings.TrimSpace(signingKey) == "" {
+ return nil, nil
+ }
+
+ return &SigningKey{
+ KeyID: strings.TrimSpace(signingKey),
+ Format: strings.TrimSpace(format),
+ }, &Signature{
+ Name: strings.TrimSpace(signingName),
+ Email: strings.TrimSpace(signingEmail),
+ }
+ }
+
+ if setting.Repository.Signing.SigningKey == "" {
+ return nil, nil
+ }
+
+ return &SigningKey{
+ KeyID: setting.Repository.Signing.SigningKey,
+ Format: setting.Repository.Signing.SigningFormat,
+ }, &Signature{
+ Name: setting.Repository.Signing.SigningName,
+ Email: setting.Repository.Signing.SigningEmail,
+ }
+}
diff --git a/modules/git/url/url_test.go b/modules/git/url/url_test.go
index 6655c20be3..76aa74a128 100644
--- a/modules/git/url/url_test.go
+++ b/modules/git/url/url_test.go
@@ -34,12 +34,12 @@ func TestParseGitURLs(t *testing.T) {
},
},
{
- kase: "git@[fe80:14fc:cec5:c174:d88%2510]:go-gitea/gitea.git",
+ kase: "git@[fe80::14fc:cec5:c174:d88%2510]:go-gitea/gitea.git",
expected: &GitURL{
URL: &url.URL{
Scheme: "ssh",
User: url.User("git"),
- Host: "[fe80:14fc:cec5:c174:d88%10]",
+ Host: "[fe80::14fc:cec5:c174:d88%10]",
Path: "go-gitea/gitea.git",
},
extraMark: 1,
@@ -137,11 +137,11 @@ func TestParseGitURLs(t *testing.T) {
},
},
{
- kase: "https://[fe80:14fc:cec5:c174:d88%2510]:20/go-gitea/gitea.git",
+ kase: "https://[fe80::14fc:cec5:c174:d88%2510]:20/go-gitea/gitea.git",
expected: &GitURL{
URL: &url.URL{
Scheme: "https",
- Host: "[fe80:14fc:cec5:c174:d88%10]:20",
+ Host: "[fe80::14fc:cec5:c174:d88%10]:20",
Path: "/go-gitea/gitea.git",
},
extraMark: 0,
diff --git a/modules/gitrepo/clone.go b/modules/gitrepo/clone.go
new file mode 100644
index 0000000000..8c437f657c
--- /dev/null
+++ b/modules/gitrepo/clone.go
@@ -0,0 +1,20 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package gitrepo
+
+import (
+ "context"
+
+ "code.gitea.io/gitea/modules/git"
+)
+
+// CloneExternalRepo clones an external repository to the managed repository.
+func CloneExternalRepo(ctx context.Context, fromRemoteURL string, toRepo Repository, opts git.CloneRepoOptions) error {
+ return git.Clone(ctx, fromRemoteURL, repoPath(toRepo), opts)
+}
+
+// CloneRepoToLocal clones a managed repository to a local path.
+func CloneRepoToLocal(ctx context.Context, fromRepo Repository, toLocalPath string, opts git.CloneRepoOptions) error {
+ return git.Clone(ctx, repoPath(fromRepo), toLocalPath, opts)
+}
diff --git a/modules/gitrepo/commitgraph.go b/modules/gitrepo/commitgraph.go
new file mode 100644
index 0000000000..7310e167f6
--- /dev/null
+++ b/modules/gitrepo/commitgraph.go
@@ -0,0 +1,14 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package gitrepo
+
+import (
+ "context"
+
+ "code.gitea.io/gitea/modules/git"
+)
+
+func WriteCommitGraph(ctx context.Context, repo Repository) error {
+ return git.WriteCommitGraph(ctx, repoPath(repo))
+}
diff --git a/modules/gitrepo/gitrepo.go b/modules/gitrepo/gitrepo.go
index 59d2323599..4dd03c18fe 100644
--- a/modules/gitrepo/gitrepo.go
+++ b/modules/gitrepo/gitrepo.go
@@ -7,9 +7,12 @@ import (
"context"
"fmt"
"io"
+ "io/fs"
+ "os"
"path/filepath"
"code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/git/gitcmd"
"code.gitea.io/gitea/modules/reqctx"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
@@ -86,3 +89,12 @@ func RenameRepository(ctx context.Context, repo, newRepo Repository) error {
func InitRepository(ctx context.Context, repo Repository, objectFormatName string) error {
return git.InitRepository(ctx, repoPath(repo), true, objectFormatName)
}
+
+func UpdateServerInfo(ctx context.Context, repo Repository) error {
+ _, _, err := RunCmdBytes(ctx, repo, gitcmd.NewCommand("update-server-info"))
+ return err
+}
+
+func GetRepoFS(repo Repository) fs.FS {
+ return os.DirFS(repoPath(repo))
+}
diff --git a/modules/gitrepo/push.go b/modules/gitrepo/push.go
new file mode 100644
index 0000000000..18808cac24
--- /dev/null
+++ b/modules/gitrepo/push.go
@@ -0,0 +1,14 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package gitrepo
+
+import (
+ "context"
+
+ "code.gitea.io/gitea/modules/git"
+)
+
+func Push(ctx context.Context, repo Repository, opts git.PushOptions) error {
+ return git.Push(ctx, repoPath(repo), opts)
+}
diff --git a/modules/gitrepo/signing.go b/modules/gitrepo/signing.go
new file mode 100644
index 0000000000..c50978d15a
--- /dev/null
+++ b/modules/gitrepo/signing.go
@@ -0,0 +1,14 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package gitrepo
+
+import (
+ "context"
+
+ "code.gitea.io/gitea/modules/git"
+)
+
+func GetSigningKey(ctx context.Context, repo Repository) (*git.SigningKey, *git.Signature) {
+ return git.GetSigningKey(ctx, repoPath(repo))
+}
diff --git a/modules/hcaptcha/hcaptcha_test.go b/modules/hcaptcha/hcaptcha_test.go
index 55e01ec535..5906faf17c 100644
--- a/modules/hcaptcha/hcaptcha_test.go
+++ b/modules/hcaptcha/hcaptcha_test.go
@@ -4,7 +4,10 @@
package hcaptcha
import (
+ "errors"
+ "io"
"net/http"
+ "net/url"
"os"
"strings"
"testing"
@@ -21,6 +24,33 @@ func TestMain(m *testing.M) {
os.Exit(m.Run())
}
+type mockTransport struct{}
+
+func (mockTransport) RoundTrip(req *http.Request) (*http.Response, error) {
+ if req.URL.String() != verifyURL {
+ return nil, errors.New("unsupported url")
+ }
+
+ body, err := io.ReadAll(req.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ bodyValues, err := url.ParseQuery(string(body))
+ if err != nil {
+ return nil, err
+ }
+
+ var responseText string
+ if bodyValues.Get("response") == dummyToken {
+ responseText = `{"success":true,"credit":false,"hostname":"dummy-key-pass","challenge_ts":"2025-10-08T16:02:56.136Z"}`
+ } else {
+ responseText = `{"success":false,"error-codes":["invalid-input-response"]}`
+ }
+
+ return &http.Response{Request: req, Body: io.NopCloser(strings.NewReader(responseText))}, nil
+}
+
func TestCaptcha(t *testing.T) {
tt := []struct {
Name string
@@ -54,7 +84,8 @@ func TestCaptcha(t *testing.T) {
for _, tc := range tt {
t.Run(tc.Name, func(t *testing.T) {
client, err := New(tc.Secret, WithHTTP(&http.Client{
- Timeout: time.Second * 5,
+ Timeout: time.Second * 5,
+ Transport: mockTransport{},
}))
if err != nil {
// The only error that can be returned from creating a client
diff --git a/modules/httplib/request.go b/modules/httplib/request.go
index 49ea6f4b73..8542a57d36 100644
--- a/modules/httplib/request.go
+++ b/modules/httplib/request.go
@@ -7,54 +7,53 @@ package httplib
import (
"bytes"
"context"
- "crypto/tls"
- "errors"
"fmt"
"io"
"net"
"net/http"
"net/url"
"strings"
+ "sync"
"time"
)
-var defaultSetting = Settings{"GiteaServer", 60 * time.Second, 60 * time.Second, nil, nil}
-
-// newRequest returns *Request with specific method
-func newRequest(url, method string) *Request {
- var resp http.Response
- req := http.Request{
- Method: method,
- Header: make(http.Header),
- Proto: "HTTP/1.1",
- ProtoMajor: 1,
- ProtoMinor: 1,
+var defaultTransport = sync.OnceValue(func() http.RoundTripper {
+ return &http.Transport{
+ Proxy: http.ProxyFromEnvironment,
+ DialContext: DialContextWithTimeout(10 * time.Second), // it is good enough in modern days
+ }
+})
+
+func DialContextWithTimeout(timeout time.Duration) func(ctx context.Context, network, address string) (net.Conn, error) {
+ return func(ctx context.Context, network, address string) (net.Conn, error) {
+ return (&net.Dialer{Timeout: timeout}).DialContext(ctx, network, address)
}
- return &Request{url, &req, map[string]string{}, defaultSetting, &resp, nil}
}
-// NewRequest returns *Request with specific method
func NewRequest(url, method string) *Request {
- return newRequest(url, method)
+ return &Request{
+ url: url,
+ req: &http.Request{
+ Method: method,
+ Header: make(http.Header),
+ Proto: "HTTP/1.1", // FIXME: from legacy httplib, it shouldn't be hardcoded
+ ProtoMajor: 1,
+ ProtoMinor: 1,
+ },
+ params: map[string]string{},
+
+ // ATTENTION: from legacy httplib, callers must pay more attention to it, it will cause annoying bugs when the response takes a long time
+ readWriteTimeout: 60 * time.Second,
+ }
}
-// Settings is the default settings for http client
-type Settings struct {
- UserAgent string
- ConnectTimeout time.Duration
- ReadWriteTimeout time.Duration
- TLSClientConfig *tls.Config
- Transport http.RoundTripper
-}
-
-// Request provides more useful methods for requesting one url than http.Request.
type Request struct {
- url string
- req *http.Request
- params map[string]string
- setting Settings
- resp *http.Response
- body []byte
+ url string
+ req *http.Request
+ params map[string]string
+
+ readWriteTimeout time.Duration
+ transport http.RoundTripper
}
// SetContext sets the request's Context
@@ -63,36 +62,24 @@ func (r *Request) SetContext(ctx context.Context) *Request {
return r
}
-// SetTimeout sets connect time out and read-write time out for BeegoRequest.
-func (r *Request) SetTimeout(connectTimeout, readWriteTimeout time.Duration) *Request {
- r.setting.ConnectTimeout = connectTimeout
- r.setting.ReadWriteTimeout = readWriteTimeout
+// SetTransport sets the request transport, if not set, will use httplib's default transport with environment proxy support
+// ATTENTION: the http.Transport has a connection pool, so it should be reused as much as possible, do not create a lot of transports
+func (r *Request) SetTransport(transport http.RoundTripper) *Request {
+ r.transport = transport
return r
}
func (r *Request) SetReadWriteTimeout(readWriteTimeout time.Duration) *Request {
- r.setting.ReadWriteTimeout = readWriteTimeout
+ r.readWriteTimeout = readWriteTimeout
return r
}
-// SetTLSClientConfig sets tls connection configurations if visiting https url.
-func (r *Request) SetTLSClientConfig(config *tls.Config) *Request {
- r.setting.TLSClientConfig = config
- return r
-}
-
-// Header add header item string in request.
+// Header set header item string in request.
func (r *Request) Header(key, value string) *Request {
r.req.Header.Set(key, value)
return r
}
-// SetTransport sets transport to
-func (r *Request) SetTransport(transport http.RoundTripper) *Request {
- r.setting.Transport = transport
- return r
-}
-
// Param adds query param in to request.
// params build query string as ?key1=value1&key2=value2...
func (r *Request) Param(key, value string) *Request {
@@ -125,11 +112,9 @@ func (r *Request) Body(data any) *Request {
return r
}
-func (r *Request) getResponse() (*http.Response, error) {
- if r.resp.StatusCode != 0 {
- return r.resp, nil
- }
-
+// Response executes request client and returns the response.
+// Caller MUST close the response body if no error occurs.
+func (r *Request) Response() (*http.Response, error) {
var paramBody string
if len(r.params) > 0 {
var buf bytes.Buffer
@@ -160,59 +145,19 @@ func (r *Request) getResponse() (*http.Response, error) {
return nil, err
}
- trans := r.setting.Transport
- if trans == nil {
- // create default transport
- trans = &http.Transport{
- TLSClientConfig: r.setting.TLSClientConfig,
- Proxy: http.ProxyFromEnvironment,
- DialContext: TimeoutDialer(r.setting.ConnectTimeout),
- }
- } else if t, ok := trans.(*http.Transport); ok {
- if t.TLSClientConfig == nil {
- t.TLSClientConfig = r.setting.TLSClientConfig
- }
- if t.DialContext == nil {
- t.DialContext = TimeoutDialer(r.setting.ConnectTimeout)
- }
- }
-
client := &http.Client{
- Transport: trans,
- Timeout: r.setting.ReadWriteTimeout,
+ Transport: r.transport,
+ Timeout: r.readWriteTimeout,
+ }
+ if client.Transport == nil {
+ client.Transport = defaultTransport()
}
- if len(r.setting.UserAgent) > 0 && len(r.req.Header.Get("User-Agent")) == 0 {
- r.req.Header.Set("User-Agent", r.setting.UserAgent)
+ if r.req.Header.Get("User-Agent") == "" {
+ r.req.Header.Set("User-Agent", "GiteaHttpLib")
}
- resp, err := client.Do(r.req)
- if err != nil {
- return nil, err
- }
- r.resp = resp
- return resp, nil
-}
-
-// Response executes request client gets response manually.
-// Caller MUST close the response body if no error occurs
-func (r *Request) Response() (*http.Response, error) {
- if r == nil {
- return nil, errors.New("invalid request")
- }
- return r.getResponse()
-}
-
-// TimeoutDialer returns functions of connection dialer with timeout settings for http.Transport Dial field.
-func TimeoutDialer(cTimeout time.Duration) func(ctx context.Context, net, addr string) (c net.Conn, err error) {
- return func(ctx context.Context, netw, addr string) (net.Conn, error) {
- d := net.Dialer{Timeout: cTimeout}
- conn, err := d.DialContext(ctx, netw, addr)
- if err != nil {
- return nil, err
- }
- return conn, nil
- }
+ return client.Do(r.req)
}
func (r *Request) GoString() string {
diff --git a/modules/lfstransfer/backend/backend.go b/modules/lfstransfer/backend/backend.go
index dd4108ea56..f4e6157091 100644
--- a/modules/lfstransfer/backend/backend.go
+++ b/modules/lfstransfer/backend/backend.go
@@ -157,7 +157,7 @@ func (g *GiteaBackend) Batch(_ string, pointers []transfer.BatchItem, args trans
}
// Download implements transfer.Backend. The returned reader must be closed by the caller.
-func (g *GiteaBackend) Download(oid string, args transfer.Args) (io.ReadCloser, int64, error) {
+func (g *GiteaBackend) Download(oid string, args transfer.Args) (_ io.ReadCloser, _ int64, retErr error) {
idMapStr, exists := args[argID]
if !exists {
return nil, 0, ErrMissingID
@@ -188,7 +188,15 @@ func (g *GiteaBackend) Download(oid string, args transfer.Args) (io.ReadCloser,
if err != nil {
return nil, 0, fmt.Errorf("failed to get response: %w", err)
}
- // no need to close the body here by "defer resp.Body.Close()", see below
+ // We must return the ReaderCloser but not "ReadAll", to avoid OOM.
+ // "transfer.Backend" will check io.Closer interface and close the Body reader.
+ // So only close the Body when error occurs
+ defer func() {
+ if retErr != nil {
+ _ = resp.Body.Close()
+ }
+ }()
+
if resp.StatusCode != http.StatusOK {
return nil, 0, statusCodeToErr(resp.StatusCode)
}
@@ -197,7 +205,6 @@ func (g *GiteaBackend) Download(oid string, args transfer.Args) (io.ReadCloser,
if err != nil {
return nil, 0, fmt.Errorf("failed to parse content length: %w", err)
}
- // transfer.Backend will check io.Closer interface and close this Body reader
return resp.Body, respSize, nil
}
diff --git a/modules/private/internal.go b/modules/private/internal.go
index e599c6eb8e..1fd72a3732 100644
--- a/modules/private/internal.go
+++ b/modules/private/internal.go
@@ -10,6 +10,7 @@ import (
"net/http"
"os"
"strings"
+ "sync"
"time"
"code.gitea.io/gitea/modules/httplib"
@@ -33,6 +34,35 @@ func getClientIP() string {
return strings.Fields(sshConnEnv)[0]
}
+func dialContextInternalAPI(ctx context.Context, network, address string) (conn net.Conn, err error) {
+ d := net.Dialer{Timeout: 10 * time.Second}
+ if setting.Protocol == setting.HTTPUnix {
+ conn, err = d.DialContext(ctx, "unix", setting.HTTPAddr)
+ } else {
+ conn, err = d.DialContext(ctx, network, address)
+ }
+ if err != nil {
+ return nil, err
+ }
+ if setting.LocalUseProxyProtocol {
+ if err = proxyprotocol.WriteLocalHeader(conn); err != nil {
+ _ = conn.Close()
+ return nil, err
+ }
+ }
+ return conn, nil
+}
+
+var internalAPITransport = sync.OnceValue(func() http.RoundTripper {
+ return &http.Transport{
+ DialContext: dialContextInternalAPI,
+ TLSClientConfig: &tls.Config{
+ InsecureSkipVerify: true,
+ ServerName: setting.Domain,
+ },
+ }
+})
+
func NewInternalRequest(ctx context.Context, url, method string) *httplib.Request {
if setting.InternalToken == "" {
log.Fatal(`The INTERNAL_TOKEN setting is missing from the configuration file: %q.
@@ -43,49 +73,11 @@ Ensure you are running in the correct environment or set the correct configurati
log.Fatal("Invalid internal request URL: %q", url)
}
- req := httplib.NewRequest(url, method).
+ return httplib.NewRequest(url, method).
SetContext(ctx).
+ SetTransport(internalAPITransport()).
Header("X-Real-IP", getClientIP()).
- Header("X-Gitea-Internal-Auth", "Bearer "+setting.InternalToken).
- SetTLSClientConfig(&tls.Config{
- InsecureSkipVerify: true,
- ServerName: setting.Domain,
- })
-
- if setting.Protocol == setting.HTTPUnix {
- req.SetTransport(&http.Transport{
- DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
- var d net.Dialer
- conn, err := d.DialContext(ctx, "unix", setting.HTTPAddr)
- if err != nil {
- return conn, err
- }
- if setting.LocalUseProxyProtocol {
- if err = proxyprotocol.WriteLocalHeader(conn); err != nil {
- _ = conn.Close()
- return nil, err
- }
- }
- return conn, err
- },
- })
- } else if setting.LocalUseProxyProtocol {
- req.SetTransport(&http.Transport{
- DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
- var d net.Dialer
- conn, err := d.DialContext(ctx, network, address)
- if err != nil {
- return conn, err
- }
- if err = proxyprotocol.WriteLocalHeader(conn); err != nil {
- _ = conn.Close()
- return nil, err
- }
- return conn, err
- },
- })
- }
- return req
+ Header("X-Gitea-Internal-Auth", "Bearer "+setting.InternalToken)
}
func newInternalRequestAPI(ctx context.Context, url, method string, body ...any) *httplib.Request {
@@ -98,6 +90,6 @@ func newInternalRequestAPI(ctx context.Context, url, method string, body ...any)
log.Fatal("Too many arguments for newInternalRequestAPI")
}
- req.SetTimeout(10*time.Second, 60*time.Second)
+ req.SetReadWriteTimeout(60 * time.Second)
return req
}
diff --git a/modules/private/restore_repo.go b/modules/private/restore_repo.go
index 9c3a008142..9d65962fcd 100644
--- a/modules/private/restore_repo.go
+++ b/modules/private/restore_repo.go
@@ -6,7 +6,6 @@ package private
import (
"context"
"fmt"
- "time"
"code.gitea.io/gitea/modules/setting"
)
@@ -31,6 +30,6 @@ func RestoreRepo(ctx context.Context, repoDir, ownerName, repoName string, units
Units: units,
Validation: validation,
})
- req.SetTimeout(3*time.Second, 0) // since the request will spend much time, don't timeout
+ req.SetReadWriteTimeout(0) // since the request will spend much time, don't timeout
return requestJSONClientMsg(req, fmt.Sprintf("Restore repo %s/%s successfully", ownerName, repoName))
}
diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini
index 9144916e45..475954f03a 100644
--- a/options/locale/locale_ja-JP.ini
+++ b/options/locale/locale_ja-JP.ini
@@ -109,6 +109,7 @@ copy_path=パスをコピー
copy_success=コピーされました!
copy_error=コピーに失敗しました
copy_type_unsupported=このファイルタイプはコピーできません
+copy_filename=ファイル名をコピー
write=書き込み
preview=プレビュー
@@ -2433,6 +2434,9 @@ settings.event_workflow_job_desc=Gitea Actions のワークフロージョブが
settings.event_package=パッケージ
settings.event_package_desc=リポジトリにパッケージが作成または削除されたとき。
settings.branch_filter=ブランチ フィルター
+settings.branch_filter_desc_1=プッシュ、ブランチ作成、ブランチ削除イベントに対するブランチ(およびref名)の許可リストで、globパターンで指定します。 空または*の場合、すべてのブランチとタグのイベントが報告されます。
+settings.branch_filter_desc_2=完全なref名にマッチさせるには、 refs/heads/ または refs/tags/ を前に付けてください。
+settings.branch_filter_desc_doc=書き方についてはドキュメント %[2]s を参照してください。
settings.authorization_header=Authorizationヘッダー
settings.authorization_header_desc=入力した場合、リクエストにAuthorizationヘッダーとして付加します。 例: %s
settings.active=有効
diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini
index 0960cd800f..b6292c139b 100644
--- a/options/locale/locale_pt-BR.ini
+++ b/options/locale/locale_pt-BR.ini
@@ -2075,6 +2075,8 @@ settings=Configurações
settings.desc=Configurações é onde você pode gerenciar as opções para o repositório.
settings.options=Repositório
settings.public_access=Acesso Público
+settings.public_access_desc=Configurar permissões de acesso do visitante público para substituir os padrões deste repositório.
+settings.public_access.docs.not_set=Não definido: nenhuma permissão extra de acesso público. A permissão do visitante segue a visibilidade e as permissões de membro do repositório.
settings.collaboration=Colaboradores
settings.collaboration.admin=Administrador
settings.collaboration.write=Escrita
@@ -2760,6 +2762,11 @@ view_as_role=Ver como: %s
view_as_public_hint=Você está vendo o README como um usuário público.
view_as_member_hint=Você está vendo o README como um membro desta organização.
+worktime.date_range_start=Data de início
+worktime.date_range_end=Data de término
+worktime.by_repositories=Por repositórios
+worktime.by_milestones=Por marcos
+worktime.by_members=Por membros
[admin]
maintenance=Manutenção
@@ -3371,6 +3378,7 @@ versions=Versões
versions.view_all=Ver todas
dependency.id=ID
dependency.version=Versão
+search_in_external_registry=Pesquisar em %s
alpine.registry=Configure este registro adicionando o URL no arquivo /etc/apk/repositories:
alpine.registry.key=Baixe a chave RSA pública do registro para a pasta /etc/apk/keys/ para verificar a assinatura do índice:
alpine.registry.info=Escolha o $branch e $repository da lista abaixo.
@@ -3398,6 +3406,7 @@ conda.install=Para instalar o pacote usando o Conda, execute o seguinte comando:
container.details.type=Tipo de Imagem
container.details.platform=Plataforma
container.pull=Puxe a imagem pela linha de comando:
+container.images=Imagens
container.digest=Digest
container.multi_arch=S.O. / Arquitetura
container.layers=Camadas da Imagem
@@ -3506,6 +3515,8 @@ creation.name_placeholder=apenas caracteres alfanuméricos ou underline (_), nã
creation.value_placeholder=Insira qualquer conteúdo. Espaços em branco no início e no fim serão omitidos.
+add_secret=Adicionar segredo
+edit_secret=Editar segredo
deletion=Excluir segredo
deletion.description=A exclusão de um segredo é permanente e não pode ser desfeita. Continuar?
deletion.success=O segredo foi excluído.
@@ -3605,9 +3616,11 @@ variables.update.success=A variável foi editada.
[projects]
+deleted.display_name=Excluir Projeto
type-1.display_name=Projeto Individual
type-2.display_name=Projeto do Repositório
type-3.display_name=Projeto da Organização
+enter_fullscreen=Tela cheia
exit_fullscreen=Sair da Tela Cheia
[git.filemode]
diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini
index 9d353faa64..29eb6be949 100644
--- a/options/locale/locale_zh-CN.ini
+++ b/options/locale/locale_zh-CN.ini
@@ -109,6 +109,7 @@ copy_path=复制路径
copy_success=复制成功!
copy_error=复制失败
copy_type_unsupported=无法复制此类型的文件内容
+copy_filename=复制文件名
write=撰写
preview=预览
@@ -2434,6 +2435,9 @@ settings.event_workflow_job_desc=Gitea 工作流队列中、等待中、正在
settings.event_package=软件包
settings.event_package_desc=软件包在仓库中已创建或删除。
settings.branch_filter=分支过滤
+settings.branch_filter_desc_1=推送、分支创建和分支删除事件的分支(和引用名称)白名单,以全局模式指定。如果为空或为 *,则报告所有分支和标签的事件。
+settings.branch_filter_desc_2=使用 refs/heads/ 或 refs/tags/ 前缀来匹配完整的引用名称。
+settings.branch_filter_desc_doc=请参阅 %[2]s 文档了解语法。
settings.authorization_header=授权标头
settings.authorization_header_desc=当存在时将被作为授权标头包含在内。例如: %s。
settings.active=激活
diff --git a/package.json b/package.json
index e8e6f63eeb..2c5d5f8a0a 100644
--- a/package.json
+++ b/package.json
@@ -15,13 +15,13 @@
"@github/relative-time-element": "4.4.8",
"@github/text-expander-element": "2.9.2",
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
- "@primer/octicons": "19.18.0",
+ "@primer/octicons": "19.19.0",
"@resvg/resvg-wasm": "2.6.2",
"@silverwind/vue3-calendar-heatmap": "2.0.6",
"@techknowlogick/license-checker-webpack-plugin": "0.3.0",
"add-asset-webpack-plugin": "3.1.1",
"ansi_up": "6.0.6",
- "asciinema-player": "3.10.0",
+ "asciinema-player": "3.12.0",
"chart.js": "4.5.0",
"chartjs-adapter-dayjs-4": "1.0.4",
"chartjs-plugin-zoom": "2.2.0",
@@ -31,22 +31,22 @@
"dayjs": "1.11.18",
"dropzone": "6.0.0-beta.2",
"easymde": "2.20.0",
- "esbuild-loader": "4.3.0",
+ "esbuild-loader": "4.4.0",
"htmx.org": "2.0.7",
"idiomorph": "0.7.4",
"jquery": "3.7.1",
- "katex": "0.16.22",
+ "katex": "0.16.23",
"mermaid": "11.12.0",
"mini-css-extract-plugin": "2.9.4",
- "monaco-editor": "0.53.0",
- "monaco-editor-webpack-plugin": "7.1.0",
+ "monaco-editor": "0.54.0",
+ "monaco-editor-webpack-plugin": "7.1.1",
"online-3d-viewer": "0.16.0",
"pdfobject": "2.3.1",
"perfect-debounce": "2.0.0",
"postcss": "8.5.6",
"postcss-loader": "8.2.0",
"sortablejs": "1.15.6",
- "swagger-ui-dist": "5.29.1",
+ "swagger-ui-dist": "5.29.4",
"tailwindcss": "3.4.17",
"throttle-debounce": "5.0.2",
"tinycolor2": "1.6.0",
@@ -60,13 +60,13 @@
"vue-bar-graph": "2.2.0",
"vue-chartjs": "5.3.2",
"vue-loader": "17.4.2",
- "webpack": "5.102.0",
+ "webpack": "5.102.1",
"webpack-cli": "6.0.1",
"wrap-ansi": "9.0.2"
},
"devDependencies": {
"@eslint-community/eslint-plugin-eslint-comments": "4.5.0",
- "@playwright/test": "1.55.1",
+ "@playwright/test": "1.56.0",
"@stylistic/eslint-plugin": "5.4.0",
"@stylistic/stylelint-plugin": "4.0.0",
"@types/codemirror": "5.60.16",
@@ -79,10 +79,10 @@
"@types/throttle-debounce": "5.0.2",
"@types/tinycolor2": "1.4.6",
"@types/toastify-js": "1.12.4",
- "@typescript-eslint/parser": "8.45.0",
+ "@typescript-eslint/parser": "8.46.0",
"@vitejs/plugin-vue": "6.0.1",
- "@vitest/eslint-plugin": "1.3.13",
- "eslint": "9.36.0",
+ "@vitest/eslint-plugin": "1.3.16",
+ "eslint": "9.37.0",
"eslint-import-resolver-typescript": "4.4.4",
"eslint-plugin-array-func": "5.1.0",
"eslint-plugin-github": "6.0.0",
@@ -96,23 +96,23 @@
"eslint-plugin-vue-scoped-css": "2.12.0",
"eslint-plugin-wc": "3.0.2",
"globals": "16.4.0",
- "happy-dom": "19.0.2",
+ "happy-dom": "20.0.2",
"markdownlint-cli": "0.45.0",
"material-icon-theme": "5.27.0",
"nolyfill": "1.0.44",
"postcss-html": "1.8.0",
"spectral-cli-bundle": "1.0.3",
- "stylelint": "16.24.0",
+ "stylelint": "16.25.0",
"stylelint-config-recommended": "17.0.0",
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
"stylelint-declaration-strict-value": "1.10.11",
"stylelint-value-no-unknown-custom-properties": "6.0.1",
"svgo": "4.0.0",
- "typescript-eslint": "8.45.0",
- "updates": "16.7.4",
+ "typescript-eslint": "8.46.0",
+ "updates": "16.8.0",
"vite-string-plugin": "1.4.6",
"vitest": "3.2.4",
- "vue-tsc": "3.1.0"
+ "vue-tsc": "3.1.1"
},
"browserslist": [
"defaults"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 376d70c506..c0950022e5 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -54,8 +54,8 @@ importers:
specifier: 0.1.0-alpha-3
version: 0.1.0-alpha-3
'@primer/octicons':
- specifier: 19.18.0
- version: 19.18.0
+ specifier: 19.19.0
+ version: 19.19.0
'@resvg/resvg-wasm':
specifier: 2.6.2
version: 2.6.2
@@ -64,16 +64,16 @@ importers:
version: 2.0.6(tippy.js@6.3.7)(vue@3.5.22(typescript@5.9.3))
'@techknowlogick/license-checker-webpack-plugin':
specifier: 0.3.0
- version: 0.3.0(webpack@5.102.0)
+ version: 0.3.0(webpack@5.102.1)
add-asset-webpack-plugin:
specifier: 3.1.1
- version: 3.1.1(webpack@5.102.0)
+ version: 3.1.1(webpack@5.102.1)
ansi_up:
specifier: 6.0.6
version: 6.0.6
asciinema-player:
- specifier: 3.10.0
- version: 3.10.0
+ specifier: 3.12.0
+ version: 3.12.0
chart.js:
specifier: 4.5.0
version: 4.5.0
@@ -91,7 +91,7 @@ importers:
version: 1.6.2
css-loader:
specifier: 7.1.2
- version: 7.1.2(webpack@5.102.0)
+ version: 7.1.2(webpack@5.102.1)
dayjs:
specifier: 1.11.18
version: 1.11.18
@@ -102,8 +102,8 @@ importers:
specifier: 2.20.0
version: 2.20.0
esbuild-loader:
- specifier: 4.3.0
- version: 4.3.0(webpack@5.102.0)
+ specifier: 4.4.0
+ version: 4.4.0(webpack@5.102.1)
htmx.org:
specifier: 2.0.7
version: 2.0.7
@@ -114,20 +114,20 @@ importers:
specifier: 3.7.1
version: 3.7.1
katex:
- specifier: 0.16.22
- version: 0.16.22
+ specifier: 0.16.23
+ version: 0.16.23
mermaid:
specifier: 11.12.0
version: 11.12.0
mini-css-extract-plugin:
specifier: 2.9.4
- version: 2.9.4(webpack@5.102.0)
+ version: 2.9.4(webpack@5.102.1)
monaco-editor:
- specifier: 0.53.0
- version: 0.53.0
+ specifier: 0.54.0
+ version: 0.54.0
monaco-editor-webpack-plugin:
- specifier: 7.1.0
- version: 7.1.0(monaco-editor@0.53.0)(webpack@5.102.0)
+ specifier: 7.1.1
+ version: 7.1.1(monaco-editor@0.54.0)(webpack@5.102.1)
online-3d-viewer:
specifier: 0.16.0
version: 0.16.0
@@ -142,13 +142,13 @@ importers:
version: 8.5.6
postcss-loader:
specifier: 8.2.0
- version: 8.2.0(postcss@8.5.6)(typescript@5.9.3)(webpack@5.102.0)
+ version: 8.2.0(postcss@8.5.6)(typescript@5.9.3)(webpack@5.102.1)
sortablejs:
specifier: 1.15.6
version: 1.15.6
swagger-ui-dist:
- specifier: 5.29.1
- version: 5.29.1
+ specifier: 5.29.4
+ version: 5.29.4
tailwindcss:
specifier: 3.4.17
version: 3.4.17
@@ -187,29 +187,29 @@ importers:
version: 5.3.2(chart.js@4.5.0)(vue@3.5.22(typescript@5.9.3))
vue-loader:
specifier: 17.4.2
- version: 17.4.2(vue@3.5.22(typescript@5.9.3))(webpack@5.102.0)
+ version: 17.4.2(vue@3.5.22(typescript@5.9.3))(webpack@5.102.1)
webpack:
- specifier: 5.102.0
- version: 5.102.0(webpack-cli@6.0.1)
+ specifier: 5.102.1
+ version: 5.102.1(webpack-cli@6.0.1)
webpack-cli:
specifier: 6.0.1
- version: 6.0.1(webpack@5.102.0)
+ version: 6.0.1(webpack@5.102.1)
wrap-ansi:
specifier: 9.0.2
version: 9.0.2
devDependencies:
'@eslint-community/eslint-plugin-eslint-comments':
specifier: 4.5.0
- version: 4.5.0(eslint@9.36.0(jiti@2.6.1))
+ version: 4.5.0(eslint@9.37.0(jiti@2.6.1))
'@playwright/test':
- specifier: 1.55.1
- version: 1.55.1
+ specifier: 1.56.0
+ version: 1.56.0
'@stylistic/eslint-plugin':
specifier: 5.4.0
- version: 5.4.0(eslint@9.36.0(jiti@2.6.1))
+ version: 5.4.0(eslint@9.37.0(jiti@2.6.1))
'@stylistic/stylelint-plugin':
specifier: 4.0.0
- version: 4.0.0(stylelint@16.24.0(typescript@5.9.3))
+ version: 4.0.0(stylelint@16.25.0(typescript@5.9.3))
'@types/codemirror':
specifier: 5.60.16
version: 5.60.16
@@ -241,59 +241,59 @@ importers:
specifier: 1.12.4
version: 1.12.4
'@typescript-eslint/parser':
- specifier: 8.45.0
- version: 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)
+ specifier: 8.46.0
+ version: 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)
'@vitejs/plugin-vue':
specifier: 6.0.1
- version: 6.0.1(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3))
+ version: 6.0.1(vite@7.1.9(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3))
'@vitest/eslint-plugin':
- specifier: 1.3.13
- version: 1.3.13(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.6.2)(happy-dom@19.0.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))
+ specifier: 1.3.16
+ version: 1.3.16(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.7.2)(happy-dom@20.0.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))
eslint:
- specifier: 9.36.0
- version: 9.36.0(jiti@2.6.1)
+ specifier: 9.37.0
+ version: 9.37.0(jiti@2.6.1)
eslint-import-resolver-typescript:
specifier: 4.4.4
- version: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.1)))(eslint-plugin-import@2.32.0)(eslint@9.36.0(jiti@2.6.1))
+ version: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.37.0(jiti@2.6.1)))(eslint-plugin-import@2.32.0)(eslint@9.37.0(jiti@2.6.1))
eslint-plugin-array-func:
specifier: 5.1.0
- version: 5.1.0(eslint@9.36.0(jiti@2.6.1))
+ version: 5.1.0(eslint@9.37.0(jiti@2.6.1))
eslint-plugin-github:
specifier: 6.0.0
- version: 6.0.0(@types/eslint@9.6.1)(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1))
+ version: 6.0.0(@types/eslint@9.6.1)(eslint-import-resolver-typescript@4.4.4)(eslint@9.37.0(jiti@2.6.1))
eslint-plugin-import-x:
specifier: 4.16.1
- version: 4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.1))
+ version: 4.16.1(@typescript-eslint/utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.37.0(jiti@2.6.1))
eslint-plugin-no-use-extend-native:
specifier: 0.7.2
- version: 0.7.2(eslint@9.36.0(jiti@2.6.1))
+ version: 0.7.2(eslint@9.37.0(jiti@2.6.1))
eslint-plugin-playwright:
specifier: 2.2.2
- version: 2.2.2(eslint@9.36.0(jiti@2.6.1))
+ version: 2.2.2(eslint@9.37.0(jiti@2.6.1))
eslint-plugin-regexp:
specifier: 2.10.0
- version: 2.10.0(eslint@9.36.0(jiti@2.6.1))
+ version: 2.10.0(eslint@9.37.0(jiti@2.6.1))
eslint-plugin-sonarjs:
specifier: 3.0.5
- version: 3.0.5(eslint@9.36.0(jiti@2.6.1))
+ version: 3.0.5(eslint@9.37.0(jiti@2.6.1))
eslint-plugin-unicorn:
specifier: 61.0.2
- version: 61.0.2(eslint@9.36.0(jiti@2.6.1))
+ version: 61.0.2(eslint@9.37.0(jiti@2.6.1))
eslint-plugin-vue:
specifier: 10.5.0
- version: 10.5.0(@stylistic/eslint-plugin@5.4.0(eslint@9.36.0(jiti@2.6.1)))(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.36.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.36.0(jiti@2.6.1)))
+ version: 10.5.0(@stylistic/eslint-plugin@5.4.0(eslint@9.37.0(jiti@2.6.1)))(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.37.0(jiti@2.6.1)))
eslint-plugin-vue-scoped-css:
specifier: 2.12.0
- version: 2.12.0(eslint@9.36.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.36.0(jiti@2.6.1)))
+ version: 2.12.0(eslint@9.37.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.37.0(jiti@2.6.1)))
eslint-plugin-wc:
specifier: 3.0.2
- version: 3.0.2(eslint@9.36.0(jiti@2.6.1))
+ version: 3.0.2(eslint@9.37.0(jiti@2.6.1))
globals:
specifier: 16.4.0
version: 16.4.0
happy-dom:
- specifier: 19.0.2
- version: 19.0.2
+ specifier: 20.0.2
+ version: 20.0.2
markdownlint-cli:
specifier: 0.45.0
version: 0.45.0
@@ -310,38 +310,38 @@ importers:
specifier: 1.0.3
version: 1.0.3
stylelint:
- specifier: 16.24.0
- version: 16.24.0(typescript@5.9.3)
+ specifier: 16.25.0
+ version: 16.25.0(typescript@5.9.3)
stylelint-config-recommended:
specifier: 17.0.0
- version: 17.0.0(stylelint@16.24.0(typescript@5.9.3))
+ version: 17.0.0(stylelint@16.25.0(typescript@5.9.3))
stylelint-declaration-block-no-ignored-properties:
specifier: 2.8.0
- version: 2.8.0(stylelint@16.24.0(typescript@5.9.3))
+ version: 2.8.0(stylelint@16.25.0(typescript@5.9.3))
stylelint-declaration-strict-value:
specifier: 1.10.11
- version: 1.10.11(stylelint@16.24.0(typescript@5.9.3))
+ version: 1.10.11(stylelint@16.25.0(typescript@5.9.3))
stylelint-value-no-unknown-custom-properties:
specifier: 6.0.1
- version: 6.0.1(stylelint@16.24.0(typescript@5.9.3))
+ version: 6.0.1(stylelint@16.25.0(typescript@5.9.3))
svgo:
specifier: 4.0.0
version: 4.0.0
typescript-eslint:
- specifier: 8.45.0
- version: 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)
+ specifier: 8.46.0
+ version: 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)
updates:
- specifier: 16.7.4
- version: 16.7.4
+ specifier: 16.8.0
+ version: 16.8.0
vite-string-plugin:
specifier: 1.4.6
version: 1.4.6
vitest:
specifier: 3.2.4
- version: 3.2.4(@types/debug@4.1.12)(@types/node@24.6.2)(happy-dom@19.0.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)
+ version: 3.2.4(@types/debug@4.1.12)(@types/node@24.7.2)(happy-dom@20.0.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)
vue-tsc:
- specifier: 3.1.0
- version: 3.1.0(typescript@5.9.3)
+ specifier: 3.1.1
+ version: 3.1.1(typescript@5.9.3)
packages:
@@ -352,8 +352,8 @@ packages:
'@antfu/install-pkg@1.1.0':
resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==}
- '@antfu/utils@9.2.1':
- resolution: {integrity: sha512-TMilPqXyii1AsiEii6l6ubRzbo76p6oshUSYPaKsmXDavyMLqjzVDkcp3pHp5ELMUNJHATcEOGxKTTsX9yYhGg==}
+ '@antfu/utils@9.3.0':
+ resolution: {integrity: sha512-9hFT4RauhcUzqOE4f1+frMKLZrgNog5b06I7VmZQV1BkvwvqrbC8EBZf3L1eEL2AKb6rNKjER0sEvJiSP1FXEA==}
'@babel/code-frame@7.27.1':
resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
@@ -389,8 +389,8 @@ packages:
'@cacheable/memory@2.0.3':
resolution: {integrity: sha512-R3UKy/CKOyb1LZG/VRCTMcpiMDyLH7SH3JrraRdK6kf3GweWCOU3sgvE13W3TiDRbxnDKylzKJvhUAvWl9LQOA==}
- '@cacheable/utils@2.0.3':
- resolution: {integrity: sha512-m7Rce68cMHlAUjvWBy9Ru1Nmw5gU0SjGGtQDdhpe6E0xnbcvrIY0Epy//JU1VYYBUTzrG9jvgmTauULGKzOkWA==}
+ '@cacheable/utils@2.1.0':
+ resolution: {integrity: sha512-ZdxfOiaarMqMj+H7qwlt5EBKWaeGihSYVHdQv5lUsbn8MJJOTW82OIwirQ39U5tMZkNvy3bQE+ryzC+xTAb9/g==}
'@chevrotain/cst-dts-gen@11.0.3':
resolution: {integrity: sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==}
@@ -679,8 +679,8 @@ packages:
resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/config-helpers@0.3.1':
- resolution: {integrity: sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==}
+ '@eslint/config-helpers@0.4.0':
+ resolution: {integrity: sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/core@0.15.2':
@@ -695,8 +695,8 @@ packages:
resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/js@9.36.0':
- resolution: {integrity: sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==}
+ '@eslint/js@9.37.0':
+ resolution: {integrity: sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/object-schema@2.1.6':
@@ -707,6 +707,10 @@ packages:
resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ '@eslint/plugin-kit@0.4.0':
+ resolution: {integrity: sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
'@github/browserslist-config@1.0.0':
resolution: {integrity: sha512-gIhjdJp/c2beaIWWIlsXdqXVRUz3r2BxBCpfz/F3JXHvSAQ1paMYjLH+maEATtENg+k5eLV7gA+9yPp762ieuw==}
@@ -775,8 +779,8 @@ packages:
'@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
- '@keyv/bigmap@1.0.2':
- resolution: {integrity: sha512-KR03xkEZlAZNF4IxXgVXb+uNIVNvwdh8UwI0cnc7WI6a+aQcDp8GL80qVfeB4E5NpsKJzou5jU0r6yLSSbMOtA==}
+ '@keyv/bigmap@1.0.3':
+ resolution: {integrity: sha512-jUEkNlnE9tYzX2AIBeoSe1gVUvSOfIOQ5EFPL5Un8cFHGvjD9L/fxpxlS1tEivRLHgapO2RZJ3D93HYAa049pg==}
engines: {node: '>= 18'}
'@keyv/serialize@1.1.1':
@@ -791,8 +795,8 @@ packages:
'@mcaptcha/vanilla-glue@0.1.0-alpha-3':
resolution: {integrity: sha512-GT6TJBgmViGXcXiT5VOr+h/6iOnThSlZuCoOWncubyTZU9R3cgU5vWPkF7G6Ob6ee2CBe3yqBxxk24CFVGTVXw==}
- '@mermaid-js/parser@0.6.2':
- resolution: {integrity: sha512-+PO02uGF6L6Cs0Bw8RpGhikVvMWEysfAyl27qTlroUB8jSWr1lL0Sf6zi78ZxlSnmgSY2AMMKVgghnN9jTtwkQ==}
+ '@mermaid-js/parser@0.6.3':
+ resolution: {integrity: sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==}
'@napi-rs/wasm-runtime@0.2.12':
resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
@@ -880,16 +884,16 @@ packages:
resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
- '@playwright/test@1.55.1':
- resolution: {integrity: sha512-IVAh/nOJaw6W9g+RJVlIQJ6gSiER+ae6mKQ5CX1bERzQgbC1VSeBlwdvczT7pxb0GWiyrxH4TGKbMfDb4Sq/ig==}
+ '@playwright/test@1.56.0':
+ resolution: {integrity: sha512-Tzh95Twig7hUwwNe381/K3PggZBZblKUe2wv25oIpzWLr6Z0m4KgV1ZVIjnR6GM9ANEqjZD7XsZEa6JL/7YEgg==}
engines: {node: '>=18'}
hasBin: true
'@popperjs/core@2.11.8':
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
- '@primer/octicons@19.18.0':
- resolution: {integrity: sha512-4P8FS7slUp0vHE7zLtlfOQcgF99r0tdxpriT3ahp6iwwnf1hF3OlDWXEp5n6b6G5eIY1cNr1bCrjRL+DkRjFVw==}
+ '@primer/octicons@19.19.0':
+ resolution: {integrity: sha512-LBbL8nOl6FWMDy7riKB5ppHLtffY7loRq+CDGj0D5G1Xdo2mKlSOQy3rWy2RVE8SxxPFL+mj46C1nG+smKBEZA==}
'@resvg/resvg-wasm@2.6.2':
resolution: {integrity: sha512-FqALmHI8D4o6lk/LRWDnhw95z5eO+eAa6ORjVg09YRR7BkcM6oPHU9uyC0gtQG5vpFLvgpeU4+zEAz2H8APHNw==}
@@ -898,113 +902,113 @@ packages:
'@rolldown/pluginutils@1.0.0-beta.29':
resolution: {integrity: sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==}
- '@rollup/rollup-android-arm-eabi@4.52.3':
- resolution: {integrity: sha512-h6cqHGZ6VdnwliFG1NXvMPTy/9PS3h8oLh7ImwR+kl+oYnQizgjxsONmmPSb2C66RksfkfIxEVtDSEcJiO0tqw==}
+ '@rollup/rollup-android-arm-eabi@4.52.4':
+ resolution: {integrity: sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==}
cpu: [arm]
os: [android]
- '@rollup/rollup-android-arm64@4.52.3':
- resolution: {integrity: sha512-wd+u7SLT/u6knklV/ifG7gr5Qy4GUbH2hMWcDauPFJzmCZUAJ8L2bTkVXC2niOIxp8lk3iH/QX8kSrUxVZrOVw==}
+ '@rollup/rollup-android-arm64@4.52.4':
+ resolution: {integrity: sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w==}
cpu: [arm64]
os: [android]
- '@rollup/rollup-darwin-arm64@4.52.3':
- resolution: {integrity: sha512-lj9ViATR1SsqycwFkJCtYfQTheBdvlWJqzqxwc9f2qrcVrQaF/gCuBRTiTolkRWS6KvNxSk4KHZWG7tDktLgjg==}
+ '@rollup/rollup-darwin-arm64@4.52.4':
+ resolution: {integrity: sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg==}
cpu: [arm64]
os: [darwin]
- '@rollup/rollup-darwin-x64@4.52.3':
- resolution: {integrity: sha512-+Dyo7O1KUmIsbzx1l+4V4tvEVnVQqMOIYtrxK7ncLSknl1xnMHLgn7gddJVrYPNZfEB8CIi3hK8gq8bDhb3h5A==}
+ '@rollup/rollup-darwin-x64@4.52.4':
+ resolution: {integrity: sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw==}
cpu: [x64]
os: [darwin]
- '@rollup/rollup-freebsd-arm64@4.52.3':
- resolution: {integrity: sha512-u9Xg2FavYbD30g3DSfNhxgNrxhi6xVG4Y6i9Ur1C7xUuGDW3banRbXj+qgnIrwRN4KeJ396jchwy9bCIzbyBEQ==}
+ '@rollup/rollup-freebsd-arm64@4.52.4':
+ resolution: {integrity: sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ==}
cpu: [arm64]
os: [freebsd]
- '@rollup/rollup-freebsd-x64@4.52.3':
- resolution: {integrity: sha512-5M8kyi/OX96wtD5qJR89a/3x5x8x5inXBZO04JWhkQb2JWavOWfjgkdvUqibGJeNNaz1/Z1PPza5/tAPXICI6A==}
+ '@rollup/rollup-freebsd-x64@4.52.4':
+ resolution: {integrity: sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw==}
cpu: [x64]
os: [freebsd]
- '@rollup/rollup-linux-arm-gnueabihf@4.52.3':
- resolution: {integrity: sha512-IoerZJ4l1wRMopEHRKOO16e04iXRDyZFZnNZKrWeNquh5d6bucjezgd+OxG03mOMTnS1x7hilzb3uURPkJ0OfA==}
+ '@rollup/rollup-linux-arm-gnueabihf@4.52.4':
+ resolution: {integrity: sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ==}
cpu: [arm]
os: [linux]
- '@rollup/rollup-linux-arm-musleabihf@4.52.3':
- resolution: {integrity: sha512-ZYdtqgHTDfvrJHSh3W22TvjWxwOgc3ThK/XjgcNGP2DIwFIPeAPNsQxrJO5XqleSlgDux2VAoWQ5iJrtaC1TbA==}
+ '@rollup/rollup-linux-arm-musleabihf@4.52.4':
+ resolution: {integrity: sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q==}
cpu: [arm]
os: [linux]
- '@rollup/rollup-linux-arm64-gnu@4.52.3':
- resolution: {integrity: sha512-NcViG7A0YtuFDA6xWSgmFb6iPFzHlf5vcqb2p0lGEbT+gjrEEz8nC/EeDHvx6mnGXnGCC1SeVV+8u+smj0CeGQ==}
+ '@rollup/rollup-linux-arm64-gnu@4.52.4':
+ resolution: {integrity: sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg==}
cpu: [arm64]
os: [linux]
- '@rollup/rollup-linux-arm64-musl@4.52.3':
- resolution: {integrity: sha512-d3pY7LWno6SYNXRm6Ebsq0DJGoiLXTb83AIPCXl9fmtIQs/rXoS8SJxxUNtFbJ5MiOvs+7y34np77+9l4nfFMw==}
+ '@rollup/rollup-linux-arm64-musl@4.52.4':
+ resolution: {integrity: sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g==}
cpu: [arm64]
os: [linux]
- '@rollup/rollup-linux-loong64-gnu@4.52.3':
- resolution: {integrity: sha512-3y5GA0JkBuirLqmjwAKwB0keDlI6JfGYduMlJD/Rl7fvb4Ni8iKdQs1eiunMZJhwDWdCvrcqXRY++VEBbvk6Eg==}
+ '@rollup/rollup-linux-loong64-gnu@4.52.4':
+ resolution: {integrity: sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ==}
cpu: [loong64]
os: [linux]
- '@rollup/rollup-linux-ppc64-gnu@4.52.3':
- resolution: {integrity: sha512-AUUH65a0p3Q0Yfm5oD2KVgzTKgwPyp9DSXc3UA7DtxhEb/WSPfbG4wqXeSN62OG5gSo18em4xv6dbfcUGXcagw==}
+ '@rollup/rollup-linux-ppc64-gnu@4.52.4':
+ resolution: {integrity: sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g==}
cpu: [ppc64]
os: [linux]
- '@rollup/rollup-linux-riscv64-gnu@4.52.3':
- resolution: {integrity: sha512-1makPhFFVBqZE+XFg3Dkq+IkQ7JvmUrwwqaYBL2CE+ZpxPaqkGaiWFEWVGyvTwZace6WLJHwjVh/+CXbKDGPmg==}
+ '@rollup/rollup-linux-riscv64-gnu@4.52.4':
+ resolution: {integrity: sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg==}
cpu: [riscv64]
os: [linux]
- '@rollup/rollup-linux-riscv64-musl@4.52.3':
- resolution: {integrity: sha512-OOFJa28dxfl8kLOPMUOQBCO6z3X2SAfzIE276fwT52uXDWUS178KWq0pL7d6p1kz7pkzA0yQwtqL0dEPoVcRWg==}
+ '@rollup/rollup-linux-riscv64-musl@4.52.4':
+ resolution: {integrity: sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA==}
cpu: [riscv64]
os: [linux]
- '@rollup/rollup-linux-s390x-gnu@4.52.3':
- resolution: {integrity: sha512-jMdsML2VI5l+V7cKfZx3ak+SLlJ8fKvLJ0Eoa4b9/vCUrzXKgoKxvHqvJ/mkWhFiyp88nCkM5S2v6nIwRtPcgg==}
+ '@rollup/rollup-linux-s390x-gnu@4.52.4':
+ resolution: {integrity: sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA==}
cpu: [s390x]
os: [linux]
- '@rollup/rollup-linux-x64-gnu@4.52.3':
- resolution: {integrity: sha512-tPgGd6bY2M2LJTA1uGq8fkSPK8ZLYjDjY+ZLK9WHncCnfIz29LIXIqUgzCR0hIefzy6Hpbe8Th5WOSwTM8E7LA==}
+ '@rollup/rollup-linux-x64-gnu@4.52.4':
+ resolution: {integrity: sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg==}
cpu: [x64]
os: [linux]
- '@rollup/rollup-linux-x64-musl@4.52.3':
- resolution: {integrity: sha512-BCFkJjgk+WFzP+tcSMXq77ymAPIxsX9lFJWs+2JzuZTLtksJ2o5hvgTdIcZ5+oKzUDMwI0PfWzRBYAydAHF2Mw==}
+ '@rollup/rollup-linux-x64-musl@4.52.4':
+ resolution: {integrity: sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw==}
cpu: [x64]
os: [linux]
- '@rollup/rollup-openharmony-arm64@4.52.3':
- resolution: {integrity: sha512-KTD/EqjZF3yvRaWUJdD1cW+IQBk4fbQaHYJUmP8N4XoKFZilVL8cobFSTDnjTtxWJQ3JYaMgF4nObY/+nYkumA==}
+ '@rollup/rollup-openharmony-arm64@4.52.4':
+ resolution: {integrity: sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA==}
cpu: [arm64]
os: [openharmony]
- '@rollup/rollup-win32-arm64-msvc@4.52.3':
- resolution: {integrity: sha512-+zteHZdoUYLkyYKObGHieibUFLbttX2r+58l27XZauq0tcWYYuKUwY2wjeCN9oK1Um2YgH2ibd6cnX/wFD7DuA==}
+ '@rollup/rollup-win32-arm64-msvc@4.52.4':
+ resolution: {integrity: sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ==}
cpu: [arm64]
os: [win32]
- '@rollup/rollup-win32-ia32-msvc@4.52.3':
- resolution: {integrity: sha512-of1iHkTQSo3kr6dTIRX6t81uj/c/b15HXVsPcEElN5sS859qHrOepM5p9G41Hah+CTqSh2r8Bm56dL2z9UQQ7g==}
+ '@rollup/rollup-win32-ia32-msvc@4.52.4':
+ resolution: {integrity: sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw==}
cpu: [ia32]
os: [win32]
- '@rollup/rollup-win32-x64-gnu@4.52.3':
- resolution: {integrity: sha512-s0hybmlHb56mWVZQj8ra9048/WZTPLILKxcvcq+8awSZmyiSUZjjem1AhU3Tf4ZKpYhK4mg36HtHDOe8QJS5PQ==}
+ '@rollup/rollup-win32-x64-gnu@4.52.4':
+ resolution: {integrity: sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ==}
cpu: [x64]
os: [win32]
- '@rollup/rollup-win32-x64-msvc@4.52.3':
- resolution: {integrity: sha512-zGIbEVVXVtauFgl3MRwGWEN36P5ZGenHRMgNw88X5wEhEBpq0XrMEZwOn07+ICrwM17XO5xfMZqh0OldCH5VTA==}
+ '@rollup/rollup-win32-x64-msvc@4.52.4':
+ resolution: {integrity: sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w==}
cpu: [x64]
os: [win32]
@@ -1024,6 +1028,21 @@ packages:
'@simonwep/pickr@1.9.0':
resolution: {integrity: sha512-oEYvv15PyfZzjoAzvXYt3UyNGwzsrpFxLaZKzkOSd0WYBVwLd19iJerePDONxC1iF6+DpcswPdLIM2KzCJuYFg==}
+ '@solid-primitives/refs@1.1.2':
+ resolution: {integrity: sha512-K7tf2thy7L+YJjdqXspXOg5xvNEOH8tgEWsp0+1mQk3obHBRD6hEjYZk7p7FlJphSZImS35je3UfmWuD7MhDfg==}
+ peerDependencies:
+ solid-js: ^1.6.12
+
+ '@solid-primitives/transition-group@1.1.2':
+ resolution: {integrity: sha512-gnHS0OmcdjeoHN9n7Khu8KNrOlRc8a2weETDt2YT6o1zeW/XtUC6Db3Q9pkMU/9cCKdEmN4b0a/41MKAHRhzWA==}
+ peerDependencies:
+ solid-js: ^1.6.12
+
+ '@solid-primitives/utils@6.3.2':
+ resolution: {integrity: sha512-hZ/M/qr25QOCcwDPOHtGjxTD8w2mNyVAYvcfgwzBHq2RwNqHNdDNsMZYap20+ruRwW4A3Cdkczyoz0TSxLCAPQ==}
+ peerDependencies:
+ solid-js: ^1.6.12
+
'@stylistic/eslint-plugin@5.4.0':
resolution: {integrity: sha512-UG8hdElzuBDzIbjG1QDwnYH0MQ73YLXDFHgZzB4Zh/YJfnw8XNsloVtytqzx0I2Qky9THSdpTmi8Vjn/pf/Lew==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -1188,11 +1207,11 @@ packages:
'@types/ms@2.1.0':
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
- '@types/node@20.19.19':
- resolution: {integrity: sha512-pb1Uqj5WJP7wrcbLU7Ru4QtA0+3kAXrkutGiD26wUKzSMgNNaPARTUDQmElUXp64kh3cWdou3Q0C7qwwxqSFmg==}
+ '@types/node@20.19.21':
+ resolution: {integrity: sha512-CsGG2P3I5y48RPMfprQGfy4JPRZ6csfC3ltBZSRItG3ngggmNY/qs2uZKp4p9VbrpqNNSMzUZNFZKzgOGnd/VA==}
- '@types/node@24.6.2':
- resolution: {integrity: sha512-d2L25Y4j+W3ZlNAeMKcy7yDsK425ibcAOO2t7aPTz6gNMH0z2GThtwENCDc0d/Pw9wgyRqE5Px1wkV7naz8ang==}
+ '@types/node@24.7.2':
+ resolution: {integrity: sha512-/NbVmcGTP+lj5oa4yiYxxeBjRivKQ5Ns1eSZeB99ExsEQ6rX5XYU1Zy/gGxY/ilqtD4Etx9mKyrPxZRetiahhA==}
'@types/pdfobject@2.2.5':
resolution: {integrity: sha512-7gD5tqc/RUDq0PyoLemL0vEHxBYi+zY0WVaFAx/Y0jBsXFgot1vB9No1GhDZGwRGJMCIZbgAb74QG9MTyTNU/g==}
@@ -1218,9 +1237,6 @@ packages:
'@types/toastify-js@1.12.4':
resolution: {integrity: sha512-zfZHU4tKffPCnZRe7pjv/eFKzTVHozKewFCKaCjZ4gFinKgJRz/t0bkZiMCXJxPhv/ZoeDGNOeRD09R0kQZ/nw==}
- '@types/trusted-types@1.0.6':
- resolution: {integrity: sha512-230RC8sFeHoT6sSUlRO6a8cAnclO06eeiq1QDfiv2FGCLWFvvERWgwIQD4FWqD9A69BN7Lzee4OXwoMVnnsWDw==}
-
'@types/trusted-types@2.0.7':
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
@@ -1230,63 +1246,63 @@ packages:
'@types/whatwg-mimetype@3.0.2':
resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==}
- '@typescript-eslint/eslint-plugin@8.45.0':
- resolution: {integrity: sha512-HC3y9CVuevvWCl/oyZuI47dOeDF9ztdMEfMH8/DW/Mhwa9cCLnK1oD7JoTVGW/u7kFzNZUKUoyJEqkaJh5y3Wg==}
+ '@typescript-eslint/eslint-plugin@8.46.0':
+ resolution: {integrity: sha512-hA8gxBq4ukonVXPy0OKhiaUh/68D0E88GSmtC1iAEnGaieuDi38LhS7jdCHRLi6ErJBNDGCzvh5EnzdPwUc0DA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
- '@typescript-eslint/parser': ^8.45.0
+ '@typescript-eslint/parser': ^8.46.0
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/parser@8.45.0':
- resolution: {integrity: sha512-TGf22kon8KW+DeKaUmOibKWktRY8b2NSAZNdtWh798COm1NWx8+xJ6iFBtk3IvLdv6+LGLJLRlyhrhEDZWargQ==}
+ '@typescript-eslint/parser@8.46.0':
+ resolution: {integrity: sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/project-service@8.45.0':
- resolution: {integrity: sha512-3pcVHwMG/iA8afdGLMuTibGR7pDsn9RjDev6CCB+naRsSYs2pns5QbinF4Xqw6YC/Sj3lMrm/Im0eMfaa61WUg==}
+ '@typescript-eslint/project-service@8.46.0':
+ resolution: {integrity: sha512-OEhec0mH+U5Je2NZOeK1AbVCdm0ChyapAyTeXVIYTPXDJ3F07+cu87PPXcGoYqZ7M9YJVvFnfpGg1UmCIqM+QQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/scope-manager@8.45.0':
- resolution: {integrity: sha512-clmm8XSNj/1dGvJeO6VGH7EUSeA0FMs+5au/u3lrA3KfG8iJ4u8ym9/j2tTEoacAffdW1TVUzXO30W1JTJS7dA==}
+ '@typescript-eslint/scope-manager@8.46.0':
+ resolution: {integrity: sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/tsconfig-utils@8.45.0':
- resolution: {integrity: sha512-aFdr+c37sc+jqNMGhH+ajxPXwjv9UtFZk79k8pLoJ6p4y0snmYpPA52GuWHgt2ZF4gRRW6odsEj41uZLojDt5w==}
+ '@typescript-eslint/tsconfig-utils@8.46.0':
+ resolution: {integrity: sha512-WrYXKGAHY836/N7zoK/kzi6p8tXFhasHh8ocFL9VZSAkvH956gfeRfcnhs3xzRy8qQ/dq3q44v1jvQieMFg2cw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/type-utils@8.45.0':
- resolution: {integrity: sha512-bpjepLlHceKgyMEPglAeULX1vixJDgaKocp0RVJ5u4wLJIMNuKtUXIczpJCPcn2waII0yuvks/5m5/h3ZQKs0A==}
+ '@typescript-eslint/type-utils@8.46.0':
+ resolution: {integrity: sha512-hy+lvYV1lZpVs2jRaEYvgCblZxUoJiPyCemwbQZ+NGulWkQRy0HRPYAoef/CNSzaLt+MLvMptZsHXHlkEilaeg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/types@8.45.0':
- resolution: {integrity: sha512-WugXLuOIq67BMgQInIxxnsSyRLFxdkJEJu8r4ngLR56q/4Q5LrbfkFRH27vMTjxEK8Pyz7QfzuZe/G15qQnVRA==}
+ '@typescript-eslint/types@8.46.0':
+ resolution: {integrity: sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/typescript-estree@8.45.0':
- resolution: {integrity: sha512-GfE1NfVbLam6XQ0LcERKwdTTPlLvHvXXhOeUGC1OXi4eQBoyy1iVsW+uzJ/J9jtCz6/7GCQ9MtrQ0fml/jWCnA==}
+ '@typescript-eslint/typescript-estree@8.46.0':
+ resolution: {integrity: sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/utils@8.45.0':
- resolution: {integrity: sha512-bxi1ht+tLYg4+XV2knz/F7RVhU0k6VrSMc9sb8DQ6fyCTrGQLHfo7lDtN0QJjZjKkLA2ThrKuCdHEvLReqtIGg==}
+ '@typescript-eslint/utils@8.46.0':
+ resolution: {integrity: sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/visitor-keys@8.45.0':
- resolution: {integrity: sha512-qsaFBA3e09MIDAGFUrTk+dzqtfv1XPVz8t8d1f0ybTzrCY7BKiMC5cjrl1O/P7UmHsNyW90EYSkU/ZWpmXelag==}
+ '@typescript-eslint/visitor-keys@8.46.0':
+ resolution: {integrity: sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@unrs/resolver-binding-android-arm-eabi@1.11.1':
@@ -1391,8 +1407,8 @@ packages:
vite: ^5.0.0 || ^6.0.0 || ^7.0.0
vue: ^3.2.25
- '@vitest/eslint-plugin@1.3.13':
- resolution: {integrity: sha512-QfzXd1+lCY3dIqPHOZlagA2bJYoWC5yAU3adv8Gks0rHAL6FpyXKYBiyMCuU6mRrbKUMphGqwDQobinOvYgJig==}
+ '@vitest/eslint-plugin@1.3.16':
+ resolution: {integrity: sha512-EvXGiZpz3L1G/pmebcmMe61UzqgR8LFwmm+QGgQEHcrTCFkMgl+c0mj2jneo38/CkHhofbK3zc3xafV6/SpzNw==}
peerDependencies:
eslint: '>= 8.57.0'
typescript: '>= 5.0.0'
@@ -1453,8 +1469,8 @@ packages:
'@vue/compiler-ssr@3.5.22':
resolution: {integrity: sha512-GdgyLvg4R+7T8Nk2Mlighx7XGxq/fJf9jaVofc3IL0EPesTE86cP/8DD1lT3h1JeZr2ySBvyqKQJgbS54IX1Ww==}
- '@vue/language-core@3.1.0':
- resolution: {integrity: sha512-a7ns+X9vTbdmk7QLrvnZs8s4E1wwtxG/sELzr6F2j4pU+r/OoAv6jJGSz+5tVTU6e4+3rjepGhSP8jDmBBcb3w==}
+ '@vue/language-core@3.1.1':
+ resolution: {integrity: sha512-qjMY3Q+hUCjdH+jLrQapqgpsJ0rd/2mAY02lZoHG3VFJZZZKLjAlV+Oo9QmWIT4jh8+Rx8RUGUi++d7T9Wb6Mw==}
peerDependencies:
typescript: '*'
peerDependenciesMeta:
@@ -1645,8 +1661,8 @@ packages:
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
engines: {node: '>=8'}
- asciinema-player@3.10.0:
- resolution: {integrity: sha512-shoOK6F606nDKZxDVM7JuGSCAyWLePoGRFNlV+FqiP5Sqvyn0BlE7wlbjZyd2X4P1iRhv/HKfVNtnQIxmgphRA==}
+ asciinema-player@3.12.0:
+ resolution: {integrity: sha512-qKaqcN4gkssF5shAk0SOyREJfMAFmmek0cYUmx+qVDGTUKIEA2oU5mXCRFgszYAJqu2kyGlu20BYhr9mH7mmpQ==}
assertion-error@2.0.1:
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
@@ -1664,8 +1680,8 @@ packages:
engines: {node: '>= 4.5.0'}
hasBin: true
- axe-core@4.10.3:
- resolution: {integrity: sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==}
+ axe-core@4.11.0:
+ resolution: {integrity: sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==}
engines: {node: '>=4'}
axobject-query@4.1.0:
@@ -1681,8 +1697,8 @@ packages:
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
- baseline-browser-mapping@2.8.10:
- resolution: {integrity: sha512-uLfgBi+7IBNay8ECBO2mVMGZAc1VgZWEChxm4lv+TobGdG82LnXMjuNGo/BSSZZL4UmkWhxEHP2f5ziLNwGWMA==}
+ baseline-browser-mapping@2.8.16:
+ resolution: {integrity: sha512-OMu3BGQ4E7P1ErFsIPpbJh0qvDudM/UuJeHgkAvfWe+0HFJCXh+t/l8L6fVLR55RI/UbKrVLnAXZSVwd9ysWYw==}
hasBin: true
big.js@5.2.2:
@@ -1732,8 +1748,8 @@ packages:
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
engines: {node: '>=8'}
- cacheable@2.0.3:
- resolution: {integrity: sha512-nZF80J3d8RMrroMSYm1E9pBllVDXWPuECZgEZxH+vusCY4MAXAJVrY0jutcHSgh3xYX3G2EUNnmtWGZVVjWCXw==}
+ cacheable@2.1.0:
+ resolution: {integrity: sha512-zzL1BxdnqwD69JRT0dihnawAcLkBMwAH+hZSKjUzeBbPedVhk3qYPjRw9VOMYWwt5xRih5xd8S+3kEdGohZm/g==}
callsites@3.1.0:
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
@@ -1743,8 +1759,8 @@ packages:
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
engines: {node: '>= 6'}
- caniuse-lite@1.0.30001746:
- resolution: {integrity: sha512-eA7Ys/DGw+pnkWWSE/id29f2IcPHVoE8wxtvE5JdvD2V28VTDPy1yEeo11Guz0sJ4ZeGRcm3uaTcAqK1LXaphA==}
+ caniuse-lite@1.0.30001750:
+ resolution: {integrity: sha512-cuom0g5sdX6rw00qOoLNSFCJ9/mYIsuSOA+yzpDw8eopiFqcVwQvZHqov0vmEighRxX++cfC0Vg1G+1Iy/mSpQ==}
chai@5.3.3:
resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==}
@@ -1805,8 +1821,8 @@ packages:
resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==}
engines: {node: '>=6.0'}
- ci-info@4.3.0:
- resolution: {integrity: sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==}
+ ci-info@4.3.1:
+ resolution: {integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==}
engines: {node: '>=8'}
citeproc@2.4.63:
@@ -1882,8 +1898,8 @@ packages:
confbox@0.2.2:
resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==}
- core-js-compat@3.45.1:
- resolution: {integrity: sha512-tqTt5T4PzsMIZ430XGviK4vzYSoeNJ6CXODi6c/voxOT6IZqBht5/EKaSNnYiEjjRYxjVz7DQIsOsY0XNi8PIA==}
+ core-js-compat@3.46.0:
+ resolution: {integrity: sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==}
core-js@3.32.2:
resolution: {integrity: sha512-pxXSw1mYZPDGvTQqEc5vgIb83jGQKFGYWY76z4a7weZXUolw3G+OvpZqSRcfYOoOVUQJYEPsWeQK8pKEnUtWxQ==}
@@ -2194,6 +2210,9 @@ packages:
resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
engines: {node: '>= 4'}
+ dompurify@3.1.7:
+ resolution: {integrity: sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==}
+
dompurify@3.2.7:
resolution: {integrity: sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==}
@@ -2209,8 +2228,8 @@ packages:
easymde@2.20.0:
resolution: {integrity: sha512-V1Z5f92TfR42Na852OWnIZMbM7zotWQYTddNaLYZFVKj7APBbyZ3FYJ27gBw2grMW3R6Qdv9J8n5Ij7XRSIgXQ==}
- electron-to-chromium@1.5.228:
- resolution: {integrity: sha512-nxkiyuqAn4MJ1QbobwqJILiDtu/jk14hEAWaMiJmNPh1Z+jqoFlBFZjdXwLWGeVSeu9hGLg6+2G9yJaW8rBIFA==}
+ electron-to-chromium@1.5.234:
+ resolution: {integrity: sha512-RXfEp2x+VRYn8jbKfQlRImzoJU01kyDvVPBmG39eU2iuRVhuS6vQNocB8J0/8GrIMLnPzgz4eW6WiRnJkTuNWg==}
emoji-regex@10.5.0:
resolution: {integrity: sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==}
@@ -2237,8 +2256,8 @@ packages:
resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
engines: {node: '>=6'}
- envinfo@7.15.0:
- resolution: {integrity: sha512-chR+t7exF6y59kelhXw5I3849nTy7KIRO+ePdLMhCD+JRP/JvmkenDWP7QSFGlsHX+kxGxdDutOPrmj5j1HR6g==}
+ envinfo@7.17.0:
+ resolution: {integrity: sha512-GpfViocsFM7viwClFgxK26OtjMlKN67GCR5v6ASFkotxtpBWd9d+vNy+AH7F2E1TUkMDZ8P/dDPZX71/NG8xnQ==}
engines: {node: '>=4'}
hasBin: true
@@ -2248,8 +2267,8 @@ packages:
es-module-lexer@1.7.0:
resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
- esbuild-loader@4.3.0:
- resolution: {integrity: sha512-D7HeJNdkDKKMarPQO/3dlJT6RwN2YJO7ENU6RPlpOz5YxSHnUNi2yvW41Bckvi1EVwctIaLzlb0ni5ag2GINYA==}
+ esbuild-loader@4.4.0:
+ resolution: {integrity: sha512-4J+hXTpTtEdzUNLoY8ReqDNJx2NoldfiljRCiKbeYUuZmVaiJeDqFgyAzz8uOopaekwRoCcqBFyEroGQLFVZ1g==}
peerDependencies:
webpack: ^4.40.0 || ^5.0.0
@@ -2483,8 +2502,8 @@ packages:
resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- eslint@9.36.0:
- resolution: {integrity: sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==}
+ eslint@9.37.0:
+ resolution: {integrity: sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
hasBin: true
peerDependencies:
@@ -2643,8 +2662,8 @@ packages:
resolution: {integrity: sha512-YCmOj+4YAeEB5Dd9jfp6ETdejMet4zSxXjNkgaa4npBEKRI9uDOGB5MmAdAgi2OoFGAKshYhCbmLq2DS03CgVA==}
engines: {node: '>=18.0.0'}
- get-tsconfig@4.10.1:
- resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==}
+ get-tsconfig@4.12.0:
+ resolution: {integrity: sha512-LScr2aNr2FbjAjZh2C6X6BxRx1/x+aTDExct/xyq2XKbYOiG5c0aK7pMsSuyc0brz3ibr/lbQiHD9jzt4lccJw==}
glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
@@ -2714,8 +2733,8 @@ packages:
resolution: {integrity: sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==}
engines: {node: '>=0.8.0'}
- happy-dom@19.0.2:
- resolution: {integrity: sha512-831CLbgDyjRbd2lApHZFsBDe56onuFcjsCBPodzWpzedTpeDr8CGZjs7iEIdNW1DVwSFRecfwzLpVyGBPamwGA==}
+ happy-dom@20.0.2:
+ resolution: {integrity: sha512-pYOyu624+6HDbY+qkjILpQGnpvZOusItCk+rvF5/V+6NkcgTKnbOldpIy22tBnxoaLtlM9nXgoqAcW29/B7CIw==}
engines: {node: '>=20.0.0'}
has-flag@4.0.0:
@@ -2981,8 +3000,8 @@ packages:
just-extend@5.1.1:
resolution: {integrity: sha512-b+z6yF1d4EOyDgylzQo5IminlUmzSeqR1hs/bzjBNjuGras4FXq/6TrzjxfN0j+TmI0ltJzTNlqXUMCniciwKQ==}
- katex@0.16.22:
- resolution: {integrity: sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==}
+ katex@0.16.23:
+ resolution: {integrity: sha512-7VlC1hsEEolL9xNO05v9VjrvWZePkCVBJqj8ruICxYjZfHaHbaU53AlP+PODyFIXEnaEIEWi3wJy7FPZ95JAVg==}
hasBin: true
keyv@4.5.4:
@@ -3039,8 +3058,8 @@ packages:
linkify-it@5.0.0:
resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==}
- loader-runner@4.3.0:
- resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==}
+ loader-runner@4.3.1:
+ resolution: {integrity: sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==}
engines: {node: '>=6.11.5'}
loader-utils@2.0.4:
@@ -3116,8 +3135,13 @@ packages:
resolution: {integrity: sha512-xaSxkaU7wY/0852zGApM8LdlIfGCW8ETZ0Rr62IQtAnUMlMuifsg09vWJcNYeL4f0anvr8Vo4ZQar8jGpV0btQ==}
engines: {node: '>=20'}
- marked@16.3.0:
- resolution: {integrity: sha512-K3UxuKu6l6bmA5FUwYho8CfJBlsUWAooKtdGgMcERSpF7gcBUrCGsLH7wDaaNOzwq18JzSUDyoEb/YsrqMac3w==}
+ marked@14.0.0:
+ resolution: {integrity: sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==}
+ engines: {node: '>= 18'}
+ hasBin: true
+
+ marked@16.4.0:
+ resolution: {integrity: sha512-CTPAcRBq57cn3R8n3hwc2REddc28hjR7RzDXQ+lXLmMJYqn20BaI2cGw6QjgZGIgVfp2Wdfw4aMzgNteQ6qJgQ==}
engines: {node: '>= 20'}
hasBin: true
@@ -3270,14 +3294,14 @@ packages:
mlly@1.8.0:
resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==}
- monaco-editor-webpack-plugin@7.1.0:
- resolution: {integrity: sha512-ZjnGINHN963JQkFqjjcBtn1XBtUATDZBMgNQhDQwd78w2ukRhFXAPNgWuacaQiDZsUr4h1rWv5Mv6eriKuOSzA==}
+ monaco-editor-webpack-plugin@7.1.1:
+ resolution: {integrity: sha512-WxdbFHS3Wtz4V9hzhe/Xog5hQRSMxmDLkEEYZwqMDHgJlkZo00HVFZR0j5d0nKypjTUkkygH3dDSXERLG4757A==}
peerDependencies:
monaco-editor: '>= 0.31.0'
webpack: ^4.5.0 || 5.x
- monaco-editor@0.53.0:
- resolution: {integrity: sha512-0WNThgC6CMWNXXBxTbaYYcunj08iB5rnx4/G56UOPeL9UVIUGGHA1GR0EWIh9Ebabj7NpCRawQ5b0hfN1jQmYQ==}
+ monaco-editor@0.54.0:
+ resolution: {integrity: sha512-hx45SEUoLatgWxHKCmlLJH81xBo0uXP4sRkESUpmDQevfi+e7K1VuiSprK6UpQ8u4zOcKNiH0pMvHvlMWA/4cw==}
moo@0.5.2:
resolution: {integrity: sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==}
@@ -3299,8 +3323,8 @@ packages:
nanopop@2.3.0:
resolution: {integrity: sha512-fzN+T2K7/Ah25XU02MJkPZ5q4Tj5FpjmIYq4rvoHX4yb16HzFdCO6JxFFn5Y/oBhQ8no8fUZavnyIv9/+xkBBw==}
- napi-postinstall@0.3.3:
- resolution: {integrity: sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==}
+ napi-postinstall@0.3.4:
+ resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
hasBin: true
@@ -3328,8 +3352,8 @@ packages:
encoding:
optional: true
- node-releases@2.0.21:
- resolution: {integrity: sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==}
+ node-releases@2.0.23:
+ resolution: {integrity: sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==}
nolyfill@1.0.44:
resolution: {integrity: sha512-PoggwVLiJUn0MnodpftsiC7EuknW5+6v62ntTOQ6T6l7g2r6aoaOwgk0tQW2BxGLYw9bF298LL8jDFTmEFuzlA==}
@@ -3388,8 +3412,8 @@ packages:
package-json-from-dist@1.0.1:
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
- package-manager-detector@1.3.0:
- resolution: {integrity: sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==}
+ package-manager-detector@1.4.0:
+ resolution: {integrity: sha512-rRZ+pR1Usc+ND9M2NkmCvE/LYJS+8ORVV9X0KuNSY/gFsp7RBHJM/ADh9LYq4Vvfq6QkKrW6/weuh8SMEtN5gw==}
parent-module@1.0.1:
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
@@ -3477,13 +3501,13 @@ packages:
pkg-types@2.3.0:
resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==}
- playwright-core@1.55.1:
- resolution: {integrity: sha512-Z6Mh9mkwX+zxSlHqdr5AOcJnfp+xUWLCt9uKV18fhzA8eyxUd8NUWzAjxUh55RZKSYwDGX0cfaySdhZJGMoJ+w==}
+ playwright-core@1.56.0:
+ resolution: {integrity: sha512-1SXl7pMfemAMSDn5rkPeZljxOCYAmQnYLBTExuh6E8USHXGSX3dx6lYZN/xPpTz1vimXmPA9CDnILvmJaB8aSQ==}
engines: {node: '>=18'}
hasBin: true
- playwright@1.55.1:
- resolution: {integrity: sha512-cJW4Xd/G3v5ovXtJJ52MAOclqeac9S/aGGgRzLabuF8TnIb6xHvMzKIa6JmrRzUkeXJgfL1MhukP0NK6l39h3A==}
+ playwright@1.56.0:
+ resolution: {integrity: sha512-X5Q1b8lOdWIE4KAoHpW3SE8HvUB+ZZsUoN64ZhjnN8dOb1UpujxBtENGiZFE+9F/yhzJwYa+ca3u43FeLbboHA==}
engines: {node: '>=18'}
hasBin: true
@@ -3633,6 +3657,10 @@ packages:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
+ qified@0.5.0:
+ resolution: {integrity: sha512-Zj6Q/Vc/SQ+Fzc87N90jJUzBzxD7MVQ2ZvGyMmYtnl2u1a07CejAhvtk4ZwASos+SiHKCAIylyGHJKIek75QBw==}
+ engines: {node: '>=20'}
+
quansync@0.2.11:
resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==}
@@ -3704,8 +3732,8 @@ packages:
robust-predicates@3.0.2:
resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==}
- rollup@4.52.3:
- resolution: {integrity: sha512-RIDh866U8agLgiIcdpB+COKnlCreHJLfIhWC3LVflku5YHfpnsIKigRZeFfMfCc4dVcqNVfQQ5gO/afOck064A==}
+ rollup@4.52.4:
+ resolution: {integrity: sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
@@ -3728,8 +3756,8 @@ packages:
sax@1.4.1:
resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==}
- schema-utils@4.3.2:
- resolution: {integrity: sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==}
+ schema-utils@4.3.3:
+ resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==}
engines: {node: '>= 10.13.0'}
scslre@0.3.0:
@@ -3745,6 +3773,11 @@ packages:
engines: {node: '>=10'}
hasBin: true
+ semver@7.7.3:
+ resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==}
+ engines: {node: '>=10'}
+ hasBin: true
+
serialize-javascript@6.0.2:
resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==}
@@ -3792,6 +3825,12 @@ packages:
solid-js@1.9.9:
resolution: {integrity: sha512-A0ZBPJQldAeGCTW0YRYJmt7RCeh5rbFfPZ2aOttgYnctHE7HgKeHCBB/PVc2P7eOfmNXqMFFFoYYdm3S4dcbkA==}
+ solid-transition-group@0.2.3:
+ resolution: {integrity: sha512-iB72c9N5Kz9ykRqIXl0lQohOau4t0dhel9kjwFvx81UZJbVwaChMuBuyhiZmK24b8aKEK0w3uFM96ZxzcyZGdg==}
+ engines: {node: '>=18.0.0', pnpm: '>=8.6.0'}
+ peerDependencies:
+ solid-js: ^1.6.12
+
sortablejs@1.15.6:
resolution: {integrity: sha512-aNfiuwMEpfBM/CN6LY0ibyhxPfPbyFeBTYJKCvzkJ2GkUpazIt3H+QIPAMHwqQ7tMKaHz1Qj+rJJCqljnf4p3A==}
@@ -3915,8 +3954,8 @@ packages:
peerDependencies:
stylelint: '>=16'
- stylelint@16.24.0:
- resolution: {integrity: sha512-7ksgz3zJaSbTUGr/ujMXvLVKdDhLbGl3R/3arNudH7z88+XZZGNLMTepsY28WlnvEFcuOmUe7fg40Q3lfhOfSQ==}
+ stylelint@16.25.0:
+ resolution: {integrity: sha512-Li0avYWV4nfv1zPbdnxLYBGq4z8DVZxbRgx4Kn6V+Uftz1rMoF1qiEI3oL4kgWqyYgCgs7gT5maHNZ82Gk03vQ==}
engines: {node: '>=18.12.0'}
hasBin: true
@@ -3965,8 +4004,8 @@ packages:
svgson@5.3.1:
resolution: {integrity: sha512-qdPgvUNWb40gWktBJnbJRelWcPzkLed/ShhnRsjbayXz8OtdPOzbil9jtiZdrYvSDumAz/VNQr6JaNfPx/gvPA==}
- swagger-ui-dist@5.29.1:
- resolution: {integrity: sha512-qyjpz0qgcomRr41a5Aye42o69TKwCeHM9F8htLGVeUMKekNS6qAqz9oS7CtSvgGJSppSNAYAIh7vrfrSdHj9zw==}
+ swagger-ui-dist@5.29.4:
+ resolution: {integrity: sha512-gJFDz/gyLOCQtWwAgqs6Rk78z9ONnqTnlW11gimG9nLap8drKa3AJBKpzIQMIjl5PD2Ix+Tn+mc/tfoT2tgsng==}
sync-fetch@0.4.5:
resolution: {integrity: sha512-esiWJ7ixSKGpd9DJPBTC4ckChqdOjIwJfYhVHkcQ2Gnm41323p1TRmEI+esTQ9ppD+b5opps2OTEGTCGX5kF+g==}
@@ -3985,8 +4024,8 @@ packages:
engines: {node: '>=14.0.0'}
hasBin: true
- tapable@2.2.3:
- resolution: {integrity: sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==}
+ tapable@2.3.0:
+ resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==}
engines: {node: '>=6'}
terser-webpack-plugin@5.3.14:
@@ -4095,8 +4134,8 @@ packages:
resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
engines: {node: '>=10'}
- typescript-eslint@8.45.0:
- resolution: {integrity: sha512-qzDmZw/Z5beNLUrXfd0HIW6MzIaAV5WNDxmMs9/3ojGOpYavofgNAAD/nC6tGV2PczIi0iw8vot2eAe/sBn7zg==}
+ typescript-eslint@8.46.0:
+ resolution: {integrity: sha512-6+ZrB6y2bT2DX3K+Qd9vn7OFOJR+xSLDj+Aw/N3zBwUt27uTw2sw2TE2+UcY1RiyBZkaGbTkVg9SSdPNUG6aUw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
@@ -4122,8 +4161,8 @@ packages:
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
- undici-types@7.13.0:
- resolution: {integrity: sha512-Ov2Rr9Sx+fRgagJ5AX0qvItZG/JKKoBRAVITs1zk7IqZGTJUwgUr7qoYBpWwakpWilTZFM98rG/AFRocu10iIQ==}
+ undici-types@7.14.0:
+ resolution: {integrity: sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==}
unrs-resolver@1.11.1:
resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==}
@@ -4134,8 +4173,8 @@ packages:
peerDependencies:
browserslist: '>= 4.21.0'
- updates@16.7.4:
- resolution: {integrity: sha512-w8nMoQRFKL7iVTUBUF9pP9lxqe/vqQfxljKcCmY0pKwofXqGEUr3OUQznsGa62V6pvFvg097pm4jT4eDdPq6ow==}
+ updates@16.8.0:
+ resolution: {integrity: sha512-iKLehaYwcz9sdL/PIYX+V0quBl0hGXXqwLGPy/jlLOrXdFdz15QtE7kxtJATJhH2oPOi7+Y3VcL2rY90IU4L4g==}
engines: {node: '>=20'}
hasBin: true
@@ -4160,8 +4199,8 @@ packages:
vite-string-plugin@1.4.6:
resolution: {integrity: sha512-Csjtny8/uVIynzlaRRj4RpHrPAakNwlH9jw6kgQ8tQhc2f0zzA6bCbAgWD0y84EgB8aLNrz7pZFUqSt3LOtk+w==}
- vite@7.1.7:
- resolution: {integrity: sha512-VbA8ScMvAISJNJVbRDTJdCwqQoAareR/wutevKanhR2/1EkoXVZVkkORaYm/tNVCjP/UDTKtcw3bAkwOUdedmA==}
+ vite@7.1.9:
+ resolution: {integrity: sha512-4nVGliEpxmhCL8DslSAUdxlB6+SMrhB0a1v5ijlh1xB1nEPuy1mxaHxysVucLHuWryAxLWg6a5ei+U4TLn/rFg==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
peerDependencies:
@@ -4278,8 +4317,8 @@ packages:
vue:
optional: true
- vue-tsc@3.1.0:
- resolution: {integrity: sha512-fbMynMG7kXSnqZTRBSCh9ROYaVpXfCZbEO0gY3lqOjLbp361uuS88n6BDajiUriDIF+SGLWoinjvf6stS2J3Gg==}
+ vue-tsc@3.1.1:
+ resolution: {integrity: sha512-fyixKxFniOVgn+L/4+g8zCG6dflLLt01Agz9jl3TO45Bgk87NZJRmJVPsiK+ouq3LB91jJCbOV+pDkzYTxbI7A==}
hasBin: true
peerDependencies:
typescript: '>=5.0.0'
@@ -4324,8 +4363,8 @@ packages:
resolution: {integrity: sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==}
engines: {node: '>=10.13.0'}
- webpack@5.102.0:
- resolution: {integrity: sha512-hUtqAR3ZLVEYDEABdBioQCIqSoguHbFn1K7WlPPWSuXmx0031BD73PSE35jKyftdSh4YLDoQNgK4pqBt5Q82MA==}
+ webpack@5.102.1:
+ resolution: {integrity: sha512-7h/weGm9d/ywQ6qzJ+Xy+r9n/3qgp/thalBbpOi5i223dPXKi04IBtqPN9nTd+jBc7QKfvDbaBnFipYp4sJAUQ==}
engines: {node: '>=10.13.0'}
hasBin: true
peerDependencies:
@@ -4410,10 +4449,10 @@ snapshots:
'@antfu/install-pkg@1.1.0':
dependencies:
- package-manager-detector: 1.3.0
+ package-manager-detector: 1.4.0
tinyexec: 1.0.1
- '@antfu/utils@9.2.1': {}
+ '@antfu/utils@9.3.0': {}
'@babel/code-frame@7.27.1':
dependencies:
@@ -4440,17 +4479,19 @@ snapshots:
'@cacheable/memoize@2.0.3':
dependencies:
- '@cacheable/utils': 2.0.3
+ '@cacheable/utils': 2.1.0
'@cacheable/memory@2.0.3':
dependencies:
'@cacheable/memoize': 2.0.3
- '@cacheable/utils': 2.0.3
- '@keyv/bigmap': 1.0.2
+ '@cacheable/utils': 2.1.0
+ '@keyv/bigmap': 1.0.3
hookified: 1.12.1
keyv: 5.5.3
- '@cacheable/utils@2.0.3': {}
+ '@cacheable/utils@2.1.0':
+ dependencies:
+ keyv: 5.5.3
'@chevrotain/cst-dts-gen@11.0.3':
dependencies:
@@ -4640,24 +4681,24 @@ snapshots:
'@esbuild/win32-x64@0.25.10':
optional: true
- '@eslint-community/eslint-plugin-eslint-comments@4.5.0(eslint@9.36.0(jiti@2.6.1))':
+ '@eslint-community/eslint-plugin-eslint-comments@4.5.0(eslint@9.37.0(jiti@2.6.1))':
dependencies:
escape-string-regexp: 4.0.0
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
ignore: 5.3.2
- '@eslint-community/eslint-utils@4.9.0(eslint@9.36.0(jiti@2.6.1))':
+ '@eslint-community/eslint-utils@4.9.0(eslint@9.37.0(jiti@2.6.1))':
dependencies:
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
eslint-visitor-keys: 3.4.3
'@eslint-community/regexpp@4.12.1': {}
- '@eslint/compat@1.4.0(eslint@9.36.0(jiti@2.6.1))':
+ '@eslint/compat@1.4.0(eslint@9.37.0(jiti@2.6.1))':
dependencies:
'@eslint/core': 0.16.0
optionalDependencies:
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
'@eslint/config-array@0.21.0':
dependencies:
@@ -4667,7 +4708,9 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@eslint/config-helpers@0.3.1': {}
+ '@eslint/config-helpers@0.4.0':
+ dependencies:
+ '@eslint/core': 0.16.0
'@eslint/core@0.15.2':
dependencies:
@@ -4691,7 +4734,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@eslint/js@9.36.0': {}
+ '@eslint/js@9.37.0': {}
'@eslint/object-schema@2.1.6': {}
@@ -4700,6 +4743,11 @@ snapshots:
'@eslint/core': 0.15.2
levn: 0.4.1
+ '@eslint/plugin-kit@0.4.0':
+ dependencies:
+ '@eslint/core': 0.16.0
+ levn: 0.4.1
+
'@github/browserslist-config@1.0.0': {}
'@github/combobox-nav@2.3.1': {}
@@ -4731,7 +4779,7 @@ snapshots:
'@iconify/utils@3.0.2':
dependencies:
'@antfu/install-pkg': 1.1.0
- '@antfu/utils': 9.2.1
+ '@antfu/utils': 9.3.0
'@iconify/types': 2.0.0
debug: 4.4.3
globals: 15.15.0
@@ -4775,7 +4823,7 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
- '@keyv/bigmap@1.0.2':
+ '@keyv/bigmap@1.0.3':
dependencies:
hookified: 1.12.1
@@ -4789,7 +4837,7 @@ snapshots:
dependencies:
'@mcaptcha/core-glue': 0.1.0-alpha-5
- '@mermaid-js/parser@0.6.2':
+ '@mermaid-js/parser@0.6.3':
dependencies:
langium: 3.3.1
@@ -4869,13 +4917,13 @@ snapshots:
'@pkgr/core@0.2.9': {}
- '@playwright/test@1.55.1':
+ '@playwright/test@1.56.0':
dependencies:
- playwright: 1.55.1
+ playwright: 1.56.0
'@popperjs/core@2.11.8': {}
- '@primer/octicons@19.18.0':
+ '@primer/octicons@19.19.0':
dependencies:
object-assign: 4.1.1
@@ -4883,70 +4931,70 @@ snapshots:
'@rolldown/pluginutils@1.0.0-beta.29': {}
- '@rollup/rollup-android-arm-eabi@4.52.3':
+ '@rollup/rollup-android-arm-eabi@4.52.4':
optional: true
- '@rollup/rollup-android-arm64@4.52.3':
+ '@rollup/rollup-android-arm64@4.52.4':
optional: true
- '@rollup/rollup-darwin-arm64@4.52.3':
+ '@rollup/rollup-darwin-arm64@4.52.4':
optional: true
- '@rollup/rollup-darwin-x64@4.52.3':
+ '@rollup/rollup-darwin-x64@4.52.4':
optional: true
- '@rollup/rollup-freebsd-arm64@4.52.3':
+ '@rollup/rollup-freebsd-arm64@4.52.4':
optional: true
- '@rollup/rollup-freebsd-x64@4.52.3':
+ '@rollup/rollup-freebsd-x64@4.52.4':
optional: true
- '@rollup/rollup-linux-arm-gnueabihf@4.52.3':
+ '@rollup/rollup-linux-arm-gnueabihf@4.52.4':
optional: true
- '@rollup/rollup-linux-arm-musleabihf@4.52.3':
+ '@rollup/rollup-linux-arm-musleabihf@4.52.4':
optional: true
- '@rollup/rollup-linux-arm64-gnu@4.52.3':
+ '@rollup/rollup-linux-arm64-gnu@4.52.4':
optional: true
- '@rollup/rollup-linux-arm64-musl@4.52.3':
+ '@rollup/rollup-linux-arm64-musl@4.52.4':
optional: true
- '@rollup/rollup-linux-loong64-gnu@4.52.3':
+ '@rollup/rollup-linux-loong64-gnu@4.52.4':
optional: true
- '@rollup/rollup-linux-ppc64-gnu@4.52.3':
+ '@rollup/rollup-linux-ppc64-gnu@4.52.4':
optional: true
- '@rollup/rollup-linux-riscv64-gnu@4.52.3':
+ '@rollup/rollup-linux-riscv64-gnu@4.52.4':
optional: true
- '@rollup/rollup-linux-riscv64-musl@4.52.3':
+ '@rollup/rollup-linux-riscv64-musl@4.52.4':
optional: true
- '@rollup/rollup-linux-s390x-gnu@4.52.3':
+ '@rollup/rollup-linux-s390x-gnu@4.52.4':
optional: true
- '@rollup/rollup-linux-x64-gnu@4.52.3':
+ '@rollup/rollup-linux-x64-gnu@4.52.4':
optional: true
- '@rollup/rollup-linux-x64-musl@4.52.3':
+ '@rollup/rollup-linux-x64-musl@4.52.4':
optional: true
- '@rollup/rollup-openharmony-arm64@4.52.3':
+ '@rollup/rollup-openharmony-arm64@4.52.4':
optional: true
- '@rollup/rollup-win32-arm64-msvc@4.52.3':
+ '@rollup/rollup-win32-arm64-msvc@4.52.4':
optional: true
- '@rollup/rollup-win32-ia32-msvc@4.52.3':
+ '@rollup/rollup-win32-ia32-msvc@4.52.4':
optional: true
- '@rollup/rollup-win32-x64-gnu@4.52.3':
+ '@rollup/rollup-win32-x64-gnu@4.52.4':
optional: true
- '@rollup/rollup-win32-x64-msvc@4.52.3':
+ '@rollup/rollup-win32-x64-msvc@4.52.4':
optional: true
'@rtsao/scc@1.1.0': {}
@@ -4963,17 +5011,30 @@ snapshots:
core-js: 3.32.2
nanopop: 2.3.0
- '@stylistic/eslint-plugin@5.4.0(eslint@9.36.0(jiti@2.6.1))':
+ '@solid-primitives/refs@1.1.2(solid-js@1.9.9)':
dependencies:
- '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1))
- '@typescript-eslint/types': 8.45.0
- eslint: 9.36.0(jiti@2.6.1)
+ '@solid-primitives/utils': 6.3.2(solid-js@1.9.9)
+ solid-js: 1.9.9
+
+ '@solid-primitives/transition-group@1.1.2(solid-js@1.9.9)':
+ dependencies:
+ solid-js: 1.9.9
+
+ '@solid-primitives/utils@6.3.2(solid-js@1.9.9)':
+ dependencies:
+ solid-js: 1.9.9
+
+ '@stylistic/eslint-plugin@5.4.0(eslint@9.37.0(jiti@2.6.1))':
+ dependencies:
+ '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1))
+ '@typescript-eslint/types': 8.46.0
+ eslint: 9.37.0(jiti@2.6.1)
eslint-visitor-keys: 4.2.1
espree: 10.4.0
estraverse: 5.3.0
picomatch: 4.0.3
- '@stylistic/stylelint-plugin@4.0.0(stylelint@16.24.0(typescript@5.9.3))':
+ '@stylistic/stylelint-plugin@4.0.0(stylelint@16.25.0(typescript@5.9.3))':
dependencies:
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
'@csstools/css-tokenizer': 3.0.4
@@ -4982,11 +5043,11 @@ snapshots:
postcss-selector-parser: 7.1.0
postcss-value-parser: 4.2.0
style-search: 0.1.0
- stylelint: 16.24.0(typescript@5.9.3)
+ stylelint: 16.25.0(typescript@5.9.3)
'@swc/helpers@0.2.14': {}
- '@techknowlogick/license-checker-webpack-plugin@0.3.0(webpack@5.102.0)':
+ '@techknowlogick/license-checker-webpack-plugin@0.3.0(webpack@5.102.1)':
dependencies:
glob: 7.2.3
lodash: 4.17.21
@@ -4995,7 +5056,7 @@ snapshots:
spdx-expression-validate: 2.0.0
spdx-satisfies: 5.0.1
superstruct: 0.10.13
- webpack: 5.102.0(webpack-cli@6.0.1)
+ webpack: 5.102.1(webpack-cli@6.0.1)
webpack-sources: 1.4.3
wrap-ansi: 6.2.0
@@ -5169,13 +5230,13 @@ snapshots:
'@types/ms@2.1.0': {}
- '@types/node@20.19.19':
+ '@types/node@20.19.21':
dependencies:
undici-types: 6.21.0
- '@types/node@24.6.2':
+ '@types/node@24.7.2':
dependencies:
- undici-types: 7.13.0
+ undici-types: 7.14.0
'@types/pdfobject@2.2.5': {}
@@ -5195,8 +5256,6 @@ snapshots:
'@types/toastify-js@1.12.4': {}
- '@types/trusted-types@1.0.6': {}
-
'@types/trusted-types@2.0.7':
optional: true
@@ -5204,15 +5263,15 @@ snapshots:
'@types/whatwg-mimetype@3.0.2': {}
- '@typescript-eslint/eslint-plugin@8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)':
+ '@typescript-eslint/eslint-plugin@8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
'@eslint-community/regexpp': 4.12.1
- '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/scope-manager': 8.45.0
- '@typescript-eslint/type-utils': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/visitor-keys': 8.45.0
- eslint: 9.36.0(jiti@2.6.1)
+ '@typescript-eslint/parser': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/scope-manager': 8.46.0
+ '@typescript-eslint/type-utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/visitor-keys': 8.46.0
+ eslint: 9.37.0(jiti@2.6.1)
graphemer: 1.4.0
ignore: 7.0.5
natural-compare: 1.4.0
@@ -5221,80 +5280,80 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)':
+ '@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
- '@typescript-eslint/scope-manager': 8.45.0
- '@typescript-eslint/types': 8.45.0
- '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.3)
- '@typescript-eslint/visitor-keys': 8.45.0
+ '@typescript-eslint/scope-manager': 8.46.0
+ '@typescript-eslint/types': 8.46.0
+ '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3)
+ '@typescript-eslint/visitor-keys': 8.46.0
debug: 4.4.3
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/project-service@8.45.0(typescript@5.9.3)':
+ '@typescript-eslint/project-service@8.46.0(typescript@5.9.3)':
dependencies:
- '@typescript-eslint/tsconfig-utils': 8.45.0(typescript@5.9.3)
- '@typescript-eslint/types': 8.45.0
+ '@typescript-eslint/tsconfig-utils': 8.46.0(typescript@5.9.3)
+ '@typescript-eslint/types': 8.46.0
debug: 4.4.3
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/scope-manager@8.45.0':
+ '@typescript-eslint/scope-manager@8.46.0':
dependencies:
- '@typescript-eslint/types': 8.45.0
- '@typescript-eslint/visitor-keys': 8.45.0
+ '@typescript-eslint/types': 8.46.0
+ '@typescript-eslint/visitor-keys': 8.46.0
- '@typescript-eslint/tsconfig-utils@8.45.0(typescript@5.9.3)':
+ '@typescript-eslint/tsconfig-utils@8.46.0(typescript@5.9.3)':
dependencies:
typescript: 5.9.3
- '@typescript-eslint/type-utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)':
+ '@typescript-eslint/type-utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
- '@typescript-eslint/types': 8.45.0
- '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.3)
- '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/types': 8.46.0
+ '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)
debug: 4.4.3
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
ts-api-utils: 2.1.0(typescript@5.9.3)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/types@8.45.0': {}
+ '@typescript-eslint/types@8.46.0': {}
- '@typescript-eslint/typescript-estree@8.45.0(typescript@5.9.3)':
+ '@typescript-eslint/typescript-estree@8.46.0(typescript@5.9.3)':
dependencies:
- '@typescript-eslint/project-service': 8.45.0(typescript@5.9.3)
- '@typescript-eslint/tsconfig-utils': 8.45.0(typescript@5.9.3)
- '@typescript-eslint/types': 8.45.0
- '@typescript-eslint/visitor-keys': 8.45.0
+ '@typescript-eslint/project-service': 8.46.0(typescript@5.9.3)
+ '@typescript-eslint/tsconfig-utils': 8.46.0(typescript@5.9.3)
+ '@typescript-eslint/types': 8.46.0
+ '@typescript-eslint/visitor-keys': 8.46.0
debug: 4.4.3
fast-glob: 3.3.3
is-glob: 4.0.3
minimatch: 9.0.5
- semver: 7.7.2
+ semver: 7.7.3
ts-api-utils: 2.1.0(typescript@5.9.3)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)':
+ '@typescript-eslint/utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)':
dependencies:
- '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1))
- '@typescript-eslint/scope-manager': 8.45.0
- '@typescript-eslint/types': 8.45.0
- '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.3)
- eslint: 9.36.0(jiti@2.6.1)
+ '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1))
+ '@typescript-eslint/scope-manager': 8.46.0
+ '@typescript-eslint/types': 8.46.0
+ '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3)
+ eslint: 9.37.0(jiti@2.6.1)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/visitor-keys@8.45.0':
+ '@typescript-eslint/visitor-keys@8.46.0':
dependencies:
- '@typescript-eslint/types': 8.45.0
+ '@typescript-eslint/types': 8.46.0
eslint-visitor-keys: 4.2.1
'@unrs/resolver-binding-android-arm-eabi@1.11.1':
@@ -5356,20 +5415,20 @@ snapshots:
'@unrs/resolver-binding-win32-x64-msvc@1.11.1':
optional: true
- '@vitejs/plugin-vue@6.0.1(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3))':
+ '@vitejs/plugin-vue@6.0.1(vite@7.1.9(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3))':
dependencies:
'@rolldown/pluginutils': 1.0.0-beta.29
- vite: 7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)
+ vite: 7.1.9(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)
vue: 3.5.22(typescript@5.9.3)
- '@vitest/eslint-plugin@1.3.13(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.6.2)(happy-dom@19.0.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))':
+ '@vitest/eslint-plugin@1.3.16(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.7.2)(happy-dom@20.0.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))':
dependencies:
- '@typescript-eslint/scope-manager': 8.45.0
- '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)
- eslint: 9.36.0(jiti@2.6.1)
+ '@typescript-eslint/scope-manager': 8.46.0
+ '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)
+ eslint: 9.37.0(jiti@2.6.1)
optionalDependencies:
typescript: 5.9.3
- vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.6.2)(happy-dom@19.0.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)
+ vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.7.2)(happy-dom@20.0.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)
transitivePeerDependencies:
- supports-color
@@ -5381,13 +5440,13 @@ snapshots:
chai: 5.3.3
tinyrainbow: 2.0.0
- '@vitest/mocker@3.2.4(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))':
+ '@vitest/mocker@3.2.4(vite@7.1.9(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))':
dependencies:
'@vitest/spy': 3.2.4
estree-walker: 3.0.3
magic-string: 0.30.19
optionalDependencies:
- vite: 7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)
+ vite: 7.1.9(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)
'@vitest/pretty-format@3.2.4':
dependencies:
@@ -5457,7 +5516,7 @@ snapshots:
'@vue/compiler-dom': 3.5.22
'@vue/shared': 3.5.22
- '@vue/language-core@3.1.0(typescript@5.9.3)':
+ '@vue/language-core@3.1.1(typescript@5.9.3)':
dependencies:
'@volar/language-core': 2.4.23
'@vue/compiler-dom': 3.5.22
@@ -5569,20 +5628,20 @@ snapshots:
'@webassemblyjs/ast': 1.14.1
'@xtuc/long': 4.2.2
- '@webpack-cli/configtest@3.0.1(webpack-cli@6.0.1)(webpack@5.102.0)':
+ '@webpack-cli/configtest@3.0.1(webpack-cli@6.0.1)(webpack@5.102.1)':
dependencies:
- webpack: 5.102.0(webpack-cli@6.0.1)
- webpack-cli: 6.0.1(webpack@5.102.0)
+ webpack: 5.102.1(webpack-cli@6.0.1)
+ webpack-cli: 6.0.1(webpack@5.102.1)
- '@webpack-cli/info@3.0.1(webpack-cli@6.0.1)(webpack@5.102.0)':
+ '@webpack-cli/info@3.0.1(webpack-cli@6.0.1)(webpack@5.102.1)':
dependencies:
- webpack: 5.102.0(webpack-cli@6.0.1)
- webpack-cli: 6.0.1(webpack@5.102.0)
+ webpack: 5.102.1(webpack-cli@6.0.1)
+ webpack-cli: 6.0.1(webpack@5.102.1)
- '@webpack-cli/serve@3.0.1(webpack-cli@6.0.1)(webpack@5.102.0)':
+ '@webpack-cli/serve@3.0.1(webpack-cli@6.0.1)(webpack@5.102.1)':
dependencies:
- webpack: 5.102.0(webpack-cli@6.0.1)
- webpack-cli: 6.0.1(webpack@5.102.0)
+ webpack: 5.102.1(webpack-cli@6.0.1)
+ webpack-cli: 6.0.1(webpack@5.102.1)
'@xtuc/ieee754@1.2.0': {}
@@ -5598,9 +5657,9 @@ snapshots:
acorn@8.15.0: {}
- add-asset-webpack-plugin@3.1.1(webpack@5.102.0):
+ add-asset-webpack-plugin@3.1.1(webpack@5.102.1):
optionalDependencies:
- webpack: 5.102.0(webpack-cli@6.0.1)
+ webpack: 5.102.1(webpack-cli@6.0.1)
ajv-formats@2.1.1(ajv@8.17.1):
optionalDependencies:
@@ -5656,10 +5715,11 @@ snapshots:
array-union@2.1.0: {}
- asciinema-player@3.10.0:
+ asciinema-player@3.12.0:
dependencies:
'@babel/runtime': 7.28.4
solid-js: 1.9.9
+ solid-transition-group: 0.2.3(solid-js@1.9.9)
assertion-error@2.0.1: {}
@@ -5669,7 +5729,7 @@ snapshots:
atob@2.1.2: {}
- axe-core@4.10.3: {}
+ axe-core@4.11.0: {}
axobject-query@4.1.0: {}
@@ -5679,7 +5739,7 @@ snapshots:
base64-js@1.5.1: {}
- baseline-browser-mapping@2.8.10: {}
+ baseline-browser-mapping@2.8.16: {}
big.js@5.2.2: {}
@@ -5702,10 +5762,10 @@ snapshots:
browserslist@4.26.3:
dependencies:
- baseline-browser-mapping: 2.8.10
- caniuse-lite: 1.0.30001746
- electron-to-chromium: 1.5.228
- node-releases: 2.0.21
+ baseline-browser-mapping: 2.8.16
+ caniuse-lite: 1.0.30001750
+ electron-to-chromium: 1.5.234
+ node-releases: 2.0.23
update-browserslist-db: 1.1.3(browserslist@4.26.3)
buffer-from@1.1.2: {}
@@ -5723,19 +5783,20 @@ snapshots:
cac@6.7.14: {}
- cacheable@2.0.3:
+ cacheable@2.1.0:
dependencies:
'@cacheable/memoize': 2.0.3
'@cacheable/memory': 2.0.3
- '@cacheable/utils': 2.0.3
+ '@cacheable/utils': 2.1.0
hookified: 1.12.1
keyv: 5.5.3
+ qified: 0.5.0
callsites@3.1.0: {}
camelcase-css@2.0.1: {}
- caniuse-lite@1.0.30001746: {}
+ caniuse-lite@1.0.30001750: {}
chai@5.3.3:
dependencies:
@@ -5805,7 +5866,7 @@ snapshots:
chrome-trace-event@1.0.4: {}
- ci-info@4.3.0: {}
+ ci-info@4.3.1: {}
citeproc@2.4.63: {}
@@ -5859,7 +5920,7 @@ snapshots:
confbox@0.2.2: {}
- core-js-compat@3.45.1:
+ core-js-compat@3.46.0:
dependencies:
browserslist: 4.26.3
@@ -5892,7 +5953,7 @@ snapshots:
css-functions-list@3.2.3: {}
- css-loader@7.1.2(webpack@5.102.0):
+ css-loader@7.1.2(webpack@5.102.1):
dependencies:
icss-utils: 5.1.0(postcss@8.5.6)
postcss: 8.5.6
@@ -5901,9 +5962,9 @@ snapshots:
postcss-modules-scope: 3.2.1(postcss@8.5.6)
postcss-modules-values: 4.0.0(postcss@8.5.6)
postcss-value-parser: 4.2.0
- semver: 7.7.2
+ semver: 7.7.3
optionalDependencies:
- webpack: 5.102.0(webpack-cli@6.0.1)
+ webpack: 5.102.1(webpack-cli@6.0.1)
css-select@5.2.2:
dependencies:
@@ -6188,6 +6249,8 @@ snapshots:
dependencies:
domelementtype: 2.3.0
+ dompurify@3.1.7: {}
+
dompurify@3.2.7:
optionalDependencies:
'@types/trusted-types': 2.0.7
@@ -6213,7 +6276,7 @@ snapshots:
codemirror-spell-checker: 1.1.2
marked: 4.3.0
- electron-to-chromium@1.5.228: {}
+ electron-to-chromium@1.5.234: {}
emoji-regex@10.5.0: {}
@@ -6226,13 +6289,13 @@ snapshots:
enhanced-resolve@5.18.3:
dependencies:
graceful-fs: 4.2.11
- tapable: 2.2.3
+ tapable: 2.3.0
entities@4.5.0: {}
env-paths@2.2.1: {}
- envinfo@7.15.0: {}
+ envinfo@7.17.0: {}
error-ex@1.3.4:
dependencies:
@@ -6240,12 +6303,12 @@ snapshots:
es-module-lexer@1.7.0: {}
- esbuild-loader@4.3.0(webpack@5.102.0):
+ esbuild-loader@4.4.0(webpack@5.102.1):
dependencies:
esbuild: 0.25.10
- get-tsconfig: 4.10.1
+ get-tsconfig: 4.12.0
loader-utils: 2.0.4
- webpack: 5.102.0(webpack-cli@6.0.1)
+ webpack: 5.102.1(webpack-cli@6.0.1)
webpack-sources: 1.4.3
esbuild@0.25.10:
@@ -6283,18 +6346,18 @@ snapshots:
escape-string-regexp@4.0.0: {}
- eslint-compat-utils@0.6.5(eslint@9.36.0(jiti@2.6.1)):
+ eslint-compat-utils@0.6.5(eslint@9.37.0(jiti@2.6.1)):
dependencies:
- eslint: 9.36.0(jiti@2.6.1)
- semver: 7.7.2
+ eslint: 9.37.0(jiti@2.6.1)
+ semver: 7.7.3
- eslint-config-prettier@10.1.8(eslint@9.36.0(jiti@2.6.1)):
+ eslint-config-prettier@10.1.8(eslint@9.37.0(jiti@2.6.1)):
dependencies:
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
eslint-import-context@0.1.9(unrs-resolver@1.11.1):
dependencies:
- get-tsconfig: 4.10.1
+ get-tsconfig: 4.12.0
stable-hash-x: 0.2.0
optionalDependencies:
unrs-resolver: 1.11.1
@@ -6307,111 +6370,111 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.1)))(eslint-plugin-import@2.32.0)(eslint@9.36.0(jiti@2.6.1)):
+ eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.37.0(jiti@2.6.1)))(eslint-plugin-import@2.32.0)(eslint@9.37.0(jiti@2.6.1)):
dependencies:
debug: 4.4.3
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
eslint-import-context: 0.1.9(unrs-resolver@1.11.1)
- get-tsconfig: 4.10.1
+ get-tsconfig: 4.12.0
is-bun-module: 2.0.0
stable-hash-x: 0.2.0
tinyglobby: 0.2.15
unrs-resolver: 1.11.1
optionalDependencies:
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1))
- eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.1))
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.37.0(jiti@2.6.1))
+ eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.37.0(jiti@2.6.1))
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.12.1(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1)):
+ eslint-module-utils@2.12.1(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.37.0(jiti@2.6.1)):
dependencies:
debug: 3.2.7
optionalDependencies:
- '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)
- eslint: 9.36.0(jiti@2.6.1)
+ '@typescript-eslint/parser': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)
+ eslint: 9.37.0(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.1)))(eslint-plugin-import@2.32.0)(eslint@9.36.0(jiti@2.6.1))
+ eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.37.0(jiti@2.6.1)))(eslint-plugin-import@2.32.0)(eslint@9.37.0(jiti@2.6.1))
transitivePeerDependencies:
- supports-color
- eslint-plugin-array-func@5.1.0(eslint@9.36.0(jiti@2.6.1)):
+ eslint-plugin-array-func@5.1.0(eslint@9.37.0(jiti@2.6.1)):
dependencies:
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
- eslint-plugin-escompat@3.11.4(eslint@9.36.0(jiti@2.6.1)):
+ eslint-plugin-escompat@3.11.4(eslint@9.37.0(jiti@2.6.1)):
dependencies:
browserslist: 4.26.3
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
- eslint-plugin-eslint-comments@3.2.0(eslint@9.36.0(jiti@2.6.1)):
+ eslint-plugin-eslint-comments@3.2.0(eslint@9.37.0(jiti@2.6.1)):
dependencies:
escape-string-regexp: 1.0.5
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
ignore: 5.3.2
- eslint-plugin-filenames@1.3.2(eslint@9.36.0(jiti@2.6.1)):
+ eslint-plugin-filenames@1.3.2(eslint@9.37.0(jiti@2.6.1)):
dependencies:
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
lodash.camelcase: 4.3.0
lodash.kebabcase: 4.1.1
lodash.snakecase: 4.1.1
lodash.upperfirst: 4.3.1
- eslint-plugin-github@6.0.0(@types/eslint@9.6.1)(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1)):
+ eslint-plugin-github@6.0.0(@types/eslint@9.6.1)(eslint-import-resolver-typescript@4.4.4)(eslint@9.37.0(jiti@2.6.1)):
dependencies:
- '@eslint/compat': 1.4.0(eslint@9.36.0(jiti@2.6.1))
+ '@eslint/compat': 1.4.0(eslint@9.37.0(jiti@2.6.1))
'@eslint/eslintrc': 3.3.1
- '@eslint/js': 9.36.0
+ '@eslint/js': 9.37.0
'@github/browserslist-config': 1.0.0
- '@typescript-eslint/eslint-plugin': 8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/eslint-plugin': 8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/parser': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)
aria-query: 5.3.2
- eslint: 9.36.0(jiti@2.6.1)
- eslint-config-prettier: 10.1.8(eslint@9.36.0(jiti@2.6.1))
- eslint-plugin-escompat: 3.11.4(eslint@9.36.0(jiti@2.6.1))
- eslint-plugin-eslint-comments: 3.2.0(eslint@9.36.0(jiti@2.6.1))
- eslint-plugin-filenames: 1.3.2(eslint@9.36.0(jiti@2.6.1))
- eslint-plugin-i18n-text: 1.0.1(eslint@9.36.0(jiti@2.6.1))
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1))
- eslint-plugin-jsx-a11y: 6.10.2(eslint@9.36.0(jiti@2.6.1))
+ eslint: 9.37.0(jiti@2.6.1)
+ eslint-config-prettier: 10.1.8(eslint@9.37.0(jiti@2.6.1))
+ eslint-plugin-escompat: 3.11.4(eslint@9.37.0(jiti@2.6.1))
+ eslint-plugin-eslint-comments: 3.2.0(eslint@9.37.0(jiti@2.6.1))
+ eslint-plugin-filenames: 1.3.2(eslint@9.37.0(jiti@2.6.1))
+ eslint-plugin-i18n-text: 1.0.1(eslint@9.37.0(jiti@2.6.1))
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.37.0(jiti@2.6.1))
+ eslint-plugin-jsx-a11y: 6.10.2(eslint@9.37.0(jiti@2.6.1))
eslint-plugin-no-only-tests: 3.3.0
- eslint-plugin-prettier: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.36.0(jiti@2.6.1)))(eslint@9.36.0(jiti@2.6.1))(prettier@3.6.2)
+ eslint-plugin-prettier: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.37.0(jiti@2.6.1)))(eslint@9.37.0(jiti@2.6.1))(prettier@3.6.2)
eslint-rule-documentation: 1.0.23
globals: 16.4.0
jsx-ast-utils: 3.3.5
prettier: 3.6.2
svg-element-attributes: 1.3.1
typescript: 5.9.3
- typescript-eslint: 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)
+ typescript-eslint: 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)
transitivePeerDependencies:
- '@types/eslint'
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
- supports-color
- eslint-plugin-i18n-text@1.0.1(eslint@9.36.0(jiti@2.6.1)):
+ eslint-plugin-i18n-text@1.0.1(eslint@9.37.0(jiti@2.6.1)):
dependencies:
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
- eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.1)):
+ eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.37.0(jiti@2.6.1)):
dependencies:
- '@typescript-eslint/types': 8.45.0
+ '@typescript-eslint/types': 8.46.0
comment-parser: 1.4.1
debug: 4.4.3
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
eslint-import-context: 0.1.9(unrs-resolver@1.11.1)
is-glob: 4.0.3
minimatch: 10.0.3
- semver: 7.7.2
+ semver: 7.7.3
stable-hash-x: 0.2.0
unrs-resolver: 1.11.1
optionalDependencies:
- '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)
eslint-import-resolver-node: 0.3.9
transitivePeerDependencies:
- supports-color
- eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1)):
+ eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.37.0(jiti@2.6.1)):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: '@nolyfill/array-includes@1.0.44'
@@ -6420,9 +6483,9 @@ snapshots:
array.prototype.flatmap: '@nolyfill/array.prototype.flatmap@1.0.44'
debug: 3.2.7
doctrine: 2.1.0
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1))
+ eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.37.0(jiti@2.6.1))
hasown: '@nolyfill/hasown@1.0.44'
is-core-module: '@nolyfill/is-core-module@1.0.39'
is-glob: 4.0.3
@@ -6434,23 +6497,23 @@ snapshots:
string.prototype.trimend: '@nolyfill/string.prototype.trimend@1.0.44'
tsconfig-paths: 3.15.0
optionalDependencies:
- '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/parser': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
- supports-color
- eslint-plugin-jsx-a11y@6.10.2(eslint@9.36.0(jiti@2.6.1)):
+ eslint-plugin-jsx-a11y@6.10.2(eslint@9.37.0(jiti@2.6.1)):
dependencies:
aria-query: 5.3.2
array-includes: '@nolyfill/array-includes@1.0.44'
array.prototype.flatmap: '@nolyfill/array.prototype.flatmap@1.0.44'
ast-types-flow: 0.0.8
- axe-core: 4.10.3
+ axe-core: 4.11.0
axobject-query: 4.1.0
damerau-levenshtein: 1.0.8
emoji-regex: 9.2.2
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
hasown: '@nolyfill/hasown@1.0.44'
jsx-ast-utils: 3.3.5
language-tags: 1.0.9
@@ -6461,46 +6524,46 @@ snapshots:
eslint-plugin-no-only-tests@3.3.0: {}
- eslint-plugin-no-use-extend-native@0.7.2(eslint@9.36.0(jiti@2.6.1)):
+ eslint-plugin-no-use-extend-native@0.7.2(eslint@9.37.0(jiti@2.6.1)):
dependencies:
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
is-get-set-prop: 2.0.0
is-js-type: 3.0.0
is-obj-prop: 2.0.0
is-proto-prop: 3.0.1
- eslint-plugin-playwright@2.2.2(eslint@9.36.0(jiti@2.6.1)):
+ eslint-plugin-playwright@2.2.2(eslint@9.37.0(jiti@2.6.1)):
dependencies:
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
globals: 13.24.0
- eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.36.0(jiti@2.6.1)))(eslint@9.36.0(jiti@2.6.1))(prettier@3.6.2):
+ eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.37.0(jiti@2.6.1)))(eslint@9.37.0(jiti@2.6.1))(prettier@3.6.2):
dependencies:
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
prettier: 3.6.2
prettier-linter-helpers: 1.0.0
synckit: 0.11.11
optionalDependencies:
'@types/eslint': 9.6.1
- eslint-config-prettier: 10.1.8(eslint@9.36.0(jiti@2.6.1))
+ eslint-config-prettier: 10.1.8(eslint@9.37.0(jiti@2.6.1))
- eslint-plugin-regexp@2.10.0(eslint@9.36.0(jiti@2.6.1)):
+ eslint-plugin-regexp@2.10.0(eslint@9.37.0(jiti@2.6.1)):
dependencies:
- '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1))
+ '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1))
'@eslint-community/regexpp': 4.12.1
comment-parser: 1.4.1
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
jsdoc-type-pratt-parser: 4.8.0
refa: 0.12.1
regexp-ast-analysis: 0.7.1
scslre: 0.3.0
- eslint-plugin-sonarjs@3.0.5(eslint@9.36.0(jiti@2.6.1)):
+ eslint-plugin-sonarjs@3.0.5(eslint@9.37.0(jiti@2.6.1)):
dependencies:
'@eslint-community/regexpp': 4.12.1
builtin-modules: 3.3.0
bytes: 3.1.2
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
functional-red-black-tree: 1.0.1
jsx-ast-utils-x: 0.1.0
lodash.merge: 4.6.2
@@ -6509,16 +6572,16 @@ snapshots:
semver: 7.7.2
typescript: 5.9.3
- eslint-plugin-unicorn@61.0.2(eslint@9.36.0(jiti@2.6.1)):
+ eslint-plugin-unicorn@61.0.2(eslint@9.37.0(jiti@2.6.1)):
dependencies:
'@babel/helper-validator-identifier': 7.27.1
- '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1))
+ '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1))
'@eslint/plugin-kit': 0.3.5
change-case: 5.4.4
- ci-info: 4.3.0
+ ci-info: 4.3.1
clean-regexp: 1.0.0
- core-js-compat: 3.45.1
- eslint: 9.36.0(jiti@2.6.1)
+ core-js-compat: 3.46.0
+ eslint: 9.37.0(jiti@2.6.1)
esquery: 1.6.0
find-up-simple: 1.0.1
globals: 16.4.0
@@ -6528,41 +6591,41 @@ snapshots:
pluralize: 8.0.0
regexp-tree: 0.1.27
regjsparser: 0.12.0
- semver: 7.7.2
+ semver: 7.7.3
strip-indent: 4.1.0
- eslint-plugin-vue-scoped-css@2.12.0(eslint@9.36.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.36.0(jiti@2.6.1))):
+ eslint-plugin-vue-scoped-css@2.12.0(eslint@9.37.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.37.0(jiti@2.6.1))):
dependencies:
- '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1))
- eslint: 9.36.0(jiti@2.6.1)
- eslint-compat-utils: 0.6.5(eslint@9.36.0(jiti@2.6.1))
+ '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1))
+ eslint: 9.37.0(jiti@2.6.1)
+ eslint-compat-utils: 0.6.5(eslint@9.37.0(jiti@2.6.1))
lodash: 4.17.21
postcss: 8.5.6
postcss-safe-parser: 6.0.0(postcss@8.5.6)
postcss-scss: 4.0.9(postcss@8.5.6)
postcss-selector-parser: 7.1.0
postcss-styl: 0.12.3
- vue-eslint-parser: 10.2.0(eslint@9.36.0(jiti@2.6.1))
+ vue-eslint-parser: 10.2.0(eslint@9.37.0(jiti@2.6.1))
transitivePeerDependencies:
- supports-color
- eslint-plugin-vue@10.5.0(@stylistic/eslint-plugin@5.4.0(eslint@9.36.0(jiti@2.6.1)))(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.36.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.36.0(jiti@2.6.1))):
+ eslint-plugin-vue@10.5.0(@stylistic/eslint-plugin@5.4.0(eslint@9.37.0(jiti@2.6.1)))(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.37.0(jiti@2.6.1))):
dependencies:
- '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1))
- eslint: 9.36.0(jiti@2.6.1)
+ '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1))
+ eslint: 9.37.0(jiti@2.6.1)
natural-compare: 1.4.0
nth-check: 2.1.1
postcss-selector-parser: 6.1.2
- semver: 7.7.2
- vue-eslint-parser: 10.2.0(eslint@9.36.0(jiti@2.6.1))
+ semver: 7.7.3
+ vue-eslint-parser: 10.2.0(eslint@9.37.0(jiti@2.6.1))
xml-name-validator: 4.0.0
optionalDependencies:
- '@stylistic/eslint-plugin': 5.4.0(eslint@9.36.0(jiti@2.6.1))
- '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)
+ '@stylistic/eslint-plugin': 5.4.0(eslint@9.37.0(jiti@2.6.1))
+ '@typescript-eslint/parser': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)
- eslint-plugin-wc@3.0.2(eslint@9.36.0(jiti@2.6.1)):
+ eslint-plugin-wc@3.0.2(eslint@9.37.0(jiti@2.6.1)):
dependencies:
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
is-valid-element-name: 1.0.0
js-levenshtein-esm: 2.0.0
@@ -6582,16 +6645,16 @@ snapshots:
eslint-visitor-keys@4.2.1: {}
- eslint@9.36.0(jiti@2.6.1):
+ eslint@9.37.0(jiti@2.6.1):
dependencies:
- '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1))
+ '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1))
'@eslint-community/regexpp': 4.12.1
'@eslint/config-array': 0.21.0
- '@eslint/config-helpers': 0.3.1
- '@eslint/core': 0.15.2
+ '@eslint/config-helpers': 0.4.0
+ '@eslint/core': 0.16.0
'@eslint/eslintrc': 3.3.1
- '@eslint/js': 9.36.0
- '@eslint/plugin-kit': 0.3.5
+ '@eslint/js': 9.37.0
+ '@eslint/plugin-kit': 0.4.0
'@humanfs/node': 0.16.7
'@humanwhocodes/module-importer': 1.0.1
'@humanwhocodes/retry': 0.4.3
@@ -6725,7 +6788,7 @@ snapshots:
flat-cache@6.1.17:
dependencies:
- cacheable: 2.0.3
+ cacheable: 2.1.0
flatted: 3.3.3
hookified: 1.12.1
@@ -6752,7 +6815,7 @@ snapshots:
get-set-props@0.2.0: {}
- get-tsconfig@4.10.1:
+ get-tsconfig@4.12.0:
dependencies:
resolve-pkg-maps: 1.0.0
@@ -6832,9 +6895,9 @@ snapshots:
hammerjs@2.0.8: {}
- happy-dom@19.0.2:
+ happy-dom@20.0.2:
dependencies:
- '@types/node': 20.19.19
+ '@types/node': 20.19.21
'@types/whatwg-mimetype': 3.0.2
whatwg-mimetype: 3.0.0
@@ -6923,7 +6986,7 @@ snapshots:
is-bun-module@2.0.0:
dependencies:
- semver: 7.7.2
+ semver: 7.7.3
is-decimal@2.0.1: {}
@@ -6986,7 +7049,7 @@ snapshots:
jest-worker@27.5.1:
dependencies:
- '@types/node': 24.6.2
+ '@types/node': 24.7.2
merge-stream: 2.0.0
supports-color: 8.1.1
@@ -7045,7 +7108,7 @@ snapshots:
just-extend@5.1.1: {}
- katex@0.16.22:
+ katex@0.16.23:
dependencies:
commander: 8.3.0
@@ -7100,7 +7163,7 @@ snapshots:
dependencies:
uc.micro: 2.1.0
- loader-runner@4.3.0: {}
+ loader-runner@4.3.1: {}
loader-utils@2.0.4:
dependencies:
@@ -7190,7 +7253,9 @@ snapshots:
transitivePeerDependencies:
- supports-color
- marked@16.3.0: {}
+ marked@14.0.0: {}
+
+ marked@16.4.0: {}
marked@4.3.0: {}
@@ -7219,7 +7284,7 @@ snapshots:
dependencies:
'@braintree/sanitize-url': 7.1.1
'@iconify/utils': 3.0.2
- '@mermaid-js/parser': 0.6.2
+ '@mermaid-js/parser': 0.6.3
'@types/d3': 7.4.3
cytoscape: 3.33.1
cytoscape-cose-bilkent: 4.1.0(cytoscape@3.33.1)
@@ -7229,10 +7294,10 @@ snapshots:
dagre-d3-es: 7.0.11
dayjs: 1.11.18
dompurify: 3.2.7
- katex: 0.16.22
+ katex: 0.16.23
khroma: 2.1.0
lodash-es: 4.17.21
- marked: 16.3.0
+ marked: 16.4.0
roughjs: 4.6.6
stylis: 4.3.6
ts-dedent: 2.2.0
@@ -7299,7 +7364,7 @@ snapshots:
dependencies:
'@types/katex': 0.16.7
devlop: 1.1.0
- katex: 0.16.22
+ katex: 0.16.23
micromark-factory-space: 2.0.1
micromark-util-character: 2.1.1
micromark-util-symbol: 2.0.1
@@ -7423,11 +7488,11 @@ snapshots:
dependencies:
mime-db: 1.52.0
- mini-css-extract-plugin@2.9.4(webpack@5.102.0):
+ mini-css-extract-plugin@2.9.4(webpack@5.102.1):
dependencies:
- schema-utils: 4.3.2
- tapable: 2.2.3
- webpack: 5.102.0(webpack-cli@6.0.1)
+ schema-utils: 4.3.3
+ tapable: 2.3.0
+ webpack: 5.102.1(webpack-cli@6.0.1)
minimatch@10.0.3:
dependencies:
@@ -7452,15 +7517,16 @@ snapshots:
pkg-types: 1.3.1
ufo: 1.6.1
- monaco-editor-webpack-plugin@7.1.0(monaco-editor@0.53.0)(webpack@5.102.0):
+ monaco-editor-webpack-plugin@7.1.1(monaco-editor@0.54.0)(webpack@5.102.1):
dependencies:
loader-utils: 2.0.4
- monaco-editor: 0.53.0
- webpack: 5.102.0(webpack-cli@6.0.1)
+ monaco-editor: 0.54.0
+ webpack: 5.102.1(webpack-cli@6.0.1)
- monaco-editor@0.53.0:
+ monaco-editor@0.54.0:
dependencies:
- '@types/trusted-types': 1.0.6
+ dompurify: 3.1.7
+ marked: 14.0.0
moo@0.5.2: {}
@@ -7478,7 +7544,7 @@ snapshots:
nanopop@2.3.0: {}
- napi-postinstall@0.3.3: {}
+ napi-postinstall@0.3.4: {}
natural-compare@1.4.0: {}
@@ -7492,7 +7558,7 @@ snapshots:
dependencies:
whatwg-url: 5.0.0
- node-releases@2.0.21: {}
+ node-releases@2.0.23: {}
nolyfill@1.0.44: {}
@@ -7547,7 +7613,7 @@ snapshots:
package-json-from-dist@1.0.1: {}
- package-manager-detector@1.3.0: {}
+ package-manager-detector@1.4.0: {}
parent-module@1.0.1:
dependencies:
@@ -7628,11 +7694,11 @@ snapshots:
exsolve: 1.0.7
pathe: 2.0.3
- playwright-core@1.55.1: {}
+ playwright-core@1.56.0: {}
- playwright@1.55.1:
+ playwright@1.56.0:
dependencies:
- playwright-core: 1.55.1
+ playwright-core: 1.56.0
optionalDependencies:
fsevents: 2.3.2
@@ -7671,14 +7737,14 @@ snapshots:
optionalDependencies:
postcss: 8.5.6
- postcss-loader@8.2.0(postcss@8.5.6)(typescript@5.9.3)(webpack@5.102.0):
+ postcss-loader@8.2.0(postcss@8.5.6)(typescript@5.9.3)(webpack@5.102.1):
dependencies:
cosmiconfig: 9.0.0(typescript@5.9.3)
jiti: 2.6.1
postcss: 8.5.6
- semver: 7.7.2
+ semver: 7.7.3
optionalDependencies:
- webpack: 5.102.0(webpack-cli@6.0.1)
+ webpack: 5.102.1(webpack-cli@6.0.1)
transitivePeerDependencies:
- typescript
@@ -7764,6 +7830,10 @@ snapshots:
punycode@2.3.1: {}
+ qified@0.5.0:
+ dependencies:
+ hookified: 1.12.1
+
quansync@0.2.11: {}
queue-microtask@1.2.3: {}
@@ -7823,32 +7893,32 @@ snapshots:
robust-predicates@3.0.2: {}
- rollup@4.52.3:
+ rollup@4.52.4:
dependencies:
'@types/estree': 1.0.8
optionalDependencies:
- '@rollup/rollup-android-arm-eabi': 4.52.3
- '@rollup/rollup-android-arm64': 4.52.3
- '@rollup/rollup-darwin-arm64': 4.52.3
- '@rollup/rollup-darwin-x64': 4.52.3
- '@rollup/rollup-freebsd-arm64': 4.52.3
- '@rollup/rollup-freebsd-x64': 4.52.3
- '@rollup/rollup-linux-arm-gnueabihf': 4.52.3
- '@rollup/rollup-linux-arm-musleabihf': 4.52.3
- '@rollup/rollup-linux-arm64-gnu': 4.52.3
- '@rollup/rollup-linux-arm64-musl': 4.52.3
- '@rollup/rollup-linux-loong64-gnu': 4.52.3
- '@rollup/rollup-linux-ppc64-gnu': 4.52.3
- '@rollup/rollup-linux-riscv64-gnu': 4.52.3
- '@rollup/rollup-linux-riscv64-musl': 4.52.3
- '@rollup/rollup-linux-s390x-gnu': 4.52.3
- '@rollup/rollup-linux-x64-gnu': 4.52.3
- '@rollup/rollup-linux-x64-musl': 4.52.3
- '@rollup/rollup-openharmony-arm64': 4.52.3
- '@rollup/rollup-win32-arm64-msvc': 4.52.3
- '@rollup/rollup-win32-ia32-msvc': 4.52.3
- '@rollup/rollup-win32-x64-gnu': 4.52.3
- '@rollup/rollup-win32-x64-msvc': 4.52.3
+ '@rollup/rollup-android-arm-eabi': 4.52.4
+ '@rollup/rollup-android-arm64': 4.52.4
+ '@rollup/rollup-darwin-arm64': 4.52.4
+ '@rollup/rollup-darwin-x64': 4.52.4
+ '@rollup/rollup-freebsd-arm64': 4.52.4
+ '@rollup/rollup-freebsd-x64': 4.52.4
+ '@rollup/rollup-linux-arm-gnueabihf': 4.52.4
+ '@rollup/rollup-linux-arm-musleabihf': 4.52.4
+ '@rollup/rollup-linux-arm64-gnu': 4.52.4
+ '@rollup/rollup-linux-arm64-musl': 4.52.4
+ '@rollup/rollup-linux-loong64-gnu': 4.52.4
+ '@rollup/rollup-linux-ppc64-gnu': 4.52.4
+ '@rollup/rollup-linux-riscv64-gnu': 4.52.4
+ '@rollup/rollup-linux-riscv64-musl': 4.52.4
+ '@rollup/rollup-linux-s390x-gnu': 4.52.4
+ '@rollup/rollup-linux-x64-gnu': 4.52.4
+ '@rollup/rollup-linux-x64-musl': 4.52.4
+ '@rollup/rollup-openharmony-arm64': 4.52.4
+ '@rollup/rollup-win32-arm64-msvc': 4.52.4
+ '@rollup/rollup-win32-ia32-msvc': 4.52.4
+ '@rollup/rollup-win32-x64-gnu': 4.52.4
+ '@rollup/rollup-win32-x64-msvc': 4.52.4
fsevents: 2.3.3
roughjs@4.6.6:
@@ -7875,7 +7945,7 @@ snapshots:
sax@1.4.1: {}
- schema-utils@4.3.2:
+ schema-utils@4.3.3:
dependencies:
'@types/json-schema': 7.0.15
ajv: 8.17.1
@@ -7892,6 +7962,8 @@ snapshots:
semver@7.7.2: {}
+ semver@7.7.3: {}
+
serialize-javascript@6.0.2:
dependencies:
randombytes: 2.1.0
@@ -7932,6 +8004,12 @@ snapshots:
seroval: 1.3.2
seroval-plugins: 1.3.3(seroval@1.3.2)
+ solid-transition-group@0.2.3(solid-js@1.9.9):
+ dependencies:
+ '@solid-primitives/refs': 1.1.2(solid-js@1.9.9)
+ '@solid-primitives/transition-group': 1.1.2(solid-js@1.9.9)
+ solid-js: 1.9.9
+
sortablejs@1.15.6: {}
source-list-map@2.0.1: {}
@@ -8027,25 +8105,25 @@ snapshots:
style-search@0.1.0: {}
- stylelint-config-recommended@17.0.0(stylelint@16.24.0(typescript@5.9.3)):
+ stylelint-config-recommended@17.0.0(stylelint@16.25.0(typescript@5.9.3)):
dependencies:
- stylelint: 16.24.0(typescript@5.9.3)
+ stylelint: 16.25.0(typescript@5.9.3)
- stylelint-declaration-block-no-ignored-properties@2.8.0(stylelint@16.24.0(typescript@5.9.3)):
+ stylelint-declaration-block-no-ignored-properties@2.8.0(stylelint@16.25.0(typescript@5.9.3)):
dependencies:
- stylelint: 16.24.0(typescript@5.9.3)
+ stylelint: 16.25.0(typescript@5.9.3)
- stylelint-declaration-strict-value@1.10.11(stylelint@16.24.0(typescript@5.9.3)):
+ stylelint-declaration-strict-value@1.10.11(stylelint@16.25.0(typescript@5.9.3)):
dependencies:
- stylelint: 16.24.0(typescript@5.9.3)
+ stylelint: 16.25.0(typescript@5.9.3)
- stylelint-value-no-unknown-custom-properties@6.0.1(stylelint@16.24.0(typescript@5.9.3)):
+ stylelint-value-no-unknown-custom-properties@6.0.1(stylelint@16.25.0(typescript@5.9.3)):
dependencies:
postcss-value-parser: 4.2.0
resolve: 1.22.10
- stylelint: 16.24.0(typescript@5.9.3)
+ stylelint: 16.25.0(typescript@5.9.3)
- stylelint@16.24.0(typescript@5.9.3):
+ stylelint@16.25.0(typescript@5.9.3):
dependencies:
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
'@csstools/css-tokenizer': 3.0.4
@@ -8148,7 +8226,7 @@ snapshots:
deep-rename-keys: 0.2.1
xml-reader: 2.4.3
- swagger-ui-dist@5.29.1:
+ swagger-ui-dist@5.29.4:
dependencies:
'@scarf/scarf': 1.4.0
@@ -8198,16 +8276,16 @@ snapshots:
transitivePeerDependencies:
- ts-node
- tapable@2.2.3: {}
+ tapable@2.3.0: {}
- terser-webpack-plugin@5.3.14(webpack@5.102.0):
+ terser-webpack-plugin@5.3.14(webpack@5.102.1):
dependencies:
'@jridgewell/trace-mapping': 0.3.31
jest-worker: 27.5.1
- schema-utils: 4.3.2
+ schema-utils: 4.3.3
serialize-javascript: 6.0.2
terser: 5.44.0
- webpack: 5.102.0(webpack-cli@6.0.1)
+ webpack: 5.102.1(webpack-cli@6.0.1)
terser@5.44.0:
dependencies:
@@ -8285,13 +8363,13 @@ snapshots:
type-fest@0.20.2: {}
- typescript-eslint@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3):
+ typescript-eslint@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3):
dependencies:
- '@typescript-eslint/eslint-plugin': 8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)
- '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.3)
- '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)
- eslint: 9.36.0(jiti@2.6.1)
+ '@typescript-eslint/eslint-plugin': 8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/parser': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)
+ '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)
+ eslint: 9.37.0(jiti@2.6.1)
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
@@ -8308,11 +8386,11 @@ snapshots:
undici-types@6.21.0: {}
- undici-types@7.13.0: {}
+ undici-types@7.14.0: {}
unrs-resolver@1.11.1:
dependencies:
- napi-postinstall: 0.3.3
+ napi-postinstall: 0.3.4
optionalDependencies:
'@unrs/resolver-binding-android-arm-eabi': 1.11.1
'@unrs/resolver-binding-android-arm64': 1.11.1
@@ -8340,7 +8418,7 @@ snapshots:
escalade: 3.2.0
picocolors: 1.1.1
- updates@16.7.4: {}
+ updates@16.8.0: {}
uri-js@4.4.1:
dependencies:
@@ -8352,13 +8430,13 @@ snapshots:
vanilla-colorful@0.7.2: {}
- vite-node@3.2.4(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1):
+ vite-node@3.2.4(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1):
dependencies:
cac: 6.7.14
debug: 4.4.3
es-module-lexer: 1.7.0
pathe: 2.0.3
- vite: 7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)
+ vite: 7.1.9(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)
transitivePeerDependencies:
- '@types/node'
- jiti
@@ -8375,27 +8453,27 @@ snapshots:
vite-string-plugin@1.4.6: {}
- vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1):
+ vite@7.1.9(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1):
dependencies:
esbuild: 0.25.10
fdir: 6.5.0(picomatch@4.0.3)
picomatch: 4.0.3
postcss: 8.5.6
- rollup: 4.52.3
+ rollup: 4.52.4
tinyglobby: 0.2.15
optionalDependencies:
- '@types/node': 24.6.2
+ '@types/node': 24.7.2
fsevents: 2.3.3
jiti: 2.6.1
stylus: 0.57.0
terser: 5.44.0
yaml: 2.8.1
- vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.6.2)(happy-dom@19.0.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1):
+ vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.7.2)(happy-dom@20.0.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1):
dependencies:
'@types/chai': 5.2.2
'@vitest/expect': 3.2.4
- '@vitest/mocker': 3.2.4(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))
+ '@vitest/mocker': 3.2.4(vite@7.1.9(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))
'@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.2.4
'@vitest/snapshot': 3.2.4
@@ -8413,13 +8491,13 @@ snapshots:
tinyglobby: 0.2.15
tinypool: 1.1.1
tinyrainbow: 2.0.0
- vite: 7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)
- vite-node: 3.2.4(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)
+ vite: 7.1.9(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)
+ vite-node: 3.2.4(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)
why-is-node-running: 2.3.0
optionalDependencies:
'@types/debug': 4.1.12
- '@types/node': 24.6.2
- happy-dom: 19.0.2
+ '@types/node': 24.7.2
+ happy-dom: 20.0.2
transitivePeerDependencies:
- jiti
- less
@@ -8464,31 +8542,31 @@ snapshots:
chart.js: 4.5.0
vue: 3.5.22(typescript@5.9.3)
- vue-eslint-parser@10.2.0(eslint@9.36.0(jiti@2.6.1)):
+ vue-eslint-parser@10.2.0(eslint@9.37.0(jiti@2.6.1)):
dependencies:
debug: 4.4.3
- eslint: 9.36.0(jiti@2.6.1)
+ eslint: 9.37.0(jiti@2.6.1)
eslint-scope: 8.4.0
eslint-visitor-keys: 4.2.1
espree: 10.4.0
esquery: 1.6.0
- semver: 7.7.2
+ semver: 7.7.3
transitivePeerDependencies:
- supports-color
- vue-loader@17.4.2(vue@3.5.22(typescript@5.9.3))(webpack@5.102.0):
+ vue-loader@17.4.2(vue@3.5.22(typescript@5.9.3))(webpack@5.102.1):
dependencies:
chalk: 4.1.2
hash-sum: 2.0.0
watchpack: 2.4.4
- webpack: 5.102.0(webpack-cli@6.0.1)
+ webpack: 5.102.1(webpack-cli@6.0.1)
optionalDependencies:
vue: 3.5.22(typescript@5.9.3)
- vue-tsc@3.1.0(typescript@5.9.3):
+ vue-tsc@3.1.1(typescript@5.9.3):
dependencies:
'@volar/typescript': 2.4.23
- '@vue/language-core': 3.1.0(typescript@5.9.3)
+ '@vue/language-core': 3.1.1(typescript@5.9.3)
typescript: 5.9.3
vue@3.5.22(typescript@5.9.3):
@@ -8508,21 +8586,21 @@ snapshots:
webidl-conversions@3.0.1: {}
- webpack-cli@6.0.1(webpack@5.102.0):
+ webpack-cli@6.0.1(webpack@5.102.1):
dependencies:
'@discoveryjs/json-ext': 0.6.3
- '@webpack-cli/configtest': 3.0.1(webpack-cli@6.0.1)(webpack@5.102.0)
- '@webpack-cli/info': 3.0.1(webpack-cli@6.0.1)(webpack@5.102.0)
- '@webpack-cli/serve': 3.0.1(webpack-cli@6.0.1)(webpack@5.102.0)
+ '@webpack-cli/configtest': 3.0.1(webpack-cli@6.0.1)(webpack@5.102.1)
+ '@webpack-cli/info': 3.0.1(webpack-cli@6.0.1)(webpack@5.102.1)
+ '@webpack-cli/serve': 3.0.1(webpack-cli@6.0.1)(webpack@5.102.1)
colorette: 2.0.20
commander: 12.1.0
cross-spawn: 7.0.6
- envinfo: 7.15.0
+ envinfo: 7.17.0
fastest-levenshtein: 1.0.16
import-local: 3.2.0
interpret: 3.1.1
rechoir: 0.8.0
- webpack: 5.102.0(webpack-cli@6.0.1)
+ webpack: 5.102.1(webpack-cli@6.0.1)
webpack-merge: 6.0.1
webpack-merge@6.0.1:
@@ -8538,7 +8616,7 @@ snapshots:
webpack-sources@3.3.3: {}
- webpack@5.102.0(webpack-cli@6.0.1):
+ webpack@5.102.1(webpack-cli@6.0.1):
dependencies:
'@types/eslint-scope': 3.7.7
'@types/estree': 1.0.8
@@ -8557,16 +8635,16 @@ snapshots:
glob-to-regexp: 0.4.1
graceful-fs: 4.2.11
json-parse-even-better-errors: 2.3.1
- loader-runner: 4.3.0
+ loader-runner: 4.3.1
mime-types: 2.1.35
neo-async: 2.6.2
- schema-utils: 4.3.2
- tapable: 2.2.3
- terser-webpack-plugin: 5.3.14(webpack@5.102.0)
+ schema-utils: 4.3.3
+ tapable: 2.3.0
+ terser-webpack-plugin: 5.3.14(webpack@5.102.1)
watchpack: 2.4.4
webpack-sources: 3.3.3
optionalDependencies:
- webpack-cli: 6.0.1(webpack@5.102.0)
+ webpack-cli: 6.0.1(webpack@5.102.1)
transitivePeerDependencies:
- '@swc/core'
- esbuild
diff --git a/public/assets/img/svg/gitea-running.svg b/public/assets/img/svg/gitea-running.svg
new file mode 100644
index 0000000000..2320f8101c
--- /dev/null
+++ b/public/assets/img/svg/gitea-running.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/assets/img/svg/gitea-vscode.svg b/public/assets/img/svg/gitea-vscode.svg
deleted file mode 100644
index 453b9befcc..0000000000
--- a/public/assets/img/svg/gitea-vscode.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/assets/img/svg/octicon-comment-ai.svg b/public/assets/img/svg/octicon-comment-ai.svg
new file mode 100644
index 0000000000..72aa8715a0
--- /dev/null
+++ b/public/assets/img/svg/octicon-comment-ai.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/assets/img/svg/octicon-vscode.svg b/public/assets/img/svg/octicon-vscode.svg
new file mode 100644
index 0000000000..d226e3a574
--- /dev/null
+++ b/public/assets/img/svg/octicon-vscode.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/routers/api/actions/runner/runner.go b/routers/api/actions/runner/runner.go
index 55ba7862a9..86bab4b340 100644
--- a/routers/api/actions/runner/runner.go
+++ b/routers/api/actions/runner/runner.go
@@ -217,19 +217,19 @@ func (s *Service) UpdateTask(
return nil, status.Errorf(codes.Internal, "load run: %v", err)
}
- // don't create commit status for cron job
- if task.Job.Run.ScheduleID == 0 {
- actions_service.CreateCommitStatus(ctx, task.Job)
- }
+ actions_service.CreateCommitStatusForRunJobs(ctx, task.Job.Run, task.Job)
if task.Status.IsDone() {
notify_service.WorkflowJobStatusUpdate(ctx, task.Job.Run.Repo, task.Job.Run.TriggerUser, task.Job, task)
}
if req.Msg.State.Result != runnerv1.Result_RESULT_UNSPECIFIED {
- if err := actions_service.EmitJobsIfReady(task.Job.RunID); err != nil {
+ if err := actions_service.EmitJobsIfReadyByRun(task.Job.RunID); err != nil {
log.Error("Emit ready jobs of run %d: %v", task.Job.RunID, err)
}
+ if task.Job.Run.Status.IsDone() {
+ actions_service.NotifyWorkflowRunStatusUpdateWithReload(ctx, task.Job)
+ }
}
return connect.NewResponse(&runnerv1.UpdateTaskResponse{
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index 66afede218..5f52ee8a43 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -1423,6 +1423,7 @@ func Routes() *web.Router {
m.Get("/tags/{sha}", repo.GetAnnotatedTag)
m.Get("/notes/{sha}", repo.GetNote)
}, context.ReferencesGitRepo(true), reqRepoReader(unit.TypeCode))
+ m.Post("/diffpatch", mustEnableEditor, reqToken(), bind(api.ApplyDiffPatchFileOptions{}), repo.ReqChangeRepoFileOptionsAndCheck, repo.ApplyDiffPatch)
m.Group("/contents", func() {
m.Get("", repo.GetContentsList)
m.Get("/*", repo.GetContents)
@@ -1434,7 +1435,6 @@ func Routes() *web.Router {
m.Put("", bind(api.UpdateFileOptions{}), repo.ReqChangeRepoFileOptionsAndCheck, repo.UpdateFile)
m.Delete("", bind(api.DeleteFileOptions{}), repo.ReqChangeRepoFileOptionsAndCheck, repo.DeleteFile)
})
- m.Post("/diffpatch", bind(api.ApplyDiffPatchFileOptions{}), repo.ReqChangeRepoFileOptionsAndCheck, repo.ApplyDiffPatch)
}, mustEnableEditor, reqToken())
}, reqRepoReader(unit.TypeCode), context.ReferencesGitRepo())
m.Group("/contents-ext", func() {
diff --git a/routers/api/v1/repo/patch.go b/routers/api/v1/repo/patch.go
index e9f5cf5d90..edb09fc08f 100644
--- a/routers/api/v1/repo/patch.go
+++ b/routers/api/v1/repo/patch.go
@@ -36,7 +36,7 @@ func ApplyDiffPatch(ctx *context.APIContext) {
// in: body
// required: true
// schema:
- // "$ref": "#/definitions/UpdateFileOptions"
+ // "$ref": "#/definitions/ApplyDiffPatchFileOptions"
// responses:
// "200":
// "$ref": "#/responses/FileResponse"
diff --git a/routers/api/v1/swagger/options.go b/routers/api/v1/swagger/options.go
index 4aba74b939..b80a9c14ba 100644
--- a/routers/api/v1/swagger/options.go
+++ b/routers/api/v1/swagger/options.go
@@ -121,6 +121,9 @@ type swaggerParameterBodies struct {
// in:body
GetFilesOptions api.GetFilesOptions
+ // in:body
+ ApplyDiffPatchFileOptions api.ApplyDiffPatchFileOptions
+
// in:body
ChangeFilesOptions api.ChangeFilesOptions
diff --git a/routers/web/auth/oauth2_provider.go b/routers/web/auth/oauth2_provider.go
index 79989d8fbe..1dc40d6a75 100644
--- a/routers/web/auth/oauth2_provider.go
+++ b/routers/web/auth/oauth2_provider.go
@@ -636,6 +636,7 @@ func handleAuthorizationCode(ctx *context.Context, form forms.AccessTokenForm, s
ErrorCode: oauth2_provider.AccessTokenErrorCodeInvalidRequest,
ErrorDescription: "cannot proceed your request",
})
+ return
}
resp, tokenErr := oauth2_provider.NewAccessTokenResponse(ctx, authorizationCode.Grant, serverKey, clientKey)
if tokenErr != nil {
diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go
index 3422128026..b409e887be 100644
--- a/routers/web/repo/actions/view.go
+++ b/routers/web/repo/actions/view.go
@@ -27,7 +27,6 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/templates"
- "code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/common"
@@ -36,6 +35,7 @@ import (
notify_service "code.gitea.io/gitea/services/notify"
"github.com/nektos/act/pkg/model"
+ "gopkg.in/yaml.v3"
"xorm.io/builder"
)
@@ -420,12 +420,45 @@ func Rerun(ctx *context_module.Context) {
return
}
+ // check run (workflow-level) concurrency
+
+ job, jobs := getRunJobs(ctx, runIndex, jobIndex)
+ if ctx.Written() {
+ return
+ }
+
// reset run's start and stop time when it is done
if run.Status.IsDone() {
run.PreviousDuration = run.Duration()
run.Started = 0
run.Stopped = 0
- if err := actions_model.UpdateRun(ctx, run, "started", "stopped", "previous_duration"); err != nil {
+
+ vars, err := actions_model.GetVariablesOfRun(ctx, run)
+ if err != nil {
+ ctx.ServerError("GetVariablesOfRun", fmt.Errorf("get run %d variables: %w", run.ID, err))
+ return
+ }
+
+ if run.RawConcurrency != "" {
+ var rawConcurrency model.RawConcurrency
+ if err := yaml.Unmarshal([]byte(run.RawConcurrency), &rawConcurrency); err != nil {
+ ctx.ServerError("UnmarshalRawConcurrency", fmt.Errorf("unmarshal raw concurrency: %w", err))
+ return
+ }
+
+ err = actions_service.EvaluateRunConcurrencyFillModel(ctx, run, &rawConcurrency, vars)
+ if err != nil {
+ ctx.ServerError("EvaluateRunConcurrencyFillModel", err)
+ return
+ }
+
+ run.Status, err = actions_service.PrepareToStartRunWithConcurrency(ctx, run)
+ if err != nil {
+ ctx.ServerError("PrepareToStartRunWithConcurrency", err)
+ return
+ }
+ }
+ if err := actions_model.UpdateRun(ctx, run, "started", "stopped", "previous_duration", "status", "concurrency_group", "concurrency_cancel"); err != nil {
ctx.ServerError("UpdateRun", err)
return
}
@@ -437,16 +470,12 @@ func Rerun(ctx *context_module.Context) {
notify_service.WorkflowRunStatusUpdate(ctx, run.Repo, run.TriggerUser, run)
}
- job, jobs := getRunJobs(ctx, runIndex, jobIndex)
- if ctx.Written() {
- return
- }
-
+ isRunBlocked := run.Status == actions_model.StatusBlocked
if jobIndexStr == "" { // rerun all jobs
for _, j := range jobs {
// if the job has needs, it should be set to "blocked" status to wait for other jobs
- shouldBlock := len(j.Needs) > 0
- if err := rerunJob(ctx, j, shouldBlock); err != nil {
+ shouldBlockJob := len(j.Needs) > 0 || isRunBlocked
+ if err := rerunJob(ctx, j, shouldBlockJob); err != nil {
ctx.ServerError("RerunJob", err)
return
}
@@ -459,8 +488,8 @@ func Rerun(ctx *context_module.Context) {
for _, j := range rerunJobs {
// jobs other than the specified one should be set to "blocked" status
- shouldBlock := j.JobID != job.JobID
- if err := rerunJob(ctx, j, shouldBlock); err != nil {
+ shouldBlockJob := j.JobID != job.JobID || isRunBlocked
+ if err := rerunJob(ctx, j, shouldBlockJob); err != nil {
ctx.ServerError("RerunJob", err)
return
}
@@ -476,21 +505,43 @@ func rerunJob(ctx *context_module.Context, job *actions_model.ActionRunJob, shou
}
job.TaskID = 0
- job.Status = actions_model.StatusWaiting
- if shouldBlock {
- job.Status = actions_model.StatusBlocked
- }
+ job.Status = util.Iif(shouldBlock, actions_model.StatusBlocked, actions_model.StatusWaiting)
job.Started = 0
job.Stopped = 0
+ job.ConcurrencyGroup = ""
+ job.ConcurrencyCancel = false
+ job.IsConcurrencyEvaluated = false
+ if err := job.LoadRun(ctx); err != nil {
+ return err
+ }
+
+ vars, err := actions_model.GetVariablesOfRun(ctx, job.Run)
+ if err != nil {
+ return fmt.Errorf("get run %d variables: %w", job.Run.ID, err)
+ }
+
+ if job.RawConcurrency != "" && !shouldBlock {
+ err = actions_service.EvaluateJobConcurrencyFillModel(ctx, job.Run, job, vars)
+ if err != nil {
+ return fmt.Errorf("evaluate job concurrency: %w", err)
+ }
+
+ job.Status, err = actions_service.PrepareToStartJobWithConcurrency(ctx, job)
+ if err != nil {
+ return err
+ }
+ }
+
if err := db.WithTx(ctx, func(ctx context.Context) error {
- _, err := actions_model.UpdateRunJob(ctx, job, builder.Eq{"status": status}, "task_id", "status", "started", "stopped")
+ updateCols := []string{"task_id", "status", "started", "stopped", "concurrency_group", "concurrency_cancel", "is_concurrency_evaluated"}
+ _, err := actions_model.UpdateRunJob(ctx, job, builder.Eq{"status": status}, updateCols...)
return err
}); err != nil {
return err
}
- actions_service.CreateCommitStatus(ctx, job)
+ actions_service.CreateCommitStatusForRunJobs(ctx, job.Run, job)
notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil)
return nil
@@ -518,52 +569,34 @@ func Logs(ctx *context_module.Context) {
func Cancel(ctx *context_module.Context) {
runIndex := getRunIndex(ctx)
- _, jobs := getRunJobs(ctx, runIndex, -1)
+ firstJob, jobs := getRunJobs(ctx, runIndex, -1)
if ctx.Written() {
return
}
- var updatedjobs []*actions_model.ActionRunJob
+ var updatedJobs []*actions_model.ActionRunJob
if err := db.WithTx(ctx, func(ctx context.Context) error {
- for _, job := range jobs {
- status := job.Status
- if status.IsDone() {
- continue
- }
- if job.TaskID == 0 {
- job.Status = actions_model.StatusCancelled
- job.Stopped = timeutil.TimeStampNow()
- n, err := actions_model.UpdateRunJob(ctx, job, builder.Eq{"task_id": 0}, "status", "stopped")
- if err != nil {
- return err
- }
- if n == 0 {
- return errors.New("job has changed, try again")
- }
- if n > 0 {
- updatedjobs = append(updatedjobs, job)
- }
- continue
- }
- if err := actions_model.StopTask(ctx, job.TaskID, actions_model.StatusCancelled); err != nil {
- return err
- }
+ cancelledJobs, err := actions_model.CancelJobs(ctx, jobs)
+ if err != nil {
+ return fmt.Errorf("cancel jobs: %w", err)
}
+ updatedJobs = append(updatedJobs, cancelledJobs...)
return nil
}); err != nil {
ctx.ServerError("StopTask", err)
return
}
- actions_service.CreateCommitStatus(ctx, jobs...)
+ actions_service.CreateCommitStatusForRunJobs(ctx, firstJob.Run, jobs...)
+ actions_service.EmitJobsIfReadyByJobs(updatedJobs)
- for _, job := range updatedjobs {
+ for _, job := range updatedJobs {
_ = job.LoadAttributes(ctx)
notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil)
}
- if len(updatedjobs) > 0 {
- job := updatedjobs[0]
+ if len(updatedJobs) > 0 {
+ job := updatedJobs[0]
actions_service.NotifyWorkflowRunStatusUpdateWithReload(ctx, job)
}
ctx.JSONOK()
@@ -579,40 +612,44 @@ func Approve(ctx *context_module.Context) {
run := current.Run
doer := ctx.Doer
- var updatedjobs []*actions_model.ActionRunJob
+ var updatedJobs []*actions_model.ActionRunJob
- if err := db.WithTx(ctx, func(ctx context.Context) error {
+ err := db.WithTx(ctx, func(ctx context.Context) (err error) {
run.NeedApproval = false
run.ApprovedBy = doer.ID
if err := actions_model.UpdateRun(ctx, run, "need_approval", "approved_by"); err != nil {
return err
}
for _, job := range jobs {
- if len(job.Needs) == 0 && job.Status.IsBlocked() {
- job.Status = actions_model.StatusWaiting
+ job.Status, err = actions_service.PrepareToStartJobWithConcurrency(ctx, job)
+ if err != nil {
+ return err
+ }
+ if job.Status == actions_model.StatusWaiting {
n, err := actions_model.UpdateRunJob(ctx, job, nil, "status")
if err != nil {
return err
}
if n > 0 {
- updatedjobs = append(updatedjobs, job)
+ updatedJobs = append(updatedJobs, job)
}
}
}
return nil
- }); err != nil {
+ })
+ if err != nil {
ctx.ServerError("UpdateRunJob", err)
return
}
- actions_service.CreateCommitStatus(ctx, jobs...)
+ actions_service.CreateCommitStatusForRunJobs(ctx, current.Run, jobs...)
- if len(updatedjobs) > 0 {
- job := updatedjobs[0]
+ if len(updatedJobs) > 0 {
+ job := updatedJobs[0]
actions_service.NotifyWorkflowRunStatusUpdateWithReload(ctx, job)
}
- for _, job := range updatedjobs {
+ for _, job := range updatedJobs {
_ = job.LoadAttributes(ctx)
notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil)
}
diff --git a/routers/web/repo/editor.go b/routers/web/repo/editor.go
index 2a5ac10282..8c630cb35f 100644
--- a/routers/web/repo/editor.go
+++ b/routers/web/repo/editor.go
@@ -295,14 +295,14 @@ func EditFile(ctx *context.Context) {
}
defer dataRc.Close()
- ctx.Data["FileSize"] = fInfo.fileSize
+ ctx.Data["FileSize"] = fInfo.blobOrLfsSize
// Only some file types are editable online as text.
if fInfo.isLFSFile() {
ctx.Data["NotEditableReason"] = ctx.Tr("repo.editor.cannot_edit_lfs_files")
} else if !fInfo.st.IsRepresentableAsText() {
ctx.Data["NotEditableReason"] = ctx.Tr("repo.editor.cannot_edit_non_text_files")
- } else if fInfo.fileSize >= setting.UI.MaxDisplayFileSize {
+ } else if fInfo.blobOrLfsSize >= setting.UI.MaxDisplayFileSize {
ctx.Data["NotEditableReason"] = ctx.Tr("repo.editor.cannot_edit_too_large_file")
}
diff --git a/routers/web/repo/githttp.go b/routers/web/repo/githttp.go
index 1b7e75f84e..69b93dd060 100644
--- a/routers/web/repo/githttp.go
+++ b/routers/web/repo/githttp.go
@@ -7,11 +7,10 @@ package repo
import (
"bytes"
"compress/gzip"
- gocontext "context"
"fmt"
"net/http"
"os"
- "path/filepath"
+ "path"
"regexp"
"slices"
"strconv"
@@ -27,6 +26,7 @@ import (
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/git/gitcmd"
+ "code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
@@ -342,11 +342,11 @@ type serviceHandler struct {
environ []string
}
-func (h *serviceHandler) getRepoDir() string {
+func (h *serviceHandler) getStorageRepo() gitrepo.Repository {
if h.isWiki {
- return h.repo.WikiPath()
+ return h.repo.WikiStorageRepo()
}
- return h.repo.RepoPath()
+ return h.repo
}
func setHeaderNoCache(ctx *context.Context) {
@@ -378,19 +378,10 @@ func (h *serviceHandler) sendFile(ctx *context.Context, contentType, file string
ctx.Resp.WriteHeader(http.StatusBadRequest)
return
}
- reqFile := filepath.Join(h.getRepoDir(), filepath.Clean(file))
-
- fi, err := os.Stat(reqFile)
- if os.IsNotExist(err) {
- ctx.Resp.WriteHeader(http.StatusNotFound)
- return
- }
+ fs := gitrepo.GetRepoFS(h.getStorageRepo())
ctx.Resp.Header().Set("Content-Type", contentType)
- ctx.Resp.Header().Set("Content-Length", strconv.FormatInt(fi.Size(), 10))
- // http.TimeFormat required a UTC time, refer to https://pkg.go.dev/net/http#TimeFormat
- ctx.Resp.Header().Set("Last-Modified", fi.ModTime().UTC().Format(http.TimeFormat))
- http.ServeFile(ctx.Resp, ctx.Req, reqFile)
+ http.ServeFileFS(ctx.Resp, ctx.Req, fs, path.Clean(file))
}
// one or more key=value pairs separated by colons
@@ -416,6 +407,7 @@ func serviceRPC(ctx *context.Context, h *serviceHandler, service string) {
expectedContentType := fmt.Sprintf("application/x-git-%s-request", service)
if ctx.Req.Header.Get("Content-Type") != expectedContentType {
log.Error("Content-Type (%q) doesn't match expected: %q", ctx.Req.Header.Get("Content-Type"), expectedContentType)
+ // FIXME: why it's 401 if the content type is unexpected?
ctx.Resp.WriteHeader(http.StatusUnauthorized)
return
}
@@ -423,6 +415,7 @@ func serviceRPC(ctx *context.Context, h *serviceHandler, service string) {
cmd, err := prepareGitCmdWithAllowedService(service)
if err != nil {
log.Error("Failed to prepareGitCmdWithService: %v", err)
+ // FIXME: why it's 401 if the service type doesn't supported?
ctx.Resp.WriteHeader(http.StatusUnauthorized)
return
}
@@ -449,17 +442,14 @@ func serviceRPC(ctx *context.Context, h *serviceHandler, service string) {
}
var stderr bytes.Buffer
- if err := cmd.AddArguments("--stateless-rpc").
- AddDynamicArguments(h.getRepoDir()).
- WithDir(h.getRepoDir()).
+ if err := gitrepo.RunCmd(ctx, h.getStorageRepo(), cmd.AddArguments("--stateless-rpc", ".").
WithEnv(append(os.Environ(), h.environ...)).
WithStderr(&stderr).
WithStdin(reqBody).
WithStdout(ctx.Resp).
- WithUseContextTimeout(true).
- Run(ctx); err != nil {
+ WithUseContextTimeout(true)); err != nil {
if !git.IsErrCanceledOrKilled(err) {
- log.Error("Fail to serve RPC(%s) in %s: %v - %s", service, h.getRepoDir(), err, stderr.String())
+ log.Error("Fail to serve RPC(%s) in %s: %v - %s", service, h.getStorageRepo().RelativePath(), err, stderr.String())
}
return
}
@@ -496,14 +486,6 @@ func getServiceType(ctx *context.Context) string {
return ""
}
-func updateServerInfo(ctx gocontext.Context, dir string) []byte {
- out, _, err := gitcmd.NewCommand("update-server-info").WithDir(dir).RunStdBytes(ctx)
- if err != nil {
- log.Error(fmt.Sprintf("%v - %s", err, string(out)))
- }
- return out
-}
-
func packetWrite(str string) []byte {
s := strconv.FormatInt(int64(len(str)+4), 16)
if len(s)%4 != 0 {
@@ -527,10 +509,8 @@ func GetInfoRefs(ctx *context.Context) {
}
h.environ = append(os.Environ(), h.environ...)
- refs, _, err := cmd.AddArguments("--stateless-rpc", "--advertise-refs", ".").
- WithEnv(h.environ).
- WithDir(h.getRepoDir()).
- RunStdBytes(ctx)
+ refs, _, err := gitrepo.RunCmdBytes(ctx, h.getStorageRepo(), cmd.AddArguments("--stateless-rpc", "--advertise-refs", ".").
+ WithEnv(h.environ))
if err != nil {
log.Error(fmt.Sprintf("%v - %s", err, string(refs)))
}
@@ -541,7 +521,9 @@ func GetInfoRefs(ctx *context.Context) {
_, _ = ctx.Resp.Write([]byte("0000"))
_, _ = ctx.Resp.Write(refs)
} else {
- updateServerInfo(ctx, h.getRepoDir())
+ if err := gitrepo.UpdateServerInfo(ctx, h.getStorageRepo()); err != nil {
+ log.Error("Failed to update server info: %v", err)
+ }
h.sendFile(ctx, "text/plain; charset=utf-8", "info/refs")
}
}
diff --git a/routers/web/repo/setting/lfs.go b/routers/web/repo/setting/lfs.go
index af6708e841..a558231df1 100644
--- a/routers/web/repo/setting/lfs.go
+++ b/routers/web/repo/setting/lfs.go
@@ -270,8 +270,7 @@ func LFSFileGet(ctx *context.Context) {
// FIXME: there is no IsPlainText set, but template uses it
ctx.Data["IsTextFile"] = st.IsText()
ctx.Data["FileSize"] = meta.Size
- // FIXME: the last field is the URL-base64-encoded filename, it should not be "direct"
- ctx.Data["RawFileLink"] = fmt.Sprintf("%s%s/%s.git/info/lfs/objects/%s/%s", setting.AppURL, url.PathEscape(ctx.Repo.Repository.OwnerName), url.PathEscape(ctx.Repo.Repository.Name), url.PathEscape(meta.Oid), "direct")
+ ctx.Data["RawFileLink"] = fmt.Sprintf("%s/%s/%s.git/info/lfs/objects/%s", setting.AppSubURL, url.PathEscape(ctx.Repo.Repository.OwnerName), url.PathEscape(ctx.Repo.Repository.Name), url.PathEscape(meta.Oid))
switch {
case st.IsRepresentableAsText():
if meta.Size >= setting.UI.MaxDisplayFileSize {
diff --git a/routers/web/repo/setting/setting.go b/routers/web/repo/setting/setting.go
index 1a4f590e10..dd887d6edf 100644
--- a/routers/web/repo/setting/setting.go
+++ b/routers/web/repo/setting/setting.go
@@ -29,7 +29,6 @@ import (
"code.gitea.io/gitea/modules/validation"
"code.gitea.io/gitea/modules/web"
actions_service "code.gitea.io/gitea/services/actions"
- asymkey_service "code.gitea.io/gitea/services/asymkey"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/migrations"
@@ -62,7 +61,7 @@ func SettingsCtxData(ctx *context.Context) {
ctx.Data["MinimumMirrorInterval"] = setting.Mirror.MinInterval
ctx.Data["CanConvertFork"] = ctx.Repo.Repository.IsFork && ctx.Doer.CanCreateRepoIn(ctx.Repo.Repository.Owner)
- signing, _ := asymkey_service.SigningKey(ctx, ctx.Repo.Repository.RepoPath())
+ signing, _ := gitrepo.GetSigningKey(ctx, ctx.Repo.Repository)
ctx.Data["SigningKeyAvailable"] = signing != nil
ctx.Data["SigningSettings"] = setting.Repository.Signing
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
@@ -105,7 +104,7 @@ func SettingsPost(ctx *context.Context) {
ctx.Data["DefaultMirrorInterval"] = setting.Mirror.DefaultInterval
ctx.Data["MinimumMirrorInterval"] = setting.Mirror.MinInterval
- signing, _ := asymkey_service.SigningKey(ctx, ctx.Repo.Repository.RepoPath())
+ signing, _ := gitrepo.GetSigningKey(ctx, ctx.Repo.Repository)
ctx.Data["SigningKeyAvailable"] = signing != nil
ctx.Data["SigningSettings"] = setting.Repository.Signing
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go
index e47bc56d08..d294934622 100644
--- a/routers/web/repo/view.go
+++ b/routers/web/repo/view.go
@@ -60,9 +60,9 @@ const (
)
type fileInfo struct {
- fileSize int64
- lfsMeta *lfs.Pointer
- st typesniffer.SniffedType
+ blobOrLfsSize int64
+ lfsMeta *lfs.Pointer
+ st typesniffer.SniffedType
}
func (fi *fileInfo) isLFSFile() bool {
@@ -81,7 +81,7 @@ func getFileReader(ctx gocontext.Context, repoID int64, blob *git.Blob) (buf []b
n, _ := util.ReadAtMost(dataRc, buf)
buf = buf[:n]
- fi = &fileInfo{fileSize: blob.Size(), st: typesniffer.DetectContentType(buf)}
+ fi = &fileInfo{blobOrLfsSize: blob.Size(), st: typesniffer.DetectContentType(buf)}
// FIXME: what happens when README file is an image?
if !fi.st.IsText() || !setting.LFS.StartServer {
@@ -114,7 +114,7 @@ func getFileReader(ctx gocontext.Context, repoID int64, blob *git.Blob) (buf []b
}
buf = buf[:n]
fi.st = typesniffer.DetectContentType(buf)
- fi.fileSize = blob.Size()
+ fi.blobOrLfsSize = meta.Pointer.Size
fi.lfsMeta = &meta.Pointer
return buf, dataRc, fi, nil
}
diff --git a/routers/web/repo/view_file.go b/routers/web/repo/view_file.go
index afbbad4859..7f67034ada 100644
--- a/routers/web/repo/view_file.go
+++ b/routers/web/repo/view_file.go
@@ -226,7 +226,7 @@ func prepareFileView(ctx *context.Context, entry *git.TreeEntry) {
}
ctx.Data["IsLFSFile"] = fInfo.isLFSFile()
- ctx.Data["FileSize"] = fInfo.fileSize
+ ctx.Data["FileSize"] = fInfo.blobOrLfsSize
ctx.Data["IsRepresentableAsText"] = fInfo.st.IsRepresentableAsText()
ctx.Data["IsExecutable"] = entry.IsExecutable()
ctx.Data["CanCopyContent"] = fInfo.st.IsRepresentableAsText() || fInfo.st.IsImage()
@@ -243,7 +243,7 @@ func prepareFileView(ctx *context.Context, entry *git.TreeEntry) {
utf8Reader := charset.ToUTF8WithFallbackReader(io.MultiReader(bytes.NewReader(buf), dataRc), charset.ConvertOpts{})
switch {
- case fInfo.fileSize >= setting.UI.MaxDisplayFileSize:
+ case fInfo.blobOrLfsSize >= setting.UI.MaxDisplayFileSize:
ctx.Data["IsFileTooLarge"] = true
case handleFileViewRenderMarkup(ctx, entry.Name(), fInfo.st, buf, utf8Reader):
// it also sets ctx.Data["FileContent"] and more
diff --git a/routers/web/repo/view_home.go b/routers/web/repo/view_home.go
index 88d9fd8fe2..6b161df392 100644
--- a/routers/web/repo/view_home.go
+++ b/routers/web/repo/view_home.go
@@ -6,7 +6,6 @@ package repo
import (
"errors"
"fmt"
- "html/template"
"net/http"
"path"
"strconv"
@@ -76,16 +75,24 @@ func prepareOpenWithEditorApps(ctx *context.Context) {
}
for _, app := range apps {
schema, _, _ := strings.Cut(app.OpenURL, ":")
- var iconHTML template.HTML
- if schema == "vscode" || schema == "vscodium" || schema == "jetbrains" {
- iconHTML = svg.RenderHTML("gitea-"+schema, 16)
- } else {
- iconHTML = svg.RenderHTML("gitea-git", 16) // TODO: it could support user's customized icon in the future
+
+ var iconName string
+ switch schema {
+ case "vscode":
+ iconName = "octicon-vscode"
+ case "vscodium":
+ iconName = "gitea-vscodium"
+ case "jetbrains":
+ iconName = "gitea-jetbrains"
+ default:
+ // TODO: it could support user's customized icon in the future
+ iconName = "gitea-git"
}
+
tmplApps = append(tmplApps, map[string]any{
"DisplayName": app.DisplayName,
"OpenURL": app.OpenURL,
- "IconHTML": iconHTML,
+ "IconHTML": svg.RenderHTML(iconName, 16),
})
}
ctx.Data["OpenWithEditorApps"] = tmplApps
diff --git a/routers/web/repo/view_readme.go b/routers/web/repo/view_readme.go
index ba03febff3..edf38b7892 100644
--- a/routers/web/repo/view_readme.go
+++ b/routers/web/repo/view_readme.go
@@ -170,7 +170,7 @@ func prepareToRenderReadmeFile(ctx *context.Context, subfolder string, readmeFil
ctx.Data["FileIsText"] = fInfo.st.IsText()
ctx.Data["FileTreePath"] = readmeFullPath
- ctx.Data["FileSize"] = fInfo.fileSize
+ ctx.Data["FileSize"] = fInfo.blobOrLfsSize
ctx.Data["IsLFSFile"] = fInfo.isLFSFile()
if fInfo.isLFSFile() {
@@ -182,7 +182,7 @@ func prepareToRenderReadmeFile(ctx *context.Context, subfolder string, readmeFil
return
}
- if fInfo.fileSize >= setting.UI.MaxDisplayFileSize {
+ if fInfo.blobOrLfsSize >= setting.UI.MaxDisplayFileSize {
// Pretend that this is a normal text file to display 'This file is too large to be shown'
ctx.Data["IsFileTooLarge"] = true
return
diff --git a/services/actions/clear_tasks.go b/services/actions/clear_tasks.go
index 3c7aa0b1a5..e49bda1b16 100644
--- a/services/actions/clear_tasks.go
+++ b/services/actions/clear_tasks.go
@@ -15,6 +15,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
+ "code.gitea.io/gitea/modules/util"
webhook_module "code.gitea.io/gitea/modules/webhook"
notify_service "code.gitea.io/gitea/services/notify"
)
@@ -36,13 +37,19 @@ func StopEndlessTasks(ctx context.Context) error {
}
func notifyWorkflowJobStatusUpdate(ctx context.Context, jobs []*actions_model.ActionRunJob) {
- if len(jobs) > 0 {
- CreateCommitStatus(ctx, jobs...)
- for _, job := range jobs {
- _ = job.LoadAttributes(ctx)
- notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil)
+ if len(jobs) == 0 {
+ return
+ }
+ for _, job := range jobs {
+ if err := job.LoadAttributes(ctx); err != nil {
+ log.Error("Failed to load job attributes: %v", err)
+ continue
}
- job := jobs[0]
+ CreateCommitStatusForRunJobs(ctx, job.Run, job)
+ notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil)
+ }
+
+ if job := jobs[0]; job.Run != nil && job.Run.Repo != nil {
notify_service.WorkflowRunStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job.Run)
}
}
@@ -50,15 +57,84 @@ func notifyWorkflowJobStatusUpdate(ctx context.Context, jobs []*actions_model.Ac
func CancelPreviousJobs(ctx context.Context, repoID int64, ref, workflowID string, event webhook_module.HookEventType) error {
jobs, err := actions_model.CancelPreviousJobs(ctx, repoID, ref, workflowID, event)
notifyWorkflowJobStatusUpdate(ctx, jobs)
+ EmitJobsIfReadyByJobs(jobs)
return err
}
func CleanRepoScheduleTasks(ctx context.Context, repo *repo_model.Repository) error {
jobs, err := actions_model.CleanRepoScheduleTasks(ctx, repo)
notifyWorkflowJobStatusUpdate(ctx, jobs)
+ EmitJobsIfReadyByJobs(jobs)
return err
}
+func shouldBlockJobByConcurrency(ctx context.Context, job *actions_model.ActionRunJob) (bool, error) {
+ if job.RawConcurrency != "" && !job.IsConcurrencyEvaluated {
+ // when the job depends on other jobs, we cannot evaluate its concurrency, so it should be blocked and will be evaluated again when its dependencies are done
+ return true, nil
+ }
+
+ if job.ConcurrencyGroup == "" || job.ConcurrencyCancel {
+ return false, nil
+ }
+
+ runs, jobs, err := actions_model.GetConcurrentRunsAndJobs(ctx, job.RepoID, job.ConcurrencyGroup, []actions_model.Status{actions_model.StatusRunning})
+ if err != nil {
+ return false, fmt.Errorf("GetConcurrentRunsAndJobs: %w", err)
+ }
+
+ return len(runs) > 0 || len(jobs) > 0, nil
+}
+
+// PrepareToStartJobWithConcurrency prepares a job to start by its evaluated concurrency group and cancelling previous jobs if necessary.
+// It returns the new status of the job (either StatusBlocked or StatusWaiting) and any error encountered during the process.
+func PrepareToStartJobWithConcurrency(ctx context.Context, job *actions_model.ActionRunJob) (actions_model.Status, error) {
+ shouldBlock, err := shouldBlockJobByConcurrency(ctx, job)
+ if err != nil {
+ return actions_model.StatusBlocked, err
+ }
+
+ // even if the current job is blocked, we still need to cancel previous "waiting/blocked" jobs in the same concurrency group
+ jobs, err := actions_model.CancelPreviousJobsByJobConcurrency(ctx, job)
+ if err != nil {
+ return actions_model.StatusBlocked, fmt.Errorf("CancelPreviousJobsByJobConcurrency: %w", err)
+ }
+ notifyWorkflowJobStatusUpdate(ctx, jobs)
+
+ return util.Iif(shouldBlock, actions_model.StatusBlocked, actions_model.StatusWaiting), nil
+}
+
+func shouldBlockRunByConcurrency(ctx context.Context, actionRun *actions_model.ActionRun) (bool, error) {
+ if actionRun.ConcurrencyGroup == "" || actionRun.ConcurrencyCancel {
+ return false, nil
+ }
+
+ runs, jobs, err := actions_model.GetConcurrentRunsAndJobs(ctx, actionRun.RepoID, actionRun.ConcurrencyGroup, []actions_model.Status{actions_model.StatusRunning})
+ if err != nil {
+ return false, fmt.Errorf("find concurrent runs and jobs: %w", err)
+ }
+
+ return len(runs) > 0 || len(jobs) > 0, nil
+}
+
+// PrepareToStartRunWithConcurrency prepares a run to start by its evaluated concurrency group and cancelling previous jobs if necessary.
+// It returns the new status of the run (either StatusBlocked or StatusWaiting) and any error encountered during the process.
+func PrepareToStartRunWithConcurrency(ctx context.Context, run *actions_model.ActionRun) (actions_model.Status, error) {
+ shouldBlock, err := shouldBlockRunByConcurrency(ctx, run)
+ if err != nil {
+ return actions_model.StatusBlocked, err
+ }
+
+ // even if the current run is blocked, we still need to cancel previous "waiting/blocked" jobs in the same concurrency group
+ jobs, err := actions_model.CancelPreviousJobsByRunConcurrency(ctx, run)
+ if err != nil {
+ return actions_model.StatusBlocked, fmt.Errorf("CancelPreviousJobsByRunConcurrency: %w", err)
+ }
+ notifyWorkflowJobStatusUpdate(ctx, jobs)
+
+ return util.Iif(shouldBlock, actions_model.StatusBlocked, actions_model.StatusWaiting), nil
+}
+
func stopTasks(ctx context.Context, opts actions_model.FindTaskOptions) error {
tasks, err := db.Find[actions_model.ActionTask](ctx, opts)
if err != nil {
@@ -95,6 +171,7 @@ func stopTasks(ctx context.Context, opts actions_model.FindTaskOptions) error {
}
notifyWorkflowJobStatusUpdate(ctx, jobs)
+ EmitJobsIfReadyByJobs(jobs)
return nil
}
@@ -103,7 +180,7 @@ func stopTasks(ctx context.Context, opts actions_model.FindTaskOptions) error {
func CancelAbandonedJobs(ctx context.Context) error {
jobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{
Statuses: []actions_model.Status{actions_model.StatusWaiting, actions_model.StatusBlocked},
- UpdatedBefore: timeutil.TimeStamp(time.Now().Add(-setting.Actions.AbandonedJobTimeout).Unix()),
+ UpdatedBefore: timeutil.TimeStampNow().AddDuration(-setting.Actions.AbandonedJobTimeout),
})
if err != nil {
log.Warn("find abandoned tasks: %v", err)
@@ -114,6 +191,7 @@ func CancelAbandonedJobs(ctx context.Context) error {
// Collect one job per run to send workflow run status update
updatedRuns := map[int64]*actions_model.ActionRunJob{}
+ updatedJobs := []*actions_model.ActionRunJob{}
for _, job := range jobs {
job.Status = actions_model.StatusCancelled
@@ -136,8 +214,12 @@ func CancelAbandonedJobs(ctx context.Context) error {
log.Warn("cancel abandoned job %v: %v", job.ID, err)
// go on
}
- CreateCommitStatus(ctx, job)
+ if job.Run == nil || job.Run.Repo == nil {
+ continue // error occurs during loading attributes, the following code that depends on "Run.Repo" will fail, so ignore and skip
+ }
+ CreateCommitStatusForRunJobs(ctx, job.Run, job)
if updated {
+ updatedJobs = append(updatedJobs, job)
notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil)
}
}
@@ -145,6 +227,7 @@ func CancelAbandonedJobs(ctx context.Context) error {
for _, job := range updatedRuns {
notify_service.WorkflowRunStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job.Run)
}
+ EmitJobsIfReadyByJobs(updatedJobs)
return nil
}
diff --git a/services/actions/commit_status.go b/services/actions/commit_status.go
index ef241e5091..d3f2b0f3cc 100644
--- a/services/actions/commit_status.go
+++ b/services/actions/commit_status.go
@@ -8,14 +8,15 @@ import (
"errors"
"fmt"
"path"
+ "strconv"
actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
+ repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
actions_module "code.gitea.io/gitea/modules/actions"
"code.gitea.io/gitea/modules/commitstatus"
- git "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
webhook_module "code.gitea.io/gitea/modules/webhook"
commitstatus_service "code.gitea.io/gitea/services/repository/commitstatus"
@@ -23,38 +24,46 @@ import (
"github.com/nektos/act/pkg/jobparser"
)
-// CreateCommitStatus creates a commit status for the given job.
+// CreateCommitStatusForRunJobs creates a commit status for the given job if it has a supported event and related commit.
// It won't return an error failed, but will log it, because it's not critical.
-func CreateCommitStatus(ctx context.Context, jobs ...*actions_model.ActionRunJob) {
+func CreateCommitStatusForRunJobs(ctx context.Context, run *actions_model.ActionRun, jobs ...*actions_model.ActionRunJob) {
+ // don't create commit status for cron job
+ if run.ScheduleID != 0 {
+ return
+ }
+
+ event, commitID, err := getCommitStatusEventNameAndCommitID(run)
+ if err != nil {
+ log.Error("GetCommitStatusEventNameAndSHA: %v", err)
+ }
+ if event == "" || commitID == "" {
+ return // unsupported event, or no commit id, or error occurs, do nothing
+ }
+
+ if err = run.LoadAttributes(ctx); err != nil {
+ log.Error("run.LoadAttributes: %v", err)
+ return
+ }
+
for _, job := range jobs {
- if err := createCommitStatus(ctx, job); err != nil {
+ if err = createCommitStatus(ctx, run.Repo, event, commitID, run, job); err != nil {
log.Error("Failed to create commit status for job %d: %v", job.ID, err)
}
}
}
-func createCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) error {
- if err := job.LoadAttributes(ctx); err != nil {
- return fmt.Errorf("load run: %w", err)
- }
-
- run := job.Run
-
- var (
- sha string
- event string
- )
+func getCommitStatusEventNameAndCommitID(run *actions_model.ActionRun) (event, commitID string, _ error) {
switch run.Event {
case webhook_module.HookEventPush:
event = "push"
payload, err := run.GetPushEventPayload()
if err != nil {
- return fmt.Errorf("GetPushEventPayload: %w", err)
+ return "", "", fmt.Errorf("GetPushEventPayload: %w", err)
}
if payload.HeadCommit == nil {
- return errors.New("head commit is missing in event payload")
+ return "", "", errors.New("head commit is missing in event payload")
}
- sha = payload.HeadCommit.ID
+ commitID = payload.HeadCommit.ID
case // pull_request
webhook_module.HookEventPullRequest,
webhook_module.HookEventPullRequestSync,
@@ -69,32 +78,33 @@ func createCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) er
}
payload, err := run.GetPullRequestEventPayload()
if err != nil {
- return fmt.Errorf("GetPullRequestEventPayload: %w", err)
+ return "", "", fmt.Errorf("GetPullRequestEventPayload: %w", err)
}
if payload.PullRequest == nil {
- return errors.New("pull request is missing in event payload")
+ return "", "", errors.New("pull request is missing in event payload")
} else if payload.PullRequest.Head == nil {
- return errors.New("head of pull request is missing in event payload")
+ return "", "", errors.New("head of pull request is missing in event payload")
}
- sha = payload.PullRequest.Head.Sha
+ commitID = payload.PullRequest.Head.Sha
case webhook_module.HookEventRelease:
event = string(run.Event)
- sha = run.CommitSHA
- default:
- return nil
+ commitID = run.CommitSHA
+ default: // do nothing, return empty
}
+ return event, commitID, nil
+}
- repo := run.Repo
+func createCommitStatus(ctx context.Context, repo *repo_model.Repository, event, commitID string, run *actions_model.ActionRun, job *actions_model.ActionRunJob) error {
// TODO: store workflow name as a field in ActionRun to avoid parsing
runName := path.Base(run.WorkflowID)
if wfs, err := jobparser.Parse(job.WorkflowPayload); err == nil && len(wfs) > 0 {
runName = wfs[0].Name
}
- ctxname := fmt.Sprintf("%s / %s (%s)", runName, job.Name, event)
+ ctxName := fmt.Sprintf("%s / %s (%s)", runName, job.Name, event)
state := toCommitStatus(job.Status)
- if statuses, err := git_model.GetLatestCommitStatus(ctx, repo.ID, sha, db.ListOptionsAll); err == nil {
+ if statuses, err := git_model.GetLatestCommitStatus(ctx, repo.ID, commitID, db.ListOptionsAll); err == nil {
for _, v := range statuses {
- if v.Context == ctxname {
+ if v.Context == ctxName {
if v.State == state {
// no need to update
return nil
@@ -106,7 +116,7 @@ func createCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) er
return fmt.Errorf("GetLatestCommitStatus: %w", err)
}
- description := ""
+ var description string
switch job.Status {
// TODO: if we want support description in different languages, we need to support i18n placeholders in it
case actions_model.StatusSuccess:
@@ -123,6 +133,8 @@ func createCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) er
description = "Waiting to run"
case actions_model.StatusBlocked:
description = "Blocked by required conditions"
+ default:
+ description = "Unknown status: " + strconv.Itoa(int(job.Status))
}
index, err := getIndexOfJob(ctx, job)
@@ -131,20 +143,16 @@ func createCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) er
}
creator := user_model.NewActionsUser()
- commitID, err := git.NewIDFromString(sha)
- if err != nil {
- return fmt.Errorf("HashTypeInterfaceFromHashString: %w", err)
- }
status := git_model.CommitStatus{
- SHA: sha,
+ SHA: commitID,
TargetURL: fmt.Sprintf("%s/jobs/%d", run.Link(), index),
Description: description,
- Context: ctxname,
+ Context: ctxName,
CreatorID: creator.ID,
State: state,
}
- return commitstatus_service.CreateCommitStatus(ctx, repo, creator, commitID.String(), &status)
+ return commitstatus_service.CreateCommitStatus(ctx, repo, creator, commitID, &status)
}
func toCommitStatus(status actions_model.Status) commitstatus.CommitStatusState {
diff --git a/services/actions/concurrency.go b/services/actions/concurrency.go
new file mode 100644
index 0000000000..0908302709
--- /dev/null
+++ b/services/actions/concurrency.go
@@ -0,0 +1,115 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package actions
+
+import (
+ "context"
+ "fmt"
+
+ actions_model "code.gitea.io/gitea/models/actions"
+ "code.gitea.io/gitea/modules/json"
+ api "code.gitea.io/gitea/modules/structs"
+
+ "github.com/nektos/act/pkg/jobparser"
+ act_model "github.com/nektos/act/pkg/model"
+ "gopkg.in/yaml.v3"
+)
+
+// EvaluateRunConcurrencyFillModel evaluates the expressions in a run-level (workflow) concurrency,
+// and fills the run's model fields with `concurrency.group` and `concurrency.cancel-in-progress`.
+// Workflow-level concurrency doesn't depend on the job outputs, so it can always be evaluated if there is no syntax error.
+// See https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#concurrency
+func EvaluateRunConcurrencyFillModel(ctx context.Context, run *actions_model.ActionRun, wfRawConcurrency *act_model.RawConcurrency, vars map[string]string) error {
+ if err := run.LoadAttributes(ctx); err != nil {
+ return fmt.Errorf("run LoadAttributes: %w", err)
+ }
+
+ actionsRunCtx := GenerateGiteaContext(run, nil)
+ jobResults := map[string]*jobparser.JobResult{"": {}}
+ inputs, err := getInputsFromRun(run)
+ if err != nil {
+ return fmt.Errorf("get inputs: %w", err)
+ }
+
+ rawConcurrency, err := yaml.Marshal(wfRawConcurrency)
+ if err != nil {
+ return fmt.Errorf("marshal raw concurrency: %w", err)
+ }
+ run.RawConcurrency = string(rawConcurrency)
+ run.ConcurrencyGroup, run.ConcurrencyCancel, err = jobparser.EvaluateConcurrency(wfRawConcurrency, "", nil, actionsRunCtx, jobResults, vars, inputs)
+ if err != nil {
+ return fmt.Errorf("evaluate concurrency: %w", err)
+ }
+ return nil
+}
+
+func findJobNeedsAndFillJobResults(ctx context.Context, job *actions_model.ActionRunJob) (map[string]*jobparser.JobResult, error) {
+ taskNeeds, err := FindTaskNeeds(ctx, job)
+ if err != nil {
+ return nil, fmt.Errorf("find task needs: %w", err)
+ }
+ jobResults := make(map[string]*jobparser.JobResult, len(taskNeeds))
+ for jobID, taskNeed := range taskNeeds {
+ jobResult := &jobparser.JobResult{
+ Result: taskNeed.Result.String(),
+ Outputs: taskNeed.Outputs,
+ }
+ jobResults[jobID] = jobResult
+ }
+ jobResults[job.JobID] = &jobparser.JobResult{
+ Needs: job.Needs,
+ }
+ return jobResults, nil
+}
+
+// EvaluateJobConcurrencyFillModel evaluates the expressions in a job-level concurrency,
+// and fills the job's model fields with `concurrency.group` and `concurrency.cancel-in-progress`.
+// Job-level concurrency may depend on other job's outputs (via `needs`): `concurrency.group: my-group-${{ needs.job1.outputs.out1 }}`
+// If the needed jobs haven't been executed yet, this evaluation will also fail.
+// See https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_idconcurrency
+func EvaluateJobConcurrencyFillModel(ctx context.Context, run *actions_model.ActionRun, actionRunJob *actions_model.ActionRunJob, vars map[string]string) error {
+ if err := actionRunJob.LoadAttributes(ctx); err != nil {
+ return fmt.Errorf("job LoadAttributes: %w", err)
+ }
+
+ var rawConcurrency act_model.RawConcurrency
+ if err := yaml.Unmarshal([]byte(actionRunJob.RawConcurrency), &rawConcurrency); err != nil {
+ return fmt.Errorf("unmarshal raw concurrency: %w", err)
+ }
+
+ actionsJobCtx := GenerateGiteaContext(run, actionRunJob)
+
+ jobResults, err := findJobNeedsAndFillJobResults(ctx, actionRunJob)
+ if err != nil {
+ return fmt.Errorf("find job needs and fill job results: %w", err)
+ }
+
+ inputs, err := getInputsFromRun(run)
+ if err != nil {
+ return fmt.Errorf("get inputs: %w", err)
+ }
+
+ workflowJob, err := actionRunJob.ParseJob()
+ if err != nil {
+ return fmt.Errorf("load job %d: %w", actionRunJob.ID, err)
+ }
+
+ actionRunJob.ConcurrencyGroup, actionRunJob.ConcurrencyCancel, err = jobparser.EvaluateConcurrency(&rawConcurrency, actionRunJob.JobID, workflowJob, actionsJobCtx, jobResults, vars, inputs)
+ if err != nil {
+ return fmt.Errorf("evaluate concurrency: %w", err)
+ }
+ actionRunJob.IsConcurrencyEvaluated = true
+ return nil
+}
+
+func getInputsFromRun(run *actions_model.ActionRun) (map[string]any, error) {
+ if run.Event != "workflow_dispatch" {
+ return map[string]any{}, nil
+ }
+ var payload api.WorkflowDispatchPayload
+ if err := json.Unmarshal([]byte(run.EventPayload), &payload); err != nil {
+ return nil, err
+ }
+ return payload.Inputs, nil
+}
diff --git a/services/actions/job_emitter.go b/services/actions/job_emitter.go
index 47c9f59094..74a8a127ef 100644
--- a/services/actions/job_emitter.go
+++ b/services/actions/job_emitter.go
@@ -10,12 +10,14 @@ import (
actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db"
+ "code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/queue"
+ "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/util"
notify_service "code.gitea.io/gitea/services/notify"
- "github.com/nektos/act/pkg/jobparser"
"xorm.io/builder"
)
@@ -25,7 +27,7 @@ type jobUpdate struct {
RunID int64
}
-func EmitJobsIfReady(runID int64) error {
+func EmitJobsIfReadyByRun(runID int64) error {
err := jobEmitterQueue.Push(&jobUpdate{
RunID: runID,
})
@@ -35,53 +37,77 @@ func EmitJobsIfReady(runID int64) error {
return err
}
+func EmitJobsIfReadyByJobs(jobs []*actions_model.ActionRunJob) {
+ checkedRuns := make(container.Set[int64])
+ for _, job := range jobs {
+ if !job.Status.IsDone() || checkedRuns.Contains(job.RunID) {
+ continue
+ }
+ if err := EmitJobsIfReadyByRun(job.RunID); err != nil {
+ log.Error("Check jobs of run %d: %v", job.RunID, err)
+ }
+ checkedRuns.Add(job.RunID)
+ }
+}
+
func jobEmitterQueueHandler(items ...*jobUpdate) []*jobUpdate {
ctx := graceful.GetManager().ShutdownContext()
var ret []*jobUpdate
for _, update := range items {
- if err := checkJobsOfRun(ctx, update.RunID); err != nil {
+ if err := checkJobsByRunID(ctx, update.RunID); err != nil {
+ log.Error("check run %d: %v", update.RunID, err)
ret = append(ret, update)
}
}
return ret
}
-func checkJobsOfRun(ctx context.Context, runID int64) error {
- jobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: runID})
- if err != nil {
- return err
+func checkJobsByRunID(ctx context.Context, runID int64) error {
+ run, exist, err := db.GetByID[actions_model.ActionRun](ctx, runID)
+ if !exist {
+ return fmt.Errorf("run %d does not exist", runID)
}
- var updatedjobs []*actions_model.ActionRunJob
+ if err != nil {
+ return fmt.Errorf("get action run: %w", err)
+ }
+ var jobs, updatedJobs []*actions_model.ActionRunJob
if err := db.WithTx(ctx, func(ctx context.Context) error {
- idToJobs := make(map[string][]*actions_model.ActionRunJob, len(jobs))
- for _, job := range jobs {
- idToJobs[job.JobID] = append(idToJobs[job.JobID], job)
+ // check jobs of the current run
+ if js, ujs, err := checkJobsOfRun(ctx, run); err != nil {
+ return err
+ } else {
+ jobs = append(jobs, js...)
+ updatedJobs = append(updatedJobs, ujs...)
}
-
- updates := newJobStatusResolver(jobs).Resolve()
- for _, job := range jobs {
- if status, ok := updates[job.ID]; ok {
- job.Status = status
- if n, err := actions_model.UpdateRunJob(ctx, job, builder.Eq{"status": actions_model.StatusBlocked}, "status"); err != nil {
- return err
- } else if n != 1 {
- return fmt.Errorf("no affected for updating blocked job %v", job.ID)
- }
- updatedjobs = append(updatedjobs, job)
- }
+ if js, ujs, err := checkRunConcurrency(ctx, run); err != nil {
+ return err
+ } else {
+ jobs = append(jobs, js...)
+ updatedJobs = append(updatedJobs, ujs...)
}
return nil
}); err != nil {
return err
}
- CreateCommitStatus(ctx, jobs...)
- for _, job := range updatedjobs {
+ CreateCommitStatusForRunJobs(ctx, run, jobs...)
+ for _, job := range updatedJobs {
_ = job.LoadAttributes(ctx)
notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil)
}
- if len(jobs) > 0 {
+ runJobs := make(map[int64][]*actions_model.ActionRunJob)
+ for _, job := range jobs {
+ runJobs[job.RunID] = append(runJobs[job.RunID], job)
+ }
+ runUpdatedJobs := make(map[int64][]*actions_model.ActionRunJob)
+ for _, uj := range updatedJobs {
+ runUpdatedJobs[uj.RunID] = append(runUpdatedJobs[uj.RunID], uj)
+ }
+ for runID, js := range runJobs {
+ if len(runUpdatedJobs[runID]) == 0 {
+ continue
+ }
runUpdated := true
- for _, job := range jobs {
+ for _, job := range js {
if !job.Status.IsDone() {
runUpdated = false
break
@@ -94,6 +120,118 @@ func checkJobsOfRun(ctx context.Context, runID int64) error {
return nil
}
+// findBlockedRunByConcurrency finds the blocked concurrent run in a repo and returns `nil, nil` when there is no blocked run.
+func findBlockedRunByConcurrency(ctx context.Context, repoID int64, concurrencyGroup string) (*actions_model.ActionRun, error) {
+ if concurrencyGroup == "" {
+ return nil, nil
+ }
+ cRuns, cJobs, err := actions_model.GetConcurrentRunsAndJobs(ctx, repoID, concurrencyGroup, []actions_model.Status{actions_model.StatusBlocked})
+ if err != nil {
+ return nil, fmt.Errorf("find concurrent runs and jobs: %w", err)
+ }
+
+ // There can be at most one blocked run or job
+ var concurrentRun *actions_model.ActionRun
+ if len(cRuns) > 0 {
+ concurrentRun = cRuns[0]
+ } else if len(cJobs) > 0 {
+ jobRun, exist, err := db.GetByID[actions_model.ActionRun](ctx, cJobs[0].RunID)
+ if !exist {
+ return nil, fmt.Errorf("run %d does not exist", cJobs[0].RunID)
+ }
+ if err != nil {
+ return nil, fmt.Errorf("get run by job %d: %w", cJobs[0].ID, err)
+ }
+ concurrentRun = jobRun
+ }
+
+ return concurrentRun, nil
+}
+
+func checkRunConcurrency(ctx context.Context, run *actions_model.ActionRun) (jobs, updatedJobs []*actions_model.ActionRunJob, err error) {
+ checkedConcurrencyGroup := make(container.Set[string])
+
+ // check run (workflow-level) concurrency
+ if run.ConcurrencyGroup != "" {
+ concurrentRun, err := findBlockedRunByConcurrency(ctx, run.RepoID, run.ConcurrencyGroup)
+ if err != nil {
+ return nil, nil, fmt.Errorf("find blocked run by concurrency: %w", err)
+ }
+ if concurrentRun != nil && !concurrentRun.NeedApproval {
+ js, ujs, err := checkJobsOfRun(ctx, concurrentRun)
+ if err != nil {
+ return nil, nil, err
+ }
+ jobs = append(jobs, js...)
+ updatedJobs = append(updatedJobs, ujs...)
+ }
+ checkedConcurrencyGroup.Add(run.ConcurrencyGroup)
+ }
+
+ // check job concurrency
+ runJobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: run.ID})
+ if err != nil {
+ return nil, nil, fmt.Errorf("find run %d jobs: %w", run.ID, err)
+ }
+ for _, job := range runJobs {
+ if !job.Status.IsDone() {
+ continue
+ }
+ if job.ConcurrencyGroup == "" && checkedConcurrencyGroup.Contains(job.ConcurrencyGroup) {
+ continue
+ }
+ concurrentRun, err := findBlockedRunByConcurrency(ctx, job.RepoID, job.ConcurrencyGroup)
+ if err != nil {
+ return nil, nil, fmt.Errorf("find blocked run by concurrency: %w", err)
+ }
+ if concurrentRun != nil && !concurrentRun.NeedApproval {
+ js, ujs, err := checkJobsOfRun(ctx, concurrentRun)
+ if err != nil {
+ return nil, nil, err
+ }
+ jobs = append(jobs, js...)
+ updatedJobs = append(updatedJobs, ujs...)
+ }
+ checkedConcurrencyGroup.Add(job.ConcurrencyGroup)
+ }
+ return jobs, updatedJobs, nil
+}
+
+func checkJobsOfRun(ctx context.Context, run *actions_model.ActionRun) (jobs, updatedJobs []*actions_model.ActionRunJob, err error) {
+ jobs, err = db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: run.ID})
+ if err != nil {
+ return nil, nil, err
+ }
+ vars, err := actions_model.GetVariablesOfRun(ctx, run)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ if err = db.WithTx(ctx, func(ctx context.Context) error {
+ for _, job := range jobs {
+ job.Run = run
+ }
+
+ updates := newJobStatusResolver(jobs, vars).Resolve(ctx)
+ for _, job := range jobs {
+ if status, ok := updates[job.ID]; ok {
+ job.Status = status
+ if n, err := actions_model.UpdateRunJob(ctx, job, builder.Eq{"status": actions_model.StatusBlocked}, "status"); err != nil {
+ return err
+ } else if n != 1 {
+ return fmt.Errorf("no affected for updating blocked job %v", job.ID)
+ }
+ updatedJobs = append(updatedJobs, job)
+ }
+ }
+ return nil
+ }); err != nil {
+ return nil, nil, err
+ }
+
+ return jobs, updatedJobs, nil
+}
+
func NotifyWorkflowRunStatusUpdateWithReload(ctx context.Context, job *actions_model.ActionRunJob) {
job.Run = nil
if err := job.LoadAttributes(ctx); err != nil {
@@ -107,9 +245,10 @@ type jobStatusResolver struct {
statuses map[int64]actions_model.Status
needs map[int64][]int64
jobMap map[int64]*actions_model.ActionRunJob
+ vars map[string]string
}
-func newJobStatusResolver(jobs actions_model.ActionJobList) *jobStatusResolver {
+func newJobStatusResolver(jobs actions_model.ActionJobList, vars map[string]string) *jobStatusResolver {
idToJobs := make(map[string][]*actions_model.ActionRunJob, len(jobs))
jobMap := make(map[int64]*actions_model.ActionRunJob)
for _, job := range jobs {
@@ -131,13 +270,14 @@ func newJobStatusResolver(jobs actions_model.ActionJobList) *jobStatusResolver {
statuses: statuses,
needs: needs,
jobMap: jobMap,
+ vars: vars,
}
}
-func (r *jobStatusResolver) Resolve() map[int64]actions_model.Status {
+func (r *jobStatusResolver) Resolve(ctx context.Context) map[int64]actions_model.Status {
ret := map[int64]actions_model.Status{}
for i := 0; i < len(r.statuses); i++ {
- updated := r.resolve()
+ updated := r.resolve(ctx)
if len(updated) == 0 {
return ret
}
@@ -149,43 +289,86 @@ func (r *jobStatusResolver) Resolve() map[int64]actions_model.Status {
return ret
}
-func (r *jobStatusResolver) resolve() map[int64]actions_model.Status {
+func (r *jobStatusResolver) resolveCheckNeeds(id int64) (allDone, allSucceed bool) {
+ allDone, allSucceed = true, true
+ for _, need := range r.needs[id] {
+ needStatus := r.statuses[need]
+ if !needStatus.IsDone() {
+ allDone = false
+ }
+ if needStatus.In(actions_model.StatusFailure, actions_model.StatusCancelled, actions_model.StatusSkipped) {
+ allSucceed = false
+ }
+ }
+ return allDone, allSucceed
+}
+
+func (r *jobStatusResolver) resolveJobHasIfCondition(actionRunJob *actions_model.ActionRunJob) (hasIf bool) {
+ // FIXME evaluate this on the server side
+ if job, err := actionRunJob.ParseJob(); err == nil {
+ return len(job.If.Value) > 0
+ }
+ return hasIf
+}
+
+func (r *jobStatusResolver) resolve(ctx context.Context) map[int64]actions_model.Status {
ret := map[int64]actions_model.Status{}
for id, status := range r.statuses {
+ actionRunJob := r.jobMap[id]
if status != actions_model.StatusBlocked {
continue
}
- allDone, allSucceed := true, true
- for _, need := range r.needs[id] {
- needStatus := r.statuses[need]
- if !needStatus.IsDone() {
- allDone = false
- }
- if needStatus.In(actions_model.StatusFailure, actions_model.StatusCancelled, actions_model.StatusSkipped) {
- allSucceed = false
+ allDone, allSucceed := r.resolveCheckNeeds(id)
+ if !allDone {
+ continue
+ }
+
+ // update concurrency and check whether the job can run now
+ err := updateConcurrencyEvaluationForJobWithNeeds(ctx, actionRunJob, r.vars)
+ if err != nil {
+ // The err can be caused by different cases: database error, or syntax error, or the needed jobs haven't completed
+ // At the moment there is no way to distinguish them.
+ // Actually, for most cases, the error is caused by "syntax error" / "the needed jobs haven't completed (skipped?)"
+ // TODO: if workflow or concurrency expression has syntax error, there should be a user error message, need to show it to end users
+ log.Debug("updateConcurrencyEvaluationForJobWithNeeds failed, this job will stay blocked: job: %d, err: %v", id, err)
+ continue
+ }
+
+ shouldStartJob := true
+ if !allSucceed {
+ // Not all dependent jobs completed successfully:
+ // * if the job has "if" condition, it can be started, then the act_runner will evaluate the "if" condition.
+ // * otherwise, the job should be skipped.
+ shouldStartJob = r.resolveJobHasIfCondition(actionRunJob)
+ }
+
+ newStatus := util.Iif(shouldStartJob, actions_model.StatusWaiting, actions_model.StatusSkipped)
+ if newStatus == actions_model.StatusWaiting {
+ newStatus, err = PrepareToStartJobWithConcurrency(ctx, actionRunJob)
+ if err != nil {
+ log.Error("ShouldBlockJobByConcurrency failed, this job will stay blocked: job: %d, err: %v", id, err)
}
}
- if allDone {
- if allSucceed {
- ret[id] = actions_model.StatusWaiting
- } else {
- // Check if the job has an "if" condition
- hasIf := false
- if wfJobs, _ := jobparser.Parse(r.jobMap[id].WorkflowPayload); len(wfJobs) == 1 {
- _, wfJob := wfJobs[0].Job()
- hasIf = len(wfJob.If.Value) > 0
- }
- if hasIf {
- // act_runner will check the "if" condition
- ret[id] = actions_model.StatusWaiting
- } else {
- // If the "if" condition is empty and not all dependent jobs completed successfully,
- // the job should be skipped.
- ret[id] = actions_model.StatusSkipped
- }
- }
+ if newStatus != actions_model.StatusBlocked {
+ ret[id] = newStatus
}
}
return ret
}
+
+func updateConcurrencyEvaluationForJobWithNeeds(ctx context.Context, actionRunJob *actions_model.ActionRunJob, vars map[string]string) error {
+ if setting.IsInTesting && actionRunJob.RepoID == 0 {
+ return nil // for testing purpose only, no repo, no evaluation
+ }
+
+ err := EvaluateJobConcurrencyFillModel(ctx, actionRunJob.Run, actionRunJob, vars)
+ if err != nil {
+ return fmt.Errorf("evaluate job concurrency: %w", err)
+ }
+
+ if _, err := actions_model.UpdateRunJob(ctx, actionRunJob, nil, "concurrency_group", "concurrency_cancel", "is_concurrency_evaluated"); err != nil {
+ return fmt.Errorf("update run job: %w", err)
+ }
+ return nil
+}
diff --git a/services/actions/job_emitter_test.go b/services/actions/job_emitter_test.go
index 58c2dc3b24..a2152fb270 100644
--- a/services/actions/job_emitter_test.go
+++ b/services/actions/job_emitter_test.go
@@ -129,8 +129,8 @@ jobs:
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- r := newJobStatusResolver(tt.jobs)
- assert.Equal(t, tt.want, r.Resolve())
+ r := newJobStatusResolver(tt.jobs, nil)
+ assert.Equal(t, tt.want, r.Resolve(t.Context()))
})
}
}
diff --git a/services/actions/notifier_helper.go b/services/actions/notifier_helper.go
index d0d2572b0b..d17955b029 100644
--- a/services/actions/notifier_helper.go
+++ b/services/actions/notifier_helper.go
@@ -27,9 +27,7 @@ import (
api "code.gitea.io/gitea/modules/structs"
webhook_module "code.gitea.io/gitea/modules/webhook"
"code.gitea.io/gitea/services/convert"
- notify_service "code.gitea.io/gitea/services/notify"
- "github.com/nektos/act/pkg/jobparser"
"github.com/nektos/act/pkg/model"
)
@@ -346,66 +344,10 @@ func handleWorkflows(
run.NeedApproval = need
- if err := run.LoadAttributes(ctx); err != nil {
- log.Error("LoadAttributes: %v", err)
+ if err := PrepareRunAndInsert(ctx, dwf.Content, run, nil); err != nil {
+ log.Error("PrepareRunAndInsert: %v", err)
continue
}
-
- vars, err := actions_model.GetVariablesOfRun(ctx, run)
- if err != nil {
- log.Error("GetVariablesOfRun: %v", err)
- continue
- }
-
- giteaCtx := GenerateGiteaContext(run, nil)
-
- jobs, err := jobparser.Parse(dwf.Content, jobparser.WithVars(vars), jobparser.WithGitContext(giteaCtx.ToGitHubContext()))
- if err != nil {
- log.Error("jobparser.Parse: %v", err)
- continue
- }
-
- if len(jobs) > 0 && jobs[0].RunName != "" {
- run.Title = jobs[0].RunName
- }
-
- // cancel running jobs if the event is push or pull_request_sync
- if run.Event == webhook_module.HookEventPush ||
- run.Event == webhook_module.HookEventPullRequestSync {
- if err := CancelPreviousJobs(
- ctx,
- run.RepoID,
- run.Ref,
- run.WorkflowID,
- run.Event,
- ); err != nil {
- log.Error("CancelPreviousJobs: %v", err)
- }
- }
-
- if err := actions_model.InsertRun(ctx, run, jobs); err != nil {
- log.Error("InsertRun: %v", err)
- continue
- }
-
- alljobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: run.ID})
- if err != nil {
- log.Error("FindRunJobs: %v", err)
- continue
- }
- CreateCommitStatus(ctx, alljobs...)
- if len(alljobs) > 0 {
- job := alljobs[0]
- err := job.LoadRun(ctx)
- if err != nil {
- log.Error("LoadRun: %v", err)
- continue
- }
- notify_service.WorkflowRunStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job.Run)
- }
- for _, job := range alljobs {
- notify_service.WorkflowJobStatusUpdate(ctx, input.Repo, input.Doer, job, nil)
- }
}
return nil
}
@@ -560,24 +502,6 @@ func handleSchedules(
Content: dwf.Content,
}
- vars, err := actions_model.GetVariablesOfRun(ctx, run.ToActionRun())
- if err != nil {
- log.Error("GetVariablesOfRun: %v", err)
- continue
- }
-
- giteaCtx := GenerateGiteaContext(run.ToActionRun(), nil)
-
- jobs, err := jobparser.Parse(dwf.Content, jobparser.WithVars(vars), jobparser.WithGitContext(giteaCtx.ToGitHubContext()))
- if err != nil {
- log.Error("jobparser.Parse: %v", err)
- continue
- }
-
- if len(jobs) > 0 && jobs[0].RunName != "" {
- run.Title = jobs[0].RunName
- }
-
crons = append(crons, run)
}
diff --git a/services/actions/run.go b/services/actions/run.go
new file mode 100644
index 0000000000..90413e9bc2
--- /dev/null
+++ b/services/actions/run.go
@@ -0,0 +1,178 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package actions
+
+import (
+ "context"
+ "fmt"
+
+ actions_model "code.gitea.io/gitea/models/actions"
+ "code.gitea.io/gitea/models/db"
+ "code.gitea.io/gitea/modules/util"
+ notify_service "code.gitea.io/gitea/services/notify"
+
+ "github.com/nektos/act/pkg/jobparser"
+ "gopkg.in/yaml.v3"
+)
+
+// PrepareRunAndInsert prepares a run and inserts it into the database
+// It parses the workflow content, evaluates concurrency if needed, and inserts the run and its jobs into the database.
+// The title will be cut off at 255 characters if it's longer than 255 characters.
+func PrepareRunAndInsert(ctx context.Context, content []byte, run *actions_model.ActionRun, inputsWithDefaults map[string]any) error {
+ if err := run.LoadAttributes(ctx); err != nil {
+ return fmt.Errorf("LoadAttributes: %w", err)
+ }
+
+ vars, err := actions_model.GetVariablesOfRun(ctx, run)
+ if err != nil {
+ return fmt.Errorf("GetVariablesOfRun: %w", err)
+ }
+
+ wfRawConcurrency, err := jobparser.ReadWorkflowRawConcurrency(content)
+ if err != nil {
+ return fmt.Errorf("ReadWorkflowRawConcurrency: %w", err)
+ }
+
+ if wfRawConcurrency != nil {
+ err = EvaluateRunConcurrencyFillModel(ctx, run, wfRawConcurrency, vars)
+ if err != nil {
+ return fmt.Errorf("EvaluateRunConcurrencyFillModel: %w", err)
+ }
+ }
+
+ giteaCtx := GenerateGiteaContext(run, nil)
+
+ jobs, err := jobparser.Parse(content, jobparser.WithVars(vars), jobparser.WithGitContext(giteaCtx.ToGitHubContext()), jobparser.WithInputs(inputsWithDefaults))
+ if err != nil {
+ return fmt.Errorf("parse workflow: %w", err)
+ }
+
+ if len(jobs) > 0 && jobs[0].RunName != "" {
+ run.Title = jobs[0].RunName
+ }
+
+ if err = InsertRun(ctx, run, jobs, vars); err != nil {
+ return fmt.Errorf("InsertRun: %w", err)
+ }
+
+ // Load the newly inserted jobs with all fields from database (the job models in InsertRun are partial, so load again)
+ allJobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: run.ID})
+ if err != nil {
+ return fmt.Errorf("FindRunJob: %w", err)
+ }
+
+ CreateCommitStatusForRunJobs(ctx, run, allJobs...)
+
+ notify_service.WorkflowRunStatusUpdate(ctx, run.Repo, run.TriggerUser, run)
+ for _, job := range allJobs {
+ notify_service.WorkflowJobStatusUpdate(ctx, run.Repo, run.TriggerUser, job, nil)
+ }
+
+ return nil
+}
+
+// InsertRun inserts a run
+// The title will be cut off at 255 characters if it's longer than 255 characters.
+func InsertRun(ctx context.Context, run *actions_model.ActionRun, jobs []*jobparser.SingleWorkflow, vars map[string]string) error {
+ return db.WithTx(ctx, func(ctx context.Context) error {
+ index, err := db.GetNextResourceIndex(ctx, "action_run_index", run.RepoID)
+ if err != nil {
+ return err
+ }
+ run.Index = index
+ run.Title = util.EllipsisDisplayString(run.Title, 255)
+
+ // check run (workflow-level) concurrency
+ run.Status, err = PrepareToStartRunWithConcurrency(ctx, run)
+ if err != nil {
+ return err
+ }
+
+ if err := db.Insert(ctx, run); err != nil {
+ return err
+ }
+
+ if err := run.LoadRepo(ctx); err != nil {
+ return err
+ }
+
+ if err := actions_model.UpdateRepoRunsNumbers(ctx, run.Repo); err != nil {
+ return err
+ }
+
+ runJobs := make([]*actions_model.ActionRunJob, 0, len(jobs))
+ var hasWaitingJobs bool
+ for _, v := range jobs {
+ id, job := v.Job()
+ needs := job.Needs()
+ if err := v.SetJob(id, job.EraseNeeds()); err != nil {
+ return err
+ }
+ payload, _ := v.Marshal()
+
+ shouldBlockJob := len(needs) > 0 || run.NeedApproval || run.Status == actions_model.StatusBlocked
+
+ job.Name = util.EllipsisDisplayString(job.Name, 255)
+ runJob := &actions_model.ActionRunJob{
+ RunID: run.ID,
+ RepoID: run.RepoID,
+ OwnerID: run.OwnerID,
+ CommitSHA: run.CommitSHA,
+ IsForkPullRequest: run.IsForkPullRequest,
+ Name: job.Name,
+ WorkflowPayload: payload,
+ JobID: id,
+ Needs: needs,
+ RunsOn: job.RunsOn(),
+ Status: util.Iif(shouldBlockJob, actions_model.StatusBlocked, actions_model.StatusWaiting),
+ }
+ // check job concurrency
+ if job.RawConcurrency != nil {
+ rawConcurrency, err := yaml.Marshal(job.RawConcurrency)
+ if err != nil {
+ return fmt.Errorf("marshal raw concurrency: %w", err)
+ }
+ runJob.RawConcurrency = string(rawConcurrency)
+
+ // do not evaluate job concurrency when it requires `needs`, the jobs with `needs` will be evaluated later by job emitter
+ if len(needs) == 0 {
+ err = EvaluateJobConcurrencyFillModel(ctx, run, runJob, vars)
+ if err != nil {
+ return fmt.Errorf("evaluate job concurrency: %w", err)
+ }
+ }
+
+ // If a job needs other jobs ("needs" is not empty), its status is set to StatusBlocked at the entry of the loop
+ // No need to check job concurrency for a blocked job (it will be checked by job emitter later)
+ if runJob.Status == actions_model.StatusWaiting {
+ runJob.Status, err = PrepareToStartJobWithConcurrency(ctx, runJob)
+ if err != nil {
+ return fmt.Errorf("prepare to start job with concurrency: %w", err)
+ }
+ }
+ }
+
+ hasWaitingJobs = hasWaitingJobs || runJob.Status == actions_model.StatusWaiting
+ if err := db.Insert(ctx, runJob); err != nil {
+ return err
+ }
+
+ runJobs = append(runJobs, runJob)
+ }
+
+ run.Status = actions_model.AggregateJobStatus(runJobs)
+ if err := actions_model.UpdateRun(ctx, run, "status"); err != nil {
+ return err
+ }
+
+ // if there is a job in the waiting status, increase tasks version.
+ if hasWaitingJobs {
+ if err := actions_model.IncreaseTaskVersion(ctx, run.OwnerID, run.RepoID); err != nil {
+ return err
+ }
+ }
+
+ return nil
+ })
+}
diff --git a/services/actions/schedule_tasks.go b/services/actions/schedule_tasks.go
index c029c5a1a2..037bf5cddd 100644
--- a/services/actions/schedule_tasks.go
+++ b/services/actions/schedule_tasks.go
@@ -15,9 +15,6 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/timeutil"
webhook_module "code.gitea.io/gitea/modules/webhook"
- notify_service "code.gitea.io/gitea/services/notify"
-
- "github.com/nektos/act/pkg/jobparser"
)
// StartScheduleTasks start the task
@@ -53,20 +50,6 @@ func startTasks(ctx context.Context) error {
// Loop through each spec and create a schedule task for it
for _, row := range specs {
- // cancel running jobs if the event is push
- if row.Schedule.Event == webhook_module.HookEventPush {
- // cancel running jobs of the same workflow
- if err := CancelPreviousJobs(
- ctx,
- row.RepoID,
- row.Schedule.Ref,
- row.Schedule.WorkflowID,
- webhook_module.HookEventSchedule,
- ); err != nil {
- log.Error("CancelPreviousJobs: %v", err)
- }
- }
-
if row.Repo.IsArchived {
// Skip if the repo is archived
continue
@@ -133,34 +116,12 @@ func CreateScheduleTask(ctx context.Context, cron *actions_model.ActionSchedule)
Status: actions_model.StatusWaiting,
}
- vars, err := actions_model.GetVariablesOfRun(ctx, run)
- if err != nil {
- log.Error("GetVariablesOfRun: %v", err)
- return err
- }
-
- // Parse the workflow specification from the cron schedule
- workflows, err := jobparser.Parse(cron.Content, jobparser.WithVars(vars))
- if err != nil {
- return err
- }
-
+ // FIXME cron.Content might be outdated if the workflow file has been changed.
+ // Load the latest sha from default branch
// Insert the action run and its associated jobs into the database
- if err := actions_model.InsertRun(ctx, run, workflows); err != nil {
+ if err := PrepareRunAndInsert(ctx, cron.Content, run, nil); err != nil {
return err
}
- allJobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: run.ID})
- if err != nil {
- log.Error("FindRunJobs: %v", err)
- }
- err = run.LoadAttributes(ctx)
- if err != nil {
- log.Error("LoadAttributes: %v", err)
- }
- notify_service.WorkflowRunStatusUpdate(ctx, run.Repo, run.TriggerUser, run)
- for _, job := range allJobs {
- notify_service.WorkflowJobStatusUpdate(ctx, run.Repo, run.TriggerUser, job, nil)
- }
// Return nil if no errors occurred
return nil
diff --git a/services/actions/task.go b/services/actions/task.go
index 6a547c1c12..cf2164f456 100644
--- a/services/actions/task.go
+++ b/services/actions/task.go
@@ -97,7 +97,7 @@ func PickTask(ctx context.Context, runner *actions_model.ActionRunner) (*runnerv
return nil, false, nil
}
- CreateCommitStatus(ctx, job)
+ CreateCommitStatusForRunJobs(ctx, job.Run, job)
notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, actionTask)
return task, true, nil
diff --git a/services/actions/workflow.go b/services/actions/workflow.go
index 40b34194e9..25801d6fa1 100644
--- a/services/actions/workflow.go
+++ b/services/actions/workflow.go
@@ -8,7 +8,6 @@ import (
"strings"
actions_model "code.gitea.io/gitea/models/actions"
- "code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/perm"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
@@ -16,13 +15,11 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/actions"
"code.gitea.io/gitea/modules/git"
- "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/reqctx"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
- notify_service "code.gitea.io/gitea/services/notify"
"github.com/nektos/act/pkg/jobparser"
"github.com/nektos/act/pkg/model"
@@ -98,7 +95,6 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re
}
// find workflow from commit
- var workflows []*jobparser.SingleWorkflow
var entry *git.TreeEntry
run := &actions_model.ActionRun{
@@ -152,24 +148,6 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re
}
}
- giteaCtx := GenerateGiteaContext(run, nil)
-
- workflows, err = jobparser.Parse(content, jobparser.WithGitContext(giteaCtx.ToGitHubContext()), jobparser.WithInputs(inputsWithDefaults))
- if err != nil {
- return err
- }
-
- if len(workflows) > 0 && workflows[0].RunName != "" {
- run.Title = workflows[0].RunName
- }
-
- if len(workflows) == 0 {
- return util.ErrorWrapLocale(
- util.NewNotExistErrorf("workflow %q doesn't exist", workflowID),
- "actions.workflow.not_found", workflowID,
- )
- }
-
// ctx.Req.PostForm -> WorkflowDispatchPayload.Inputs -> ActionRun.EventPayload -> runner: ghc.Event
// https://docs.github.com/en/actions/learn-github-actions/contexts#github-context
// https://docs.github.com/en/webhooks/webhook-events-and-payloads#workflow_dispatch
@@ -187,38 +165,9 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re
}
run.EventPayload = string(eventPayload)
- // cancel running jobs of the same workflow
- if err := CancelPreviousJobs(
- ctx,
- run.RepoID,
- run.Ref,
- run.WorkflowID,
- run.Event,
- ); err != nil {
- log.Error("CancelRunningJobs: %v", err)
- }
-
// Insert the action run and its associated jobs into the database
- if err := actions_model.InsertRun(ctx, run, workflows); err != nil {
- return fmt.Errorf("InsertRun: %w", err)
- }
-
- allJobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: run.ID})
- if err != nil {
- log.Error("FindRunJobs: %v", err)
- }
- CreateCommitStatus(ctx, allJobs...)
- if len(allJobs) > 0 {
- job := allJobs[0]
- err := job.LoadRun(ctx)
- if err != nil {
- log.Error("LoadRun: %v", err)
- } else {
- notify_service.WorkflowRunStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job.Run)
- }
- }
- for _, job := range allJobs {
- notify_service.WorkflowJobStatusUpdate(ctx, repo, doer, job, nil)
+ if err := PrepareRunAndInsert(ctx, content, run, inputsWithDefaults); err != nil {
+ return fmt.Errorf("PrepareRun: %w", err)
}
return nil
}
diff --git a/services/asymkey/sign.go b/services/asymkey/sign.go
index 61b9e56d95..1ed05ba287 100644
--- a/services/asymkey/sign.go
+++ b/services/asymkey/sign.go
@@ -17,7 +17,6 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
- "code.gitea.io/gitea/modules/git/gitcmd"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/process"
@@ -109,54 +108,9 @@ func IsErrWontSign(err error) bool {
return ok
}
-// SigningKey returns the KeyID and git Signature for the repo
-func SigningKey(ctx context.Context, repoPath string) (*git.SigningKey, *git.Signature) {
- if setting.Repository.Signing.SigningKey == "none" {
- return nil, nil
- }
-
- if setting.Repository.Signing.SigningKey == "default" || setting.Repository.Signing.SigningKey == "" {
- // Can ignore the error here as it means that commit.gpgsign is not set
- value, _, _ := gitcmd.NewCommand("config", "--get", "commit.gpgsign").WithDir(repoPath).RunStdString(ctx)
- sign, valid := git.ParseBool(strings.TrimSpace(value))
- if !sign || !valid {
- return nil, nil
- }
-
- format, _, _ := gitcmd.NewCommand("config", "--default", git.SigningKeyFormatOpenPGP, "--get", "gpg.format").WithDir(repoPath).RunStdString(ctx)
- signingKey, _, _ := gitcmd.NewCommand("config", "--get", "user.signingkey").WithDir(repoPath).RunStdString(ctx)
- signingName, _, _ := gitcmd.NewCommand("config", "--get", "user.name").WithDir(repoPath).RunStdString(ctx)
- signingEmail, _, _ := gitcmd.NewCommand("config", "--get", "user.email").WithDir(repoPath).RunStdString(ctx)
-
- if strings.TrimSpace(signingKey) == "" {
- return nil, nil
- }
-
- return &git.SigningKey{
- KeyID: strings.TrimSpace(signingKey),
- Format: strings.TrimSpace(format),
- }, &git.Signature{
- Name: strings.TrimSpace(signingName),
- Email: strings.TrimSpace(signingEmail),
- }
- }
-
- if setting.Repository.Signing.SigningKey == "" {
- return nil, nil
- }
-
- return &git.SigningKey{
- KeyID: setting.Repository.Signing.SigningKey,
- Format: setting.Repository.Signing.SigningFormat,
- }, &git.Signature{
- Name: setting.Repository.Signing.SigningName,
- Email: setting.Repository.Signing.SigningEmail,
- }
-}
-
// PublicSigningKey gets the public signing key within a provided repository directory
func PublicSigningKey(ctx context.Context, repoPath string) (content, format string, err error) {
- signingKey, _ := SigningKey(ctx, repoPath)
+ signingKey, _ := git.GetSigningKey(ctx, repoPath)
if signingKey == nil {
return "", "", nil
}
@@ -181,7 +135,7 @@ func PublicSigningKey(ctx context.Context, repoPath string) (content, format str
// SignInitialCommit determines if we should sign the initial commit to this repository
func SignInitialCommit(ctx context.Context, repoPath string, u *user_model.User) (bool, *git.SigningKey, *git.Signature, error) {
rules := signingModeFromStrings(setting.Repository.Signing.InitialCommit)
- signingKey, sig := SigningKey(ctx, repoPath)
+ signingKey, sig := git.GetSigningKey(ctx, repoPath)
if signingKey == nil {
return false, nil, nil, &ErrWontSign{noKey}
}
@@ -216,9 +170,8 @@ Loop:
// SignWikiCommit determines if we should sign the commits to this repository wiki
func SignWikiCommit(ctx context.Context, repo *repo_model.Repository, u *user_model.User) (bool, *git.SigningKey, *git.Signature, error) {
- repoWikiPath := repo.WikiPath()
rules := signingModeFromStrings(setting.Repository.Signing.Wiki)
- signingKey, sig := SigningKey(ctx, repoWikiPath)
+ signingKey, sig := gitrepo.GetSigningKey(ctx, repo.WikiStorageRepo())
if signingKey == nil {
return false, nil, nil, &ErrWontSign{noKey}
}
@@ -271,7 +224,7 @@ Loop:
// SignCRUDAction determines if we should sign a CRUD commit to this repository
func SignCRUDAction(ctx context.Context, repoPath string, u *user_model.User, tmpBasePath, parentCommit string) (bool, *git.SigningKey, *git.Signature, error) {
rules := signingModeFromStrings(setting.Repository.Signing.CRUDActions)
- signingKey, sig := SigningKey(ctx, repoPath)
+ signingKey, sig := git.GetSigningKey(ctx, repoPath)
if signingKey == nil {
return false, nil, nil, &ErrWontSign{noKey}
}
@@ -335,7 +288,7 @@ func SignMerge(ctx context.Context, pr *issues_model.PullRequest, u *user_model.
}
repo := pr.BaseRepo
- signingKey, signer := SigningKey(ctx, repo.RepoPath())
+ signingKey, signer := gitrepo.GetSigningKey(ctx, repo)
if signingKey == nil {
return false, nil, nil, &ErrWontSign{noKey}
}
diff --git a/services/issue/comments.go b/services/issue/comments.go
index 9442701029..3ce2e2a5e1 100644
--- a/services/issue/comments.go
+++ b/services/issue/comments.go
@@ -15,6 +15,7 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/json"
+ "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/timeutil"
git_service "code.gitea.io/gitea/services/git"
notify_service "code.gitea.io/gitea/services/notify"
@@ -151,15 +152,15 @@ func DeleteComment(ctx context.Context, doer *user_model.User, comment *issues_m
}
// LoadCommentPushCommits Load push commits
-func LoadCommentPushCommits(ctx context.Context, c *issues_model.Comment) (err error) {
+func LoadCommentPushCommits(ctx context.Context, c *issues_model.Comment) error {
if c.Content == "" || c.Commits != nil || c.Type != issues_model.CommentTypePullRequestPush {
return nil
}
var data issues_model.PushActionContent
- err = json.Unmarshal([]byte(c.Content), &data)
- if err != nil {
- return err
+ if err := json.Unmarshal([]byte(c.Content), &data); err != nil {
+ log.Debug("Unmarshal: %v", err) // no need to show 500 error to end user when the JSON is broken
+ return nil
}
c.IsForcePush = data.IsForcePush
@@ -168,9 +169,15 @@ func LoadCommentPushCommits(ctx context.Context, c *issues_model.Comment) (err e
if len(data.CommitIDs) != 2 {
return nil
}
- c.OldCommit = data.CommitIDs[0]
- c.NewCommit = data.CommitIDs[1]
+ c.OldCommit, c.NewCommit = data.CommitIDs[0], data.CommitIDs[1]
} else {
+ if err := c.LoadIssue(ctx); err != nil {
+ return err
+ }
+ if err := c.Issue.LoadRepo(ctx); err != nil {
+ return err
+ }
+
gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, c.Issue.Repo)
if err != nil {
return err
@@ -179,10 +186,11 @@ func LoadCommentPushCommits(ctx context.Context, c *issues_model.Comment) (err e
c.Commits, err = git_service.ConvertFromGitCommit(ctx, gitRepo.GetCommitsFromIDs(data.CommitIDs), c.Issue.Repo)
if err != nil {
- return err
+ log.Debug("ConvertFromGitCommit: %v", err) // no need to show 500 error to end user when the commit does not exist
+ } else {
+ c.CommitsNum = int64(len(c.Commits))
}
- c.CommitsNum = int64(len(c.Commits))
}
- return err
+ return nil
}
diff --git a/services/mirror/mirror_pull.go b/services/mirror/mirror_pull.go
index 4b19112d3c..da58bbd1b6 100644
--- a/services/mirror/mirror_pull.go
+++ b/services/mirror/mirror_pull.go
@@ -249,8 +249,6 @@ func checkRecoverableSyncError(stderrMessage string) bool {
// runSync returns true if sync finished without error.
func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bool) {
- repoPath := m.Repo.RepoPath()
- wikiPath := m.Repo.WikiPath()
timeout := time.Duration(setting.Git.Timeout.Mirror) * time.Second
log.Trace("SyncMirrors [repo: %-v]: running git remote update...", m.Repo)
@@ -311,7 +309,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo
// If there is still an error (or there always was an error)
if err != nil {
log.Error("SyncMirrors [repo: %-v]: failed to update mirror repository:\nStdout: %s\nStderr: %s\nErr: %v", m.Repo, stdoutMessage, stderrMessage, err)
- desc := fmt.Sprintf("Failed to update mirror repository '%s': %s", repoPath, stderrMessage)
+ desc := fmt.Sprintf("Failed to update mirror repository '%s': %s", m.Repo.RelativePath(), stderrMessage)
if err = system_model.CreateRepositoryNotice(desc); err != nil {
log.Error("CreateRepositoryNotice: %v", err)
}
@@ -320,7 +318,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo
}
output := stderrBuilder.String()
- if err := git.WriteCommitGraph(ctx, repoPath); err != nil {
+ if err := gitrepo.WriteCommitGraph(ctx, m.Repo); err != nil {
log.Error("SyncMirrors [repo: %-v]: %v", m.Repo, err)
}
@@ -394,14 +392,14 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo
// If there is still an error (or there always was an error)
if err != nil {
log.Error("SyncMirrors [repo: %-v Wiki]: failed to update mirror repository wiki:\nStdout: %s\nStderr: %s\nErr: %v", m.Repo, stdoutMessage, stderrMessage, err)
- desc := fmt.Sprintf("Failed to update mirror repository wiki '%s': %s", wikiPath, stderrMessage)
+ desc := fmt.Sprintf("Failed to update mirror repository wiki '%s': %s", m.Repo.WikiStorageRepo().RelativePath(), stderrMessage)
if err = system_model.CreateRepositoryNotice(desc); err != nil {
log.Error("CreateRepositoryNotice: %v", err)
}
return nil, false
}
- if err := git.WriteCommitGraph(ctx, wikiPath); err != nil {
+ if err := gitrepo.WriteCommitGraph(ctx, m.Repo.WikiStorageRepo()); err != nil {
log.Error("SyncMirrors [repo: %-v]: %v", m.Repo, err)
}
}
diff --git a/services/mirror/mirror_push.go b/services/mirror/mirror_push.go
index 9a832a1350..b61345e830 100644
--- a/services/mirror/mirror_push.go
+++ b/services/mirror/mirror_push.go
@@ -124,14 +124,12 @@ func runPushSync(ctx context.Context, m *repo_model.PushMirror) error {
performPush := func(repo *repo_model.Repository, isWiki bool) error {
var storageRepo gitrepo.Repository = repo
- path := repo.RepoPath()
if isWiki {
storageRepo = repo.WikiStorageRepo()
- path = repo.WikiPath()
}
remoteURL, err := gitrepo.GitRemoteGetURL(ctx, storageRepo, m.RemoteName)
if err != nil {
- log.Error("GetRemoteURL(%s) Error %v", path, err)
+ log.Error("GetRemoteURL(%s) Error %v", storageRepo.RelativePath(), err)
return errors.New("Unexpected error")
}
@@ -152,17 +150,17 @@ func runPushSync(ctx context.Context, m *repo_model.PushMirror) error {
}
}
- log.Trace("Pushing %s mirror[%d] remote %s", path, m.ID, m.RemoteName)
+ log.Trace("Pushing %s mirror[%d] remote %s", storageRepo.RelativePath(), m.ID, m.RemoteName)
envs := proxy.EnvWithProxy(remoteURL.URL)
- if err := git.Push(ctx, path, git.PushOptions{
+ if err := gitrepo.Push(ctx, storageRepo, git.PushOptions{
Remote: m.RemoteName,
Force: true,
Mirror: true,
Timeout: timeout,
Env: envs,
}); err != nil {
- log.Error("Error pushing %s mirror[%d] remote %s: %v", path, m.ID, m.RemoteName, err)
+ log.Error("Error pushing %s mirror[%d] remote %s: %v", storageRepo.RelativePath(), m.ID, m.RemoteName, err)
return util.SanitizeErrorCredentialURLs(err)
}
diff --git a/services/pull/merge.go b/services/pull/merge.go
index f1ad8fa17d..1e8e9d444b 100644
--- a/services/pull/merge.go
+++ b/services/pull/merge.go
@@ -248,6 +248,11 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U
}
defer releaser()
defer func() {
+ // This is a duplicated call to AddTestPullRequestTask (it will also be called by the post-receive hook, via a push queue).
+ // This call will do some operations (push to base repo, sync commit divergence, add PR conflict check queue task, etc)
+ // immediately instead of waiting for the "push queue"'s task. The code is from https://github.com/go-gitea/gitea/pull/7082.
+ // But it's really questionable whether it's worth to do it ahead without waiting for the "push queue" task to run.
+ // TODO: DUPLICATE-PR-TASK: maybe can try to remove this in 1.26 to see if there is any issue.
go AddTestPullRequestTask(TestPullRequestOptions{
RepoID: pr.BaseRepo.ID,
Doer: doer,
diff --git a/services/pull/merge_prepare.go b/services/pull/merge_prepare.go
index 7dedf0d2a0..07935ac16d 100644
--- a/services/pull/merge_prepare.go
+++ b/services/pull/merge_prepare.go
@@ -32,6 +32,9 @@ type mergeContext struct {
env []string
}
+// PrepareGitCmd prepares a git command with the correct directory, environment, and output buffers
+// This function can only be called with gitcmd.Run()
+// Do NOT use it with gitcmd.RunStd*() functions, otherwise it will panic
func (ctx *mergeContext) PrepareGitCmd(cmd *gitcmd.Command) *gitcmd.Command {
ctx.outbuf.Reset()
ctx.errbuf.Reset()
@@ -73,7 +76,11 @@ func createTemporaryRepoForMerge(ctx context.Context, pr *issues_model.PullReque
}
if expectedHeadCommitID != "" {
- trackingCommitID, _, err := mergeCtx.PrepareGitCmd(gitcmd.NewCommand("show-ref", "--hash").AddDynamicArguments(git.BranchPrefix + trackingBranch)).RunStdString(ctx)
+ trackingCommitID, _, err := gitcmd.NewCommand("show-ref", "--hash").
+ AddDynamicArguments(git.BranchPrefix + trackingBranch).
+ WithEnv(mergeCtx.env).
+ WithDir(mergeCtx.tmpBasePath).
+ RunStdString(ctx)
if err != nil {
defer cancel()
log.Error("failed to get sha of head branch in %-v: show-ref[%s] --hash refs/heads/tracking: %v", mergeCtx.pr, mergeCtx.tmpBasePath, err)
diff --git a/services/pull/pull.go b/services/pull/pull.go
index 310aeaf525..72f571ec8e 100644
--- a/services/pull/pull.go
+++ b/services/pull/pull.go
@@ -409,10 +409,8 @@ type TestPullRequestOptions struct {
func AddTestPullRequestTask(opts TestPullRequestOptions) {
log.Trace("AddTestPullRequestTask [head_repo_id: %d, head_branch: %s]: finding pull requests", opts.RepoID, opts.Branch)
graceful.GetManager().RunWithShutdownContext(func(ctx context.Context) {
- // There is no sensible way to shut this down ":-("
- // If you don't let it run all the way then you will lose data
- // TODO: graceful: AddTestPullRequestTask needs to become a queue!
-
+ // this function does a lot of operations to various models, if the process gets killed in the middle,
+ // there is no way to recover at the moment. The best workaround is to let end user push again.
repo, err := repo_model.GetRepositoryByID(ctx, opts.RepoID)
if err != nil {
log.Error("GetRepositoryByID: %v", err)
@@ -437,11 +435,15 @@ func AddTestPullRequestTask(opts TestPullRequestOptions) {
continue
}
- StartPullRequestCheckImmediately(ctx, pr)
+ // create push comment before check pull request status,
+ // then when the status is mergeable, the comment is already in database, to make testing easy and stable
comment, err := CreatePushPullComment(ctx, opts.Doer, pr, opts.OldCommitID, opts.NewCommitID, opts.IsForcePush)
if err == nil && comment != nil {
notify_service.PullRequestPushCommits(ctx, opts.Doer, pr, comment)
}
+ // The caller can be in a goroutine or a "push queue", "conflict check" can be time-consuming,
+ // and the concurrency should be limited, so the conflict check will be done in another queue
+ StartPullRequestCheckImmediately(ctx, pr)
}
if opts.IsSync {
diff --git a/services/pull/temp_repo.go b/services/pull/temp_repo.go
index 597a4aa48c..4f7a504b11 100644
--- a/services/pull/temp_repo.go
+++ b/services/pull/temp_repo.go
@@ -37,6 +37,9 @@ type prTmpRepoContext struct {
errbuf *strings.Builder // any use should be preceded by a Reset and preferably after use
}
+// PrepareGitCmd prepares a git command with the correct directory, environment, and output buffers
+// This function can only be called with gitcmd.Run()
+// Do NOT use it with gitcmd.RunStd*() functions, otherwise it will panic
func (ctx *prTmpRepoContext) PrepareGitCmd(cmd *gitcmd.Command) *gitcmd.Command {
ctx.outbuf.Reset()
ctx.errbuf.Reset()
diff --git a/services/pull/update.go b/services/pull/update.go
index cce3937451..436e3b52a6 100644
--- a/services/pull/update.go
+++ b/services/pull/update.go
@@ -63,6 +63,9 @@ func Update(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.
}
defer func() {
+ // The code is from https://github.com/go-gitea/gitea/pull/9784,
+ // it seems a simple copy-paste from https://github.com/go-gitea/gitea/pull/7082 without a real reason.
+ // TODO: DUPLICATE-PR-TASK: search and see another TODO comment for more details
go AddTestPullRequestTask(TestPullRequestOptions{
RepoID: pr.BaseRepo.ID,
Doer: doer,
diff --git a/services/repository/migrate.go b/services/repository/migrate.go
index 9873d5deeb..acac6fd9ad 100644
--- a/services/repository/migrate.go
+++ b/services/repository/migrate.go
@@ -28,22 +28,23 @@ import (
)
func cloneWiki(ctx context.Context, repo *repo_model.Repository, opts migration.MigrateOptions, migrateTimeout time.Duration) (string, error) {
- wikiPath := repo.WikiPath()
- wikiRemotePath := repo_module.WikiRemoteURL(ctx, opts.CloneAddr)
- if wikiRemotePath == "" {
+ wikiRemoteURL := repo_module.WikiRemoteURL(ctx, opts.CloneAddr)
+ if wikiRemoteURL == "" {
return "", nil
}
- if err := util.RemoveAll(wikiPath); err != nil {
- return "", fmt.Errorf("failed to remove existing wiki dir %q, err: %w", wikiPath, err)
+ storageRepo := repo.WikiStorageRepo()
+
+ if err := gitrepo.DeleteRepository(ctx, storageRepo); err != nil {
+ return "", fmt.Errorf("failed to remove existing wiki dir %q, err: %w", storageRepo.RelativePath(), err)
}
cleanIncompleteWikiPath := func() {
- if err := util.RemoveAll(wikiPath); err != nil {
- log.Error("Failed to remove incomplete wiki dir %q, err: %v", wikiPath, err)
+ if err := gitrepo.DeleteRepository(ctx, storageRepo); err != nil {
+ log.Error("Failed to remove incomplete wiki dir %q, err: %v", storageRepo.RelativePath(), err)
}
}
- if err := git.Clone(ctx, wikiRemotePath, wikiPath, git.CloneRepoOptions{
+ if err := gitrepo.CloneExternalRepo(ctx, wikiRemoteURL, storageRepo, git.CloneRepoOptions{
Mirror: true,
Quiet: true,
Timeout: migrateTimeout,
@@ -54,15 +55,15 @@ func cloneWiki(ctx context.Context, repo *repo_model.Repository, opts migration.
return "", err
}
- if err := git.WriteCommitGraph(ctx, wikiPath); err != nil {
+ if err := gitrepo.WriteCommitGraph(ctx, storageRepo); err != nil {
cleanIncompleteWikiPath()
return "", err
}
- defaultBranch, err := gitrepo.GetDefaultBranch(ctx, repo.WikiStorageRepo())
+ defaultBranch, err := gitrepo.GetDefaultBranch(ctx, storageRepo)
if err != nil {
cleanIncompleteWikiPath()
- return "", fmt.Errorf("failed to get wiki repo default branch for %q, err: %w", wikiPath, err)
+ return "", fmt.Errorf("failed to get wiki repo default branch for %q, err: %w", storageRepo.RelativePath(), err)
}
return defaultBranch, nil
diff --git a/services/repository/transfer.go b/services/repository/transfer.go
index c30a540137..98307a447a 100644
--- a/services/repository/transfer.go
+++ b/services/repository/transfer.go
@@ -107,16 +107,18 @@ func transferOwnership(ctx context.Context, doer *user_model.User, newOwnerName
}
if repoRenamed {
- if err := util.Rename(repo_model.RepoPath(newOwnerName, repo.Name), repo_model.RepoPath(oldOwnerName, repo.Name)); err != nil {
+ oldRelativePath, newRelativePath := repo_model.RelativePath(newOwnerName, repo.Name), repo_model.RelativePath(oldOwnerName, repo.Name)
+ if err := gitrepo.RenameRepository(ctx, repo_model.StorageRepo(oldRelativePath), repo_model.StorageRepo(newRelativePath)); err != nil {
log.Critical("Unable to move repository %s/%s directory from %s back to correct place %s: %v", oldOwnerName, repo.Name,
- repo_model.RepoPath(newOwnerName, repo.Name), repo_model.RepoPath(oldOwnerName, repo.Name), err)
+ oldRelativePath, newRelativePath, err)
}
}
if wikiRenamed {
- if err := util.Rename(repo_model.WikiPath(newOwnerName, repo.Name), repo_model.WikiPath(oldOwnerName, repo.Name)); err != nil {
+ oldRelativePath, newRelativePath := repo_model.RelativeWikiPath(newOwnerName, repo.Name), repo_model.RelativeWikiPath(oldOwnerName, repo.Name)
+ if err := gitrepo.RenameRepository(ctx, repo_model.StorageRepo(oldRelativePath), repo_model.StorageRepo(newRelativePath)); err != nil {
log.Critical("Unable to move wiki for repository %s/%s directory from %s back to correct place %s: %v", oldOwnerName, repo.Name,
- repo_model.WikiPath(newOwnerName, repo.Name), repo_model.WikiPath(oldOwnerName, repo.Name), err)
+ oldRelativePath, newRelativePath, err)
}
}
@@ -289,12 +291,12 @@ func transferOwnership(ctx context.Context, doer *user_model.User, newOwnerName
repoRenamed = true
// Rename remote wiki repository to new path and delete local copy.
- wikiPath := repo_model.WikiPath(oldOwner.Name, repo.Name)
- if isExist, err := util.IsExist(wikiPath); err != nil {
- log.Error("Unable to check if %s exists. Error: %v", wikiPath, err)
+ wikiStorageRepo := repo_model.StorageRepo(repo_model.RelativeWikiPath(oldOwner.Name, repo.Name))
+ if isExist, err := gitrepo.IsRepositoryExist(ctx, wikiStorageRepo); err != nil {
+ log.Error("Unable to check if %s exists. Error: %v", wikiStorageRepo.RelativePath(), err)
return err
} else if isExist {
- if err := util.Rename(wikiPath, repo_model.WikiPath(newOwner.Name, repo.Name)); err != nil {
+ if err := gitrepo.RenameRepository(ctx, wikiStorageRepo, repo_model.StorageRepo(repo_model.RelativeWikiPath(newOwner.Name, repo.Name))); err != nil {
return fmt.Errorf("rename repository wiki: %w", err)
}
wikiRenamed = true
diff --git a/services/wiki/wiki.go b/services/wiki/wiki.go
index 25c33b57fc..25f836dd5d 100644
--- a/services/wiki/wiki.go
+++ b/services/wiki/wiki.go
@@ -120,7 +120,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
cloneOpts.Branch = repo.DefaultWikiBranch
}
- if err := git.Clone(ctx, repo.WikiPath(), basePath, cloneOpts); err != nil {
+ if err := gitrepo.CloneRepoToLocal(ctx, repo.WikiStorageRepo(), basePath, cloneOpts); err != nil {
log.Error("Failed to clone repository: %s (%v)", repo.FullName(), err)
return fmt.Errorf("failed to clone repository: %s (%w)", repo.FullName(), err)
}
@@ -269,7 +269,7 @@ func DeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
}
defer cleanup()
- if err := git.Clone(ctx, repo.WikiPath(), basePath, git.CloneRepoOptions{
+ if err := gitrepo.CloneRepoToLocal(ctx, repo.WikiStorageRepo(), basePath, git.CloneRepoOptions{
Bare: true,
Shared: true,
Branch: repo.DefaultWikiBranch,
diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl
index 806347c720..080b2cd3d6 100644
--- a/templates/admin/config.tmpl
+++ b/templates/admin/config.tmpl
@@ -252,9 +252,9 @@
{{end}}
{{if .CacheConn}}
{{.CacheConn}}{{.CacheItemTTL}}{{if .SessionConfig.ProviderConfig}}{{.SessionConfig.ProviderConfig}}{{else}}-{{end}}{{.Git.GCArgs}}{{$.AccessLogTemplate}}{{.Function}}{{.File}}:{{.Line}}{{.Details | SanitizeHTML}}
+ {{.Details | SanitizeHTML}}
{{.FileContent}}
{{.FileContent}}{{or .RequestInfo.Body .PayloadContent}}
+ {{or .RequestInfo.Body .PayloadContent}}
{{else}}
-
{{end}}
@@ -79,7 +79,7 @@
{{range $key, $val := .ResponseInfo.Headers}}{{$key}}: {{$val}}
{{end}}
{{.ResponseInfo.Body}}
+ {{.ResponseInfo.Body}}
{{else}}
-
{{end}}
diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl
index 0df8356fd9..325f0b78a0 100644
--- a/templates/swagger/v1_json.tmpl
+++ b/templates/swagger/v1_json.tmpl
@@ -7844,7 +7844,7 @@
"in": "body",
"required": true,
"schema": {
- "$ref": "#/definitions/UpdateFileOptions"
+ "$ref": "#/definitions/ApplyDiffPatchFileOptions"
}
}
],
@@ -21645,6 +21645,54 @@
},
"x-go-package": "code.gitea.io/gitea/modules/structs"
},
+ "ApplyDiffPatchFileOptions": {
+ "description": "ApplyDiffPatchFileOptions options for applying a diff patch\nNote: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)",
+ "type": "object",
+ "required": [
+ "content"
+ ],
+ "properties": {
+ "author": {
+ "$ref": "#/definitions/Identity"
+ },
+ "branch": {
+ "description": "branch (optional) is the base branch for the changes. If not supplied, the default branch is used",
+ "type": "string",
+ "x-go-name": "BranchName"
+ },
+ "committer": {
+ "$ref": "#/definitions/Identity"
+ },
+ "content": {
+ "type": "string",
+ "x-go-name": "Content"
+ },
+ "dates": {
+ "$ref": "#/definitions/CommitDateOptions"
+ },
+ "force_push": {
+ "description": "force_push (optional) will do a force-push if the new branch already exists",
+ "type": "boolean",
+ "x-go-name": "ForcePush"
+ },
+ "message": {
+ "description": "message (optional) is the commit message of the changes. If not supplied, a default message will be used",
+ "type": "string",
+ "x-go-name": "Message"
+ },
+ "new_branch": {
+ "description": "new_branch (optional) will make a new branch from base branch for the changes. If not supplied, the changes will be committed to the base branch",
+ "type": "string",
+ "x-go-name": "NewBranchName"
+ },
+ "signoff": {
+ "description": "Add a Signed-off-by trailer by the committer at the end of the commit log message.",
+ "type": "boolean",
+ "x-go-name": "Signoff"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
"Attachment": {
"description": "Attachment a generic attachment",
"type": "object",
diff --git a/templates/user/settings/keys_gpg.tmpl b/templates/user/settings/keys_gpg.tmpl
index e44a838b25..bb45ea58c5 100644
--- a/templates/user/settings/keys_gpg.tmpl
+++ b/templates/user/settings/keys_gpg.tmpl
@@ -21,8 +21,8 @@
{{ctx.Locale.Tr "settings.gpg_token_help"}}
-{{printf `echo "%s" | gpg -a --default-key %s --detach-sig` .TokenToSign .PaddedKeyID}}
{{printf `echo "%s" | gpg -a --default-key %s --detach-sig` .TokenToSign .PaddedKeyID}}
{{ctx.Locale.Tr "settings.gpg_token_help"}}
-{{printf `echo "%s" | gpg -a --default-key %s --detach-sig` $.TokenToSign .PaddedKeyID}}
{{printf `echo "%s" | gpg -a --default-key %s --detach-sig` $.TokenToSign .PaddedKeyID}}
{{ctx.Locale.Tr "settings.ssh_token_help"}}
-echo -n '{{$.TokenToSign}}' | ssh-keygen -Y sign -n gitea -f /path_to_PrivateKey_or_RelatedPublicKey
echo -n '{{$.TokenToSign}}' | ssh-keygen -Y sign -n gitea -f /path_to_PrivateKey_or_RelatedPublicKey
cmd /c "<NUL set /p=`"{{$.TokenToSign}}`"| ssh-keygen -Y sign -n gitea -f /path_to_PrivateKey_or_RelatedPublicKey"
cmd /c "<NUL set /p=`"{{$.TokenToSign}}`"| ssh-keygen -Y sign -n gitea -f /path_to_PrivateKey_or_RelatedPublicKey"
set /p={{$.TokenToSign}}| ssh-keygen -Y sign -n gitea -f /path_to_PrivateKey_or_RelatedPublicKey
set /p={{$.TokenToSign}}| ssh-keygen -Y sign -n gitea -f /path_to_PrivateKey_or_RelatedPublicKey
blocks in non-markup(.markup code) / non-code-diff(code.code-inner) containers (for example: translation strings, etc),
+so we need to make have default global styles, ".markup code" has its own styles and doesn't conflict, but `.code-inner` is special.
+TODO: in the future, we should use `div` instead of `code` for `.code-inner` because it is a container for highlighted code line */
+code:not(.code-inner) {
padding: 1px 4px;
border-radius: var(--border-radius);
background-color: var(--color-label-bg);
- color: var(--color-label-text);
}
b,
diff --git a/web_src/css/form.css b/web_src/css/form.css
index 757edf7297..197c0f5af2 100644
--- a/web_src/css/form.css
+++ b/web_src/css/form.css
@@ -228,6 +228,12 @@ textarea:focus,
color: var(--color-text-light-1);
}
+.form .help pre.command-block {
+ white-space: pre-wrap;
+ overflow-wrap: anywhere;
+ margin: 0.25em 0 0.25em 1em;
+}
+
.m-captcha-style {
width: 100%;
height: 5em;
diff --git a/web_src/css/repo.css b/web_src/css/repo.css
index 9f4fa51881..c70937147a 100644
--- a/web_src/css/repo.css
+++ b/web_src/css/repo.css
@@ -1582,6 +1582,7 @@ tbody.commit-list {
display: flex;
align-items: center;
width: max-content;
+ gap: 0.25em;
}
.file-info-entry + .file-info-entry {
diff --git a/web_src/js/components/ActionRunStatus.vue b/web_src/js/components/ActionRunStatus.vue
index bc3b99ab89..22f79384e3 100644
--- a/web_src/js/components/ActionRunStatus.vue
+++ b/web_src/js/components/ActionRunStatus.vue
@@ -21,10 +21,10 @@ withDefaults(defineProps<{
-
-
+
+
-
+
diff --git a/web_src/js/components/RepoActionView.vue b/web_src/js/components/RepoActionView.vue
index b90aef7411..6e6733c7d0 100644
--- a/web_src/js/components/RepoActionView.vue
+++ b/web_src/js/components/RepoActionView.vue
@@ -601,7 +601,8 @@ export default defineComponent({