Compare commits
16 Commits
main
...
release/v1.26
| Author | SHA1 | Date | |
|---|---|---|---|
| 3b253e06a3 | |||
| df0ad4e8c1 | |||
| 68f5e40e46 | |||
| d1be5c3612 | |||
| 8687faaf3a | |||
| 789a3d3a4d | |||
| b37e098ff0 | |||
| f9b808a8d2 | |||
| 0112ec9b34 | |||
| 7a7376dfc8 | |||
| fc5e0ec877 | |||
| d0a39bc3a4 | |||
| 4eca71d6d4 | |||
| a2283a0c03 | |||
| 3e6b9e5312 | |||
| 1ad9e996be |
+379
@@ -4,6 +4,385 @@ This changelog goes through the changes that have been made in each release
|
||||
without substantial changes to our git log; to see the highlights of what has
|
||||
been added to each release, please refer to the [blog](https://blog.gitea.com).
|
||||
|
||||
## [1.26.0-rc0](https://github.com/go-gitea/gitea/releases/tag/v1.26.0-rc0) - 2026-04-07
|
||||
|
||||
* BREAKING
|
||||
* Correct swagger annotations for enums, status codes, and notification state (#37030)
|
||||
* Remove GET API registration-token (#36801)
|
||||
* Support Actions `concurrency` syntax (#32751)
|
||||
* Make PUBLIC_URL_DETECTION default to "auto" (#36955)
|
||||
* SECURITY
|
||||
* Bound PageSize in `ListUnadoptedRepositories` (#36884)
|
||||
* FEATURES
|
||||
* Support Actions `concurrency` syntax (#32751)
|
||||
* Add terraform state registry (#36710)
|
||||
* Instance-wide (global) info banner and maintenance mode (#36571)
|
||||
* Support rendering OpenAPI spec (#36449)
|
||||
* Add keyboard shortcuts for repository file and code search (#36416)
|
||||
* Add support for archive-upload rpc (#36391)
|
||||
* Add ability to download subpath archive (#36371)
|
||||
* Add workflow dependencies visualization (#26062) (#36248) & Restyle Workflow Graph (#36912)
|
||||
* Automatic generation of release notes (#35977)
|
||||
* Add "Go to file", "Delete Directory" to repo file list page (#35911)
|
||||
* Introduce "config edit-ini" sub command to help maintaining INI config file (#35735)
|
||||
* Add button to re-run failed jobs in Actions (#36924)
|
||||
* Support actions and reusable workflows from private repos (#32562)
|
||||
* Add summary to action runs view (#36883)
|
||||
* Add user badges (#36752)
|
||||
* Add configurable permissions for Actions automatic tokens (#36173)
|
||||
* Add per-runner “Disable/Pause” (#36776)
|
||||
* PERFORMANCE
|
||||
* WorkflowDispatch API optionally return runid (#36706)
|
||||
* Add render cache for SVG icons (#36863)
|
||||
* Load `mentionValues` asynchronously (#36739)
|
||||
* Lazy-load some Vue components, fix heatmap chunk loading on every page (#36719)
|
||||
* Load heatmap data asynchronously (#36622)
|
||||
* Use prev/next pagination for user profile activities page to speed up (#36642)
|
||||
* Refactor cat-file batch operations and support `--batch-command` approach (#35775)
|
||||
* Use merge tree to detect conflicts when possible (#36400)
|
||||
* ENHANCEMENTS
|
||||
* Adds option to force update new branch in contents routes (#35592)
|
||||
* Add viewer controller for mermaid (zoom, drag) (#36557)
|
||||
* Add code editor setting dropdowns (#36534)
|
||||
* Add `elk` layout support to mermaid (#36486)
|
||||
* Add resolve/unresolve review comment API endpoints (#36441)
|
||||
* Allow configuring default PR base branch (fixes #36412) (#36425)
|
||||
* Add support for RPM Errata (updateinfo.xml) (#37125)
|
||||
* Require additional user confirmation for making repo private (#36959)
|
||||
* Feature non-zipped actions artifacts (action v7 / nodejs / npm v6.2.0) (#36786)
|
||||
* Add `actions.WORKFLOW_DIRS` setting (#36619)
|
||||
* Avoid opening new tab when downloading actions logs (#36740)
|
||||
* Implements OIDC RP-Initiated Logout (#36724)
|
||||
* Show workflow link (#37070)
|
||||
* Desaturate dark theme background colors (#37056)
|
||||
* Refactor "org teams" page and help new users to "add member" to an org (#37051)
|
||||
* Add webhook name field to improve webhook identification (#37025) (#37040)
|
||||
* Make task list checkboxes clickable in the preview tab (#37010)
|
||||
* Improve severity labels in Actions logs and tweak colors (#36993)
|
||||
* Linkify URLs in Actions workflow logs (#36986)
|
||||
* Allow text selection on checkbox labels (#36970)
|
||||
* Support dark/light theme images in markdown (#36922)
|
||||
* Enable native dark mode for swagger-ui (#36899)
|
||||
* Rework checkbox styling, remove `input` border hover effect (#36870)
|
||||
* Refactor storage content-type handling of ServeDirectURL (#36804)
|
||||
* Use "Enable Gravatar" but not "Disable" (#36771)
|
||||
* Use case-insensitive matching for Git error "Not a valid object name" (#36728)
|
||||
* Add “Copy Source” to markup comment menu (#36726)
|
||||
* Change image transparency grid to CSS (#36711)
|
||||
* Add "Run" prefix for unnamed action steps (#36624)
|
||||
* Persist actions log time display settings in `localStorage` (#36623)
|
||||
* Use first commit title for multi-commit PRs and fix auto-focus title field (#36606)
|
||||
* Improve BuildCaseInsensitiveLike with lowercase (#36598)
|
||||
* Improve diff highlighting (#36583)
|
||||
* Exclude cancelled runs from failure-only email notifications (#36569)
|
||||
* Use full-file highlighting for diff sections (#36561)
|
||||
* Color command/error logs in Actions log (#36538)
|
||||
* Add paging headers (#36521)
|
||||
* Improve timeline entries for WIP prefix changes in pull requests (#36518)
|
||||
* Add FOLDER_ICON_THEME configuration option (#36496)
|
||||
* Normalize guessed languages for code highlighting (#36450)
|
||||
* Add chunked transfer encoding support for LFS uploads (#36380)
|
||||
* Indicate when only optional checks failed (#36367)
|
||||
* Add 'allow_maintainer_edit' API option for creating a pull request (#36283)
|
||||
* Support closing keywords with URL references (#36221)
|
||||
* Improve diff file headers (#36215)
|
||||
* Fix and enhance comment editor monospace toggle (#36181)
|
||||
* Add git.DIFF_RENAME_SIMILARITY_THRESHOLD option (#36164)
|
||||
* Add matching pair insertion to markdown textarea (#36121)
|
||||
* Add sorting/filtering to admin user search API endpoint (#36112)
|
||||
* Allow action user have read permission in public repo like other user (#36095)
|
||||
* Disable matchBrackets in monaco (#36089)
|
||||
* Use GitHub-style commit message for squash merge (#35987)
|
||||
* Make composer registry support tar.gz and tar.bz2 and fix bugs (#35958)
|
||||
* Add GITEA_PR_INDEX env variable to githooks (#35938)
|
||||
* Add proper error message if session provider can not be created (#35520)
|
||||
* Add button to copy file name in PR files (#35509)
|
||||
* Move `X_FRAME_OPTIONS` setting from `cors` to `security` section (#30256)
|
||||
* Add placeholder content for empty content page (#37114)
|
||||
* Add `DEFAULT_DELETE_BRANCH_AFTER_MERGE` setting (#36917)
|
||||
* Redirect to the only OAuth2 provider when no other login methods and fix various problems (#36901)
|
||||
* Add admin badge to navbar avatar (#36790)
|
||||
* Add `never` option to `PUBLIC_URL_DETECTION` configuration (#36785)
|
||||
* Add background and run count to actions list page (#36707)
|
||||
* Add icon to buttons "Close with Comment", "Close Pull Request", "Close Issue" (#36654)
|
||||
* Add support for in_progress event in workflow_run webhook (#36979)
|
||||
* Report commit status for pull_request_review events (#36589)
|
||||
* Render merged pull request title as such in dashboard feed (#36479)
|
||||
* Feature to be able to filter project boards by milestones (#36321)
|
||||
* Use user id in noreply emails (#36550)
|
||||
* Enable pagination on GiteaDownloader.getIssueReactions() (#36549)
|
||||
* Remove striped tables in UI (#36509)
|
||||
* Improve control char rendering and escape button styling (#37094)
|
||||
* Support legacy run/job index-based URLs and refactor migration 326 (#37008)
|
||||
* Add date to "No Contributions" tooltip (#36190)
|
||||
* Show edit page confirmation dialog on tree view file change (#36130)
|
||||
* Mention proc-receive in text for dashboard.resync_all_hooks func (#35991)
|
||||
* Reuse selectable style for wiki (#35990)
|
||||
* Support blue yellow colorblind theme (#35910)
|
||||
* Support selecting theme on the footer (#35741)
|
||||
* Improve online runner check (#35722)
|
||||
* Add quick approve button on PR page (#35678)
|
||||
* Enable commenting on expanded lines in PR diffs (#35662)
|
||||
* Print PR-Title into tooltip for actions (#35579)
|
||||
* Use explicit, stronger defaults for newly generated repo signing keys for Debian (#36236)
|
||||
* Improve the compare page (#36261)
|
||||
* Unify repo names in system notices (#36491)
|
||||
* Move package settings to package instead of being tied to version (#37026)
|
||||
* Add Actions API rerun endpoints for runs and jobs (#36768)
|
||||
* Add branch_count to repository API (#35351) (#36743)
|
||||
* Add created_by filter to SearchIssues (#36670)
|
||||
* Allow admins to rename non-local users (#35970)
|
||||
* Support updating branch via API (#35951)
|
||||
* Add an option to automatically verify SSH keys from LDAP (#35927)
|
||||
* Make "update file" API can create a new file when SHA is not set (#35738)
|
||||
* Update issue.go with labels documentation (labels content, not ids) (#35522)
|
||||
* Expose content_version for optimistic locking on issue and PR edits (#37035)
|
||||
* Pass ServeHeaderOptions by value instead of pointer, fine tune httplib tests (#36982)
|
||||
* BUGFIXES
|
||||
* Fix API not persisting pull request unit config when has_pull_requests is not set (#36718)
|
||||
* Rename CSS variables and improve colorblind themes (#36353)
|
||||
* Hide `add-matcher` and `remove-matcher` from actions job logs (#36520)
|
||||
* Prevent navigation keys from triggering actions during IME composition (#36540)
|
||||
* Fix vertical alignment of `.commit-sign-badge` children (#36570)
|
||||
* Fix duplicate startup warnings in admin panel (#36641)
|
||||
* Fix CODEOWNERS review request attribution using comment metadata (#36348)
|
||||
* Fix HTML tags appearing in wiki table of contents (#36284)
|
||||
* Fix various bugs (#37096)
|
||||
* Fix various legacy problems (#37092)
|
||||
* Fix RPM Registry 404 when package name contains 'package' (#37087)
|
||||
* Merge some standalone Vite entries into index.js (#37085)
|
||||
* Fix various problems (#37077)
|
||||
* Fix issue label deletion with Actions tokens (#37013)
|
||||
* Hide delete branch or tag buttons in mirror or archived repositories. (#37006)
|
||||
* Fix org contact email not clearable once set (#36975)
|
||||
* Fix a bug when forking a repository in an organization (#36950)
|
||||
* Preserve sort order of exclusive labels from template repo (#36931)
|
||||
* Make container registry support Apple Container (basic auth) (#36920)
|
||||
* Fix the wrong push commits in the pull request when force push (#36914)
|
||||
* Add class "list-header-filters" to the div for projects (#36889)
|
||||
* Fix dbfs error handling (#36844)
|
||||
* Fix incorrect viewed files counter if reverted change was viewed (#36819)
|
||||
* Refactor avatar package, support default avatar fallback (#36788)
|
||||
* Fix README symlink resolution in subdirectories like .github (#36775)
|
||||
* Fix CSS stacking context issue in actions log (#36749)
|
||||
* Add gpg signing for merge rebase and update by rebase (#36701)
|
||||
* Delete non-exist branch should return 404 (#36694)
|
||||
* Fix `TestActionsCollaborativeOwner` (#36657)
|
||||
* Fix multi-arch Docker build SIGILL by splitting frontend stage (#36646)
|
||||
* Fix linguist-detectable attribute being ignored for configuration files (#36640)
|
||||
* Fix state desync in ComboMarkdownEditor (#36625)
|
||||
* Unify DEFAULT_SHOW_FULL_NAME output in templates and dropdown (#36597)
|
||||
* Pull Request Pusher should be the author of the merge (#36581)
|
||||
* Fix various version parsing problems (#36553)
|
||||
* Fix highlight diff result (#36539)
|
||||
* Fix mirror sync parser and fix mirror messages (#36504)
|
||||
* Fix bug when list pull request commits (#36485)
|
||||
* Fix various bugs (#36446)
|
||||
* Fix issue filter menu layout (#36426)
|
||||
* Restrict branch naming when new change matches with protection rules (#36405)
|
||||
* Fix link/origin referrer and login redirect (#36279)
|
||||
* Generate IDs for HTML headings without id attribute (#36233)
|
||||
* Use a migration test instead of a wrong test which populated the meta test repositories and fix a migration bug (#36160)
|
||||
* Fix issue close timeline icon (#36138)
|
||||
* Fix diff blob excerpt expansion (#35922)
|
||||
* Fix external render (#35727)
|
||||
* Fix review request webhook bug (#35339) (#35723)
|
||||
* Fix shutdown waitgroup panic (#35676)
|
||||
* Cleanup ActionRun creation (#35624)
|
||||
* Fix possible bug when migrating issues/pull requests (#33487)
|
||||
* Various fixes (#36697)
|
||||
* Apply notify/register mail flags during install load (#37120)
|
||||
* Repair duration display for bad stopped timestamps (#37121)
|
||||
* Fix(upgrade.sh): use HTTPS for GPG key import and restore SELinux context after upgrade (#36930)
|
||||
* Fix various trivial problems (#36921)
|
||||
* Fix various trivial problems (#36953)
|
||||
* Fix NuGet package upload error handling (#37074)
|
||||
* Fix CodeQL code scanning alerts (#36858)
|
||||
* Refactor issue sidebar and fix various problems (#37045)
|
||||
* Fix various problems (#37029)
|
||||
* Fix relative-time RangeError (#37021)
|
||||
* Fix chroma lexer mapping (#36629)
|
||||
* Fix typos and grammar in English locale (#36751)
|
||||
* Fix milestone/project text overflow in issue sidebar (#36741)
|
||||
* Fix `no-content` message not rendering after comment edit (#36733)
|
||||
* Fix theme loading in development (#36605)
|
||||
* Fix workflow run jobs API returning null steps (#36603)
|
||||
* Fix timeline event layout overflow with long content (#36595)
|
||||
* Fix minor UI issues in runner edit page (#36590)
|
||||
* Fix incorrect vendored detections (#36508)
|
||||
* Fix editorconfig not respected in PR Conversation view (#36492)
|
||||
* Don't create self-references in merged PRs (#36490)
|
||||
* Fix potential incorrect runID in run status update (#36437)
|
||||
* Fix file-tree ui error when adding files to repo without commits (#36312)
|
||||
* Improve image captcha contrast for dark mode (#36265)
|
||||
* Fix panic in blame view when a file has only a single commit (#36230)
|
||||
* Fix spelling error in migrate-storage cmd utility (#36226)
|
||||
* Fix code highlighting on blame page (#36157)
|
||||
* Fix nilnil in onedev downloader (#36154)
|
||||
* Fix actions lint (#36029)
|
||||
* Fix oauth2 session gob register (#36017)
|
||||
* Fix Arch repo pacman.conf snippet (#35825)
|
||||
* Fix a number of `strictNullChecks`-related issues (#35795)
|
||||
* Fix URLJoin, markup render link reoslving, sign-in/up/linkaccount page common data (#36861)
|
||||
* Hide delete directory button for mirror or archive repository and disable the menu item if user have no permission (#36384)
|
||||
* Update message severity colors, fix navbar double border (#37019)
|
||||
* Inline and lazy-load EasyMDE CSS, fix border colors (#36714)
|
||||
* Closed milestones with no issues now show as 100% completed (#36220)
|
||||
* Add test for ExtendCommentTreePathLength migration and fix bugs (#35791)
|
||||
* Only turn links to current instance into hash links (#36237)
|
||||
* Fix typos in code comments: doesnt, dont, wont (#36890)
|
||||
* REFACTOR
|
||||
* Replace Monaco with CodeMirror (#36764)
|
||||
* Replace CSRF cookie with `CrossOriginProtection` (#36183)
|
||||
* Replace index with id in actions routes (#36842)
|
||||
* Remove unnecessary function parameter (#35765)
|
||||
* Move jobparser from act repository to Gitea (#36699)
|
||||
* Refactor compare router param parse (#36105)
|
||||
* Optimize 'refreshAccesses' to perform update without removing then adding (#35702)
|
||||
* Clean up checkbox cursor styles (#37016)
|
||||
* Remove undocumented support of signing key in the repository git configuration file (#36143)
|
||||
* Switch `cmd/` to use constructor functions. (#36962)
|
||||
* Use `relative-time` to render absolute dates (#36238)
|
||||
* Some refactors about GetMergeBase (#36186)
|
||||
* Some small refactors (#36163)
|
||||
* Use gitRepo as parameter instead of repopath when invoking sign functions (#36162)
|
||||
* Move blame to gitrepo (#36161)
|
||||
* Move some functions to gitrepo package to reduce RepoPath reference directly (#36126)
|
||||
* Use gitrepo's clone and push when possible (#36093)
|
||||
* Remove mermaid margin workaround (#35732)
|
||||
* Move some functions to gitrepo package (#35543)
|
||||
* Move GetDiverging functions to gitrepo (#35524)
|
||||
* Use global lock instead of status pool for cron lock (#35507)
|
||||
* Use explicit mux instead of DefaultServeMux (#36276)
|
||||
* Use gitrepo's push function (#36245)
|
||||
* Pass request context to generateAdditionalHeadersForIssue (#36274)
|
||||
* Move assign project when creating pull request to the same database transaction (#36244)
|
||||
* Move catfile batch to a sub package of git module (#36232)
|
||||
* Use gitrepo.Repository instead of wikipath (#35398)
|
||||
* Use experimental go json v2 library (#35392)
|
||||
* Refactor template render (#36438)
|
||||
* Refactor GetRepoRawDiffForFile to avoid unnecessary pipe or goroutine (#36434)
|
||||
* Refactor text utility classes to Tailwind CSS (#36703)
|
||||
* Refactor git command stdio pipe (#36422)
|
||||
* Refactor git command context & pipeline (#36406)
|
||||
* Refactor git command stdio pipe (#36393)
|
||||
* Remove unused functions (#36672)
|
||||
* Refactor Actions Token Access (#35688)
|
||||
* Move commit related functions to gitrepo package (#35600)
|
||||
* Move archive function to repo_model and gitrepo (#35514)
|
||||
* Move some functions to gitrepo package (#35503)
|
||||
* Use git model to detect whether branch exist instead of gitrepo method (#35459)
|
||||
* Some refactor for repo path (#36251)
|
||||
* Extract helper functions from SearchIssues (#36158)
|
||||
* Refactor merge conan and container auth preserve actions taskID (#36560)
|
||||
* Refactor Nuget Auth to reuse Basic Auth Token Validation (#36558)
|
||||
* Refactor ActionsTaskID (#36503)
|
||||
* Refactor auth middleware (#36848)
|
||||
* Refactor code render and render control chars (#37078)
|
||||
* Clean up AppURL, remove legacy origin-url webcomponent (#37090)
|
||||
* Remove `util.URLJoin` and replace all callers with direct path concatenation (#36867)
|
||||
* Replace legacy tw-flex utility classes with flex-text-block/inline (#36778)
|
||||
* Mark unused&immature activitypub as "not implemented" (#36789)
|
||||
* TESTING
|
||||
* Add e2e tests for server push events (#36879)
|
||||
* Rework e2e tests (#36634)
|
||||
* Add e2e reaction test, improve accessibility, enable parallel testing (#37081)
|
||||
* Increase e2e test timeouts on CI to fix flaky tests (#37053)
|
||||
* BUILD
|
||||
* Convert locale files from ini to json format (#35489)
|
||||
* Bump golangci-lint to 2.7.2, enable modernize stringsbuilder (#36180)
|
||||
* Port away from `flake-utils` (#35675)
|
||||
* Remove nolint (#36252)
|
||||
* Update the Unlicense copy to latest version (#36636)
|
||||
* Update to go 1.26.0 and golangci-lint 2.9.0 (#36588)
|
||||
* Replace `google/go-licenses` with custom generation (#36575)
|
||||
* Update go dependencies (#36548)
|
||||
* Bump appleboy/git-push-action from 1.0.0 to 1.2.0 (#36306)
|
||||
* Remove fomantic form module (#36222)
|
||||
* Bump setup-node to v6, re-enable cache (#36207)
|
||||
* Bump crowdin/github-action from 1 to 2 (#36204)
|
||||
* Revert "Bump alpine to 3.23 (#36185)" (#36202)
|
||||
* Update chroma to v2.21.1 (#36201)
|
||||
* Bump astral-sh/setup-uv from 6 to 7 (#36198)
|
||||
* Bump docker/build-push-action from 5 to 6 (#36197)
|
||||
* Bump aws-actions/configure-aws-credentials from 4 to 5 (#36196)
|
||||
* Bump dev-hanz-ops/install-gh-cli-action from 0.1.0 to 0.2.1 (#36195)
|
||||
* Add JSON linting (#36192)
|
||||
* Enable dependabot for actions (#36191)
|
||||
* Bump alpine to 3.23 (#36185)
|
||||
* Update chroma to v2.21.0 (#36171)
|
||||
* Update JS deps and eslint enhancements (#36147)
|
||||
* Update JS deps (#36091)
|
||||
* update golangci-lint to v2.7.0 (#36079)
|
||||
* Update JS deps, fix deprecations (#36040)
|
||||
* Update JS deps (#35978)
|
||||
* Add toolchain directive to go.mod (#35901)
|
||||
* Move `gitea-vet` to use `go tool` (#35878)
|
||||
* Update to go 1.25.4 (#35877)
|
||||
* Enable TypeScript `strictNullChecks` (#35843)
|
||||
* Enable `vue/require-typed-ref` eslint rule (#35764)
|
||||
* Update JS dependencies (#35759)
|
||||
* Move `codeformat` folder to tools (#35758)
|
||||
* Update dependencies (#35733)
|
||||
* Bump happy-dom from 20.0.0 to 20.0.2 (#35677)
|
||||
* Bump setup-go to v6 (#35660)
|
||||
* Update JS deps, misc tweaks (#35643)
|
||||
* Bump happy-dom from 19.0.2 to 20.0.0 (#35625)
|
||||
* Use bundled version of spectral (#35573)
|
||||
* Update JS and PY deps (#35565)
|
||||
* Bump github.com/wneessen/go-mail from 0.6.2 to 0.7.1 (#35557)
|
||||
* Migrate from webpack to vite (#37002)
|
||||
* Update JS dependencies and misc tweaks (#37064)
|
||||
* Update to eslint 10 (#36925)
|
||||
* Optimize Docker build with dependency layer caching (#36864)
|
||||
* Update JS deps (#36850)
|
||||
* Update tool dependencies and fix new lint issues (#36702)
|
||||
* Remove redundant linter rules (#36658)
|
||||
* Move Fomantic dropdown CSS to custom module (#36530)
|
||||
* Remove and forbid `@ts-expect-error` (#36513)
|
||||
* Refactor git command stderr handling (#36402)
|
||||
* Enable gocheckcompilerdirectives linter (#36156)
|
||||
* Replace `lint-go-gopls` with additional `govet` linters (#36028)
|
||||
* Update golangci-lint to v2.6.0 (#35801)
|
||||
* Misc tool tweaks (#35734)
|
||||
* Add cache to container build (#35697)
|
||||
* Upgrade vite (#37126)
|
||||
* Update `setup-uv` to v8.0.0 (#37101)
|
||||
* Upgrade `go-git` to v5.17.2 and related dependencies (#37060)
|
||||
* Raise minimum Node.js version to 22.18.0 (#37058)
|
||||
* Upgrade `golang.org/x/image` to v0.38.0 (#37054)
|
||||
* Update minimum go version to 1.26.1, golangci-lint to 2.11.2, fix test style (#36876)
|
||||
* Enable eslint concurrency (#36878)
|
||||
* Vendor relative-time-element as local web component (#36853)
|
||||
* Update material-icon-theme v5.32.0 (#36832)
|
||||
* Update Go dependencies (#36781)
|
||||
* Upgrade minimatch (#36760)
|
||||
* Remove i18n backport tool at the moment because of translation format changed (#36643)
|
||||
* Update emoji data for Unicode 16 (#36596)
|
||||
* Update JS dependencies, adjust webpack config, misc fixes (#36431)
|
||||
* Update material-icon-theme to v5.31.0 (#36427)
|
||||
* Update JS and PY deps (#36383)
|
||||
* Bump alpine to 3.23, add platforms to `docker-dryrun` (#36379)
|
||||
* Update JS deps (#36354)
|
||||
* Update goldmark to v1.7.16 (#36343)
|
||||
* Update chroma to v2.22.0 (#36342)
|
||||
* DOCS
|
||||
* Update AI Contribution Policy (#37022)
|
||||
* Update AGENTS.md with additional guidelines (#37018)
|
||||
* Add missing cron tasks to example ini (#37012)
|
||||
* Add AI Contribution Policy to CONTRIBUTING.md (#36651)
|
||||
* Minor punctuation improvement in CONTRIBUTING.md (#36291)
|
||||
* Add documentation for markdown anchor post-processing (#36443)
|
||||
* MISC
|
||||
* Correct spelling (#36783)
|
||||
* Update Nix flake (#37110)
|
||||
* Update Nix flake (#37024)
|
||||
* Add valid github scopes (#36977)
|
||||
* Update Nix flake (#36943)
|
||||
* Update Nix flake (#36902)
|
||||
* Update Nix flake (#36857)
|
||||
* Update Nix flake (#36787)
|
||||
|
||||
## [1.25.5](https://github.com/go-gitea/gitea/releases/tag/v1.25.5) - 2026-03-10
|
||||
|
||||
* SECURITY
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
|
||||
// regexp is based on go-license, excluding README and NOTICE
|
||||
// https://github.com/google/go-licenses/blob/master/licenses/find.go
|
||||
// also defined in vite.config.ts
|
||||
var licenseRe = regexp.MustCompile(`^(?i)((UN)?LICEN(S|C)E|COPYING).*$`)
|
||||
|
||||
// primaryLicenseRe matches exact primary license filenames without suffixes.
|
||||
|
||||
@@ -41,10 +41,10 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; App name that shows in every page title
|
||||
APP_NAME = ; Gitea: Git with a cup of tea
|
||||
;APP_NAME = Gitea: Git with a cup of tea
|
||||
;;
|
||||
;; RUN_USER will automatically detect the current user - but you can set it here change it if you run locally
|
||||
RUN_USER = ; git
|
||||
;RUN_USER =
|
||||
;;
|
||||
;; Application run mode, affects performance and debugging: "dev" or "prod", default is "prod"
|
||||
;; Mode "dev" makes Gitea easier to develop and debug, values other than "dev" are treated as "prod" which is for production use.
|
||||
@@ -461,6 +461,11 @@ INTERNAL_TOKEN =
|
||||
;; Name of cookie used to store authentication information.
|
||||
;COOKIE_REMEMBER_NAME = gitea_incredible
|
||||
;;
|
||||
;; URL or path that Gitea should redirect users to *after* performing its own logout.
|
||||
;; Use this, if needed, when authentication is handled by a reverse proxy or SSO.
|
||||
;; For example: "/my-sso/logout?return=/my-sso/home"
|
||||
;REVERSE_PROXY_LOGOUT_REDIRECT =
|
||||
;;
|
||||
;; Reverse proxy authentication header name of user name, email, and full name
|
||||
;REVERSE_PROXY_AUTHENTICATION_USER = X-WEBAUTH-USER
|
||||
;REVERSE_PROXY_AUTHENTICATION_EMAIL = X-WEBAUTH-EMAIL
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module code.gitea.io/gitea
|
||||
|
||||
go 1.26.1
|
||||
go 1.26.2
|
||||
|
||||
// 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:
|
||||
@@ -12,7 +12,7 @@ require (
|
||||
code.gitea.io/sdk/gitea v0.24.1
|
||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
|
||||
connectrpc.com/connect v1.19.1
|
||||
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed
|
||||
gitea.com/go-chi/binding v0.0.0-20260414111559-654cea7ac60a
|
||||
gitea.com/go-chi/cache v0.2.1
|
||||
gitea.com/go-chi/captcha v0.0.0-20240315150714-fb487f629098
|
||||
gitea.com/go-chi/session v0.0.0-20251124165456-68e0254e989e
|
||||
@@ -57,7 +57,6 @@ require (
|
||||
github.com/go-redsync/redsync/v4 v4.16.0
|
||||
github.com/go-sql-driver/mysql v1.9.3
|
||||
github.com/go-webauthn/webauthn v0.16.1
|
||||
github.com/goccy/go-json v0.10.6
|
||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
|
||||
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1
|
||||
@@ -196,6 +195,7 @@ require (
|
||||
github.com/go-ini/ini v1.67.0 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
|
||||
github.com/go-webauthn/x v0.2.2 // indirect
|
||||
github.com/goccy/go-json v0.10.6 // indirect
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
|
||||
@@ -18,8 +18,8 @@ filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo=
|
||||
filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc=
|
||||
gitea.com/gitea/act v0.261.10 h1:ndwbtuMXXz1dpYF2iwY1/PkgKNETo4jmPXfinTZt8cs=
|
||||
gitea.com/gitea/act v0.261.10/go.mod h1:oIkqQHvU0lfuIWwcpqa4FmU+t3prA89tgkuHUTsrI2c=
|
||||
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed h1:EZZBtilMLSZNWtHHcgq2mt6NSGhJSZBuduAlinMEmso=
|
||||
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed/go.mod h1:E3i3cgB04dDx0v3CytCgRTTn9Z/9x891aet3r456RVw=
|
||||
gitea.com/go-chi/binding v0.0.0-20260414111559-654cea7ac60a h1:JHoBrfuTSF9Ke9aNfSYj1XRPBHjKPgCApVprnt2Am0M=
|
||||
gitea.com/go-chi/binding v0.0.0-20260414111559-654cea7ac60a/go.mod h1:FOsLJIMdpiHzBp3Vby6Wfkdw2ppGscrjgU1IC7E4/zQ=
|
||||
gitea.com/go-chi/cache v0.2.1 h1:bfAPkvXlbcZxPCpcmDVCWoHgiBSBmZN/QosnZvEC0+g=
|
||||
gitea.com/go-chi/cache v0.2.1/go.mod h1:Qic0HZ8hOHW62ETGbonpwz8WYypj9NieU9659wFUJ8Q=
|
||||
gitea.com/go-chi/captcha v0.0.0-20240315150714-fb487f629098 h1:p2ki+WK0cIeNQuqjR98IP2KZQKRzJJiV7aTeMAFwaWo=
|
||||
|
||||
@@ -103,10 +103,20 @@ func GetEventsFromContent(content []byte) ([]*jobparser.Event, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := ValidateWorkflowContent(content); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return events, nil
|
||||
}
|
||||
|
||||
// ValidateWorkflowContent catches structural errors (e.g. blank lines in run: | blocks)
|
||||
// that model.ReadWorkflow alone does not detect.
|
||||
func ValidateWorkflowContent(content []byte) error {
|
||||
_, err := jobparser.Parse(content)
|
||||
return err
|
||||
}
|
||||
|
||||
func DetectWorkflows(
|
||||
gitRepo *git.Repository,
|
||||
commit *git.Commit,
|
||||
|
||||
@@ -9,16 +9,26 @@ import (
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
webhook_module "code.gitea.io/gitea/modules/webhook"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func fullWorkflowContent(part string) []byte {
|
||||
return []byte(`
|
||||
name: test
|
||||
` + part + `
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo hello
|
||||
`)
|
||||
}
|
||||
|
||||
func TestIsWorkflow(t *testing.T) {
|
||||
oldDirs := setting.Actions.WorkflowDirs
|
||||
defer func() {
|
||||
setting.Actions.WorkflowDirs = oldDirs
|
||||
}()
|
||||
defer test.MockVariableValue(&setting.Actions.WorkflowDirs)()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -218,7 +228,7 @@ func TestDetectMatched(t *testing.T) {
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
evts, err := GetEventsFromContent([]byte(tc.yamlOn))
|
||||
evts, err := GetEventsFromContent(fullWorkflowContent(tc.yamlOn))
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, evts, 1)
|
||||
assert.Equal(t, tc.expected, detectMatched(nil, tc.commit, tc.triggedEvent, tc.payload, evts[0]))
|
||||
@@ -373,7 +383,7 @@ func TestMatchIssuesEvent(t *testing.T) {
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
evts, err := GetEventsFromContent([]byte(tc.yamlOn))
|
||||
evts, err := GetEventsFromContent(fullWorkflowContent(tc.yamlOn))
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, evts, 1)
|
||||
|
||||
|
||||
@@ -13,63 +13,45 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
var catFileBatchDebugWaitClose atomic.Int64
|
||||
|
||||
type catFileBatchCommunicator struct {
|
||||
closeFunc func(err error)
|
||||
closeFunc atomic.Pointer[func(err error)]
|
||||
reqWriter io.Writer
|
||||
respReader *bufio.Reader
|
||||
debugGitCmd *gitcmd.Command
|
||||
}
|
||||
|
||||
func (b *catFileBatchCommunicator) Close() {
|
||||
if b.closeFunc != nil {
|
||||
b.closeFunc(nil)
|
||||
b.closeFunc = nil
|
||||
func (b *catFileBatchCommunicator) Close(err ...error) {
|
||||
if fn := b.closeFunc.Swap(nil); fn != nil {
|
||||
(*fn)(util.OptionalArg(err))
|
||||
}
|
||||
}
|
||||
|
||||
// newCatFileBatch opens git cat-file --batch in the provided repo and returns a stdin pipe, a stdout reader and cancel function
|
||||
func newCatFileBatch(ctx context.Context, repoPath string, cmdCatFile *gitcmd.Command) (ret *catFileBatchCommunicator) {
|
||||
// newCatFileBatch opens git cat-file --batch/--batch-check/--batch-command command and prepares the stdin/stdout pipes for communication.
|
||||
func newCatFileBatch(ctx context.Context, repoPath string, cmdCatFile *gitcmd.Command) *catFileBatchCommunicator {
|
||||
ctx, ctxCancel := context.WithCancelCause(ctx)
|
||||
|
||||
// We often want to feed the commits in order into cat-file --batch, followed by their trees and subtrees as necessary.
|
||||
stdinWriter, stdoutReader, stdPipeClose := cmdCatFile.MakeStdinStdoutPipe()
|
||||
pipeClose := func() {
|
||||
if delay := catFileBatchDebugWaitClose.Load(); delay > 0 {
|
||||
time.Sleep(time.Duration(delay)) // for testing purpose only
|
||||
}
|
||||
stdPipeClose()
|
||||
}
|
||||
closeFunc := func(err error) {
|
||||
ctxCancel(err)
|
||||
pipeClose()
|
||||
}
|
||||
return newCatFileBatchWithCloseFunc(ctx, repoPath, cmdCatFile, stdinWriter, stdoutReader, closeFunc)
|
||||
}
|
||||
|
||||
func newCatFileBatchWithCloseFunc(ctx context.Context, repoPath string, cmdCatFile *gitcmd.Command,
|
||||
stdinWriter gitcmd.PipeWriter, stdoutReader gitcmd.PipeReader, closeFunc func(err error),
|
||||
) *catFileBatchCommunicator {
|
||||
ret := &catFileBatchCommunicator{
|
||||
debugGitCmd: cmdCatFile,
|
||||
closeFunc: closeFunc,
|
||||
reqWriter: stdinWriter,
|
||||
respReader: bufio.NewReaderSize(stdoutReader, 32*1024), // use a buffered reader for rich operations
|
||||
}
|
||||
ret.closeFunc.Store(new(func(err error) {
|
||||
ctxCancel(err)
|
||||
stdPipeClose()
|
||||
}))
|
||||
|
||||
err := cmdCatFile.WithDir(repoPath).StartWithStderr(ctx)
|
||||
if err != nil {
|
||||
log.Error("Unable to start git command %v: %v", cmdCatFile.LogString(), err)
|
||||
// ideally here it should return the error, but it would require refactoring all callers
|
||||
// so just return a dummy communicator that does nothing, almost the same behavior as before, not bad
|
||||
closeFunc(err)
|
||||
ret.Close(err)
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -78,12 +60,33 @@ func newCatFileBatchWithCloseFunc(ctx context.Context, repoPath string, cmdCatFi
|
||||
if err != nil && !errors.Is(err, context.Canceled) {
|
||||
log.Error("cat-file --batch command failed in repo %s, error: %v", repoPath, err)
|
||||
}
|
||||
closeFunc(err)
|
||||
ret.Close(err)
|
||||
}()
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (b *catFileBatchCommunicator) debugKill() (ret struct {
|
||||
beforeClose chan struct{}
|
||||
blockClose chan struct{}
|
||||
afterClose chan struct{}
|
||||
},
|
||||
) {
|
||||
ret.beforeClose = make(chan struct{})
|
||||
ret.blockClose = make(chan struct{})
|
||||
ret.afterClose = make(chan struct{})
|
||||
oldCloseFunc := b.closeFunc.Load()
|
||||
b.closeFunc.Store(new(func(err error) {
|
||||
b.closeFunc.Store(nil)
|
||||
close(ret.beforeClose)
|
||||
<-ret.blockClose
|
||||
(*oldCloseFunc)(err)
|
||||
close(ret.afterClose)
|
||||
}))
|
||||
b.debugGitCmd.DebugKill()
|
||||
return ret
|
||||
}
|
||||
|
||||
// catFileBatchParseInfoLine reads the header line from cat-file --batch
|
||||
// We expect: <oid> SP <type> SP <size> LF
|
||||
// then leaving the rest of the stream "<contents> LF" to be read
|
||||
|
||||
@@ -7,9 +7,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
|
||||
@@ -39,13 +37,22 @@ func testCatFileBatch(t *testing.T) {
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
simulateQueryTerminated := func(pipeCloseDelay, pipeReadDelay time.Duration) (errRead error) {
|
||||
catFileBatchDebugWaitClose.Store(int64(pipeCloseDelay))
|
||||
defer catFileBatchDebugWaitClose.Store(0)
|
||||
simulateQueryTerminated := func(t *testing.T, errBeforePipeClose, errAfterPipeClose error) {
|
||||
readError := func(t *testing.T, r io.Reader, expectedErr error) {
|
||||
if expectedErr == nil {
|
||||
return // expectedErr == nil means this read should be skipped
|
||||
}
|
||||
n, err := r.Read(make([]byte, 100))
|
||||
assert.Zero(t, n)
|
||||
assert.ErrorIs(t, err, expectedErr)
|
||||
}
|
||||
|
||||
batch, err := NewBatch(t.Context(), filepath.Join(testReposDir, "repo1_bare"))
|
||||
require.NoError(t, err)
|
||||
defer batch.Close()
|
||||
_, _ = batch.QueryInfo("e2129701f1a4d54dc44f03c93bca0a2aec7c5449")
|
||||
_, err = batch.QueryInfo("e2129701f1a4d54dc44f03c93bca0a2aec7c5449")
|
||||
require.NoError(t, err)
|
||||
|
||||
var c *catFileBatchCommunicator
|
||||
switch b := batch.(type) {
|
||||
case *catFileBatchLegacy:
|
||||
@@ -58,24 +65,18 @@ func testCatFileBatch(t *testing.T) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Go(func() {
|
||||
time.Sleep(pipeReadDelay)
|
||||
var n int
|
||||
n, errRead = c.respReader.Read(make([]byte, 100))
|
||||
assert.Zero(t, n)
|
||||
})
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
c.debugGitCmd.DebugKill()
|
||||
wg.Wait()
|
||||
return errRead
|
||||
}
|
||||
require.NotEqual(t, errBeforePipeClose == nil, errAfterPipeClose == nil, "must set exactly one of the expected errors")
|
||||
|
||||
inceptor := c.debugKill()
|
||||
<-inceptor.beforeClose // wait for the command's Close to be called, the pipe is not closed yet
|
||||
readError(t, c.respReader, errBeforePipeClose) // then caller will read on an open pipe which will be closed soon
|
||||
close(inceptor.blockClose) // continue to close the pipe
|
||||
<-inceptor.afterClose // wait for the pipe to be closed
|
||||
readError(t, c.respReader, errAfterPipeClose) // then caller will read on a closed pipe
|
||||
}
|
||||
t.Run("QueryTerminated", func(t *testing.T) {
|
||||
err := simulateQueryTerminated(0, 20*time.Millisecond)
|
||||
assert.ErrorIs(t, err, os.ErrClosed) // pipes are closed faster
|
||||
err = simulateQueryTerminated(40*time.Millisecond, 20*time.Millisecond)
|
||||
assert.ErrorIs(t, err, io.EOF) // reader is faster
|
||||
simulateQueryTerminated(t, io.EOF, nil) // reader is faster
|
||||
simulateQueryTerminated(t, nil, os.ErrClosed) // pipes are closed faster
|
||||
})
|
||||
|
||||
batch, err := NewBatch(t.Context(), filepath.Join(testReposDir, "repo1_bare"))
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
)
|
||||
|
||||
var _ Interface = jsonGoccy{}
|
||||
|
||||
type jsonGoccy struct{}
|
||||
|
||||
func (jsonGoccy) Marshal(v any) ([]byte, error) {
|
||||
return json.Marshal(v)
|
||||
}
|
||||
|
||||
func (jsonGoccy) Unmarshal(data []byte, v any) error {
|
||||
return json.Unmarshal(data, v)
|
||||
}
|
||||
|
||||
func (jsonGoccy) NewEncoder(writer io.Writer) Encoder {
|
||||
return json.NewEncoder(writer)
|
||||
}
|
||||
|
||||
func (jsonGoccy) NewDecoder(reader io.Reader) Decoder {
|
||||
return json.NewDecoder(reader)
|
||||
}
|
||||
|
||||
func (jsonGoccy) Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
|
||||
return json.Indent(dst, src, prefix, indent)
|
||||
}
|
||||
@@ -6,12 +6,12 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"encoding/json" //nolint:depguard // this package wraps it
|
||||
"io"
|
||||
)
|
||||
|
||||
func getDefaultJSONHandler() Interface {
|
||||
return jsonGoccy{}
|
||||
return jsonV1{}
|
||||
}
|
||||
|
||||
func MarshalKeepOptionalEmpty(v any) ([]byte, error) {
|
||||
|
||||
@@ -31,6 +31,7 @@ var (
|
||||
ReverseProxyAuthEmail string
|
||||
ReverseProxyAuthFullName string
|
||||
ReverseProxyLimit int
|
||||
ReverseProxyLogoutRedirect string
|
||||
ReverseProxyTrustedProxies []string
|
||||
MinPasswordLength int
|
||||
ImportLocalPaths bool
|
||||
@@ -124,6 +125,7 @@ func loadSecurityFrom(rootCfg ConfigProvider) {
|
||||
ReverseProxyAuthFullName = sec.Key("REVERSE_PROXY_AUTHENTICATION_FULL_NAME").MustString("X-WEBAUTH-FULLNAME")
|
||||
|
||||
ReverseProxyLimit = sec.Key("REVERSE_PROXY_LIMIT").MustInt(1)
|
||||
ReverseProxyLogoutRedirect = sec.Key("REVERSE_PROXY_LOGOUT_REDIRECT").String()
|
||||
ReverseProxyTrustedProxies = sec.Key("REVERSE_PROXY_TRUSTED_PROXIES").Strings(",")
|
||||
if len(ReverseProxyTrustedProxies) == 0 {
|
||||
ReverseProxyTrustedProxies = []string{"127.0.0.0/8", "::1/128"}
|
||||
|
||||
@@ -201,7 +201,7 @@ func mustCurrentRunUserMatch(rootCfg ConfigProvider) {
|
||||
if HasInstallLock(rootCfg) {
|
||||
currentUser, match := IsRunUserMatchCurrentUser(RunUser)
|
||||
if !match {
|
||||
log.Fatal("Expect user '%s' but current user is: %s", RunUser, currentUser)
|
||||
log.Fatal("Expect user '%s' (RUN_USER in app.ini) but current user is: %s", RunUser, currentUser)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,14 @@ package validation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/auth"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/glob"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"gitea.com/go-chi/binding"
|
||||
@@ -31,8 +33,23 @@ const (
|
||||
ErrInvalidBadgeSlug = "InvalidBadgeSlug"
|
||||
)
|
||||
|
||||
type jsonProvider struct{}
|
||||
|
||||
func (j jsonProvider) Marshal(v any) ([]byte, error) { return json.Marshal(v) }
|
||||
|
||||
func (j jsonProvider) Unmarshal(data []byte, v any) error { return json.Unmarshal(data, v) }
|
||||
|
||||
func (j jsonProvider) NewDecoder(reader io.Reader) binding.JSONDecoder {
|
||||
return json.NewDecoder(reader)
|
||||
}
|
||||
|
||||
func (j jsonProvider) NewEncoder(writer io.Writer) binding.JSONEncoder {
|
||||
return json.NewEncoder(writer)
|
||||
}
|
||||
|
||||
// AddBindingRules adds additional binding rules
|
||||
func AddBindingRules() {
|
||||
binding.JSONProvider = jsonProvider{}
|
||||
addGitRefNameBindingRule()
|
||||
addValidURLListBindingRule()
|
||||
addValidURLBindingRule()
|
||||
|
||||
@@ -269,7 +269,7 @@
|
||||
"install.lfs_path": "Git LFS Root Path",
|
||||
"install.lfs_path_helper": "Files tracked by Git LFS will be stored in this directory. Leave empty to disable.",
|
||||
"install.run_user": "Run As Username",
|
||||
"install.run_user_helper": "The operating system username that Gitea runs as. Note that this user must have access to the repository root path.",
|
||||
"install.run_user_helper": "The operating system username that Gitea runs as, it must have write access to the data paths. This value is auto-detected and cannot be changed here. To use a different user, restart Gitea under that account.",
|
||||
"install.domain": "Server Domain",
|
||||
"install.domain_helper": "Domain or host address for the server.",
|
||||
"install.ssh_port": "SSH Server Port",
|
||||
@@ -316,7 +316,6 @@
|
||||
"install.invalid_db_table": "The database table \"%s\" is invalid: %v",
|
||||
"install.invalid_repo_path": "The repository root path is invalid: %v",
|
||||
"install.invalid_app_data_path": "The app data path is invalid: %v",
|
||||
"install.run_user_not_match": "The 'run as' username is not the current username: %s -> %s",
|
||||
"install.internal_token_failed": "Failed to generate internal token: %v",
|
||||
"install.secret_key_failed": "Failed to generate secret key: %v",
|
||||
"install.save_config_failed": "Failed to save configuration: %v",
|
||||
|
||||
+2
-3
@@ -59,7 +59,7 @@
|
||||
"pdfobject": "2.3.1",
|
||||
"perfect-debounce": "2.1.0",
|
||||
"postcss": "8.5.8",
|
||||
"rollup-plugin-license": "3.7.0",
|
||||
"rolldown-license-plugin": "2.2.0",
|
||||
"sortablejs": "1.15.7",
|
||||
"swagger-ui-dist": "5.32.1",
|
||||
"tailwindcss": "3.4.19",
|
||||
@@ -73,8 +73,7 @@
|
||||
"vite-string-plugin": "2.0.2",
|
||||
"vue": "3.5.31",
|
||||
"vue-bar-graph": "2.2.0",
|
||||
"vue-chartjs": "5.3.3",
|
||||
"wrap-ansi": "10.0.0"
|
||||
"vue-chartjs": "5.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint-community/eslint-plugin-eslint-comments": "4.7.1",
|
||||
|
||||
Generated
+8
-361
@@ -185,9 +185,9 @@ importers:
|
||||
postcss:
|
||||
specifier: 8.5.8
|
||||
version: 8.5.8
|
||||
rollup-plugin-license:
|
||||
specifier: 3.7.0
|
||||
version: 3.7.0(picomatch@4.0.4)(rollup@4.60.1)
|
||||
rolldown-license-plugin:
|
||||
specifier: 2.2.0
|
||||
version: 2.2.0
|
||||
sortablejs:
|
||||
specifier: 1.15.7
|
||||
version: 1.15.7
|
||||
@@ -230,9 +230,6 @@ importers:
|
||||
vue-chartjs:
|
||||
specifier: 5.3.3
|
||||
version: 5.3.3(chart.js@4.5.1)(vue@3.5.31(typescript@6.0.2))
|
||||
wrap-ansi:
|
||||
specifier: 10.0.0
|
||||
version: 10.0.0
|
||||
devDependencies:
|
||||
'@eslint-community/eslint-plugin-eslint-comments':
|
||||
specifier: 4.7.1
|
||||
@@ -1235,144 +1232,6 @@ packages:
|
||||
'@rolldown/pluginutils@1.0.0-rc.2':
|
||||
resolution: {integrity: sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==}
|
||||
|
||||
'@rollup/rollup-android-arm-eabi@4.60.1':
|
||||
resolution: {integrity: sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@rollup/rollup-android-arm64@4.60.1':
|
||||
resolution: {integrity: sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@rollup/rollup-darwin-arm64@4.60.1':
|
||||
resolution: {integrity: sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@rollup/rollup-darwin-x64@4.60.1':
|
||||
resolution: {integrity: sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@rollup/rollup-freebsd-arm64@4.60.1':
|
||||
resolution: {integrity: sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@rollup/rollup-freebsd-x64@4.60.1':
|
||||
resolution: {integrity: sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.60.1':
|
||||
resolution: {integrity: sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.60.1':
|
||||
resolution: {integrity: sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.60.1':
|
||||
resolution: {integrity: sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.60.1':
|
||||
resolution: {integrity: sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-loong64-gnu@4.60.1':
|
||||
resolution: {integrity: sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-loong64-musl@4.60.1':
|
||||
resolution: {integrity: sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-ppc64-gnu@4.60.1':
|
||||
resolution: {integrity: sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-ppc64-musl@4.60.1':
|
||||
resolution: {integrity: sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.60.1':
|
||||
resolution: {integrity: sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-musl@4.60.1':
|
||||
resolution: {integrity: sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.60.1':
|
||||
resolution: {integrity: sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.60.1':
|
||||
resolution: {integrity: sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.60.1':
|
||||
resolution: {integrity: sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-openbsd-x64@4.60.1':
|
||||
resolution: {integrity: sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
|
||||
'@rollup/rollup-openharmony-arm64@4.60.1':
|
||||
resolution: {integrity: sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==}
|
||||
cpu: [arm64]
|
||||
os: [openharmony]
|
||||
|
||||
'@rollup/rollup-win32-arm64-msvc@4.60.1':
|
||||
resolution: {integrity: sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-win32-ia32-msvc@4.60.1':
|
||||
resolution: {integrity: sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-win32-x64-gnu@4.60.1':
|
||||
resolution: {integrity: sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-win32-x64-msvc@4.60.1':
|
||||
resolution: {integrity: sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@rtsao/scc@1.1.0':
|
||||
resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
|
||||
|
||||
@@ -1892,10 +1751,6 @@ packages:
|
||||
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
ansi-styles@6.2.3:
|
||||
resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
ansi_up@6.0.6:
|
||||
resolution: {integrity: sha512-yIa1x3Ecf8jWP4UWEunNjqNX6gzE4vg2gGz+xqRGY+TBSucnYp6RRdPV4brmtg6bQ1ljD48mZ5iGSEj7QEpRKA==}
|
||||
|
||||
@@ -1916,10 +1771,6 @@ packages:
|
||||
resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
array-find-index@1.0.2:
|
||||
resolution: {integrity: sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
asciinema-player@3.15.1:
|
||||
resolution: {integrity: sha512-agVYeNlPxthLyAb92l9AS7ypW0uhesqOuQzyR58Q4Sj+MvesQztZBgx86lHqNJkB8rQ6EP0LeA9czGytQUBpYw==}
|
||||
|
||||
@@ -2113,9 +1964,6 @@ packages:
|
||||
resolution: {integrity: sha512-ObxuY6vnbWTN6Od72xfwN9DbzC7Y2vv8u1Soi9ahRKL37gb6y1qk6/dgjs+3JWuXJHWvsg3BXIwzd/rkmAwavg==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
|
||||
commenting@1.1.0:
|
||||
resolution: {integrity: sha512-YeNK4tavZwtH7jEgK1ZINXzLKm6DZdEMfsaaieOsCAN0S8vsY7UeuO3Q7d/M018EFgE+IeUAuBOKkFccBZsUZA==}
|
||||
|
||||
compare-versions@6.1.1:
|
||||
resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==}
|
||||
|
||||
@@ -3385,9 +3233,6 @@ packages:
|
||||
mlly@1.8.2:
|
||||
resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==}
|
||||
|
||||
moment@2.30.1:
|
||||
resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
|
||||
|
||||
moo@0.5.3:
|
||||
resolution: {integrity: sha512-m2fmM2dDm7GZQsY7KK2cme8agi+AAljILjQnof7p1ZMDe6dQ4bdnSMx0cPppudoeNv5hEFQirN6u+O4fDE0IWA==}
|
||||
|
||||
@@ -3478,10 +3323,6 @@ packages:
|
||||
package-manager-detector@1.6.0:
|
||||
resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==}
|
||||
|
||||
package-name-regex@2.0.6:
|
||||
resolution: {integrity: sha512-gFL35q7kbE/zBaPA3UKhp2vSzcPYx2ecbYuwv1ucE9Il6IIgBDweBlH8D68UFGZic2MkllKa2KHCfC1IQBQUYA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
parent-module@1.0.1:
|
||||
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -3706,22 +3547,14 @@ packages:
|
||||
robust-predicates@3.0.3:
|
||||
resolution: {integrity: sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==}
|
||||
|
||||
rolldown-license-plugin@2.2.0:
|
||||
resolution: {integrity: sha512-7a/v9/9o5/pCpPtx4WSX68/xHC8wmmR/cxkofWQ7I7ep5Tvhjb9KkIUdTyuKc52SHiGSz2PxrS0qm/z2PjJyiQ==}
|
||||
|
||||
rolldown@1.0.0-rc.12:
|
||||
resolution: {integrity: sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
hasBin: true
|
||||
|
||||
rollup-plugin-license@3.7.0:
|
||||
resolution: {integrity: sha512-RvvOIF+GH3fBR3wffgc/vmjQn6qOn72WjppWVDp/v+CLpT0BbcRBdSkPeeIOL6U5XccdYgSIMjUyXgxlKEEFcw==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
peerDependencies:
|
||||
rollup: ^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0
|
||||
|
||||
rollup@4.60.1:
|
||||
resolution: {integrity: sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==}
|
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||
hasBin: true
|
||||
|
||||
roughjs@4.6.6:
|
||||
resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==}
|
||||
|
||||
@@ -3805,27 +3638,6 @@ packages:
|
||||
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
spdx-compare@1.0.0:
|
||||
resolution: {integrity: sha512-C1mDZOX0hnu0ep9dfmuoi03+eOdDoz2yvK79RxbcrVEG1NO1Ph35yW102DHWKN4pk80nwCgeMmSY5L25VE4D9A==}
|
||||
|
||||
spdx-exceptions@2.5.0:
|
||||
resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==}
|
||||
|
||||
spdx-expression-parse@3.0.1:
|
||||
resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==}
|
||||
|
||||
spdx-expression-validate@2.0.0:
|
||||
resolution: {integrity: sha512-b3wydZLM+Tc6CFvaRDBOF9d76oGIHNCLYFeHbftFXUWjnfZWganmDmvtM5sm1cRwJc/VDBMLyGGrsLFd1vOxbg==}
|
||||
|
||||
spdx-license-ids@3.0.23:
|
||||
resolution: {integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==}
|
||||
|
||||
spdx-ranges@2.1.1:
|
||||
resolution: {integrity: sha512-mcdpQFV7UDAgLpXEE/jOMqvK4LBoO0uTQg0uvXUewmEFhpiZx5yJSZITHB8w1ZahKdhfZqP5GPEOKLyEq5p8XA==}
|
||||
|
||||
spdx-satisfies@5.0.1:
|
||||
resolution: {integrity: sha512-Nwor6W6gzFp8XX4neaKQ7ChV4wmpSh2sSDemMFSzHxpTw460jxFYeOn+jq4ybnSSw/5sc3pjka9MQPouksQNpw==}
|
||||
|
||||
spectral-cli-bundle@1.0.7:
|
||||
resolution: {integrity: sha512-vIUC0nwv9tYxWV1xHdR3CTVDOEEtLKaDCcQpARZgO0Db7VmSpSWJ4xrnVPNSmO59hBtGwW2CVzHf0OimJBaKAA==}
|
||||
engines: {node: '>=20'}
|
||||
@@ -4256,10 +4068,6 @@ packages:
|
||||
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
wrap-ansi@10.0.0:
|
||||
resolution: {integrity: sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
write-file-atomic@7.0.1:
|
||||
resolution: {integrity: sha512-OTIk8iR8/aCRWBqvxrzxR0hgxWpnYBblY1S5hDWBQfk/VFmJwzmJgQFN3WsoUKHISv2eAwe+PpbUzyL1CKTLXg==}
|
||||
engines: {node: ^20.17.0 || >=22.9.0}
|
||||
@@ -5205,81 +5013,6 @@ snapshots:
|
||||
|
||||
'@rolldown/pluginutils@1.0.0-rc.2': {}
|
||||
|
||||
'@rollup/rollup-android-arm-eabi@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-android-arm64@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-darwin-arm64@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-darwin-x64@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-freebsd-arm64@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-freebsd-x64@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-loong64-gnu@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-loong64-musl@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-ppc64-gnu@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-ppc64-musl@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-riscv64-musl@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-openbsd-x64@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-openharmony-arm64@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-arm64-msvc@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-ia32-msvc@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-x64-gnu@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-x64-msvc@4.60.1':
|
||||
optional: true
|
||||
|
||||
'@rtsao/scc@1.1.0': {}
|
||||
|
||||
'@scarf/scarf@1.4.0': {}
|
||||
@@ -5925,8 +5658,6 @@ snapshots:
|
||||
dependencies:
|
||||
color-convert: 2.0.1
|
||||
|
||||
ansi-styles@6.2.3: {}
|
||||
|
||||
ansi_up@6.0.6: {}
|
||||
|
||||
any-promise@1.3.0: {}
|
||||
@@ -5942,8 +5673,6 @@ snapshots:
|
||||
|
||||
aria-query@5.3.2: {}
|
||||
|
||||
array-find-index@1.0.2: {}
|
||||
|
||||
asciinema-player@3.15.1:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.29.2
|
||||
@@ -6112,8 +5841,6 @@ snapshots:
|
||||
|
||||
comment-parser@1.4.6: {}
|
||||
|
||||
commenting@1.1.0: {}
|
||||
|
||||
compare-versions@6.1.1: {}
|
||||
|
||||
concat-map@0.0.1: {}
|
||||
@@ -7556,8 +7283,6 @@ snapshots:
|
||||
pkg-types: 1.3.1
|
||||
ufo: 1.6.3
|
||||
|
||||
moment@2.30.1: {}
|
||||
|
||||
moo@0.5.3: {}
|
||||
|
||||
ms@2.1.3: {}
|
||||
@@ -7627,8 +7352,6 @@ snapshots:
|
||||
|
||||
package-manager-detector@1.6.0: {}
|
||||
|
||||
package-name-regex@2.0.6: {}
|
||||
|
||||
parent-module@1.0.1:
|
||||
dependencies:
|
||||
callsites: 3.1.0
|
||||
@@ -7815,6 +7538,8 @@ snapshots:
|
||||
|
||||
robust-predicates@3.0.3: {}
|
||||
|
||||
rolldown-license-plugin@2.2.0: {}
|
||||
|
||||
rolldown@1.0.0-rc.12(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1):
|
||||
dependencies:
|
||||
'@oxc-project/types': 0.122.0
|
||||
@@ -7839,51 +7564,6 @@ snapshots:
|
||||
- '@emnapi/core'
|
||||
- '@emnapi/runtime'
|
||||
|
||||
rollup-plugin-license@3.7.0(picomatch@4.0.4)(rollup@4.60.1):
|
||||
dependencies:
|
||||
commenting: 1.1.0
|
||||
fdir: 6.5.0(picomatch@4.0.4)
|
||||
lodash: 4.17.23
|
||||
magic-string: 0.30.21
|
||||
moment: 2.30.1
|
||||
package-name-regex: 2.0.6
|
||||
rollup: 4.60.1
|
||||
spdx-expression-validate: 2.0.0
|
||||
spdx-satisfies: 5.0.1
|
||||
transitivePeerDependencies:
|
||||
- picomatch
|
||||
|
||||
rollup@4.60.1:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
optionalDependencies:
|
||||
'@rollup/rollup-android-arm-eabi': 4.60.1
|
||||
'@rollup/rollup-android-arm64': 4.60.1
|
||||
'@rollup/rollup-darwin-arm64': 4.60.1
|
||||
'@rollup/rollup-darwin-x64': 4.60.1
|
||||
'@rollup/rollup-freebsd-arm64': 4.60.1
|
||||
'@rollup/rollup-freebsd-x64': 4.60.1
|
||||
'@rollup/rollup-linux-arm-gnueabihf': 4.60.1
|
||||
'@rollup/rollup-linux-arm-musleabihf': 4.60.1
|
||||
'@rollup/rollup-linux-arm64-gnu': 4.60.1
|
||||
'@rollup/rollup-linux-arm64-musl': 4.60.1
|
||||
'@rollup/rollup-linux-loong64-gnu': 4.60.1
|
||||
'@rollup/rollup-linux-loong64-musl': 4.60.1
|
||||
'@rollup/rollup-linux-ppc64-gnu': 4.60.1
|
||||
'@rollup/rollup-linux-ppc64-musl': 4.60.1
|
||||
'@rollup/rollup-linux-riscv64-gnu': 4.60.1
|
||||
'@rollup/rollup-linux-riscv64-musl': 4.60.1
|
||||
'@rollup/rollup-linux-s390x-gnu': 4.60.1
|
||||
'@rollup/rollup-linux-x64-gnu': 4.60.1
|
||||
'@rollup/rollup-linux-x64-musl': 4.60.1
|
||||
'@rollup/rollup-openbsd-x64': 4.60.1
|
||||
'@rollup/rollup-openharmony-arm64': 4.60.1
|
||||
'@rollup/rollup-win32-arm64-msvc': 4.60.1
|
||||
'@rollup/rollup-win32-ia32-msvc': 4.60.1
|
||||
'@rollup/rollup-win32-x64-gnu': 4.60.1
|
||||
'@rollup/rollup-win32-x64-msvc': 4.60.1
|
||||
fsevents: 2.3.3
|
||||
|
||||
roughjs@4.6.6:
|
||||
dependencies:
|
||||
hachure-fill: 0.5.2
|
||||
@@ -7958,33 +7638,6 @@ snapshots:
|
||||
|
||||
source-map-js@1.2.1: {}
|
||||
|
||||
spdx-compare@1.0.0:
|
||||
dependencies:
|
||||
array-find-index: 1.0.2
|
||||
spdx-expression-parse: 3.0.1
|
||||
spdx-ranges: 2.1.1
|
||||
|
||||
spdx-exceptions@2.5.0: {}
|
||||
|
||||
spdx-expression-parse@3.0.1:
|
||||
dependencies:
|
||||
spdx-exceptions: 2.5.0
|
||||
spdx-license-ids: 3.0.23
|
||||
|
||||
spdx-expression-validate@2.0.0:
|
||||
dependencies:
|
||||
spdx-expression-parse: 3.0.1
|
||||
|
||||
spdx-license-ids@3.0.23: {}
|
||||
|
||||
spdx-ranges@2.1.1: {}
|
||||
|
||||
spdx-satisfies@5.0.1:
|
||||
dependencies:
|
||||
spdx-compare: 1.0.0
|
||||
spdx-expression-parse: 3.0.1
|
||||
spdx-ranges: 2.1.1
|
||||
|
||||
spectral-cli-bundle@1.0.7:
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
@@ -8453,12 +8106,6 @@ snapshots:
|
||||
|
||||
word-wrap@1.2.5: {}
|
||||
|
||||
wrap-ansi@10.0.0:
|
||||
dependencies:
|
||||
ansi-styles: 6.2.3
|
||||
string-width: 8.2.0
|
||||
strip-ansi: 7.2.0
|
||||
|
||||
write-file-atomic@7.0.1:
|
||||
dependencies:
|
||||
signal-exit: 4.1.0
|
||||
|
||||
@@ -62,13 +62,20 @@ func CompareDiff(ctx *context.APIContext) {
|
||||
|
||||
apiCommits := make([]*api.Commit, 0, len(compareInfo.Commits))
|
||||
userCache := make(map[string]*user_model.User)
|
||||
|
||||
for i := 0; i < len(compareInfo.Commits); i++ {
|
||||
apiCommit, err := convert.ToCommit(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, compareInfo.Commits[i], userCache,
|
||||
apiCommit, err := convert.ToCommit(
|
||||
ctx,
|
||||
compareInfo.HeadRepo,
|
||||
compareInfo.HeadGitRepo,
|
||||
compareInfo.Commits[i],
|
||||
userCache,
|
||||
convert.ToCommitOptions{
|
||||
Stat: true,
|
||||
Verification: verification,
|
||||
Files: files,
|
||||
})
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
ctx.APIErrorInternal(err)
|
||||
return
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/graceful"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
@@ -1429,7 +1430,11 @@ func GetPullRequestCommits(ctx *context.APIContext) {
|
||||
} else {
|
||||
compareInfo, err = git_service.GetCompareInfo(ctx, pr.BaseRepo, pr.BaseRepo, baseGitRepo, git.RefNameFromBranch(pr.BaseBranch), git.RefName(pr.GetGitHeadRefName()), false, false)
|
||||
}
|
||||
if err != nil {
|
||||
|
||||
if gitcmd.StderrHasPrefix(err, "fatal: bad revision") {
|
||||
ctx.APIError(http.StatusNotFound, "invalid base branch or revision")
|
||||
return
|
||||
} else if err != nil {
|
||||
ctx.APIErrorInternal(err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import (
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/templates"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/user"
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
"code.gitea.io/gitea/modules/web/middleware"
|
||||
"code.gitea.io/gitea/routers/common"
|
||||
@@ -87,15 +86,7 @@ func Install(ctx *context.Context) {
|
||||
form.AppName = setting.AppName
|
||||
form.RepoRootPath = setting.RepoRootPath
|
||||
form.LFSRootPath = setting.LFS.Storage.Path
|
||||
|
||||
// Note(unknown): it's hard for Windows users change a running user,
|
||||
// so just use current one if config says default.
|
||||
if setting.IsWindows && setting.RunUser == "git" {
|
||||
form.RunUser = user.CurrentUsername()
|
||||
} else {
|
||||
form.RunUser = setting.RunUser
|
||||
}
|
||||
|
||||
form.RunUser = setting.RunUser
|
||||
form.Domain = setting.Domain
|
||||
form.SSHPort = setting.SSH.Port
|
||||
form.HTTPPort = setting.HTTPPort
|
||||
@@ -272,13 +263,6 @@ func SubmitInstall(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
currentUser, match := setting.IsRunUserMatchCurrentUser(form.RunUser)
|
||||
if !match {
|
||||
ctx.Data["Err_RunUser"] = true
|
||||
ctx.RenderWithErrDeprecated(ctx.Tr("install.run_user_not_match", form.RunUser, currentUser), tplInstall, &form)
|
||||
return
|
||||
}
|
||||
|
||||
// Check logic loophole between disable self-registration and no admin account.
|
||||
if form.DisableRegistration && len(form.AdminName) == 0 {
|
||||
ctx.Data["Err_Services"] = true
|
||||
|
||||
@@ -493,12 +493,17 @@ func SignOut(ctx *context.Context) {
|
||||
}
|
||||
|
||||
func buildSignOutRedirectURL(ctx *context.Context) string {
|
||||
// TODO: can also support REVERSE_PROXY_AUTHENTICATION logout URL in the future
|
||||
if ctx.Doer != nil && ctx.Doer.LoginType == auth.OAuth2 {
|
||||
if s := buildOIDCEndSessionURL(ctx, ctx.Doer); s != "" {
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
// The assumption is: if reverse proxy auth is enabled, then the users should only sign-in via reverse proxy auth.
|
||||
// TODO: in the future, if we need to distinguish different sign-in methods, we need to save the sign-in method in session and check here
|
||||
if setting.Service.EnableReverseProxyAuth && setting.ReverseProxyLogoutRedirect != "" {
|
||||
return setting.ReverseProxyLogoutRedirect
|
||||
}
|
||||
return setting.AppSubURL + "/"
|
||||
}
|
||||
|
||||
|
||||
@@ -151,6 +151,11 @@ func prepareWorkflowTemplate(ctx *context.Context, commit *git.Commit) (workflow
|
||||
workflows = append(workflows, workflow)
|
||||
continue
|
||||
}
|
||||
if err := actions.ValidateWorkflowContent(content); err != nil {
|
||||
workflow.ErrMsg = ctx.Locale.TrString("actions.runs.invalid_workflow_helper", err.Error())
|
||||
workflows = append(workflows, workflow)
|
||||
continue
|
||||
}
|
||||
workflow.Workflow = wf
|
||||
// The workflow must contain at least one job without "needs". Otherwise, a deadlock will occur and no jobs will be able to run.
|
||||
hasJobWithoutNeeds := false
|
||||
@@ -315,6 +320,10 @@ func prepareWorkflowList(ctx *context.Context, workflows []WorkflowInfo) {
|
||||
if !job.Status.IsWaiting() {
|
||||
continue
|
||||
}
|
||||
if err := actions.ValidateWorkflowContent(job.WorkflowPayload); err != nil {
|
||||
runErrors[run.ID] = ctx.Locale.TrString("actions.runs.invalid_workflow_helper", err.Error())
|
||||
break
|
||||
}
|
||||
hasOnlineRunner := false
|
||||
for _, runner := range runners {
|
||||
if !runner.IsDisabled && runner.CanMatchLabels(job.RunsOn) {
|
||||
|
||||
@@ -450,12 +450,21 @@ func MatrixHooksEditPost(ctx *context.Context) {
|
||||
editWebhook(ctx, matrixHookParams(ctx))
|
||||
}
|
||||
|
||||
func matrixRoomIDEncode(roomID string) string {
|
||||
// See https://spec.matrix.org/latest/appendices/#room-ids
|
||||
// Some (unrelated) demo links: https://spec.matrix.org/latest/appendices/#matrixto-navigation
|
||||
// API spec: https://spec.matrix.org/v1.18/client-server-api/#sending-events-to-a-room
|
||||
// Some of their examples show links like: "PUT /rooms/!roomid:domain/state/m.example.event"
|
||||
return strings.NewReplacer("%21", "!", "%3A", ":").Replace(url.PathEscape(roomID))
|
||||
}
|
||||
|
||||
func matrixHookParams(ctx *context.Context) webhookParams {
|
||||
form := web.GetForm(ctx).(*forms.NewMatrixHookForm)
|
||||
|
||||
// TODO: need to migrate to the latest (v3) API: https://spec.matrix.org/v1.18/client-server-api/
|
||||
return webhookParams{
|
||||
Type: webhook_module.MATRIX,
|
||||
URL: fmt.Sprintf("%s/_matrix/client/r0/rooms/%s/send/m.room.message", form.HomeserverURL, url.PathEscape(form.RoomID)),
|
||||
URL: fmt.Sprintf("%s/_matrix/client/r0/rooms/%s/send/m.room.message", form.HomeserverURL, matrixRoomIDEncode(form.RoomID)),
|
||||
ContentType: webhook.ContentTypeJSON,
|
||||
HTTPMethod: http.MethodPut,
|
||||
WebhookForm: form.WebhookForm,
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package setting
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestWebhookMatrix(t *testing.T) {
|
||||
assert.Equal(t, "!roomid:domain", matrixRoomIDEncode("!roomid:domain"))
|
||||
assert.Equal(t, "!room%23id:domain", matrixRoomIDEncode("!room#id:domain")) // maybe it should never really happen in real world
|
||||
}
|
||||
@@ -25,8 +25,6 @@ import (
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
issue_service "code.gitea.io/gitea/services/issue"
|
||||
|
||||
"github.com/nektos/act/pkg/model"
|
||||
)
|
||||
|
||||
func prepareLatestCommitInfo(ctx *context.Context) bool {
|
||||
@@ -184,8 +182,7 @@ func prepareFileView(ctx *context.Context, entry *git.TreeEntry) {
|
||||
if err != nil {
|
||||
log.Error("actions.GetContentFromEntry: %v", err)
|
||||
}
|
||||
_, workFlowErr := model.ReadWorkflow(bytes.NewReader(content))
|
||||
if workFlowErr != nil {
|
||||
if workFlowErr := actions.ValidateWorkflowContent(content); workFlowErr != nil {
|
||||
ctx.Data["FileError"] = ctx.Locale.Tr("actions.runs.invalid_workflow_helper", workFlowErr.Error())
|
||||
}
|
||||
} else if issue_service.IsCodeOwnerFile(ctx.Repo.TreePath) {
|
||||
|
||||
@@ -10,7 +10,9 @@ import (
|
||||
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
project_model "code.gitea.io/gitea/models/project"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/modules/web/middleware"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
"code.gitea.io/gitea/services/webhook"
|
||||
@@ -523,16 +525,49 @@ func (f *InitializeLabelsForm) Validate(req *http.Request, errs binding.Errors)
|
||||
type MergePullRequestForm struct {
|
||||
// required: true
|
||||
// enum: ["merge","rebase","rebase-merge","squash","fast-forward-only","manually-merged"]
|
||||
Do string `binding:"Required;In(merge,rebase,rebase-merge,squash,fast-forward-only,manually-merged)"`
|
||||
MergeTitleField string
|
||||
MergeMessageField string
|
||||
MergeCommitID string // only used for manually-merged
|
||||
Do string `json:"do" binding:"Required;In(merge,rebase,rebase-merge,squash,fast-forward-only,manually-merged)"`
|
||||
MergeTitleField string `json:"merge_title_field,omitempty"`
|
||||
MergeMessageField string `json:"merge_message_field,omitempty"`
|
||||
MergeCommitID string `json:"merge_commit_id,omitempty"` // only used for manually-merged
|
||||
HeadCommitID string `json:"head_commit_id,omitempty"`
|
||||
ForceMerge bool `json:"force_merge,omitempty"`
|
||||
MergeWhenChecksSucceed bool `json:"merge_when_checks_succeed,omitempty"`
|
||||
DeleteBranchAfterMerge *bool `json:"delete_branch_after_merge,omitempty"`
|
||||
}
|
||||
|
||||
func (f *MergePullRequestForm) UnmarshalJSON(b []byte) error {
|
||||
// This is for backward compatibility, to support both field names like "do" and "Do",
|
||||
// because old code doesn't have "json" tag for these fields
|
||||
type aux struct {
|
||||
Do1 string `json:"do"`
|
||||
Do2 string `json:"Do"`
|
||||
MergeTitleField1 string `json:"merge_title_field"`
|
||||
MergeTitleField2 string `json:"MergeTitleField"`
|
||||
MergeMessageField1 string `json:"merge_message_field"`
|
||||
MergeMessageField2 string `json:"MergeMessageField"`
|
||||
MergeCommitID1 string `json:"merge_commit_id"`
|
||||
MergeCommitID2 string `json:"MergeCommitID"`
|
||||
|
||||
HeadCommitID string `json:"head_commit_id"`
|
||||
ForceMerge bool `json:"force_merge"`
|
||||
MergeWhenChecksSucceed bool `json:"merge_when_checks_succeed"`
|
||||
DeleteBranchAfterMerge *bool `json:"delete_branch_after_merge"`
|
||||
}
|
||||
var a aux
|
||||
if err := json.Unmarshal(b, &a); err != nil {
|
||||
return err
|
||||
}
|
||||
f.Do = util.IfZero(a.Do1, a.Do2)
|
||||
f.MergeTitleField = util.IfZero(a.MergeTitleField1, a.MergeTitleField2)
|
||||
f.MergeMessageField = util.IfZero(a.MergeMessageField1, a.MergeMessageField2)
|
||||
f.MergeCommitID = util.IfZero(a.MergeCommitID1, a.MergeCommitID2)
|
||||
f.HeadCommitID = a.HeadCommitID
|
||||
f.ForceMerge = a.ForceMerge
|
||||
f.MergeWhenChecksSucceed = a.MergeWhenChecksSucceed
|
||||
f.DeleteBranchAfterMerge = a.DeleteBranchAfterMerge
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate validates the fields
|
||||
func (f *MergePullRequestForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
|
||||
ctx := context.GetValidateContext(req)
|
||||
|
||||
@@ -6,7 +6,10 @@ package forms
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSubmitReviewForm_IsEmpty(t *testing.T) {
|
||||
@@ -37,3 +40,48 @@ func TestSubmitReviewForm_IsEmpty(t *testing.T) {
|
||||
assert.Equal(t, v.expected, v.form.HasEmptyContent())
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergePullRequestForm(t *testing.T) {
|
||||
expected := &MergePullRequestForm{
|
||||
Do: "merge",
|
||||
MergeTitleField: "title",
|
||||
MergeMessageField: "message",
|
||||
MergeCommitID: "merge-id",
|
||||
HeadCommitID: "head-id",
|
||||
ForceMerge: true,
|
||||
MergeWhenChecksSucceed: true,
|
||||
DeleteBranchAfterMerge: new(true),
|
||||
}
|
||||
|
||||
t.Run("NewFields", func(t *testing.T) {
|
||||
input := `{
|
||||
"do": "merge",
|
||||
"merge_title_field": "title",
|
||||
"merge_message_field": "message",
|
||||
"merge_commit_id": "merge-id",
|
||||
"head_commit_id": "head-id",
|
||||
"force_merge": true,
|
||||
"merge_when_checks_succeed": true,
|
||||
"delete_branch_after_merge": true
|
||||
}`
|
||||
var m *MergePullRequestForm
|
||||
require.NoError(t, json.Unmarshal([]byte(input), &m))
|
||||
assert.Equal(t, expected, m)
|
||||
})
|
||||
|
||||
t.Run("OldFields", func(t *testing.T) {
|
||||
input := `{
|
||||
"Do": "merge",
|
||||
"MergeTitleField": "title",
|
||||
"MergeMessageField": "message",
|
||||
"MergeCommitID": "merge-id",
|
||||
"head_commit_id": "head-id",
|
||||
"force_merge": true,
|
||||
"merge_when_checks_succeed": true,
|
||||
"delete_branch_after_merge": true
|
||||
}`
|
||||
var m *MergePullRequestForm
|
||||
require.NoError(t, json.Unmarshal([]byte(input), &m))
|
||||
assert.Equal(t, expected, m)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -93,6 +93,9 @@ export default {
|
||||
return [`${i}`, `${i === 0 ? '0' : `${i}px`}`];
|
||||
})),
|
||||
},
|
||||
extend: {
|
||||
zIndex: {'1': '1'},
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
plugin(({addUtilities}) => {
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
{{template "devtest/devtest-header"}}
|
||||
<div class="page-content devtest ui container">
|
||||
<form class="ui form left-right-form">
|
||||
<h4 class="ui dividing header">Input</h4>
|
||||
<div class="inline field">
|
||||
<label>Normal</label>
|
||||
<input type="text" value="value">
|
||||
</div>
|
||||
<div class="inline field">
|
||||
<label>Readonly</label>
|
||||
<input type="text" value="value" readonly>
|
||||
</div>
|
||||
<div class="inline disabled field">
|
||||
<label>Disabled</label>
|
||||
<input type="text" value="value" disabled>
|
||||
</div>
|
||||
<div class="inline field error">
|
||||
<label>Error</label>
|
||||
<input type="text" value="value">
|
||||
</div>
|
||||
|
||||
<h4 class="ui dividing header">Textarea</h4>
|
||||
<div class="inline field">
|
||||
<label>Normal</label>
|
||||
<textarea rows="2">value</textarea>
|
||||
</div>
|
||||
<div class="inline field">
|
||||
<label>Readonly</label>
|
||||
<textarea rows="2" readonly>value</textarea>
|
||||
</div>
|
||||
<div class="inline disabled field">
|
||||
<label>Disabled</label>
|
||||
<textarea rows="2" disabled>value</textarea>
|
||||
</div>
|
||||
<div class="inline field error">
|
||||
<label>Error</label>
|
||||
<textarea rows="2">value</textarea>
|
||||
</div>
|
||||
|
||||
<h4 class="ui dividing header">Dropdown</h4>
|
||||
<div class="inline field">
|
||||
<label>Normal</label>
|
||||
<div class="ui selection dropdown">
|
||||
<input type="hidden" value="a">
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
<div class="text">Option A</div>
|
||||
<div class="menu">
|
||||
<div class="item" data-value="a">Option A</div>
|
||||
<div class="item" data-value="b">Option B</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline field">
|
||||
<label>Readonly</label>
|
||||
<div class="ui selection dropdown" readonly>
|
||||
<input type="hidden" value="a">
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
<div class="text">Option A</div>
|
||||
<div class="menu">
|
||||
<div class="item" data-value="a">Option A</div>
|
||||
<div class="item" data-value="b">Option B</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline disabled field">
|
||||
<label>Disabled</label>
|
||||
<div class="ui selection dropdown">
|
||||
<input type="hidden" value="a">
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
<div class="text">Option A</div>
|
||||
<div class="menu">
|
||||
<div class="item" data-value="a">Option A</div>
|
||||
<div class="item" data-value="b">Option B</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline field error">
|
||||
<label>Error</label>
|
||||
<div class="ui selection dropdown">
|
||||
<input type="hidden" value="a">
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
<div class="text">Option A</div>
|
||||
<div class="menu">
|
||||
<div class="item" data-value="a">Option A</div>
|
||||
<div class="item" data-value="b">Option B</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 class="ui dividing header">Required</h4>
|
||||
<div class="inline required field">
|
||||
<label>Normal</label>
|
||||
<input type="text" value="value">
|
||||
</div>
|
||||
<div class="inline required field">
|
||||
<label>Readonly</label>
|
||||
<input type="text" value="value" readonly>
|
||||
</div>
|
||||
<div class="inline required disabled field">
|
||||
<label>Disabled</label>
|
||||
<input type="text" value="value" disabled>
|
||||
</div>
|
||||
<div class="inline required field error">
|
||||
<label>Error</label>
|
||||
<input type="text" value="value">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{template "devtest/devtest-footer"}}
|
||||
@@ -117,7 +117,7 @@
|
||||
<input id="lfs_root_path" name="lfs_root_path" value="{{.lfs_root_path}}">
|
||||
<span class="help">{{ctx.Locale.Tr "install.lfs_path_helper"}}</span>
|
||||
</div>
|
||||
<div class="inline required field {{if .Err_RunUser}}error{{end}}">
|
||||
<div class="inline field">
|
||||
<label for="run_user">{{ctx.Locale.Tr "install.run_user"}}</label>
|
||||
<input id="run_user" name="run_user" value="{{.run_user}}" readonly>
|
||||
<span class="help">{{ctx.Locale.Tr "install.run_user_helper"}}</span>
|
||||
|
||||
@@ -25,49 +25,49 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-container-main">
|
||||
<div class="ui top attached header tw-flex tw-items-center tw-justify-between">
|
||||
<span class="tw-text-base tw-font-semibold">{{ctx.Locale.TrN .Page.Paginater.Total "actions.runs.workflow_run_count_1" "actions.runs.workflow_run_count_n" .Page.Paginater.Total}}</span>
|
||||
<div class="ui secondary filter menu tw-flex tw-items-center tw-m-0">
|
||||
<!-- Actor -->
|
||||
<div class="ui{{if not .Actors}} disabled{{end}} dropdown jump item">
|
||||
<span class="text">{{ctx.Locale.Tr "actions.runs.actor"}}</span>
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
<div class="menu">
|
||||
<div class="ui icon search input">
|
||||
<i class="icon">{{svg "octicon-search"}}</i>
|
||||
<input type="text" placeholder="{{ctx.Locale.Tr "actions.runs.actor"}}">
|
||||
</div>
|
||||
<a class="item{{if not $.CurActor}} active{{end}}" href="?workflow={{$.CurWorkflow}}&status={{$.CurStatus}}&actor=0">
|
||||
{{ctx.Locale.Tr "actions.runs.actors_no_select"}}
|
||||
</a>
|
||||
{{range .Actors}}
|
||||
<a class="item{{if eq .ID $.CurActor}} active{{end}}" href="?workflow={{$.CurWorkflow}}&actor={{.ID}}&status={{$.CurStatus}}">
|
||||
{{ctx.AvatarUtils.Avatar . 20}} {{.GetDisplayName}}
|
||||
<div class="ui top attached header flex-text-block tw-flex-wrap tw-justify-between">
|
||||
<strong>{{ctx.Locale.TrN .Page.Paginater.Total "actions.runs.workflow_run_count_1" "actions.runs.workflow_run_count_n" .Page.Paginater.Total}}</strong>
|
||||
<div class="ui secondary filter menu flex-text-block tw-m-0">
|
||||
<!-- Actor -->
|
||||
<div class="ui{{if not .Actors}} disabled{{end}} dropdown jump item">
|
||||
<span class="text">{{ctx.Locale.Tr "actions.runs.actor"}}</span>
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
<div class="menu">
|
||||
<div class="ui icon search input">
|
||||
<i class="icon">{{svg "octicon-search"}}</i>
|
||||
<input type="text" placeholder="{{ctx.Locale.Tr "actions.runs.actor"}}">
|
||||
</div>
|
||||
<a class="item{{if not $.CurActor}} active{{end}}" href="?workflow={{$.CurWorkflow}}&status={{$.CurStatus}}&actor=0">
|
||||
{{ctx.Locale.Tr "actions.runs.actors_no_select"}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<!-- Status -->
|
||||
<div class="ui dropdown jump item">
|
||||
<span class="text">{{ctx.Locale.Tr "actions.runs.status"}}</span>
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
<div class="menu">
|
||||
<div class="ui icon search input">
|
||||
<i class="icon">{{svg "octicon-search"}}</i>
|
||||
<input type="text" placeholder="{{ctx.Locale.Tr "actions.runs.status"}}">
|
||||
{{range .Actors}}
|
||||
<a class="item{{if eq .ID $.CurActor}} active{{end}}" href="?workflow={{$.CurWorkflow}}&actor={{.ID}}&status={{$.CurStatus}}">
|
||||
{{ctx.AvatarUtils.Avatar . 20}} {{.GetDisplayName}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<!-- Status -->
|
||||
<div class="ui dropdown jump item">
|
||||
<span class="text">{{ctx.Locale.Tr "actions.runs.status"}}</span>
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
<div class="menu">
|
||||
<div class="ui icon search input">
|
||||
<i class="icon">{{svg "octicon-search"}}</i>
|
||||
<input type="text" placeholder="{{ctx.Locale.Tr "actions.runs.status"}}">
|
||||
</div>
|
||||
<a class="item{{if not $.CurStatus}} active{{end}}" href="?workflow={{$.CurWorkflow}}&actor={{$.CurActor}}&status=0">
|
||||
{{ctx.Locale.Tr "actions.runs.status_no_select"}}
|
||||
</a>
|
||||
{{range .StatusInfoList}}
|
||||
<a class="item{{if eq .Status $.CurStatus}} active{{end}}" href="?workflow={{$.CurWorkflow}}&actor={{$.CurActor}}&status={{.Status}}">
|
||||
{{.DisplayedStatus}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
<a class="item{{if not $.CurStatus}} active{{end}}" href="?workflow={{$.CurWorkflow}}&actor={{$.CurActor}}&status=0">
|
||||
{{ctx.Locale.Tr "actions.runs.status_no_select"}}
|
||||
</a>
|
||||
{{range .StatusInfoList}}
|
||||
<a class="item{{if eq .Status $.CurStatus}} active{{end}}" href="?workflow={{$.CurWorkflow}}&actor={{$.CurActor}}&status={{.Status}}">
|
||||
{{.DisplayedStatus}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if .AllowDisableOrEnableWorkflow}}
|
||||
{{if .AllowDisableOrEnableWorkflow}}
|
||||
<button class="ui jump dropdown btn interact-bg tw-p-2">
|
||||
{{svg "octicon-kebab-horizontal"}}
|
||||
<div class="menu">
|
||||
@@ -76,7 +76,7 @@
|
||||
</a>
|
||||
</div>
|
||||
</button>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<div class="ui blue info attached message tw-relative tw-z-10 tw-flex tw-justify-between tw-items-center">
|
||||
<span class="ui text middle">{{ctx.Locale.Tr "actions.workflow.has_workflow_dispatch"}}</span>
|
||||
<button class="ui mini button show-modal" data-modal="#runWorkflowDispatchModal">{{ctx.Locale.Tr "actions.workflow.run"}}{{svg "octicon-triangle-down" 14 "dropdown icon"}}</button>
|
||||
{{/* "z-index" is used to maintain continuous attached styling and keep the colored border-bottom visible (pre-existing fomantic issue with negative margins) */}}
|
||||
<div class="ui blue info attached message flex-text-block tw-flex-wrap tw-justify-between tw-z-1">
|
||||
<span>{{ctx.Locale.Tr "actions.workflow.has_workflow_dispatch"}}</span>
|
||||
<div class="flex-text-block tw-bg-box-body tw-rounded">{{/*make the button have correct hovered color */}}
|
||||
<button class="ui mini button show-modal" data-modal="#runWorkflowDispatchModal">{{ctx.Locale.Tr "actions.workflow.run"}}{{svg "octicon-triangle-down" 14 "dropdown icon"}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="runWorkflowDispatchModal" class="ui tiny modal">
|
||||
<div class="content">
|
||||
|
||||
@@ -13,22 +13,16 @@
|
||||
{{ctx.Locale.Tr "action.compare_commits_general"}}
|
||||
{{end}}
|
||||
</h2>
|
||||
{{$BaseCompareName := $.BaseName -}}
|
||||
{{- $HeadCompareName := $.HeadRepo.OwnerName -}}
|
||||
{{- if and (eq $.BaseName $.HeadRepo.OwnerName) (ne $.Repository.Name $.HeadRepo.Name) -}}
|
||||
{{- $HeadCompareName = printf "%s/%s" $.HeadRepo.OwnerName $.HeadRepo.Name -}}
|
||||
{{- end -}}
|
||||
{{- $OwnForkCompareName := "" -}}
|
||||
{{- if .OwnForkRepo -}}
|
||||
{{- $OwnForkCompareName = .OwnForkRepo.OwnerName -}}
|
||||
{{- end -}}
|
||||
{{- $RootRepoCompareName := "" -}}
|
||||
{{- if .RootRepo -}}
|
||||
{{- $RootRepoCompareName = .RootRepo.OwnerName -}}
|
||||
{{- if eq $.HeadRepo.OwnerName .RootRepo.OwnerName -}}
|
||||
{{- $HeadCompareName = printf "%s/%s" $.HeadRepo.OwnerName $.HeadRepo.Name -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{$BaseCompareName := $.Repository.FullName -}}
|
||||
{{$HeadCompareName := $.HeadRepo.FullName -}}
|
||||
{{$OwnForkCompareName := "" -}}
|
||||
{{if $.OwnForkRepo -}}
|
||||
{{$OwnForkCompareName = $.OwnForkRepo.FullName -}}
|
||||
{{end -}}
|
||||
{{$RootRepoCompareName := "" -}}
|
||||
{{if $.RootRepo -}}
|
||||
{{$RootRepoCompareName = $.RootRepo.FullName -}}
|
||||
{{end -}}
|
||||
|
||||
<div class="ui segment choose branch">
|
||||
<a class="tw-mr-2" href="{{$.HeadRepo.Link}}/compare/{{PathEscapeSegments $.HeadBranch}}{{$compareSeparator}}{{if not $.PullRequestCtx.SameRepo}}{{PathEscape $.BaseName}}/{{PathEscape $.Repository.Name}}:{{end}}{{PathEscapeSegments $.BaseBranch}}" title="{{ctx.Locale.Tr "repo.pulls.switch_head_and_base"}}">{{svg "octicon-git-compare"}}</a>
|
||||
|
||||
Generated
+20
-16
@@ -26771,10 +26771,14 @@
|
||||
"description": "MergePullRequestForm form for merging Pull Request",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"Do"
|
||||
"do"
|
||||
],
|
||||
"properties": {
|
||||
"Do": {
|
||||
"delete_branch_after_merge": {
|
||||
"type": "boolean",
|
||||
"x-go-name": "DeleteBranchAfterMerge"
|
||||
},
|
||||
"do": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"merge",
|
||||
@@ -26783,20 +26787,8 @@
|
||||
"squash",
|
||||
"fast-forward-only",
|
||||
"manually-merged"
|
||||
]
|
||||
},
|
||||
"MergeCommitID": {
|
||||
"type": "string"
|
||||
},
|
||||
"MergeMessageField": {
|
||||
"type": "string"
|
||||
},
|
||||
"MergeTitleField": {
|
||||
"type": "string"
|
||||
},
|
||||
"delete_branch_after_merge": {
|
||||
"type": "boolean",
|
||||
"x-go-name": "DeleteBranchAfterMerge"
|
||||
],
|
||||
"x-go-name": "Do"
|
||||
},
|
||||
"force_merge": {
|
||||
"type": "boolean",
|
||||
@@ -26806,6 +26798,18 @@
|
||||
"type": "string",
|
||||
"x-go-name": "HeadCommitID"
|
||||
},
|
||||
"merge_commit_id": {
|
||||
"type": "string",
|
||||
"x-go-name": "MergeCommitID"
|
||||
},
|
||||
"merge_message_field": {
|
||||
"type": "string",
|
||||
"x-go-name": "MergeMessageField"
|
||||
},
|
||||
"merge_title_field": {
|
||||
"type": "string",
|
||||
"x-go-name": "MergeTitleField"
|
||||
},
|
||||
"merge_when_checks_succeed": {
|
||||
"type": "boolean",
|
||||
"x-go-name": "MergeWhenChecksSucceed"
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import {test, expect} from '@playwright/test';
|
||||
|
||||
test('licenses.txt', async ({page}) => {
|
||||
const resp = await page.goto('/assets/licenses.txt');
|
||||
expect(resp?.status()).toBe(200);
|
||||
const content = await resp!.text();
|
||||
expect(content).toContain('@vue/');
|
||||
expect(content).toContain('code.gitea.io/');
|
||||
});
|
||||
@@ -55,7 +55,10 @@ func TestAPIIssuesReactions(t *testing.T) {
|
||||
DecodeJSON(t, resp, &apiNewReaction)
|
||||
|
||||
// Add existing reaction
|
||||
MakeRequest(t, req, http.StatusForbidden)
|
||||
req = NewRequestWithJSON(t, "POST", urlStr, &api.EditReactionOption{
|
||||
Reaction: "rocket",
|
||||
}).AddTokenAuth(token)
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// Blocked user can't react to comment
|
||||
user34 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 34})
|
||||
@@ -142,7 +145,10 @@ func TestAPICommentReactions(t *testing.T) {
|
||||
DecodeJSON(t, resp, &apiNewReaction)
|
||||
|
||||
// Add existing reaction
|
||||
MakeRequest(t, req, http.StatusForbidden)
|
||||
req = NewRequestWithJSON(t, "POST", urlStr, &api.EditReactionOption{
|
||||
Reaction: "+1",
|
||||
}).AddTokenAuth(token)
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// Get end result of reaction list of issue #1
|
||||
req = NewRequest(t, "GET", urlStr).
|
||||
|
||||
@@ -5,46 +5,60 @@ package integration
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAPICompareBranches(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
onGiteaRun(t, func(t *testing.T, _ *url.URL) {
|
||||
session2 := loginUser(t, "user2")
|
||||
token2 := getTokenForLoggedInUser(t, session2, auth_model.AccessTokenScopeWriteRepository)
|
||||
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
// Login as User2.
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||
t.Run("CompareBranches", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
t.Run("CompareBranches", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo20/compare/add-csv...remove-files-b").AddTokenAuth(token)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo20/compare/add-csv...remove-files-b").AddTokenAuth(token2)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
apiResp := DecodeJSON(t, resp, &api.Compare{})
|
||||
assert.Equal(t, 2, apiResp.TotalCommits)
|
||||
assert.Len(t, apiResp.Commits, 2)
|
||||
})
|
||||
|
||||
var apiResp *api.Compare
|
||||
DecodeJSON(t, resp, &apiResp)
|
||||
t.Run("CompareCommits", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
assert.Equal(t, 2, apiResp.TotalCommits)
|
||||
assert.Len(t, apiResp.Commits, 2)
|
||||
})
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo20/compare/808038d2f71b0ab02099...c8e31bc7688741a5287f").AddTokenAuth(token2)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
apiResp := DecodeJSON(t, resp, &api.Compare{})
|
||||
assert.Equal(t, 1, apiResp.TotalCommits)
|
||||
assert.Len(t, apiResp.Commits, 1)
|
||||
})
|
||||
|
||||
t.Run("CompareCommits", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo20/compare/808038d2f71b0ab02099...c8e31bc7688741a5287f").AddTokenAuth(token)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
t.Run("CompareForkOnlyCommit", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
var apiResp *api.Compare
|
||||
DecodeJSON(t, resp, &apiResp)
|
||||
user13 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 13})
|
||||
repo11 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 11})
|
||||
user13Sess := loginUser(t, "user13")
|
||||
user13Token := getTokenForLoggedInUser(t, user13Sess, auth_model.AccessTokenScopeWriteRepository)
|
||||
|
||||
assert.Equal(t, 1, apiResp.TotalCommits)
|
||||
assert.Len(t, apiResp.Commits, 1)
|
||||
_, err := createFileInBranch(user13, repo11, createFileInBranchOptions{OldBranch: "master", NewBranch: "new-branch"}, map[string]string{"file.txt": "content"})
|
||||
require.NoError(t, err)
|
||||
req := NewRequestf(t, "GET", "/api/v1/repos/user12/repo10/compare/master...user13:new-branch").AddTokenAuth(user13Token)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
apiResp := DecodeJSON(t, resp, &api.Compare{})
|
||||
assert.Equal(t, 1, apiResp.TotalCommits)
|
||||
assert.Len(t, apiResp.Commits, 1)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
@@ -16,13 +17,29 @@ import (
|
||||
func TestSignOut(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
t.Run("NormalLogout", func(t *testing.T) {
|
||||
session := loginUser(t, "user2")
|
||||
|
||||
req := NewRequest(t, "GET", "/user/logout")
|
||||
resp := session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
assert.Equal(t, "/", test.RedirectURL(resp))
|
||||
req := NewRequest(t, "GET", "/user/logout")
|
||||
resp := session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
assert.Equal(t, "/", resp.Header().Get("Location"))
|
||||
|
||||
// try to view a private repo, should fail
|
||||
req = NewRequest(t, "GET", "/user2/repo2")
|
||||
session.MakeRequest(t, req, http.StatusNotFound)
|
||||
// logged out, try to view a private repo, should fail
|
||||
req = NewRequest(t, "GET", "/user2/repo2")
|
||||
session.MakeRequest(t, req, http.StatusNotFound)
|
||||
})
|
||||
|
||||
t.Run("ReverseProxyLogoutRedirect", func(t *testing.T) {
|
||||
defer test.MockVariableValue(&setting.Service.EnableReverseProxyAuth, true)()
|
||||
defer test.MockVariableValue(&setting.ReverseProxyLogoutRedirect, "/my-sso/logout?return_to=/my-sso/home")()
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
req := NewRequest(t, "GET", "/user/logout")
|
||||
resp := session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
assert.Equal(t, "/my-sso/logout?return_to=/my-sso/home", resp.Header().Get("Location"))
|
||||
|
||||
// logged out, try to view a private repo, should fail
|
||||
req = NewRequest(t, "GET", "/user2/repo2")
|
||||
session.MakeRequest(t, req, http.StatusNotFound)
|
||||
})
|
||||
}
|
||||
|
||||
+21
-30
@@ -1,13 +1,12 @@
|
||||
import {build, defineConfig} from 'vite';
|
||||
import vuePlugin from '@vitejs/plugin-vue';
|
||||
import {stringPlugin} from 'vite-string-plugin';
|
||||
import {licensePlugin, wrap} from 'rolldown-license-plugin';
|
||||
import {readFileSync, writeFileSync, mkdirSync, unlinkSync, globSync} from 'node:fs';
|
||||
import path, {basename, join, parse} from 'node:path';
|
||||
import {env} from 'node:process';
|
||||
import tailwindcss from 'tailwindcss';
|
||||
import tailwindConfig from './tailwind.config.ts';
|
||||
import wrapAnsi from 'wrap-ansi';
|
||||
import licensePlugin from 'rollup-plugin-license';
|
||||
import type {InlineConfig, Plugin, Rolldown} from 'vite';
|
||||
import {camelize} from 'vue';
|
||||
|
||||
@@ -39,10 +38,6 @@ const webComponents = new Set([
|
||||
'text-expander',
|
||||
]);
|
||||
|
||||
function formatLicenseText(licenseText: string) {
|
||||
return wrapAnsi(licenseText || '', 80).trim();
|
||||
}
|
||||
|
||||
const commonRolldownOptions: Rolldown.RolldownOptions = {
|
||||
checks: {
|
||||
eval: false, // htmx needs eval
|
||||
@@ -314,33 +309,29 @@ export default defineConfig(commonViteOpts({
|
||||
},
|
||||
}),
|
||||
isProduction ? licensePlugin({
|
||||
thirdParty: {
|
||||
output: {
|
||||
file: join(import.meta.dirname, 'public/assets/licenses.txt'),
|
||||
template(deps) {
|
||||
const line = '-'.repeat(80);
|
||||
const goJson = readFileSync(join(import.meta.dirname, 'assets/go-licenses.json'), 'utf8');
|
||||
const goModules = JSON.parse(goJson).map(({name, licenseText}: {name: string, licenseText: string}) => {
|
||||
return {name, body: formatLicenseText(licenseText)};
|
||||
});
|
||||
const jsModules = deps.map((dep) => {
|
||||
return {name: dep.name, version: dep.version, body: formatLicenseText(dep.licenseText ?? '')};
|
||||
});
|
||||
const modules = [...goModules, ...jsModules].sort((a, b) => a.name.localeCompare(b.name));
|
||||
return modules.map(({name, version, body}: {name: string, version?: string, body: string}) => {
|
||||
const title = version ? `${name}@${version}` : name;
|
||||
return `${line}\n${title}\n${line}\n${body}`;
|
||||
}).join('\n');
|
||||
},
|
||||
},
|
||||
allow(dependency) {
|
||||
if (dependency.name === 'khroma') return true; // MIT: https://github.com/fabiospampinato/khroma/pull/33
|
||||
return /(Apache-2\.0|0BSD|BSD-2-Clause|BSD-3-Clause|MIT|ISC|CPAL-1\.0|Unlicense|EPL-1\.0|EPL-2\.0)/.test(dependency.license ?? '');
|
||||
},
|
||||
done(deps, context) {
|
||||
const line = '-'.repeat(80);
|
||||
const goLicenses = JSON.parse(readFileSync(join(import.meta.dirname, 'assets/go-licenses.json'), 'utf8'));
|
||||
const combined: Record<string, string> = {};
|
||||
for (const {name, licenseText} of goLicenses) {
|
||||
combined[name] = wrap(licenseText || '', 80).trim();
|
||||
}
|
||||
for (const {name, version, licenseText} of deps) {
|
||||
combined[`${name}@${version}`] = wrap(licenseText, 80).trim();
|
||||
}
|
||||
const content = Object.entries(combined)
|
||||
.sort(([a], [b]) => a.localeCompare(b))
|
||||
.map(([title, body]) => `${line}\n${title}\n${line}\n${body}`).join('\n');
|
||||
context.emitFile({type: 'asset', fileName: 'licenses.txt', source: content});
|
||||
},
|
||||
match: /^((UN)?LICEN(S|C)E|COPYING).*$/i, // also defined in build/generate-go-licenses.go
|
||||
allow(dep) {
|
||||
if (dep.name === 'khroma') return true; // MIT: https://github.com/fabiospampinato/khroma/pull/33
|
||||
return /(Apache-2\.0|0BSD|BSD-2-Clause|BSD-3-Clause|MIT|ISC|CPAL-1\.0|Unlicense|EPL-1\.0|EPL-2\.0)/.test(dep.license);
|
||||
},
|
||||
}) : {
|
||||
name: 'dev-licenses-stub',
|
||||
closeBundle() {
|
||||
configureServer() {
|
||||
writeFileSync(join(outDir, 'licenses.txt'), 'Licenses are disabled during development');
|
||||
},
|
||||
},
|
||||
|
||||
@@ -6,14 +6,6 @@
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.runner-container .runner-new-text {
|
||||
color: var(--color-white);
|
||||
}
|
||||
|
||||
.runner-container #runner-new:hover .runner-new-text {
|
||||
color: var(--color-white) !important;
|
||||
}
|
||||
|
||||
.runner-container .task-status-success {
|
||||
background-color: var(--color-green);
|
||||
color: var(--color-white);
|
||||
|
||||
@@ -643,10 +643,6 @@ overflow-menu .ui.label {
|
||||
color: var(--color-primary-contrast);
|
||||
}
|
||||
|
||||
.archived-icon {
|
||||
color: var(--color-secondary-dark-2) !important;
|
||||
}
|
||||
|
||||
.oauth2-authorize-application-box {
|
||||
margin-top: 3em !important;
|
||||
}
|
||||
@@ -670,10 +666,6 @@ overflow-menu .ui.label {
|
||||
min-width: 50px;
|
||||
}
|
||||
|
||||
.lines-num span.bottom-line::after {
|
||||
border-bottom: 1px solid var(--color-secondary);
|
||||
}
|
||||
|
||||
.lines-num span::after {
|
||||
content: attr(data-line-number);
|
||||
line-height: var(--line-height-code) !important;
|
||||
@@ -783,11 +775,6 @@ tr.top-line-blame:first-of-type {
|
||||
border-top: none; /* merge code lines belonging to the same commit into one block */
|
||||
}
|
||||
|
||||
.lines-code .bottom-line,
|
||||
.lines-commit .bottom-line {
|
||||
border-bottom: 1px solid var(--color-secondary);
|
||||
}
|
||||
|
||||
.migrate .svg.gitea-git {
|
||||
color: var(--color-git);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.ap-terminal {
|
||||
/* Related: https://github.com/asciinema/asciinema-player/blob/develop/src/components/Terminal.js : <div class="ap-term" ...>
|
||||
Old PR: Fix UI regression of asciinema player https://github.com/go-gitea/gitea/pull/26159 */
|
||||
.ap-term {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
@@ -154,12 +154,6 @@ In markup content, we always use bottom margin for all elements */
|
||||
padding-inline-start: 2em;
|
||||
}
|
||||
|
||||
.markup ul.no-list,
|
||||
.markup ol.no-list {
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.markup .task-list-item {
|
||||
list-style-type: none;
|
||||
}
|
||||
@@ -357,69 +351,6 @@ html[data-gitea-theme-dark="false"] .markup img[src*="#gh-dark-mode-only"] {
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.markup span.align-center {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.markup span.align-center > span {
|
||||
display: block;
|
||||
margin: 13px auto 0;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.markup span.align-center span img,
|
||||
.markup span.align-center span video {
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.markup span.align-right {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.markup span.align-right > span {
|
||||
display: block;
|
||||
margin: 13px 0 0;
|
||||
overflow: hidden;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.markup span.align-right span img,
|
||||
.markup span.align-right span video {
|
||||
margin: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.markup span.float-left {
|
||||
display: block;
|
||||
float: left;
|
||||
margin-inline-end: 13px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.markup span.float-left span {
|
||||
margin: 13px 0 0;
|
||||
}
|
||||
|
||||
.markup span.float-right {
|
||||
display: block;
|
||||
float: right;
|
||||
margin-inline-start: 13px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.markup span.float-right > span {
|
||||
display: block;
|
||||
margin: 13px auto 0;
|
||||
overflow: hidden;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.markup code,
|
||||
.markup tt {
|
||||
padding: 0.2em 0.4em;
|
||||
|
||||
@@ -99,6 +99,13 @@ textarea:focus,
|
||||
color: var(--color-input-text);
|
||||
}
|
||||
|
||||
.ui.form input:not([type="checkbox"], [type="radio"])[readonly],
|
||||
.ui.form textarea[readonly],
|
||||
.ui.form select[readonly],
|
||||
.ui.form .ui.selection.dropdown[readonly] {
|
||||
background: var(--color-secondary-bg);
|
||||
}
|
||||
|
||||
.ui.input {
|
||||
color: var(--color-input-text);
|
||||
}
|
||||
@@ -198,7 +205,6 @@ textarea:focus,
|
||||
background-color: var(--color-error-bg);
|
||||
border-color: var(--color-error-border);
|
||||
color: var(--color-error-text);
|
||||
border-radius: 0;
|
||||
}
|
||||
.ui.form .field.error textarea:focus,
|
||||
.ui.form .field.error select:focus,
|
||||
|
||||
@@ -84,15 +84,6 @@
|
||||
border-color: var(--color-warning-border);
|
||||
}
|
||||
|
||||
/* use opaque colors for buttons inside colored messages */
|
||||
.ui.message .ui.button:hover {
|
||||
background: var(--color-secondary);
|
||||
}
|
||||
|
||||
.ui.message .ui.button:active {
|
||||
background: var(--color-secondary-hover);
|
||||
}
|
||||
|
||||
.ui.message > .close.icon {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
|
||||
@@ -159,19 +159,11 @@
|
||||
display: block;
|
||||
}
|
||||
|
||||
.scrolling.dimmable.dimmed {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.scrolling.dimmable > .dimmer {
|
||||
justify-content: flex-start;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.scrolling.dimmable.dimmed > .dimmer {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.modals.dimmer .ui.scrolling.modal {
|
||||
margin: 2rem auto;
|
||||
}
|
||||
|
||||
@@ -287,10 +287,6 @@ td .commit-summary {
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.repository.view.issue .instruct-toggle {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* issue title & meta & edit */
|
||||
.issue-title-header {
|
||||
width: 100%;
|
||||
@@ -1463,11 +1459,6 @@ tbody.commit-list {
|
||||
}
|
||||
}
|
||||
|
||||
.commit-list .commit-status-link {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.commit-body {
|
||||
margin: 0.25em 0;
|
||||
white-space: pre-wrap;
|
||||
|
||||
@@ -1,4 +1,19 @@
|
||||
import {showGlobalErrorMessage} from './errors.ts';
|
||||
import {isGiteaError, showGlobalErrorMessage} from './errors.ts';
|
||||
|
||||
test('isGiteaError', () => {
|
||||
expect(isGiteaError('', '')).toBe(true);
|
||||
expect(isGiteaError('moz-extension://abc/content.js', '')).toBe(false);
|
||||
expect(isGiteaError('safari-extension://abc/content.js', '')).toBe(false);
|
||||
expect(isGiteaError('safari-web-extension://abc/content.js', '')).toBe(false);
|
||||
expect(isGiteaError('chrome-extension://abc/content.js', '')).toBe(false);
|
||||
expect(isGiteaError('https://other-site.com/script.js', '')).toBe(false);
|
||||
expect(isGiteaError('http://localhost:3000/some/page', '')).toBe(true);
|
||||
expect(isGiteaError('http://localhost:3000/assets/js/index.abc123.js', '')).toBe(true);
|
||||
expect(isGiteaError('', `Error\n at chrome-extension://abc/content.js:1:1`)).toBe(false);
|
||||
expect(isGiteaError('', `Error\n at https://other-site.com/script.js:1:1`)).toBe(false);
|
||||
expect(isGiteaError('', `Error\n at http://localhost:3000/assets/js/index.abc123.js:1:1`)).toBe(true);
|
||||
expect(isGiteaError('http://localhost:3000/assets/js/index.js', `Error\n at chrome-extension://abc/content.js:1:1`)).toBe(false);
|
||||
});
|
||||
|
||||
test('showGlobalErrorMessage', () => {
|
||||
document.body.innerHTML = '<div class="page-content"></div>';
|
||||
|
||||
@@ -23,11 +23,19 @@ export function showGlobalErrorMessage(msg: string, msgType: Intent = 'error') {
|
||||
msgContainer.prepend(msgDiv);
|
||||
}
|
||||
|
||||
// Detect whether an error originated from Gitea's own scripts, not from
|
||||
// browser extensions or other external scripts.
|
||||
const extensionRe = /(chrome|moz|safari(-web)?)-extension:\/\//;
|
||||
export function isGiteaError(filename: string, stack: string): boolean {
|
||||
if (extensionRe.test(filename) || extensionRe.test(stack)) return false;
|
||||
const assetBaseUrl = new URL(`${window.config.assetUrlPrefix}/`, window.location.origin).href;
|
||||
if (filename && !filename.startsWith(assetBaseUrl) && !filename.startsWith(window.location.origin)) return false;
|
||||
if (stack && !stack.includes(assetBaseUrl)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
export function processWindowErrorEvent({error, reason, message, type, filename, lineno, colno}: ErrorEvent & PromiseRejectionEvent) {
|
||||
const err = error ?? reason;
|
||||
const assetBaseUrl = String(new URL(`${window.config?.assetUrlPrefix ?? '/assets'}/`, window.location.origin));
|
||||
const {runModeIsProd} = window.config ?? {};
|
||||
|
||||
// `error` and `reason` are not guaranteed to be errors. If the value is falsy, it is likely a
|
||||
// non-critical event from the browser. We log them but don't show them to users. Examples:
|
||||
// - https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#observation_errors
|
||||
@@ -35,12 +43,11 @@ export function processWindowErrorEvent({error, reason, message, type, filename,
|
||||
// - https://github.com/go-gitea/gitea/issues/20240
|
||||
if (!err) {
|
||||
if (message) console.error(new Error(message));
|
||||
if (runModeIsProd) return;
|
||||
if (window.config.runModeIsProd) return;
|
||||
}
|
||||
|
||||
// If the error stack trace does not include the base URL of our script assets, it likely came
|
||||
// from a browser extension or inline script. Do not show such errors in production.
|
||||
if (err instanceof Error && !err.stack?.includes(assetBaseUrl) && runModeIsProd) return;
|
||||
// Filter out errors from browser extensions or other non-Gitea scripts.
|
||||
if (!isGiteaError(filename ?? '', err?.stack ?? '')) return;
|
||||
|
||||
let msg = err?.message ?? message;
|
||||
if (lineno) msg += ` (${filename} @ ${lineno}:${colno})`;
|
||||
|
||||
@@ -13,7 +13,7 @@ await import('./globals.ts');
|
||||
window.config = {
|
||||
appUrl: 'http://localhost:3000/',
|
||||
appSubUrl: '',
|
||||
assetUrlPrefix: '',
|
||||
assetUrlPrefix: '/assets',
|
||||
sharedWorkerUri: '',
|
||||
runModeIsProd: true,
|
||||
customEmojis: {},
|
||||
|
||||
Reference in New Issue
Block a user