Compare commits
80 commits
forgejo
...
forgejo-de
Author | SHA1 | Date | |
---|---|---|---|
|
d405e13322 | ||
|
6fc9ce83ca | ||
|
fd4995b8d8 | ||
|
29bdaed6d2 | ||
|
96d10e793b | ||
|
1e3c6af5fe | ||
|
6c7b5e322d | ||
|
d0d004fe02 | ||
|
e18d574ca4 | ||
|
c296aeaca6 | ||
|
6c22e906fb | ||
|
73a050c001 | ||
|
8c43c2ada8 | ||
|
93f62e9852 | ||
|
f87e11e2eb | ||
|
c2e62c6705 | ||
|
fd287a9134 | ||
|
747a176048 | ||
|
90b3d0ca09 | ||
|
f0ab85cd06 | ||
|
1f4d33de2b | ||
|
f3dbd90a74 | ||
|
1eaba14638 | ||
|
f140388ae4 | ||
|
caf5780c57 | ||
|
be081bca69 | ||
|
e53c0314e9 | ||
|
9dda715111 | ||
|
0d093d76e2 | ||
|
e70d51bd26 | ||
|
a996fe0fe4 | ||
|
7c2f4f749f | ||
|
0a3f370162 | ||
|
816c5b0c4e | ||
|
f9927a2253 | ||
|
a039b3b0c9 | ||
|
77aa18227e | ||
|
1550d00198 | ||
|
85e687e551 | ||
|
658417e7ad | ||
|
6894213154 | ||
|
807d587285 | ||
|
bce1ab85f7 | ||
|
39ade66aac | ||
|
d5b5f6ac50 | ||
|
f48ef0b788 | ||
|
cc25e3f35f | ||
|
be3adcf77b | ||
|
265be677fb | ||
|
69a21774e9 | ||
|
15fd92924a | ||
|
ca1a0256b4 | ||
|
006f064416 | ||
|
f4a21a873c | ||
|
2a4b3a2a43 | ||
|
22d8ed2544 | ||
|
644f7cb733 | ||
|
f5f5eb53fa | ||
|
fd0ebd1a65 | ||
|
fe783424e1 | ||
|
7499661326 | ||
|
f1c5e86d83 | ||
|
92c084fd2c | ||
|
209bbbf1fd | ||
|
314ae5e183 | ||
|
41001442e3 | ||
|
7a1b3fef59 | ||
|
82afc7c30b | ||
|
acde52ddb6 | ||
|
df23f83545 | ||
|
dd42a30d6a | ||
|
6ba6f62c7e | ||
|
1c39bae3ec | ||
|
fbe2fb5861 | ||
|
cf05ec745a | ||
|
59a797db40 | ||
|
8871d1aac7 | ||
|
cf054a0461 | ||
|
dc6d291b71 | ||
|
299da907a0 |
3521 changed files with 102680 additions and 166119 deletions
20
.air.toml
20
.air.toml
|
@ -2,28 +2,12 @@ root = "."
|
||||||
tmp_dir = ".air"
|
tmp_dir = ".air"
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
pre_cmd = ["killall -9 gitea 2>/dev/null || true"] # kill off potential zombie processes from previous runs
|
|
||||||
cmd = "make --no-print-directory backend"
|
cmd = "make --no-print-directory backend"
|
||||||
bin = "gitea"
|
bin = "gitea"
|
||||||
delay = 2000
|
delay = 1000
|
||||||
include_ext = ["go", "tmpl"]
|
include_ext = ["go", "tmpl"]
|
||||||
include_file = ["main.go"]
|
include_file = ["main.go"]
|
||||||
include_dir = ["cmd", "models", "modules", "options", "routers", "services"]
|
include_dir = ["cmd", "models", "modules", "options", "routers", "services"]
|
||||||
exclude_dir = [
|
exclude_dir = ["modules/git/tests", "services/gitdiff/testdata", "modules/avatar/testdata", "models/fixtures", "models/migrations/fixtures", "modules/migration/file_format_testdata", "modules/avatar/identicon/testdata"]
|
||||||
"models/fixtures",
|
|
||||||
"models/migrations/fixtures",
|
|
||||||
"modules/avatar/identicon/testdata",
|
|
||||||
"modules/avatar/testdata",
|
|
||||||
"modules/git/tests",
|
|
||||||
"modules/migration/file_format_testdata",
|
|
||||||
"modules/markup/tests/repo/repo1_filepreview",
|
|
||||||
"routers/private/tests",
|
|
||||||
"services/gitdiff/testdata",
|
|
||||||
"services/migrations/testdata",
|
|
||||||
"services/webhook/sourcehut/testdata",
|
|
||||||
]
|
|
||||||
exclude_regex = ["_test.go$", "_gen.go$"]
|
exclude_regex = ["_test.go$", "_gen.go$"]
|
||||||
stop_on_error = true
|
stop_on_error = true
|
||||||
|
|
||||||
[log]
|
|
||||||
main_only = true
|
|
||||||
|
|
57
.changelog.yml
Normal file
57
.changelog.yml
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
# The full repository name
|
||||||
|
repo: go-gitea/gitea
|
||||||
|
|
||||||
|
# Service type (gitea or github)
|
||||||
|
service: github
|
||||||
|
|
||||||
|
# Base URL for Gitea instance if using gitea service type (optional)
|
||||||
|
# Default: https://gitea.com
|
||||||
|
base-url:
|
||||||
|
|
||||||
|
# Changelog groups and which labeled PRs to add to each group
|
||||||
|
groups:
|
||||||
|
-
|
||||||
|
name: BREAKING
|
||||||
|
labels:
|
||||||
|
- pr/breaking
|
||||||
|
-
|
||||||
|
name: SECURITY
|
||||||
|
labels:
|
||||||
|
- topic/security
|
||||||
|
-
|
||||||
|
name: FEATURES
|
||||||
|
labels:
|
||||||
|
- type/feature
|
||||||
|
-
|
||||||
|
name: API
|
||||||
|
labels:
|
||||||
|
- modifies/api
|
||||||
|
-
|
||||||
|
name: ENHANCEMENTS
|
||||||
|
labels:
|
||||||
|
- type/enhancement
|
||||||
|
- type/refactoring
|
||||||
|
- topic/ui
|
||||||
|
-
|
||||||
|
name: BUGFIXES
|
||||||
|
labels:
|
||||||
|
- type/bug
|
||||||
|
-
|
||||||
|
name: TESTING
|
||||||
|
labels:
|
||||||
|
- type/testing
|
||||||
|
-
|
||||||
|
name: BUILD
|
||||||
|
labels:
|
||||||
|
- topic/build
|
||||||
|
- topic/code-linting
|
||||||
|
-
|
||||||
|
name: DOCS
|
||||||
|
labels:
|
||||||
|
- type/docs
|
||||||
|
-
|
||||||
|
name: MISC
|
||||||
|
default: true
|
||||||
|
|
||||||
|
# regex indicating which labels to skip for the changelog
|
||||||
|
skip-labels: skip-changelog|backport\/.+
|
638
.deadcode-out
638
.deadcode-out
|
@ -1,303 +1,337 @@
|
||||||
code.gitea.io/gitea/cmd
|
package "code.gitea.io/gitea/cmd"
|
||||||
NoMainListener
|
func NoMainListener
|
||||||
|
|
||||||
code.gitea.io/gitea/cmd/forgejo
|
package "code.gitea.io/gitea/cmd/forgejo"
|
||||||
ContextSetNoInit
|
func ContextSetNoInit
|
||||||
ContextSetNoExit
|
func ContextSetNoExit
|
||||||
ContextSetStderr
|
func ContextSetStderr
|
||||||
ContextGetStderr
|
func ContextGetStderr
|
||||||
ContextSetStdout
|
func ContextSetStdout
|
||||||
ContextSetStdin
|
func ContextSetStdin
|
||||||
|
|
||||||
code.gitea.io/gitea/models
|
package "code.gitea.io/gitea/models"
|
||||||
IsErrUpdateTaskNotExist
|
func IsErrUpdateTaskNotExist
|
||||||
ErrUpdateTaskNotExist.Error
|
func (ErrUpdateTaskNotExist).Error
|
||||||
ErrUpdateTaskNotExist.Unwrap
|
func (ErrUpdateTaskNotExist).Unwrap
|
||||||
IsErrSHANotFound
|
func IsErrSHANotFound
|
||||||
IsErrMergeDivergingFastForwardOnly
|
func GetYamlFixturesAccess
|
||||||
GetYamlFixturesAccess
|
|
||||||
|
package "code.gitea.io/gitea/models/actions"
|
||||||
code.gitea.io/gitea/models/actions
|
func (ScheduleList).GetUserIDs
|
||||||
ScheduleList.GetUserIDs
|
func (ScheduleList).GetRepoIDs
|
||||||
ScheduleList.GetRepoIDs
|
func (ScheduleList).LoadTriggerUser
|
||||||
ScheduleList.LoadTriggerUser
|
func (ScheduleList).LoadRepos
|
||||||
ScheduleList.LoadRepos
|
func GetVariableByID
|
||||||
|
|
||||||
code.gitea.io/gitea/models/asymkey
|
package "code.gitea.io/gitea/models/asymkey"
|
||||||
ErrGPGKeyAccessDenied.Error
|
func (ErrGPGKeyAccessDenied).Error
|
||||||
ErrGPGKeyAccessDenied.Unwrap
|
func (ErrGPGKeyAccessDenied).Unwrap
|
||||||
HasDeployKey
|
func HasDeployKey
|
||||||
|
|
||||||
code.gitea.io/gitea/models/auth
|
package "code.gitea.io/gitea/models/auth"
|
||||||
GetSourceByName
|
func GetSourceByName
|
||||||
WebAuthnCredentials
|
func GetWebAuthnCredentialByID
|
||||||
|
func WebAuthnCredentials
|
||||||
code.gitea.io/gitea/models/db
|
|
||||||
TruncateBeans
|
package "code.gitea.io/gitea/models/db"
|
||||||
InTransaction
|
func TruncateBeans
|
||||||
DumpTables
|
func InTransaction
|
||||||
|
func DumpTables
|
||||||
code.gitea.io/gitea/models/dbfs
|
|
||||||
file.renameTo
|
package "code.gitea.io/gitea/models/dbfs"
|
||||||
Create
|
func (*file).renameTo
|
||||||
Rename
|
func Create
|
||||||
|
func Rename
|
||||||
code.gitea.io/gitea/models/forgefed
|
|
||||||
GetFederationHost
|
package "code.gitea.io/gitea/models/forgejo/semver"
|
||||||
|
func GetVersion
|
||||||
code.gitea.io/gitea/models/forgejo/semver
|
func SetVersionString
|
||||||
GetVersion
|
func SetVersion
|
||||||
SetVersionString
|
|
||||||
SetVersion
|
package "code.gitea.io/gitea/models/git"
|
||||||
|
func RemoveDeletedBranchByID
|
||||||
code.gitea.io/gitea/models/git
|
|
||||||
RemoveDeletedBranchByID
|
package "code.gitea.io/gitea/models/issues"
|
||||||
|
func IsErrUnknownDependencyType
|
||||||
code.gitea.io/gitea/models/issues
|
func (ErrNewIssueInsert).Error
|
||||||
IsErrUnknownDependencyType
|
func IsErrIssueWasClosed
|
||||||
ErrNewIssueInsert.Error
|
func ChangeMilestoneStatus
|
||||||
IsErrIssueWasClosed
|
|
||||||
ChangeMilestoneStatus
|
package "code.gitea.io/gitea/models/migrations/base"
|
||||||
|
func removeAllWithRetry
|
||||||
code.gitea.io/gitea/models/organization
|
func newXORMEngine
|
||||||
GetTeamNamesByID
|
func deleteDB
|
||||||
UpdateTeamUnits
|
func PrepareTestEnv
|
||||||
SearchMembersOptions.ToConds
|
func MainTest
|
||||||
UsersInTeamsCount
|
|
||||||
|
package "code.gitea.io/gitea/models/organization"
|
||||||
code.gitea.io/gitea/models/perm/access
|
func UpdateTeamUnits
|
||||||
GetRepoWriters
|
func (SearchMembersOptions).ToConds
|
||||||
|
func UsersInTeamsCount
|
||||||
code.gitea.io/gitea/models/project
|
|
||||||
UpdateColumnSorting
|
package "code.gitea.io/gitea/models/perm/access"
|
||||||
ChangeProjectStatus
|
func GetRepoWriters
|
||||||
|
|
||||||
code.gitea.io/gitea/models/repo
|
package "code.gitea.io/gitea/models/project"
|
||||||
DeleteAttachmentsByIssue
|
func UpdateBoardSorting
|
||||||
FindReposMapByIDs
|
func ChangeProjectStatus
|
||||||
IsErrTopicNotExist
|
|
||||||
ErrTopicNotExist.Error
|
package "code.gitea.io/gitea/models/repo"
|
||||||
ErrTopicNotExist.Unwrap
|
func DeleteAttachmentsByIssue
|
||||||
GetTopicByName
|
func (*releaseSorter).Len
|
||||||
WatchRepoMode
|
func (*releaseSorter).Less
|
||||||
|
func (*releaseSorter).Swap
|
||||||
code.gitea.io/gitea/models/user
|
func SortReleases
|
||||||
ErrUserInactive.Error
|
func FindReposMapByIDs
|
||||||
ErrUserInactive.Unwrap
|
func RepositoryListOfMap
|
||||||
IsErrExternalLoginUserAlreadyExist
|
func (SearchOrderBy).String
|
||||||
IsErrExternalLoginUserNotExist
|
func IsErrTopicNotExist
|
||||||
NewFederatedUser
|
func (ErrTopicNotExist).Error
|
||||||
IsErrUserSettingIsNotExist
|
func (ErrTopicNotExist).Unwrap
|
||||||
GetUserAllSettings
|
func GetTopicByName
|
||||||
DeleteUserSetting
|
func WatchRepoMode
|
||||||
GetUserEmailsByNames
|
|
||||||
GetUserNamesByIDs
|
package "code.gitea.io/gitea/models/unittest"
|
||||||
|
func CheckConsistencyFor
|
||||||
code.gitea.io/gitea/modules/activitypub
|
func checkForConsistency
|
||||||
NewContext
|
func GetXORMEngine
|
||||||
Context.APClientFactory
|
func OverrideFixtures
|
||||||
|
func InitFixtures
|
||||||
code.gitea.io/gitea/modules/assetfs
|
func LoadFixtures
|
||||||
Bindata
|
func Copy
|
||||||
|
func CopyDir
|
||||||
code.gitea.io/gitea/modules/auth/password/hash
|
func FixturesDir
|
||||||
DummyHasher.HashWithSaltBytes
|
func fatalTestError
|
||||||
NewDummyHasher
|
func InitSettings
|
||||||
|
func MainTest
|
||||||
code.gitea.io/gitea/modules/auth/password/pwn
|
func CreateTestEngine
|
||||||
WithHTTP
|
func PrepareTestDatabase
|
||||||
|
func PrepareTestEnv
|
||||||
code.gitea.io/gitea/modules/base
|
func Cond
|
||||||
SetupGiteaRoot
|
func OrderBy
|
||||||
|
func LoadBeanIfExists
|
||||||
code.gitea.io/gitea/modules/cache
|
func BeanExists
|
||||||
GetInt
|
func AssertExistsAndLoadBean
|
||||||
WithNoCacheContext
|
func GetCount
|
||||||
RemoveContextData
|
func AssertNotExistsBean
|
||||||
|
func AssertExistsIf
|
||||||
code.gitea.io/gitea/modules/charset
|
func AssertSuccessfulInsert
|
||||||
BreakWriter.Write
|
func AssertCount
|
||||||
|
func AssertInt64InRange
|
||||||
code.gitea.io/gitea/modules/emoji
|
|
||||||
ReplaceCodes
|
package "code.gitea.io/gitea/models/user"
|
||||||
|
func IsErrPrimaryEmailCannotDelete
|
||||||
code.gitea.io/gitea/modules/eventsource
|
func (ErrUserInactive).Error
|
||||||
Event.String
|
func (ErrUserInactive).Unwrap
|
||||||
|
func IsErrExternalLoginUserAlreadyExist
|
||||||
code.gitea.io/gitea/modules/forgefed
|
func IsErrExternalLoginUserNotExist
|
||||||
GetItemByType
|
func IsErrUserSettingIsNotExist
|
||||||
JSONUnmarshalerFn
|
func GetUserAllSettings
|
||||||
NotEmpty
|
func DeleteUserSetting
|
||||||
ToRepository
|
func GetUserEmailsByNames
|
||||||
OnRepository
|
|
||||||
|
package "code.gitea.io/gitea/modules/activitypub"
|
||||||
code.gitea.io/gitea/modules/git
|
func CurrentTime
|
||||||
AllowLFSFiltersArgs
|
func containsRequiredHTTPHeaders
|
||||||
AddChanges
|
func NewClient
|
||||||
AddChangesWithArgs
|
func (*Client).NewRequest
|
||||||
CommitChanges
|
func (*Client).Post
|
||||||
CommitChangesWithArgs
|
func GetPrivateKey
|
||||||
IsErrExecTimeout
|
|
||||||
ErrExecTimeout.Error
|
package "code.gitea.io/gitea/modules/assetfs"
|
||||||
ErrUnsupportedVersion.Error
|
func Bindata
|
||||||
SetUpdateHook
|
|
||||||
openRepositoryWithDefaultContext
|
package "code.gitea.io/gitea/modules/auth/password/hash"
|
||||||
IsTagExist
|
func (*DummyHasher).HashWithSaltBytes
|
||||||
ToEntryMode
|
func NewDummyHasher
|
||||||
LimitedReaderCloser.Read
|
|
||||||
LimitedReaderCloser.Close
|
package "code.gitea.io/gitea/modules/auth/password/pwn"
|
||||||
|
func WithHTTP
|
||||||
code.gitea.io/gitea/modules/gitgraph
|
|
||||||
Parser.Reset
|
package "code.gitea.io/gitea/modules/base"
|
||||||
|
func SetupGiteaRoot
|
||||||
code.gitea.io/gitea/modules/gitrepo
|
|
||||||
GetBranchCommitID
|
package "code.gitea.io/gitea/modules/cache"
|
||||||
GetWikiDefaultBranch
|
func GetInt
|
||||||
|
func WithNoCacheContext
|
||||||
code.gitea.io/gitea/modules/graceful
|
func RemoveContextData
|
||||||
Manager.TerminateContext
|
|
||||||
Manager.Err
|
package "code.gitea.io/gitea/modules/charset"
|
||||||
Manager.Value
|
func (*BreakWriter).Write
|
||||||
Manager.Deadline
|
|
||||||
|
package "code.gitea.io/gitea/modules/context"
|
||||||
code.gitea.io/gitea/modules/hcaptcha
|
func GetPrivateContext
|
||||||
WithHTTP
|
|
||||||
|
package "code.gitea.io/gitea/modules/emoji"
|
||||||
code.gitea.io/gitea/modules/hostmatcher
|
func ReplaceCodes
|
||||||
HostMatchList.AppendPattern
|
|
||||||
|
package "code.gitea.io/gitea/modules/eventsource"
|
||||||
code.gitea.io/gitea/modules/json
|
func (*Event).String
|
||||||
StdJSON.Marshal
|
|
||||||
StdJSON.Unmarshal
|
package "code.gitea.io/gitea/modules/git"
|
||||||
StdJSON.NewEncoder
|
func AllowLFSFiltersArgs
|
||||||
StdJSON.NewDecoder
|
func AddChanges
|
||||||
StdJSON.Indent
|
func AddChangesWithArgs
|
||||||
|
func CommitChanges
|
||||||
code.gitea.io/gitea/modules/markup
|
func CommitChangesWithArgs
|
||||||
GetRendererByType
|
func IsErrExecTimeout
|
||||||
RenderString
|
func (ErrExecTimeout).Error
|
||||||
IsMarkupFile
|
func (ErrUnsupportedVersion).Error
|
||||||
|
func SetUpdateHook
|
||||||
code.gitea.io/gitea/modules/markup/console
|
func openRepositoryWithDefaultContext
|
||||||
Render
|
func IsTagExist
|
||||||
RenderString
|
func ToEntryMode
|
||||||
|
func (*LimitedReaderCloser).Read
|
||||||
code.gitea.io/gitea/modules/markup/markdown
|
func (*LimitedReaderCloser).Close
|
||||||
IsDetails
|
|
||||||
IsSummary
|
package "code.gitea.io/gitea/modules/gitgraph"
|
||||||
IsTaskCheckBoxListItem
|
func (*Parser).Reset
|
||||||
IsIcon
|
|
||||||
RenderRawString
|
package "code.gitea.io/gitea/modules/gitrepo"
|
||||||
|
func GetBranchCommitID
|
||||||
code.gitea.io/gitea/modules/markup/markdown/math
|
|
||||||
WithInlineDollarParser
|
package "code.gitea.io/gitea/modules/graceful"
|
||||||
WithBlockDollarParser
|
func (*Manager).TerminateContext
|
||||||
|
func (*Manager).Err
|
||||||
code.gitea.io/gitea/modules/markup/mdstripper
|
func (*Manager).Value
|
||||||
stripRenderer.AddOptions
|
func (*Manager).Deadline
|
||||||
StripMarkdown
|
|
||||||
|
package "code.gitea.io/gitea/modules/hcaptcha"
|
||||||
code.gitea.io/gitea/modules/markup/orgmode
|
func WithHTTP
|
||||||
RenderString
|
|
||||||
|
package "code.gitea.io/gitea/modules/json"
|
||||||
code.gitea.io/gitea/modules/private
|
func (StdJSON).Marshal
|
||||||
ActionsRunnerRegister
|
func (StdJSON).Unmarshal
|
||||||
|
func (StdJSON).NewEncoder
|
||||||
code.gitea.io/gitea/modules/process
|
func (StdJSON).NewDecoder
|
||||||
Manager.ExecTimeout
|
func (StdJSON).Indent
|
||||||
|
|
||||||
code.gitea.io/gitea/modules/queue
|
package "code.gitea.io/gitea/modules/markup"
|
||||||
newBaseChannelSimple
|
func IsSameDomain
|
||||||
newBaseChannelUnique
|
func GetRendererByType
|
||||||
newBaseRedisSimple
|
func RenderString
|
||||||
newBaseRedisUnique
|
func IsMarkupFile
|
||||||
testStateRecorder.Records
|
|
||||||
testStateRecorder.Reset
|
package "code.gitea.io/gitea/modules/markup/console"
|
||||||
newWorkerPoolQueueForTest
|
func Render
|
||||||
|
func RenderString
|
||||||
code.gitea.io/gitea/modules/queue/lqinternal
|
|
||||||
QueueItemIDBytes
|
package "code.gitea.io/gitea/modules/markup/markdown"
|
||||||
QueueItemKeyBytes
|
func IsDetails
|
||||||
ListLevelQueueKeys
|
func IsSummary
|
||||||
|
func IsTaskCheckBoxListItem
|
||||||
code.gitea.io/gitea/modules/setting
|
func IsIcon
|
||||||
NewConfigProviderFromData
|
func IsColorPreview
|
||||||
GitConfigType.GetOption
|
func RenderRawString
|
||||||
InitLoggersForTest
|
|
||||||
|
package "code.gitea.io/gitea/modules/markup/markdown/math"
|
||||||
code.gitea.io/gitea/modules/storage
|
func WithInlineDollarParser
|
||||||
ErrInvalidConfiguration.Error
|
func WithBlockDollarParser
|
||||||
IsErrInvalidConfiguration
|
|
||||||
|
package "code.gitea.io/gitea/modules/markup/mdstripper"
|
||||||
code.gitea.io/gitea/modules/structs
|
func StripMarkdown
|
||||||
ParseCreateHook
|
|
||||||
ParsePushHook
|
package "code.gitea.io/gitea/modules/markup/orgmode"
|
||||||
|
func RenderString
|
||||||
code.gitea.io/gitea/modules/sync
|
|
||||||
StatusTable.Start
|
package "code.gitea.io/gitea/modules/private"
|
||||||
StatusTable.IsRunning
|
func ActionsRunnerRegister
|
||||||
|
|
||||||
code.gitea.io/gitea/modules/timeutil
|
package "code.gitea.io/gitea/modules/process"
|
||||||
GetExecutableModTime
|
func (*Manager).ExecTimeout
|
||||||
MockSet
|
|
||||||
MockUnset
|
package "code.gitea.io/gitea/modules/queue"
|
||||||
|
func newBaseChannelSimple
|
||||||
code.gitea.io/gitea/modules/translation
|
func newBaseChannelUnique
|
||||||
MockLocale.Language
|
func newBaseRedisSimple
|
||||||
MockLocale.TrString
|
func newBaseRedisUnique
|
||||||
MockLocale.Tr
|
func newWorkerPoolQueueForTest
|
||||||
MockLocale.TrN
|
|
||||||
MockLocale.TrSize
|
package "code.gitea.io/gitea/modules/queue/lqinternal"
|
||||||
MockLocale.PrettyNumber
|
func QueueItemIDBytes
|
||||||
|
func QueueItemKeyBytes
|
||||||
code.gitea.io/gitea/modules/util/filebuffer
|
func ListLevelQueueKeys
|
||||||
CreateFromReader
|
|
||||||
|
package "code.gitea.io/gitea/modules/setting"
|
||||||
code.gitea.io/gitea/modules/validation
|
func NewConfigProviderFromData
|
||||||
IsErrNotValid
|
func (*GitConfigType).GetOption
|
||||||
|
func InitLoggersForTest
|
||||||
code.gitea.io/gitea/modules/web
|
|
||||||
RouteMock
|
package "code.gitea.io/gitea/modules/storage"
|
||||||
RouteMockReset
|
func (ErrInvalidConfiguration).Error
|
||||||
|
func IsErrInvalidConfiguration
|
||||||
code.gitea.io/gitea/modules/web/middleware
|
|
||||||
DeleteLocaleCookie
|
package "code.gitea.io/gitea/modules/structs"
|
||||||
|
func ParseCreateHook
|
||||||
code.gitea.io/gitea/modules/zstd
|
func ParsePushHook
|
||||||
NewWriter
|
|
||||||
Writer.Write
|
package "code.gitea.io/gitea/modules/sync"
|
||||||
Writer.Close
|
func (*StatusTable).Start
|
||||||
|
func (*StatusTable).IsRunning
|
||||||
code.gitea.io/gitea/routers/web
|
|
||||||
NotFound
|
package "code.gitea.io/gitea/modules/testlogger"
|
||||||
|
func (*testLoggerWriterCloser).pushT
|
||||||
code.gitea.io/gitea/routers/web/org
|
func (*testLoggerWriterCloser).Write
|
||||||
MustEnableProjects
|
func (*testLoggerWriterCloser).popT
|
||||||
|
func (*testLoggerWriterCloser).Close
|
||||||
code.gitea.io/gitea/services/context
|
func (*testLoggerWriterCloser).Reset
|
||||||
GetPrivateContext
|
func PrintCurrentTest
|
||||||
|
func Printf
|
||||||
code.gitea.io/gitea/services/convert
|
func NewTestLoggerWriter
|
||||||
ToSecret
|
|
||||||
|
package "code.gitea.io/gitea/modules/timeutil"
|
||||||
code.gitea.io/gitea/services/forms
|
func GetExecutableModTime
|
||||||
DeadlineForm.Validate
|
func MockSet
|
||||||
|
func MockUnset
|
||||||
code.gitea.io/gitea/services/pull
|
|
||||||
IsCommitStatusContextSuccess
|
package "code.gitea.io/gitea/modules/translation"
|
||||||
|
func (MockLocale).Language
|
||||||
code.gitea.io/gitea/services/repository
|
func (MockLocale).Tr
|
||||||
IsErrForkAlreadyExist
|
func (MockLocale).TrN
|
||||||
|
func (MockLocale).PrettyNumber
|
||||||
code.gitea.io/gitea/services/repository/archiver
|
|
||||||
ArchiveRepository
|
package "code.gitea.io/gitea/modules/util"
|
||||||
|
func UnsafeStringToBytes
|
||||||
code.gitea.io/gitea/services/repository/files
|
|
||||||
ContentType.String
|
package "code.gitea.io/gitea/modules/util/filebuffer"
|
||||||
GetFileResponseFromCommit
|
func CreateFromReader
|
||||||
TemporaryUploadRepository.GetLastCommit
|
|
||||||
TemporaryUploadRepository.GetLastCommitByRef
|
package "code.gitea.io/gitea/modules/web"
|
||||||
|
func RouteMock
|
||||||
code.gitea.io/gitea/services/webhook
|
func RouteMockReset
|
||||||
NewNotifier
|
|
||||||
|
package "code.gitea.io/gitea/modules/web/middleware"
|
||||||
|
func DeleteLocaleCookie
|
||||||
|
|
||||||
|
package "code.gitea.io/gitea/routers/web"
|
||||||
|
func NotFound
|
||||||
|
|
||||||
|
package "code.gitea.io/gitea/routers/web/org"
|
||||||
|
func MustEnableProjects
|
||||||
|
func getActionIssues
|
||||||
|
func UpdateIssueProject
|
||||||
|
|
||||||
|
package "code.gitea.io/gitea/services/convert"
|
||||||
|
func ToSecret
|
||||||
|
|
||||||
|
package "code.gitea.io/gitea/services/forms"
|
||||||
|
func (*DeadlineForm).Validate
|
||||||
|
|
||||||
|
package "code.gitea.io/gitea/services/pull"
|
||||||
|
func IsCommitStatusContextSuccess
|
||||||
|
|
||||||
|
package "code.gitea.io/gitea/services/repository"
|
||||||
|
func IsErrForkAlreadyExist
|
||||||
|
|
||||||
|
package "code.gitea.io/gitea/services/repository/archiver"
|
||||||
|
func ArchiveRepository
|
||||||
|
|
||||||
|
package "code.gitea.io/gitea/services/repository/files"
|
||||||
|
func (*ContentType).String
|
||||||
|
func GetFileResponseFromCommit
|
||||||
|
func (*TemporaryUploadRepository).GetLastCommit
|
||||||
|
func (*TemporaryUploadRepository).GetLastCommitByRef
|
||||||
|
|
||||||
|
package "code.gitea.io/gitea/services/webhook"
|
||||||
|
func NewNotifier
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,14 @@
|
||||||
{
|
{
|
||||||
"name": "Gitea DevContainer",
|
"name": "Gitea DevContainer",
|
||||||
"image": "mcr.microsoft.com/devcontainers/go:1.23-bullseye",
|
"image": "mcr.microsoft.com/devcontainers/go:1.21-bullseye",
|
||||||
"features": {
|
"features": {
|
||||||
// installs nodejs into container
|
// installs nodejs into container
|
||||||
"ghcr.io/devcontainers/features/node:1": {
|
"ghcr.io/devcontainers/features/node:1": {
|
||||||
"version": "20"
|
"version":"20"
|
||||||
},
|
},
|
||||||
"ghcr.io/devcontainers/features/git-lfs:1.2.3": {},
|
"ghcr.io/devcontainers/features/git-lfs:1.1.0": {},
|
||||||
"ghcr.io/devcontainers-contrib/features/poetry:2": {},
|
"ghcr.io/devcontainers-contrib/features/poetry:2": {},
|
||||||
"ghcr.io/devcontainers/features/python:1": {
|
"ghcr.io/devcontainers/features/python:1": {}
|
||||||
"version": "3.12"
|
|
||||||
},
|
|
||||||
"ghcr.io/warrenbuckley/codespace-features/sqlite:1": {}
|
|
||||||
},
|
},
|
||||||
"customizations": {
|
"customizations": {
|
||||||
"vscode": {
|
"vscode": {
|
||||||
|
@ -25,10 +22,9 @@
|
||||||
"DavidAnson.vscode-markdownlint",
|
"DavidAnson.vscode-markdownlint",
|
||||||
"Vue.volar",
|
"Vue.volar",
|
||||||
"ms-azuretools.vscode-docker",
|
"ms-azuretools.vscode-docker",
|
||||||
"vitest.explorer",
|
"zixuanchen.vitest-explorer",
|
||||||
"cweijan.vscode-database-client2",
|
"qwtel.sqlite-viewer",
|
||||||
"GitHub.vscode-pull-request-github",
|
"GitHub.vscode-pull-request-github"
|
||||||
"Azurite.azurite"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,7 +14,7 @@ _test
|
||||||
|
|
||||||
# MS VSCode
|
# MS VSCode
|
||||||
.vscode
|
.vscode
|
||||||
__debug_bin*
|
__debug_bin
|
||||||
|
|
||||||
# Architecture specific extensions/prefixes
|
# Architecture specific extensions/prefixes
|
||||||
*.[568vq]
|
*.[568vq]
|
||||||
|
@ -62,6 +62,7 @@ cpu.out
|
||||||
/data
|
/data
|
||||||
/indexers
|
/indexers
|
||||||
/log
|
/log
|
||||||
|
/public/img/avatar
|
||||||
/tests/integration/gitea-integration-*
|
/tests/integration/gitea-integration-*
|
||||||
/tests/integration/indexers-*
|
/tests/integration/indexers-*
|
||||||
/tests/e2e/gitea-e2e-*
|
/tests/e2e/gitea-e2e-*
|
||||||
|
@ -70,13 +71,14 @@ cpu.out
|
||||||
/tests/e2e/test-artifacts
|
/tests/e2e/test-artifacts
|
||||||
/tests/e2e/test-snapshots
|
/tests/e2e/test-snapshots
|
||||||
/tests/*.ini
|
/tests/*.ini
|
||||||
|
/node_modules
|
||||||
/yarn.lock
|
/yarn.lock
|
||||||
/yarn-error.log
|
/yarn-error.log
|
||||||
/npm-debug.log*
|
/npm-debug.log*
|
||||||
/public/assets/js
|
/public/assets/js
|
||||||
/public/assets/css
|
/public/assets/css
|
||||||
/public/assets/fonts
|
/public/assets/fonts
|
||||||
/public/assets/img/avatar
|
/public/assets/img/webpack
|
||||||
/vendor
|
/vendor
|
||||||
/web_src/fomantic/node_modules
|
/web_src/fomantic/node_modules
|
||||||
/web_src/fomantic/build/*
|
/web_src/fomantic/build/*
|
||||||
|
@ -94,9 +96,6 @@ cpu.out
|
||||||
/.air
|
/.air
|
||||||
/.go-licenses
|
/.go-licenses
|
||||||
|
|
||||||
# Files and folders that were previously generated
|
|
||||||
/public/assets/img/webpack
|
|
||||||
|
|
||||||
# Snapcraft
|
# Snapcraft
|
||||||
snap/.snapcraft/
|
snap/.snapcraft/
|
||||||
parts/
|
parts/
|
||||||
|
|
|
@ -9,7 +9,7 @@ charset = utf-8
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
|
|
||||||
[{*.{go,tmpl,html},Makefile,go.mod}]
|
[*.{go,tmpl,html}]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
|
|
||||||
[templates/custom/*.tmpl]
|
[templates/custom/*.tmpl]
|
||||||
|
@ -21,8 +21,8 @@ indent_style = space
|
||||||
[templates/user/auth/oidc_wellknown.tmpl]
|
[templates/user/auth/oidc_wellknown.tmpl]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
|
|
||||||
|
[Makefile]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
[*.svg]
|
[*.svg]
|
||||||
insert_final_newline = false
|
insert_final_newline = false
|
||||||
|
|
||||||
[options/locale/locale_*.ini]
|
|
||||||
insert_final_newline = false
|
|
||||||
|
|
1
.envrc
1
.envrc
|
@ -1 +0,0 @@
|
||||||
use flake
|
|
222
.eslintrc.yaml
222
.eslintrc.yaml
|
@ -3,8 +3,6 @@ reportUnusedDisableDirectives: true
|
||||||
|
|
||||||
ignorePatterns:
|
ignorePatterns:
|
||||||
- /web_src/js/vendor
|
- /web_src/js/vendor
|
||||||
- /web_src/fomantic
|
|
||||||
- /public/assets/js
|
|
||||||
|
|
||||||
parserOptions:
|
parserOptions:
|
||||||
sourceType: module
|
sourceType: module
|
||||||
|
@ -13,15 +11,15 @@ parserOptions:
|
||||||
plugins:
|
plugins:
|
||||||
- "@eslint-community/eslint-plugin-eslint-comments"
|
- "@eslint-community/eslint-plugin-eslint-comments"
|
||||||
- "@stylistic/eslint-plugin-js"
|
- "@stylistic/eslint-plugin-js"
|
||||||
- "@vitest"
|
|
||||||
- eslint-plugin-array-func
|
- eslint-plugin-array-func
|
||||||
- eslint-plugin-github
|
|
||||||
- eslint-plugin-i
|
- eslint-plugin-i
|
||||||
|
- eslint-plugin-jquery
|
||||||
- eslint-plugin-no-jquery
|
- eslint-plugin-no-jquery
|
||||||
- eslint-plugin-no-use-extend-native
|
- eslint-plugin-no-use-extend-native
|
||||||
- eslint-plugin-regexp
|
- eslint-plugin-regexp
|
||||||
- eslint-plugin-sonarjs
|
- eslint-plugin-sonarjs
|
||||||
- eslint-plugin-unicorn
|
- eslint-plugin-unicorn
|
||||||
|
- eslint-plugin-vitest
|
||||||
- eslint-plugin-vitest-globals
|
- eslint-plugin-vitest-globals
|
||||||
- eslint-plugin-wc
|
- eslint-plugin-wc
|
||||||
|
|
||||||
|
@ -43,6 +41,10 @@ overrides:
|
||||||
worker: true
|
worker: true
|
||||||
rules:
|
rules:
|
||||||
no-restricted-globals: [2, addEventListener, blur, close, closed, confirm, defaultStatus, defaultstatus, error, event, external, find, focus, frameElement, frames, history, innerHeight, innerWidth, isFinite, isNaN, length, locationbar, menubar, moveBy, moveTo, name, onblur, onerror, onfocus, onload, onresize, onunload, open, opener, opera, outerHeight, outerWidth, pageXOffset, pageYOffset, parent, print, removeEventListener, resizeBy, resizeTo, screen, screenLeft, screenTop, screenX, screenY, scroll, scrollbars, scrollBy, scrollTo, scrollX, scrollY, status, statusbar, stop, toolbar, top]
|
no-restricted-globals: [2, addEventListener, blur, close, closed, confirm, defaultStatus, defaultstatus, error, event, external, find, focus, frameElement, frames, history, innerHeight, innerWidth, isFinite, isNaN, length, locationbar, menubar, moveBy, moveTo, name, onblur, onerror, onfocus, onload, onresize, onunload, open, opener, opera, outerHeight, outerWidth, pageXOffset, pageYOffset, parent, print, removeEventListener, resizeBy, resizeTo, screen, screenLeft, screenTop, screenX, screenY, scroll, scrollbars, scrollBy, scrollTo, scrollX, scrollY, status, statusbar, stop, toolbar, top]
|
||||||
|
- files: ["build/generate-images.js"]
|
||||||
|
rules:
|
||||||
|
i/no-unresolved: [0]
|
||||||
|
i/no-extraneous-dependencies: [0]
|
||||||
- files: ["*.config.*"]
|
- files: ["*.config.*"]
|
||||||
rules:
|
rules:
|
||||||
i/no-unused-modules: [0]
|
i/no-unused-modules: [0]
|
||||||
|
@ -50,55 +52,55 @@ overrides:
|
||||||
env:
|
env:
|
||||||
vitest-globals/env: true
|
vitest-globals/env: true
|
||||||
rules:
|
rules:
|
||||||
"@vitest/consistent-test-filename": [0]
|
vitest/consistent-test-filename: [0]
|
||||||
"@vitest/consistent-test-it": [0]
|
vitest/consistent-test-it: [0]
|
||||||
"@vitest/expect-expect": [0]
|
vitest/expect-expect: [0]
|
||||||
"@vitest/max-expects": [0]
|
vitest/max-expects: [0]
|
||||||
"@vitest/max-nested-describe": [0]
|
vitest/max-nested-describe: [0]
|
||||||
"@vitest/no-alias-methods": [0]
|
vitest/no-alias-methods: [0]
|
||||||
"@vitest/no-commented-out-tests": [0]
|
vitest/no-commented-out-tests: [0]
|
||||||
"@vitest/no-conditional-expect": [0]
|
vitest/no-conditional-expect: [0]
|
||||||
"@vitest/no-conditional-in-test": [0]
|
vitest/no-conditional-in-test: [0]
|
||||||
"@vitest/no-conditional-tests": [0]
|
vitest/no-conditional-tests: [0]
|
||||||
"@vitest/no-disabled-tests": [0]
|
vitest/no-disabled-tests: [0]
|
||||||
"@vitest/no-done-callback": [0]
|
vitest/no-done-callback: [0]
|
||||||
"@vitest/no-duplicate-hooks": [0]
|
vitest/no-duplicate-hooks: [0]
|
||||||
"@vitest/no-focused-tests": [0]
|
vitest/no-focused-tests: [0]
|
||||||
"@vitest/no-hooks": [0]
|
vitest/no-hooks: [0]
|
||||||
"@vitest/no-identical-title": [2]
|
vitest/no-identical-title: [2]
|
||||||
"@vitest/no-interpolation-in-snapshots": [0]
|
vitest/no-interpolation-in-snapshots: [0]
|
||||||
"@vitest/no-large-snapshots": [0]
|
vitest/no-large-snapshots: [0]
|
||||||
"@vitest/no-mocks-import": [0]
|
vitest/no-mocks-import: [0]
|
||||||
"@vitest/no-restricted-matchers": [0]
|
vitest/no-restricted-matchers: [0]
|
||||||
"@vitest/no-restricted-vi-methods": [0]
|
vitest/no-restricted-vi-methods: [0]
|
||||||
"@vitest/no-standalone-expect": [0]
|
vitest/no-standalone-expect: [0]
|
||||||
"@vitest/no-test-prefixes": [0]
|
vitest/no-test-prefixes: [0]
|
||||||
"@vitest/no-test-return-statement": [0]
|
vitest/no-test-return-statement: [0]
|
||||||
"@vitest/prefer-called-with": [0]
|
vitest/prefer-called-with: [0]
|
||||||
"@vitest/prefer-comparison-matcher": [0]
|
vitest/prefer-comparison-matcher: [0]
|
||||||
"@vitest/prefer-each": [0]
|
vitest/prefer-each: [0]
|
||||||
"@vitest/prefer-equality-matcher": [0]
|
vitest/prefer-equality-matcher: [0]
|
||||||
"@vitest/prefer-expect-resolves": [0]
|
vitest/prefer-expect-resolves: [0]
|
||||||
"@vitest/prefer-hooks-in-order": [0]
|
vitest/prefer-hooks-in-order: [0]
|
||||||
"@vitest/prefer-hooks-on-top": [2]
|
vitest/prefer-hooks-on-top: [2]
|
||||||
"@vitest/prefer-lowercase-title": [0]
|
vitest/prefer-lowercase-title: [0]
|
||||||
"@vitest/prefer-mock-promise-shorthand": [0]
|
vitest/prefer-mock-promise-shorthand: [0]
|
||||||
"@vitest/prefer-snapshot-hint": [0]
|
vitest/prefer-snapshot-hint: [0]
|
||||||
"@vitest/prefer-spy-on": [0]
|
vitest/prefer-spy-on: [0]
|
||||||
"@vitest/prefer-strict-equal": [0]
|
vitest/prefer-strict-equal: [0]
|
||||||
"@vitest/prefer-to-be": [0]
|
vitest/prefer-to-be: [0]
|
||||||
"@vitest/prefer-to-be-falsy": [0]
|
vitest/prefer-to-be-falsy: [0]
|
||||||
"@vitest/prefer-to-be-object": [0]
|
vitest/prefer-to-be-object: [0]
|
||||||
"@vitest/prefer-to-be-truthy": [0]
|
vitest/prefer-to-be-truthy: [0]
|
||||||
"@vitest/prefer-to-contain": [0]
|
vitest/prefer-to-contain: [0]
|
||||||
"@vitest/prefer-to-have-length": [0]
|
vitest/prefer-to-have-length: [0]
|
||||||
"@vitest/prefer-todo": [0]
|
vitest/prefer-todo: [0]
|
||||||
"@vitest/require-hook": [0]
|
vitest/require-hook: [0]
|
||||||
"@vitest/require-to-throw-message": [0]
|
vitest/require-to-throw-message: [0]
|
||||||
"@vitest/require-top-level-describe": [0]
|
vitest/require-top-level-describe: [0]
|
||||||
"@vitest/valid-describe-callback": [2]
|
vitest/valid-describe-callback: [2]
|
||||||
"@vitest/valid-expect": [2]
|
vitest/valid-expect: [2]
|
||||||
"@vitest/valid-title": [2]
|
vitest/valid-title: [2]
|
||||||
- files: ["web_src/js/modules/fetch.js", "web_src/js/standalone/**/*"]
|
- files: ["web_src/js/modules/fetch.js", "web_src/js/standalone/**/*"]
|
||||||
rules:
|
rules:
|
||||||
no-restricted-syntax: [2, WithStatement, ForInStatement, LabeledStatement, SequenceExpression]
|
no-restricted-syntax: [2, WithStatement, ForInStatement, LabeledStatement, SequenceExpression]
|
||||||
|
@ -120,7 +122,7 @@ rules:
|
||||||
"@stylistic/js/arrow-spacing": [2, {before: true, after: true}]
|
"@stylistic/js/arrow-spacing": [2, {before: true, after: true}]
|
||||||
"@stylistic/js/block-spacing": [0]
|
"@stylistic/js/block-spacing": [0]
|
||||||
"@stylistic/js/brace-style": [2, 1tbs, {allowSingleLine: true}]
|
"@stylistic/js/brace-style": [2, 1tbs, {allowSingleLine: true}]
|
||||||
"@stylistic/js/comma-dangle": [2, always-multiline]
|
"@stylistic/js/comma-dangle": [2, only-multiline]
|
||||||
"@stylistic/js/comma-spacing": [2, {before: false, after: true}]
|
"@stylistic/js/comma-spacing": [2, {before: false, after: true}]
|
||||||
"@stylistic/js/comma-style": [2, last]
|
"@stylistic/js/comma-style": [2, last]
|
||||||
"@stylistic/js/computed-property-spacing": [2, never]
|
"@stylistic/js/computed-property-spacing": [2, never]
|
||||||
|
@ -168,7 +170,7 @@ rules:
|
||||||
"@stylistic/js/semi-spacing": [2, {before: false, after: true}]
|
"@stylistic/js/semi-spacing": [2, {before: false, after: true}]
|
||||||
"@stylistic/js/semi-style": [2, last]
|
"@stylistic/js/semi-style": [2, last]
|
||||||
"@stylistic/js/space-before-blocks": [2, always]
|
"@stylistic/js/space-before-blocks": [2, always]
|
||||||
"@stylistic/js/space-before-function-paren": [2, {anonymous: ignore, named: never, asyncArrow: always}]
|
"@stylistic/js/space-before-function-paren": [0]
|
||||||
"@stylistic/js/space-in-parens": [2, never]
|
"@stylistic/js/space-in-parens": [2, never]
|
||||||
"@stylistic/js/space-infix-ops": [2]
|
"@stylistic/js/space-infix-ops": [2]
|
||||||
"@stylistic/js/space-unary-ops": [2]
|
"@stylistic/js/space-unary-ops": [2]
|
||||||
|
@ -207,29 +209,6 @@ rules:
|
||||||
func-names: [0]
|
func-names: [0]
|
||||||
func-style: [0]
|
func-style: [0]
|
||||||
getter-return: [2]
|
getter-return: [2]
|
||||||
github/a11y-aria-label-is-well-formatted: [0]
|
|
||||||
github/a11y-no-title-attribute: [0]
|
|
||||||
github/a11y-no-visually-hidden-interactive-element: [0]
|
|
||||||
github/a11y-role-supports-aria-props: [0]
|
|
||||||
github/a11y-svg-has-accessible-name: [0]
|
|
||||||
github/array-foreach: [0]
|
|
||||||
github/async-currenttarget: [2]
|
|
||||||
github/async-preventdefault: [2]
|
|
||||||
github/authenticity-token: [0]
|
|
||||||
github/get-attribute: [0]
|
|
||||||
github/js-class-name: [0]
|
|
||||||
github/no-blur: [0]
|
|
||||||
github/no-d-none: [0]
|
|
||||||
github/no-dataset: [2]
|
|
||||||
github/no-dynamic-script-tag: [2]
|
|
||||||
github/no-implicit-buggy-globals: [2]
|
|
||||||
github/no-inner-html: [0]
|
|
||||||
github/no-innerText: [2]
|
|
||||||
github/no-then: [2]
|
|
||||||
github/no-useless-passive: [2]
|
|
||||||
github/prefer-observers: [2]
|
|
||||||
github/require-passive-events: [2]
|
|
||||||
github/unescaped-html-literal: [0]
|
|
||||||
grouped-accessor-pairs: [2]
|
grouped-accessor-pairs: [2]
|
||||||
guard-for-in: [0]
|
guard-for-in: [0]
|
||||||
id-blacklist: [0]
|
id-blacklist: [0]
|
||||||
|
@ -279,6 +258,55 @@ rules:
|
||||||
i/prefer-default-export: [0]
|
i/prefer-default-export: [0]
|
||||||
i/unambiguous: [0]
|
i/unambiguous: [0]
|
||||||
init-declarations: [0]
|
init-declarations: [0]
|
||||||
|
jquery/no-ajax-events: [2]
|
||||||
|
jquery/no-ajax: [0]
|
||||||
|
jquery/no-animate: [2]
|
||||||
|
jquery/no-attr: [0]
|
||||||
|
jquery/no-bind: [2]
|
||||||
|
jquery/no-class: [0]
|
||||||
|
jquery/no-clone: [2]
|
||||||
|
jquery/no-closest: [0]
|
||||||
|
jquery/no-css: [0]
|
||||||
|
jquery/no-data: [0]
|
||||||
|
jquery/no-deferred: [2]
|
||||||
|
jquery/no-delegate: [2]
|
||||||
|
jquery/no-each: [0]
|
||||||
|
jquery/no-extend: [2]
|
||||||
|
jquery/no-fade: [0]
|
||||||
|
jquery/no-filter: [0]
|
||||||
|
jquery/no-find: [0]
|
||||||
|
jquery/no-global-eval: [2]
|
||||||
|
jquery/no-grep: [2]
|
||||||
|
jquery/no-has: [2]
|
||||||
|
jquery/no-hide: [2]
|
||||||
|
jquery/no-html: [0]
|
||||||
|
jquery/no-in-array: [2]
|
||||||
|
jquery/no-is-array: [2]
|
||||||
|
jquery/no-is-function: [2]
|
||||||
|
jquery/no-is: [0]
|
||||||
|
jquery/no-load: [2]
|
||||||
|
jquery/no-map: [0]
|
||||||
|
jquery/no-merge: [2]
|
||||||
|
jquery/no-param: [2]
|
||||||
|
jquery/no-parent: [0]
|
||||||
|
jquery/no-parents: [0]
|
||||||
|
jquery/no-parse-html: [2]
|
||||||
|
jquery/no-prop: [0]
|
||||||
|
jquery/no-proxy: [2]
|
||||||
|
jquery/no-ready: [2]
|
||||||
|
jquery/no-serialize: [2]
|
||||||
|
jquery/no-show: [2]
|
||||||
|
jquery/no-size: [2]
|
||||||
|
jquery/no-sizzle: [0]
|
||||||
|
jquery/no-slide: [0]
|
||||||
|
jquery/no-submit: [0]
|
||||||
|
jquery/no-text: [0]
|
||||||
|
jquery/no-toggle: [2]
|
||||||
|
jquery/no-trigger: [0]
|
||||||
|
jquery/no-trim: [2]
|
||||||
|
jquery/no-val: [0]
|
||||||
|
jquery/no-when: [2]
|
||||||
|
jquery/no-wrap: [2]
|
||||||
line-comment-position: [0]
|
line-comment-position: [0]
|
||||||
logical-assignment-operators: [0]
|
logical-assignment-operators: [0]
|
||||||
max-classes-per-file: [0]
|
max-classes-per-file: [0]
|
||||||
|
@ -344,24 +372,24 @@ rules:
|
||||||
no-irregular-whitespace: [2]
|
no-irregular-whitespace: [2]
|
||||||
no-iterator: [2]
|
no-iterator: [2]
|
||||||
no-jquery/no-ajax-events: [2]
|
no-jquery/no-ajax-events: [2]
|
||||||
no-jquery/no-ajax: [2]
|
no-jquery/no-ajax: [0]
|
||||||
no-jquery/no-and-self: [2]
|
no-jquery/no-and-self: [2]
|
||||||
no-jquery/no-animate-toggle: [2]
|
no-jquery/no-animate-toggle: [2]
|
||||||
no-jquery/no-animate: [2]
|
no-jquery/no-animate: [2]
|
||||||
no-jquery/no-append-html: [2]
|
no-jquery/no-append-html: [0]
|
||||||
no-jquery/no-attr: [2]
|
no-jquery/no-attr: [0]
|
||||||
no-jquery/no-bind: [2]
|
no-jquery/no-bind: [2]
|
||||||
no-jquery/no-box-model: [2]
|
no-jquery/no-box-model: [2]
|
||||||
no-jquery/no-browser: [2]
|
no-jquery/no-browser: [2]
|
||||||
no-jquery/no-camel-case: [2]
|
no-jquery/no-camel-case: [2]
|
||||||
no-jquery/no-class-state: [2]
|
no-jquery/no-class-state: [0]
|
||||||
no-jquery/no-class: [0]
|
no-jquery/no-class: [0]
|
||||||
no-jquery/no-clone: [2]
|
no-jquery/no-clone: [2]
|
||||||
no-jquery/no-closest: [0]
|
no-jquery/no-closest: [0]
|
||||||
no-jquery/no-constructor-attributes: [2]
|
no-jquery/no-constructor-attributes: [2]
|
||||||
no-jquery/no-contains: [2]
|
no-jquery/no-contains: [2]
|
||||||
no-jquery/no-context-prop: [2]
|
no-jquery/no-context-prop: [2]
|
||||||
no-jquery/no-css: [2]
|
no-jquery/no-css: [0]
|
||||||
no-jquery/no-data: [0]
|
no-jquery/no-data: [0]
|
||||||
no-jquery/no-deferred: [2]
|
no-jquery/no-deferred: [2]
|
||||||
no-jquery/no-delegate: [2]
|
no-jquery/no-delegate: [2]
|
||||||
|
@ -392,14 +420,14 @@ rules:
|
||||||
no-jquery/no-is-numeric: [2]
|
no-jquery/no-is-numeric: [2]
|
||||||
no-jquery/no-is-plain-object: [2]
|
no-jquery/no-is-plain-object: [2]
|
||||||
no-jquery/no-is-window: [2]
|
no-jquery/no-is-window: [2]
|
||||||
no-jquery/no-is: [2]
|
no-jquery/no-is: [0]
|
||||||
no-jquery/no-jquery-constructor: [0]
|
no-jquery/no-jquery-constructor: [0]
|
||||||
no-jquery/no-live: [2]
|
no-jquery/no-live: [2]
|
||||||
no-jquery/no-load-shorthand: [2]
|
no-jquery/no-load-shorthand: [2]
|
||||||
no-jquery/no-load: [2]
|
no-jquery/no-load: [2]
|
||||||
no-jquery/no-map-collection: [0]
|
no-jquery/no-map-collection: [0]
|
||||||
no-jquery/no-map-util: [2]
|
no-jquery/no-map-util: [2]
|
||||||
no-jquery/no-map: [2]
|
no-jquery/no-map: [0]
|
||||||
no-jquery/no-merge: [2]
|
no-jquery/no-merge: [2]
|
||||||
no-jquery/no-node-name: [2]
|
no-jquery/no-node-name: [2]
|
||||||
no-jquery/no-noop: [2]
|
no-jquery/no-noop: [2]
|
||||||
|
@ -409,12 +437,12 @@ rules:
|
||||||
no-jquery/no-other-utils: [2]
|
no-jquery/no-other-utils: [2]
|
||||||
no-jquery/no-param: [2]
|
no-jquery/no-param: [2]
|
||||||
no-jquery/no-parent: [0]
|
no-jquery/no-parent: [0]
|
||||||
no-jquery/no-parents: [2]
|
no-jquery/no-parents: [0]
|
||||||
no-jquery/no-parse-html-literal: [2]
|
no-jquery/no-parse-html-literal: [0]
|
||||||
no-jquery/no-parse-html: [2]
|
no-jquery/no-parse-html: [2]
|
||||||
no-jquery/no-parse-json: [2]
|
no-jquery/no-parse-json: [2]
|
||||||
no-jquery/no-parse-xml: [2]
|
no-jquery/no-parse-xml: [2]
|
||||||
no-jquery/no-prop: [2]
|
no-jquery/no-prop: [0]
|
||||||
no-jquery/no-proxy: [2]
|
no-jquery/no-proxy: [2]
|
||||||
no-jquery/no-ready-shorthand: [2]
|
no-jquery/no-ready-shorthand: [2]
|
||||||
no-jquery/no-ready: [2]
|
no-jquery/no-ready: [2]
|
||||||
|
@ -435,7 +463,7 @@ rules:
|
||||||
no-jquery/no-visibility: [2]
|
no-jquery/no-visibility: [2]
|
||||||
no-jquery/no-when: [2]
|
no-jquery/no-when: [2]
|
||||||
no-jquery/no-wrap: [2]
|
no-jquery/no-wrap: [2]
|
||||||
no-jquery/variable-pattern: [2]
|
no-jquery/variable-pattern: [0]
|
||||||
no-label-var: [2]
|
no-label-var: [2]
|
||||||
no-labels: [0] # handled by no-restricted-syntax
|
no-labels: [0] # handled by no-restricted-syntax
|
||||||
no-lone-blocks: [2]
|
no-lone-blocks: [2]
|
||||||
|
@ -488,7 +516,7 @@ rules:
|
||||||
no-underscore-dangle: [0]
|
no-underscore-dangle: [0]
|
||||||
no-unexpected-multiline: [2]
|
no-unexpected-multiline: [2]
|
||||||
no-unmodified-loop-condition: [2]
|
no-unmodified-loop-condition: [2]
|
||||||
no-unneeded-ternary: [2]
|
no-unneeded-ternary: [0]
|
||||||
no-unreachable-loop: [2]
|
no-unreachable-loop: [2]
|
||||||
no-unreachable: [2]
|
no-unreachable: [2]
|
||||||
no-unsafe-finally: [2]
|
no-unsafe-finally: [2]
|
||||||
|
@ -530,6 +558,7 @@ rules:
|
||||||
prefer-rest-params: [2]
|
prefer-rest-params: [2]
|
||||||
prefer-spread: [2]
|
prefer-spread: [2]
|
||||||
prefer-template: [2]
|
prefer-template: [2]
|
||||||
|
quotes: [2, single, {avoidEscape: true, allowTemplateLiterals: true}]
|
||||||
radix: [2, as-needed]
|
radix: [2, as-needed]
|
||||||
regexp/confusing-quantifier: [2]
|
regexp/confusing-quantifier: [2]
|
||||||
regexp/control-character-escape: [2]
|
regexp/control-character-escape: [2]
|
||||||
|
@ -655,7 +684,6 @@ rules:
|
||||||
unicorn/better-regex: [0]
|
unicorn/better-regex: [0]
|
||||||
unicorn/catch-error-name: [0]
|
unicorn/catch-error-name: [0]
|
||||||
unicorn/consistent-destructuring: [2]
|
unicorn/consistent-destructuring: [2]
|
||||||
unicorn/consistent-empty-array-spread: [2]
|
|
||||||
unicorn/consistent-function-scoping: [2]
|
unicorn/consistent-function-scoping: [2]
|
||||||
unicorn/custom-error-definition: [0]
|
unicorn/custom-error-definition: [0]
|
||||||
unicorn/empty-brace-spaces: [2]
|
unicorn/empty-brace-spaces: [2]
|
||||||
|
@ -668,41 +696,33 @@ rules:
|
||||||
unicorn/import-style: [0]
|
unicorn/import-style: [0]
|
||||||
unicorn/new-for-builtins: [2]
|
unicorn/new-for-builtins: [2]
|
||||||
unicorn/no-abusive-eslint-disable: [0]
|
unicorn/no-abusive-eslint-disable: [0]
|
||||||
unicorn/no-anonymous-default-export: [0]
|
|
||||||
unicorn/no-array-callback-reference: [0]
|
unicorn/no-array-callback-reference: [0]
|
||||||
unicorn/no-array-for-each: [2]
|
unicorn/no-array-for-each: [2]
|
||||||
unicorn/no-array-method-this-argument: [2]
|
unicorn/no-array-method-this-argument: [2]
|
||||||
unicorn/no-array-push-push: [2]
|
unicorn/no-array-push-push: [2]
|
||||||
unicorn/no-array-reduce: [2]
|
unicorn/no-array-reduce: [2]
|
||||||
unicorn/no-await-expression-member: [0]
|
unicorn/no-await-expression-member: [0]
|
||||||
unicorn/no-await-in-promise-methods: [2]
|
|
||||||
unicorn/no-console-spaces: [0]
|
unicorn/no-console-spaces: [0]
|
||||||
unicorn/no-document-cookie: [2]
|
unicorn/no-document-cookie: [2]
|
||||||
unicorn/no-empty-file: [2]
|
unicorn/no-empty-file: [2]
|
||||||
unicorn/no-for-loop: [0]
|
unicorn/no-for-loop: [0]
|
||||||
unicorn/no-hex-escape: [0]
|
unicorn/no-hex-escape: [0]
|
||||||
unicorn/no-instanceof-array: [0]
|
unicorn/no-instanceof-array: [0]
|
||||||
unicorn/no-invalid-fetch-options: [2]
|
|
||||||
unicorn/no-invalid-remove-event-listener: [2]
|
unicorn/no-invalid-remove-event-listener: [2]
|
||||||
unicorn/no-keyword-prefix: [0]
|
unicorn/no-keyword-prefix: [0]
|
||||||
unicorn/no-length-as-slice-end: [2]
|
|
||||||
unicorn/no-lonely-if: [2]
|
unicorn/no-lonely-if: [2]
|
||||||
unicorn/no-magic-array-flat-depth: [0]
|
|
||||||
unicorn/no-negated-condition: [0]
|
unicorn/no-negated-condition: [0]
|
||||||
unicorn/no-negation-in-equality-check: [2]
|
|
||||||
unicorn/no-nested-ternary: [0]
|
unicorn/no-nested-ternary: [0]
|
||||||
unicorn/no-new-array: [0]
|
unicorn/no-new-array: [0]
|
||||||
unicorn/no-new-buffer: [0]
|
unicorn/no-new-buffer: [0]
|
||||||
unicorn/no-null: [0]
|
unicorn/no-null: [0]
|
||||||
unicorn/no-object-as-default-parameter: [0]
|
unicorn/no-object-as-default-parameter: [0]
|
||||||
unicorn/no-process-exit: [0]
|
unicorn/no-process-exit: [0]
|
||||||
unicorn/no-single-promise-in-promise-methods: [2]
|
|
||||||
unicorn/no-static-only-class: [2]
|
unicorn/no-static-only-class: [2]
|
||||||
unicorn/no-thenable: [2]
|
unicorn/no-thenable: [2]
|
||||||
unicorn/no-this-assignment: [2]
|
unicorn/no-this-assignment: [2]
|
||||||
unicorn/no-typeof-undefined: [2]
|
unicorn/no-typeof-undefined: [2]
|
||||||
unicorn/no-unnecessary-await: [2]
|
unicorn/no-unnecessary-await: [2]
|
||||||
unicorn/no-unnecessary-polyfills: [2]
|
|
||||||
unicorn/no-unreadable-array-destructuring: [0]
|
unicorn/no-unreadable-array-destructuring: [0]
|
||||||
unicorn/no-unreadable-iife: [2]
|
unicorn/no-unreadable-iife: [2]
|
||||||
unicorn/no-unused-properties: [2]
|
unicorn/no-unused-properties: [2]
|
||||||
|
@ -754,12 +774,10 @@ rules:
|
||||||
unicorn/prefer-set-has: [0]
|
unicorn/prefer-set-has: [0]
|
||||||
unicorn/prefer-set-size: [2]
|
unicorn/prefer-set-size: [2]
|
||||||
unicorn/prefer-spread: [0]
|
unicorn/prefer-spread: [0]
|
||||||
unicorn/prefer-string-raw: [0]
|
|
||||||
unicorn/prefer-string-replace-all: [0]
|
unicorn/prefer-string-replace-all: [0]
|
||||||
unicorn/prefer-string-slice: [0]
|
unicorn/prefer-string-slice: [0]
|
||||||
unicorn/prefer-string-starts-ends-with: [2]
|
unicorn/prefer-string-starts-ends-with: [2]
|
||||||
unicorn/prefer-string-trim-start-end: [2]
|
unicorn/prefer-string-trim-start-end: [2]
|
||||||
unicorn/prefer-structured-clone: [2]
|
|
||||||
unicorn/prefer-switch: [0]
|
unicorn/prefer-switch: [0]
|
||||||
unicorn/prefer-ternary: [0]
|
unicorn/prefer-ternary: [0]
|
||||||
unicorn/prefer-text-content: [2]
|
unicorn/prefer-text-content: [2]
|
||||||
|
@ -792,7 +810,7 @@ rules:
|
||||||
wc/no-constructor-params: [2]
|
wc/no-constructor-params: [2]
|
||||||
wc/no-constructor: [2]
|
wc/no-constructor: [2]
|
||||||
wc/no-customized-built-in-elements: [2]
|
wc/no-customized-built-in-elements: [2]
|
||||||
wc/no-exports-with-element: [0]
|
wc/no-exports-with-element: [2]
|
||||||
wc/no-invalid-element-name: [2]
|
wc/no-invalid-element-name: [2]
|
||||||
wc/no-invalid-extends: [2]
|
wc/no-invalid-extends: [2]
|
||||||
wc/no-method-prefixed-with-on: [2]
|
wc/no-method-prefixed-with-on: [2]
|
||||||
|
|
|
@ -5,30 +5,17 @@ set -ex
|
||||||
end_to_end=$1
|
end_to_end=$1
|
||||||
end_to_end_pr=$2
|
end_to_end_pr=$2
|
||||||
forgejo=$3
|
forgejo=$3
|
||||||
forgejo_pr_or_ref=$4
|
forgejo_pr=$4
|
||||||
|
|
||||||
cd $forgejo
|
|
||||||
full_version=$(make show-version-full)
|
|
||||||
minor_version=$(make show-version-minor)
|
|
||||||
|
|
||||||
|
head_url=$(jq --raw-output .head.repo.html_url < $forgejo_pr)
|
||||||
|
test "$head_url" != null
|
||||||
|
branch=$(jq --raw-output .head.ref < $forgejo_pr)
|
||||||
|
test "$branch" != null
|
||||||
cd $end_to_end
|
cd $end_to_end
|
||||||
|
echo $head_url $branch 7.0.0+0-gitea-1.22.0 > forgejo/sources/1.22
|
||||||
|
date > last-upgrade
|
||||||
|
|
||||||
if ! test -f forgejo/sources/$minor_version; then
|
base_url=$(jq --raw-output .base.repo.html_url < $forgejo_pr)
|
||||||
echo "FAIL: forgejo/sources/$minor_version does not exist in the end-to-end repository"
|
test "$base_url" != null
|
||||||
false
|
test "$GITHUB_RUN_NUMBER"
|
||||||
fi
|
echo $base_url/actions/runs/$GITHUB_RUN_NUMBER/artifacts/forgejo > forgejo/binary-url
|
||||||
|
|
||||||
echo -n $minor_version >forgejo/build-from-sources
|
|
||||||
date >last-upgrade
|
|
||||||
|
|
||||||
if test -f "$forgejo_pr_or_ref"; then
|
|
||||||
forgejo_pr=$forgejo_pr_or_ref
|
|
||||||
head_url=$(jq --raw-output .head.repo.html_url <$forgejo_pr)
|
|
||||||
test "$head_url" != null
|
|
||||||
branch=$(jq --raw-output .head.ref <$forgejo_pr)
|
|
||||||
test "$branch" != null
|
|
||||||
echo $head_url $branch $full_version >forgejo/sources/$minor_version
|
|
||||||
else
|
|
||||||
forgejo_ref=$forgejo_pr_or_ref
|
|
||||||
echo $GITHUB_SERVER_URL/$GITHUB_REPOSITORY ${forgejo_ref#refs/heads/} $full_version >forgejo/sources/$minor_version
|
|
||||||
fi
|
|
||||||
|
|
|
@ -8,15 +8,5 @@ forgejo=$3
|
||||||
forgejo_ref=$4
|
forgejo_ref=$4
|
||||||
|
|
||||||
cd $end_to_end
|
cd $end_to_end
|
||||||
date >last-upgrade
|
date > last-upgrade
|
||||||
organizations=lib/ORGANIZATIONS
|
echo $FORGEJO_BINARY > forgejo/binary-url
|
||||||
if ! test -f $organizations; then
|
|
||||||
echo "$organizations file not found"
|
|
||||||
false
|
|
||||||
fi
|
|
||||||
#
|
|
||||||
# Inverse the order of lookup because the goal in the release built
|
|
||||||
# pipeline is to test the latest build, if available, instead of the
|
|
||||||
# stable version by the same version.
|
|
||||||
#
|
|
||||||
echo forgejo-integration forgejo-experimental forgejo >$organizations
|
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
---
|
|
||||||
|
|
||||||
name: "Pull Request Template"
|
|
||||||
about: "Template for all Pull Requests"
|
|
||||||
labels:
|
|
||||||
|
|
||||||
- test/needed
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Checklist
|
|
||||||
|
|
||||||
The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).
|
|
||||||
|
|
||||||
### Tests
|
|
||||||
|
|
||||||
- I added test coverage for Go changes...
|
|
||||||
- [ ] in their respective `*_test.go` for unit tests.
|
|
||||||
- [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
|
|
||||||
- I added test coverage for JavaScript changes...
|
|
||||||
- [ ] in `web_src/js/*.test.js` if it can be unit tested.
|
|
||||||
- [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).
|
|
||||||
|
|
||||||
### Documentation
|
|
||||||
|
|
||||||
- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
|
|
||||||
- [ ] I did not document these changes and I do not expect someone else to do it.
|
|
||||||
|
|
||||||
### Release notes
|
|
||||||
|
|
||||||
- [ ] I do not want this change to show in the release notes.
|
|
||||||
- [ ] I want the title to show in the release notes with a link to this pull request.
|
|
||||||
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.
|
|
7
.forgejo/testdata/build-release/Dockerfile
vendored
7
.forgejo/testdata/build-release/Dockerfile
vendored
|
@ -1,6 +1,3 @@
|
||||||
FROM code.forgejo.org/oci/alpine:3.20
|
FROM public.ecr.aws/docker/library/alpine:3.18
|
||||||
ARG RELEASE_VERSION=unkown
|
|
||||||
LABEL maintainer="contact@forgejo.org" \
|
|
||||||
org.opencontainers.image.version="${RELEASE_VERSION}"
|
|
||||||
RUN mkdir -p /app/gitea
|
RUN mkdir -p /app/gitea
|
||||||
RUN ( echo '#!/bin/sh' ; echo "echo forgejo v$RELEASE_VERSION" ) > /app/gitea/forgejo-cli ; chmod +x /app/gitea/forgejo-cli
|
RUN ( echo '#!/bin/sh' ; echo "echo forgejo v1.2.3" ) > /app/gitea/gitea ; chmod +x /app/gitea/gitea
|
||||||
|
|
3
.forgejo/testdata/build-release/go.mod
vendored
3
.forgejo/testdata/build-release/go.mod
vendored
|
@ -1,3 +0,0 @@
|
||||||
module code.gitea.io/gitea
|
|
||||||
|
|
||||||
go 1.23.1
|
|
|
@ -1,29 +0,0 @@
|
||||||
inputs:
|
|
||||||
packages:
|
|
||||||
description: 'Packages to install'
|
|
||||||
required: true
|
|
||||||
release:
|
|
||||||
description: 'Release to install from'
|
|
||||||
default: testing
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: "composite"
|
|
||||||
steps:
|
|
||||||
- name: setup apt package source
|
|
||||||
run: |
|
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
|
||||||
echo "deb http://deb.debian.org/debian/ ${RELEASE} main" > "/etc/apt/sources.list.d/${RELEASE}.list"
|
|
||||||
env:
|
|
||||||
RELEASE: ${{inputs.release}}
|
|
||||||
- name: install packages
|
|
||||||
run: |
|
|
||||||
apt-get update -qq
|
|
||||||
apt-get -q install -qq -y ${PACKAGES}
|
|
||||||
env:
|
|
||||||
PACKAGES: ${{inputs.packages}}
|
|
||||||
- name: remove temporary package list to prevent using it in other steps
|
|
||||||
run: |
|
|
||||||
rm "/etc/apt/sources.list.d/${RELEASE}.list"
|
|
||||||
apt-get update -qq
|
|
||||||
env:
|
|
||||||
RELEASE: ${{inputs.release}}
|
|
|
@ -1,15 +0,0 @@
|
||||||
runs:
|
|
||||||
using: "composite"
|
|
||||||
steps:
|
|
||||||
- run: |
|
|
||||||
su forgejo -c 'make deps-backend'
|
|
||||||
- uses: actions/cache@v4
|
|
||||||
id: cache-backend
|
|
||||||
with:
|
|
||||||
path: ${{github.workspace}}/gitea
|
|
||||||
key: backend-build-${{ github.sha }}
|
|
||||||
- if: steps.cache-backend.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
su forgejo -c 'make backend'
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
|
@ -1,12 +0,0 @@
|
||||||
runs:
|
|
||||||
using: "composite"
|
|
||||||
steps:
|
|
||||||
- name: setup user and permissions
|
|
||||||
run: |
|
|
||||||
git config --add safe.directory '*'
|
|
||||||
# ignore if the user already exists (like with the playwright image)
|
|
||||||
adduser --quiet --comment forgejo --disabled-password forgejo || true
|
|
||||||
chown -R forgejo:forgejo .
|
|
||||||
- uses: https://codeberg.org/fnetx/setup-cache-go@b2214eaf6fb44c7e8512c0f462a2c3ec31f86a73
|
|
||||||
with:
|
|
||||||
username: forgejo
|
|
|
@ -1,59 +0,0 @@
|
||||||
# Copyright 2024 The Forgejo Authors
|
|
||||||
# SPDX-License-Identifier: MIT
|
|
||||||
#
|
|
||||||
# To modify this workflow:
|
|
||||||
#
|
|
||||||
# - change pull_request_target: to pull_request:
|
|
||||||
# so that it runs from a pull request instead of the default branch
|
|
||||||
#
|
|
||||||
# - push it to the wip-ci-backport branch on the forgejo repository
|
|
||||||
# otherwise it will not have access to the secrets required to push
|
|
||||||
# the PR
|
|
||||||
#
|
|
||||||
# - open a pull request targetting wip-ci-backport that includes a change
|
|
||||||
# that can be backported without conflict in v1.21 and set the
|
|
||||||
# `backport/v1.21` label.
|
|
||||||
#
|
|
||||||
# - once it works, open a pull request for the sake of keeping track
|
|
||||||
# of the change even if the PR won't run it because it will use
|
|
||||||
# whatever is in the default branch instead
|
|
||||||
#
|
|
||||||
# - after it is merged, double check it works by setting a
|
|
||||||
# `backport/v1.21` label on a merged pull request that can be backported
|
|
||||||
# without conflict.
|
|
||||||
#
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
types:
|
|
||||||
- closed
|
|
||||||
- labeled
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
backporting:
|
|
||||||
if: >
|
|
||||||
!startsWith(vars.ROLE, 'forgejo-') && (
|
|
||||||
github.event.pull_request.merged
|
|
||||||
&&
|
|
||||||
contains(toJSON(github.event.pull_request.labels), 'backport/v')
|
|
||||||
)
|
|
||||||
runs-on: docker
|
|
||||||
container:
|
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
|
||||||
steps:
|
|
||||||
- name: event info
|
|
||||||
run: |
|
|
||||||
cat <<'EOF'
|
|
||||||
${{ toJSON(github) }}
|
|
||||||
EOF
|
|
||||||
- uses: https://code.forgejo.org/actions/git-backporting@v4.8.2
|
|
||||||
with:
|
|
||||||
target-branch-pattern: "^backport/(?<target>(v.*))$"
|
|
||||||
strategy: ort
|
|
||||||
strategy-option: find-renames
|
|
||||||
cherry-pick-options: -x
|
|
||||||
auth: ${{ secrets.BACKPORT_TOKEN }}
|
|
||||||
pull-request: ${{ github.event.pull_request.url }}
|
|
||||||
auto-no-squash: true
|
|
||||||
enable-err-notification: true
|
|
||||||
git-user: forgejo-backport-action
|
|
||||||
git-email: forgejo-backport-action@noreply.codeberg.org
|
|
|
@ -9,8 +9,6 @@ on:
|
||||||
- docker/**
|
- docker/**
|
||||||
- .forgejo/workflows/build-release.yml
|
- .forgejo/workflows/build-release.yml
|
||||||
- .forgejo/workflows/build-release-integration.yml
|
- .forgejo/workflows/build-release-integration.yml
|
||||||
branches-ignore:
|
|
||||||
- renovate/**
|
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- Makefile
|
- Makefile
|
||||||
|
@ -25,7 +23,7 @@ jobs:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
runs-on: self-hosted
|
runs-on: self-hosted
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- id: forgejo
|
- id: forgejo
|
||||||
uses: https://code.forgejo.org/actions/setup-forgejo@v1
|
uses: https://code.forgejo.org/actions/setup-forgejo@v1
|
||||||
|
@ -36,10 +34,10 @@ jobs:
|
||||||
lxc-ip-prefix: 10.0.9
|
lxc-ip-prefix: 10.0.9
|
||||||
|
|
||||||
- name: publish the forgejo release
|
- name: publish the forgejo release
|
||||||
shell: bash
|
|
||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
|
|
||||||
|
version=1.2.3
|
||||||
cat > /etc/docker/daemon.json <<EOF
|
cat > /etc/docker/daemon.json <<EOF
|
||||||
{
|
{
|
||||||
"insecure-registries" : ["${{ steps.forgejo.outputs.host-port }}"]
|
"insecure-registries" : ["${{ steps.forgejo.outputs.host-port }}"]
|
||||||
|
@ -55,37 +53,6 @@ jobs:
|
||||||
url=http://root:admin1234@${{ steps.forgejo.outputs.host-port }}
|
url=http://root:admin1234@${{ steps.forgejo.outputs.host-port }}
|
||||||
export FORGEJO_RUNNER_LOGS="${{ steps.forgejo.outputs.runner-logs }}"
|
export FORGEJO_RUNNER_LOGS="${{ steps.forgejo.outputs.runner-logs }}"
|
||||||
|
|
||||||
function sanity_check() {
|
|
||||||
local url=$1 version=$2
|
|
||||||
#
|
|
||||||
# Minimal sanity checks. Since the binary
|
|
||||||
# is a script shell it does not test the sanity of the cross
|
|
||||||
# build, only the sanity of the naming of the binaries.
|
|
||||||
#
|
|
||||||
for arch in amd64 arm64 arm-6 ; do
|
|
||||||
local binary=forgejo-$version-linux-$arch
|
|
||||||
for suffix in '' '.xz' ; do
|
|
||||||
curl --fail -L -sS $url/root/forgejo/releases/download/v$version/$binary$suffix > $binary$suffix
|
|
||||||
if test "$suffix" = .xz ; then
|
|
||||||
unxz --keep $binary$suffix
|
|
||||||
fi
|
|
||||||
chmod +x $binary
|
|
||||||
./$binary --version | grep $version
|
|
||||||
curl --fail -L -sS $url/root/forgejo/releases/download/v$version/$binary$suffix.sha256 > $binary$suffix.sha256
|
|
||||||
shasum -a 256 --check $binary$suffix.sha256
|
|
||||||
rm $binary$suffix
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
local sources=forgejo-src-$version.tar.gz
|
|
||||||
curl --fail -L -sS $url/root/forgejo/releases/download/v$version/$sources > $sources
|
|
||||||
curl --fail -L -sS $url/root/forgejo/releases/download/v$version/$sources.sha256 > $sources.sha256
|
|
||||||
shasum -a 256 --check $sources.sha256
|
|
||||||
|
|
||||||
docker pull ${{ steps.forgejo.outputs.host-port }}/root/forgejo:$version
|
|
||||||
docker pull ${{ steps.forgejo.outputs.host-port }}/root/forgejo:$version-rootless
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Create a new project with a fake forgejo and the release workflow only
|
# Create a new project with a fake forgejo and the release workflow only
|
||||||
#
|
#
|
||||||
|
@ -95,41 +62,46 @@ jobs:
|
||||||
cp $dir/Dockerfile $dir/Dockerfile.rootless
|
cp $dir/Dockerfile $dir/Dockerfile.rootless
|
||||||
|
|
||||||
forgejo-test-helper.sh push $dir $url root forgejo
|
forgejo-test-helper.sh push $dir $url root forgejo
|
||||||
|
sha=$(forgejo-test-helper.sh branch_tip $url root/forgejo main)
|
||||||
forgejo-curl.sh api_json -X PUT --data-raw '{"data":"${{ steps.forgejo.outputs.token }}"}' $url/api/v1/repos/root/forgejo/actions/secrets/TOKEN
|
|
||||||
forgejo-curl.sh api_json -X PUT --data-raw '{"data":"root"}' $url/api/v1/repos/root/forgejo/actions/secrets/DOER
|
|
||||||
forgejo-curl.sh api_json -X PUT --data-raw '{"data":"true"}' $url/api/v1/repos/root/forgejo/actions/secrets/VERBOSE
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Push a tag to trigger the release workflow and wait for it to complete
|
# Push a tag to trigger the release workflow and wait for it to complete
|
||||||
#
|
#
|
||||||
version=1.2.3
|
|
||||||
sha=$(forgejo-test-helper.sh branch_tip $url root/forgejo main)
|
|
||||||
forgejo-curl.sh api_json --data-raw '{"tag_name": "v'$version'", "target": "'$sha'"}' $url/api/v1/repos/root/forgejo/tags
|
forgejo-curl.sh api_json --data-raw '{"tag_name": "v'$version'", "target": "'$sha'"}' $url/api/v1/repos/root/forgejo/tags
|
||||||
|
forgejo-curl.sh api_json -X PUT --data-raw '{"data":"${{ steps.forgejo.outputs.token }}"}' $url/api/v1/repos/root/forgejo/actions/secrets/TOKEN
|
||||||
|
forgejo-curl.sh api_json -X PUT --data-raw '{"data":"root"}' $url/api/v1/repos/root/forgejo/actions/secrets/DOER
|
||||||
LOOPS=180 forgejo-test-helper.sh wait_success "$url" root/forgejo $sha
|
LOOPS=180 forgejo-test-helper.sh wait_success "$url" root/forgejo $sha
|
||||||
sanity_check $url $version
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Push a commit to a branch that triggers the build of a test release
|
# uncomment to see the logs even when everything is reported to be working ok
|
||||||
#
|
#
|
||||||
version=1.2-test
|
#cat $FORGEJO_RUNNER_LOGS
|
||||||
(
|
|
||||||
git clone $url/root/forgejo /tmp/forgejo
|
|
||||||
cd /tmp/forgejo
|
|
||||||
date > DATE
|
|
||||||
git config user.email root@example.com
|
|
||||||
git config user.name username
|
|
||||||
git add .
|
|
||||||
git commit -m 'update'
|
|
||||||
git push $url/root/forgejo main:forgejo
|
|
||||||
)
|
|
||||||
sha=$(forgejo-test-helper.sh branch_tip $url root/forgejo forgejo)
|
|
||||||
LOOPS=180 forgejo-test-helper.sh wait_success "$url" root/forgejo $sha
|
|
||||||
sanity_check $url $version
|
|
||||||
|
|
||||||
- name: full logs
|
#
|
||||||
if: always()
|
# Minimal sanity checks. e2e test is for the setup-forgejo
|
||||||
run: |
|
# action and the infrastructure playbook. Since the binary
|
||||||
sed -e 's/^/[RUNNER LOGS] /' ${{ steps.forgejo.outputs.runner-logs }}
|
# is a script shell it does not test the sanity of the cross
|
||||||
docker logs forgejo | sed -e 's/^/[FORGEJO LOGS]/'
|
# build, only the sanity of the naming of the binaries.
|
||||||
sleep 5 # hack to avoid mixing outputs in Forgejo v1.21
|
#
|
||||||
|
for arch in amd64 arm64 arm-6 ; do
|
||||||
|
binary=forgejo-$version-linux-$arch
|
||||||
|
for suffix in '' '.xz' ; do
|
||||||
|
curl --fail -L -sS $url/root/forgejo/releases/download/v$version/$binary$suffix > $binary$suffix
|
||||||
|
if test "$suffix" = .xz ; then
|
||||||
|
unxz --keep $binary$suffix
|
||||||
|
fi
|
||||||
|
chmod +x $binary
|
||||||
|
./$binary --version | grep $version
|
||||||
|
curl --fail -L -sS $url/root/forgejo/releases/download/v$version/$binary$suffix.sha256 > $binary$suffix.sha256
|
||||||
|
shasum -a 256 --check $binary$suffix.sha256
|
||||||
|
rm $binary$suffix
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
sources=forgejo-src-$version.tar.gz
|
||||||
|
curl --fail -L -sS $url/root/forgejo/releases/download/v$version/$sources > $sources
|
||||||
|
curl --fail -L -sS $url/root/forgejo/releases/download/v$version/$sources.sha256 > $sources.sha256
|
||||||
|
shasum -a 256 --check $sources.sha256
|
||||||
|
|
||||||
|
docker pull ${{ steps.forgejo.outputs.host-port }}/root/forgejo:$version
|
||||||
|
docker pull ${{ steps.forgejo.outputs.host-port }}/root/forgejo:$version-rootless
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# See also https://forgejo.org/docs/next/contributor/release/#stable-release-process
|
# See also https://forgejo.org/docs/next/developer/RELEASE/#release-process
|
||||||
#
|
#
|
||||||
# https://codeberg.org/forgejo-integration/forgejo
|
# https://codeberg.org/forgejo-integration/forgejo
|
||||||
#
|
#
|
||||||
|
@ -14,12 +14,11 @@
|
||||||
# secrets.CASCADE_DESTINATION_TOKEN: <generated from code.forgejo.org/forgejo-ci> scope read:user, write:repository, write:issue
|
# secrets.CASCADE_DESTINATION_TOKEN: <generated from code.forgejo.org/forgejo-ci> scope read:user, write:repository, write:issue
|
||||||
# vars.CASCADE_DESTINATION_DOER: forgejo-ci
|
# vars.CASCADE_DESTINATION_DOER: forgejo-ci
|
||||||
#
|
#
|
||||||
|
name: Build release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags: 'v[0-9]+.[0-9]+.*'
|
tags: 'v*'
|
||||||
branches:
|
|
||||||
- 'forgejo'
|
|
||||||
- 'v*/forgejo'
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
|
@ -27,9 +26,7 @@ jobs:
|
||||||
# root is used for testing, allow it
|
# root is used for testing, allow it
|
||||||
if: vars.ROLE == 'forgejo-integration' || github.repository_owner == 'root'
|
if: vars.ROLE == 'forgejo-integration' || github.repository_owner == 'root'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Sanitize the name of the repository
|
- name: Sanitize the name of the repository
|
||||||
id: repository
|
id: repository
|
||||||
|
@ -37,47 +34,26 @@ jobs:
|
||||||
repository="${{ github.repository }}"
|
repository="${{ github.repository }}"
|
||||||
echo "value=${repository##*/}" >> "$GITHUB_OUTPUT"
|
echo "value=${repository##*/}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- uses: https://code.forgejo.org/actions/setup-node@v4
|
- uses: https://code.forgejo.org/actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
|
|
||||||
- uses: https://code.forgejo.org/actions/setup-go@v5
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version-file: "go.mod"
|
go-version: ">=1.21"
|
||||||
|
check-latest: true
|
||||||
|
|
||||||
- name: version from ref
|
- name: version from ref_name
|
||||||
id: release-info
|
id: tag-version
|
||||||
shell: bash
|
|
||||||
run: |
|
run: |
|
||||||
set -x
|
version="${{ github.ref_name }}"
|
||||||
ref="${{ github.ref }}"
|
version=${version##*v}
|
||||||
if [[ $ref =~ ^refs/heads/ ]] ; then
|
echo "value=$version" >> "$GITHUB_OUTPUT"
|
||||||
if test "$ref" = "refs/heads/forgejo" ; then
|
|
||||||
version=$(git tag -l --sort=version:refname --merged | grep -v -e '-test$' | tail -1 | sed -E -e 's/^(v[0-9]+\.[0-9]+).*/\1/')-test
|
|
||||||
else
|
|
||||||
version=${ref#refs/heads/}
|
|
||||||
version=${version%/forgejo}-test
|
|
||||||
fi
|
|
||||||
override=true
|
|
||||||
fi
|
|
||||||
if [[ $ref =~ ^refs/tags/ ]] ; then
|
|
||||||
version=${ref#refs/tags/}
|
|
||||||
override=false
|
|
||||||
fi
|
|
||||||
if test -z "$version" ; then
|
|
||||||
echo failed to figure out the release version from the reference=$ref
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
version=${version#v}
|
|
||||||
git describe --exclude '*-test' --tags --always
|
|
||||||
echo "sha=${{ github.sha }}" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "version=$version" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "override=$override" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
- name: release notes
|
- name: release notes
|
||||||
id: release-notes
|
id: release-notes
|
||||||
run: |
|
run: |
|
||||||
anchor=${{ steps.release-info.outputs.version }}
|
anchor=${{ steps.tag-version.outputs.value }}
|
||||||
anchor=${anchor//./-}
|
anchor=${anchor//./-}
|
||||||
cat >> "$GITHUB_OUTPUT" <<EOF
|
cat >> "$GITHUB_OUTPUT" <<EOF
|
||||||
value<<ENDVAR
|
value<<ENDVAR
|
||||||
|
@ -85,23 +61,11 @@ jobs:
|
||||||
ENDVAR
|
ENDVAR
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
- name: cache node_modules
|
|
||||||
id: node
|
|
||||||
uses: https://code.forgejo.org/actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
node_modules
|
|
||||||
key: node-${{ steps.release-info.outputs.version }}
|
|
||||||
|
|
||||||
- name: skip if node cache hit
|
|
||||||
if: steps.node.outputs.cache-hit != 'true'
|
|
||||||
run: echo no hit
|
|
||||||
|
|
||||||
- name: Build sources
|
- name: Build sources
|
||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
apt-get -qq install -y make
|
apt-get -qq install -y make
|
||||||
version=${{ steps.release-info.outputs.version }}
|
version=${{ steps.tag-version.outputs.value }}
|
||||||
#
|
#
|
||||||
# Make sure all files are owned by the current user.
|
# Make sure all files are owned by the current user.
|
||||||
# When run as root `npx webpack` will assume the identity
|
# When run as root `npx webpack` will assume the identity
|
||||||
|
@ -158,44 +122,38 @@ jobs:
|
||||||
|
|
||||||
- name: build container & release
|
- name: build container & release
|
||||||
if: ${{ secrets.TOKEN != '' }}
|
if: ${{ secrets.TOKEN != '' }}
|
||||||
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/build@v5.1.1
|
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/build@v1
|
||||||
with:
|
with:
|
||||||
forgejo: "${{ env.GITHUB_SERVER_URL }}"
|
forgejo: "${{ env.GITHUB_SERVER_URL }}"
|
||||||
owner: "${{ env.GITHUB_REPOSITORY_OWNER }}"
|
owner: "${{ env.GITHUB_REPOSITORY_OWNER }}"
|
||||||
repository: "${{ steps.repository.outputs.value }}"
|
repository: "${{ steps.repository.outputs.value }}"
|
||||||
doer: "${{ secrets.DOER }}"
|
doer: "${{ secrets.DOER }}"
|
||||||
release-version: "${{ steps.release-info.outputs.version }}"
|
tag-version: "${{ steps.tag-version.outputs.value }}"
|
||||||
sha: "${{ steps.release-info.outputs.sha }}"
|
|
||||||
token: "${{ secrets.TOKEN }}"
|
token: "${{ secrets.TOKEN }}"
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v6
|
platforms: linux/amd64,linux/arm64,linux/arm/v6
|
||||||
release-notes: "${{ steps.release-notes.outputs.value }}"
|
release-notes: "${{ steps.release-notes.outputs.value }}"
|
||||||
binary-name: forgejo
|
binary-name: forgejo
|
||||||
binary-path: /app/gitea/forgejo-cli
|
binary-path: /app/gitea/gitea
|
||||||
override: "${{ steps.release-info.outputs.override }}"
|
verbose: ${{ vars.VERBOSE || 'false' }}
|
||||||
verify-labels: "maintainer=contact@forgejo.org,org.opencontainers.image.version=${{ steps.release-info.outputs.version }}"
|
|
||||||
verbose: ${{ vars.VERBOSE || secrets.VERBOSE || 'false' }}
|
|
||||||
|
|
||||||
- name: build rootless container
|
- name: build rootless container
|
||||||
if: ${{ secrets.TOKEN != '' }}
|
if: ${{ secrets.TOKEN != '' }}
|
||||||
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/build@v5.1.1
|
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/build@v1
|
||||||
with:
|
with:
|
||||||
forgejo: "${{ env.GITHUB_SERVER_URL }}"
|
forgejo: "${{ env.GITHUB_SERVER_URL }}"
|
||||||
owner: "${{ env.GITHUB_REPOSITORY_OWNER }}"
|
owner: "${{ env.GITHUB_REPOSITORY_OWNER }}"
|
||||||
repository: "${{ steps.repository.outputs.value }}"
|
repository: "${{ steps.repository.outputs.value }}"
|
||||||
doer: "${{ secrets.DOER }}"
|
doer: "${{ secrets.DOER }}"
|
||||||
release-version: "${{ steps.release-info.outputs.version }}"
|
tag-version: "${{ steps.tag-version.outputs.value }}"
|
||||||
sha: "${{ steps.release-info.outputs.sha }}"
|
|
||||||
token: "${{ secrets.TOKEN }}"
|
token: "${{ secrets.TOKEN }}"
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v6
|
platforms: linux/amd64,linux/arm64,linux/arm/v6
|
||||||
suffix: -rootless
|
suffix: -rootless
|
||||||
dockerfile: Dockerfile.rootless
|
dockerfile: Dockerfile.rootless
|
||||||
override: "${{ steps.release-info.outputs.override }}"
|
verbose: ${{ vars.VERBOSE || 'false' }}
|
||||||
verify-labels: "maintainer=contact@forgejo.org,org.opencontainers.image.version=${{ steps.release-info.outputs.version }}"
|
|
||||||
verbose: ${{ vars.VERBOSE || secrets.VERBOSE || 'false' }}
|
|
||||||
|
|
||||||
- name: end-to-end tests
|
- name: end-to-end tests
|
||||||
if: ${{ secrets.TOKEN != '' && vars.ROLE == 'forgejo-integration' }}
|
if: ${{ secrets.TOKEN != '' && vars.ROLE == 'forgejo-integration' }}
|
||||||
uses: https://code.forgejo.org/actions/cascading-pr@v2
|
uses: https://code.forgejo.org/actions/cascading-pr@v1
|
||||||
with:
|
with:
|
||||||
origin-url: ${{ env.GITHUB_SERVER_URL }}
|
origin-url: ${{ env.GITHUB_SERVER_URL }}
|
||||||
origin-repo: ${{ github.repository }}
|
origin-repo: ${{ github.repository }}
|
||||||
|
@ -204,28 +162,8 @@ jobs:
|
||||||
destination-url: https://code.forgejo.org
|
destination-url: https://code.forgejo.org
|
||||||
destination-fork-repo: ${{ vars.CASCADE_DESTINATION_DOER }}/end-to-end
|
destination-fork-repo: ${{ vars.CASCADE_DESTINATION_DOER }}/end-to-end
|
||||||
destination-repo: forgejo/end-to-end
|
destination-repo: forgejo/end-to-end
|
||||||
destination-branch: main
|
destination-branch: forgejo-pr
|
||||||
destination-token: ${{ secrets.CASCADE_DESTINATION_TOKEN }}
|
destination-token: ${{ secrets.CASCADE_DESTINATION_TOKEN }}
|
||||||
update: .forgejo/cascading-release-end-to-end
|
update: .forgejo/cascading-release-end-to-end
|
||||||
|
env:
|
||||||
- name: copy to experimental
|
FORGEJO_BINARY: "${{ env.GITHUB_SERVER_URL }}/${{ github.repository }}/releases/download/v${{ steps.tag-version.outputs.value }}/forgejo-${{ steps.tag-version.outputs.value }}-linux-amd64"
|
||||||
if: vars.ROLE == 'forgejo-integration' && secrets.TOKEN != ''
|
|
||||||
run: |
|
|
||||||
if test "${{ vars.VERBOSE }}" = true ; then
|
|
||||||
set -x
|
|
||||||
fi
|
|
||||||
tag=v${{ steps.release-info.outputs.version }}
|
|
||||||
url=https://any:${{ secrets.TOKEN }}@codeberg.org
|
|
||||||
if test "${{ steps.release-info.outputs.override }}" = "true" ; then
|
|
||||||
curl -sS -X DELETE $url/api/v1/repos/forgejo-experimental/forgejo/releases/tags/$tag > /dev/null
|
|
||||||
curl -sS -X DELETE $url/api/v1/repos/forgejo-experimental/forgejo/tags/$tag > /dev/null
|
|
||||||
fi
|
|
||||||
# actions/checkout@v3 sets http.https://codeberg.org/.extraheader with the automatic token.
|
|
||||||
# Get rid of it so it does not prevent using the token that has write permissions
|
|
||||||
git config --local --unset http.https://codeberg.org/.extraheader
|
|
||||||
if test -f .git/shallow ; then
|
|
||||||
echo "unexptected .git/shallow file is present"
|
|
||||||
echo "it suggests a checkout --depth X was used which may prevent pushing the commit"
|
|
||||||
echo "it happens when actions/checkout is called without depth: 0"
|
|
||||||
fi
|
|
||||||
git push $url/forgejo-experimental/forgejo ${{ steps.release-info.outputs.sha }}:refs/tags/$tag
|
|
||||||
|
|
|
@ -1,33 +1,18 @@
|
||||||
# Copyright 2024 The Forgejo Authors
|
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
#
|
|
||||||
# To modify this workflow:
|
|
||||||
#
|
|
||||||
# - push it to the wip-ci-end-to-end branch on the forgejo repository
|
|
||||||
# otherwise it will not have access to the secrets required to push
|
|
||||||
# the cascading PR
|
|
||||||
#
|
|
||||||
# - once it works, open a pull request for the sake of keeping track
|
|
||||||
# of the change even if the PR won't run it because it will use
|
|
||||||
# whatever is in the default branch instead
|
|
||||||
#
|
|
||||||
# - after it is merged, double check it works by setting the
|
|
||||||
# run-end-to-end-test on a pull request (any pull request will doe
|
|
||||||
#
|
|
||||||
on:
|
on:
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- 'wip-ci-end-to-end'
|
|
||||||
pull_request_target:
|
pull_request_target:
|
||||||
types:
|
types:
|
||||||
- labeled
|
- labeled
|
||||||
|
|
||||||
|
env:
|
||||||
|
FEATURE_BRANCHES: "privacy i18n moderation branding dependency"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
info:
|
info:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: code.forgejo.org/oci/node:20-bookworm
|
image: node:20-bookworm
|
||||||
steps:
|
steps:
|
||||||
- name: event
|
- name: event
|
||||||
run: |
|
run: |
|
||||||
|
@ -38,37 +23,61 @@ jobs:
|
||||||
cat <<'EOF'
|
cat <<'EOF'
|
||||||
${{ toJSON(github.event.pull_request.labels.*.name) }}
|
${{ toJSON(github.event.pull_request.labels.*.name) }}
|
||||||
EOF
|
EOF
|
||||||
cat <<'EOF'
|
|
||||||
${{ toJSON(github.event) }}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
cascade:
|
build:
|
||||||
if: >
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') && github.event.action == 'label_updated' && contains(github.event.pull_request.labels.*.name, 'run-end-to-end-tests') }}
|
||||||
!startsWith(vars.ROLE, 'forgejo-') && (
|
|
||||||
github.event_name == 'push' ||
|
|
||||||
(
|
|
||||||
github.event.action == 'label_updated' && contains(github.event.pull_request.labels.*.name, 'run-end-to-end-tests')
|
|
||||||
)
|
|
||||||
)
|
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: code.forgejo.org/oci/node:20-bookworm
|
image: 'docker.io/node:20-bookworm'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: https://code.forgejo.org/actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: '0'
|
fetch-depth: '0'
|
||||||
show-progress: 'false'
|
show-progress: 'false'
|
||||||
- uses: actions/cascading-pr@v2
|
- name: adduser forgejo
|
||||||
|
run: |
|
||||||
|
git config --add safe.directory '*'
|
||||||
|
git config user.email "you@example.com"
|
||||||
|
git config user.name "Your Name"
|
||||||
|
adduser --quiet --comment forgejo --disabled-password forgejo
|
||||||
|
chown -R forgejo:forgejo .
|
||||||
|
- name: merge feature branches
|
||||||
|
run: |
|
||||||
|
su forgejo -c 'set -ex ; for b in ${{ env.FEATURE_BRANCHES }} ; do git merge -m $b origin/forgejo-$b ; done'
|
||||||
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: ">=1.21"
|
||||||
|
- name: make deps-backend
|
||||||
|
run: |
|
||||||
|
su forgejo -c 'make deps-backend'
|
||||||
|
- name: make forgejo
|
||||||
|
run: |
|
||||||
|
su forgejo -c 'make generate-backend static-executable && ln gitea forgejo'
|
||||||
|
env:
|
||||||
|
TAGS: bindata sqlite sqlite_unlock_notify
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: forgejo
|
||||||
|
path: forgejo
|
||||||
|
|
||||||
|
cascade:
|
||||||
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') && github.event.action == 'label_updated' && contains(github.event.pull_request.labels.*.name, 'run-end-to-end-tests') }}
|
||||||
|
needs: [build]
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: node:20-bookworm
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/cascading-pr@v1
|
||||||
with:
|
with:
|
||||||
origin-url: ${{ env.GITHUB_SERVER_URL }}
|
origin-url: ${{ env.GITHUB_SERVER_URL }}
|
||||||
origin-repo: ${{ github.repository }}
|
origin-repo: ${{ github.repository }}
|
||||||
origin-token: ${{ secrets.END_TO_END_CASCADING_PR_ORIGIN }}
|
origin-token: ${{ secrets.END_TO_END_CASCADING_PR_ORIGIN }}
|
||||||
origin-pr: ${{ github.event.pull_request.number }}
|
origin-pr: ${{ github.event.pull_request.number }}
|
||||||
origin-ref: ${{ github.event_name == 'push' && github.event.ref || '' }}
|
|
||||||
destination-url: https://code.forgejo.org
|
destination-url: https://code.forgejo.org
|
||||||
destination-fork-repo: cascading-pr/end-to-end
|
destination-fork-repo: cascading-pr/end-to-end
|
||||||
destination-repo: forgejo/end-to-end
|
destination-repo: forgejo/end-to-end
|
||||||
destination-branch: main
|
destination-branch: forgejo-pr
|
||||||
destination-token: ${{ secrets.END_TO_END_CASCADING_PR_DESTINATION }}
|
destination-token: ${{ secrets.END_TO_END_CASCADING_PR_DESTINATION }}
|
||||||
close-merge: true
|
close-merge: true
|
||||||
update: .forgejo/cascading-pr-end-to-end
|
update: .forgejo/cascading-pr-end-to-end
|
||||||
|
|
37
.forgejo/workflows/e2e.yml
Normal file
37
.forgejo/workflows/e2e.yml
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
name: e2e
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- Makefile
|
||||||
|
- .forgejo/workflows/e2e.yml
|
||||||
|
- tests/e2e/**
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test-e2e:
|
||||||
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: 'docker.io/node:20-bookworm'
|
||||||
|
steps:
|
||||||
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: "~1.21"
|
||||||
|
check-latest: true
|
||||||
|
- run: |
|
||||||
|
apt-get -qq update
|
||||||
|
apt-get -qq install -q sudo
|
||||||
|
sed -i -e 's/%sudo.*/%sudo ALL=(ALL:ALL) NOPASSWD:ALL/' /etc/sudoers
|
||||||
|
git config --add safe.directory '*'
|
||||||
|
adduser --quiet --comment forgejo --disabled-password forgejo
|
||||||
|
adduser forgejo sudo
|
||||||
|
chown -R forgejo:forgejo .
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make deps-frontend frontend deps-backend'
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make generate test-e2e-sqlite'
|
||||||
|
timeout-minutes: 40
|
||||||
|
env:
|
||||||
|
DEPS_PLAYWRIGHT: 1
|
||||||
|
USE_REPO_TEST_DIR: 1
|
|
@ -1,39 +0,0 @@
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
schedule:
|
|
||||||
- cron: '@daily'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
integration-cleanup:
|
|
||||||
if: vars.ROLE == 'forgejo-integration'
|
|
||||||
runs-on: docker
|
|
||||||
container:
|
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
|
||||||
steps:
|
|
||||||
|
|
||||||
- name: apt install curl jq
|
|
||||||
run: |
|
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
|
||||||
apt-get update -qq
|
|
||||||
apt-get -q install -qq -y curl jq
|
|
||||||
|
|
||||||
- name: remove old releases and tags
|
|
||||||
run: |
|
|
||||||
url=https://any:${{ secrets.TOKEN }}@codeberg.org
|
|
||||||
curl -sS "$url/api/v1/repos/forgejo-integration/forgejo/releases" | jq -r '.[] | "\(.published_at) \(.tag_name)"' | sort | while read published_at version ; do
|
|
||||||
if echo $version | grep -e '-test$' >/dev/null; then
|
|
||||||
old="18 months"
|
|
||||||
else
|
|
||||||
old="1 day"
|
|
||||||
fi
|
|
||||||
too_old=$(env -i date --date="- $old" +%F)
|
|
||||||
too_old_seconds=$(env -i date --date="- $old" +%s)
|
|
||||||
published_at_seconds=$(env -i date --date="$published_at" +%s)
|
|
||||||
if test $published_at_seconds -le $too_old_seconds ; then
|
|
||||||
echo "$version was published more than $old ago ($published_at <= $too_old) and will be removed"
|
|
||||||
curl -X DELETE -sS "$url/api/v1/repos/forgejo-integration/forgejo/releases/tags/$version"
|
|
||||||
else
|
|
||||||
echo "$version was published less than $old ago"
|
|
||||||
fi
|
|
||||||
done
|
|
|
@ -1,17 +1,17 @@
|
||||||
name: mirror
|
name: mirror
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
push:
|
||||||
|
branches:
|
||||||
schedule:
|
- 'forgejo'
|
||||||
- cron: '@daily'
|
- 'v*/forgejo'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
mirror:
|
mirror:
|
||||||
if: ${{ secrets.MIRROR_TOKEN != '' }}
|
if: ${{ secrets.MIRROR_TOKEN != '' }}
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'docker.io/node:20-bookworm'
|
||||||
steps:
|
steps:
|
||||||
- name: git push {v*/,}forgejo
|
- name: git push {v*/,}forgejo
|
||||||
run: |
|
run: |
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
#
|
#
|
||||||
# See also https://forgejo.org/docs/next/contributor/release/#stable-release-process
|
# See also https://forgejo.org/docs/next/developer/RELEASE/#release-process
|
||||||
#
|
#
|
||||||
# https://codeberg.org/forgejo-experimental/forgejo
|
# https://codeberg.org/forgejo-experimental/forgejo
|
||||||
#
|
#
|
||||||
|
@ -39,42 +39,30 @@ jobs:
|
||||||
runs-on: self-hosted
|
runs-on: self-hosted
|
||||||
if: vars.DOER != '' && vars.FORGEJO != '' && vars.TO_OWNER != '' && vars.FROM_OWNER != '' && secrets.TOKEN != ''
|
if: vars.DOER != '' && vars.FORGEJO != '' && vars.TO_OWNER != '' && vars.FROM_OWNER != '' && secrets.TOKEN != ''
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: copy & sign
|
- name: copy & sign
|
||||||
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/publish@v5
|
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/publish@v1
|
||||||
with:
|
with:
|
||||||
from-forgejo: ${{ vars.FORGEJO }}
|
forgejo: ${{ vars.FORGEJO }}
|
||||||
to-forgejo: ${{ vars.FORGEJO }}
|
|
||||||
from-owner: ${{ vars.FROM_OWNER }}
|
from-owner: ${{ vars.FROM_OWNER }}
|
||||||
to-owner: ${{ vars.TO_OWNER }}
|
to-owner: ${{ vars.TO_OWNER }}
|
||||||
repo: ${{ vars.REPO }}
|
repo: ${{ vars.REPO }}
|
||||||
release-notes: "See https://codeberg.org/forgejo/forgejo/src/branch/forgejo/RELEASE-NOTES.md#{ANCHOR}"
|
|
||||||
ref-name: ${{ github.ref_name }}
|
ref-name: ${{ github.ref_name }}
|
||||||
sha: ${{ github.sha }}
|
release-notes: "See https://codeberg.org/forgejo/forgejo/src/branch/forgejo/RELEASE-NOTES.md#{ANCHOR}"
|
||||||
from-token: ${{ secrets.TOKEN }}
|
doer: ${{ vars.DOER }}
|
||||||
to-doer: ${{ vars.DOER }}
|
token: ${{ secrets.TOKEN }}
|
||||||
to-token: ${{ secrets.TOKEN }}
|
|
||||||
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
|
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||||
gpg-passphrase: ${{ secrets.GPG_PASSPHRASE }}
|
gpg-passphrase: ${{ secrets.GPG_PASSPHRASE }}
|
||||||
verbose: ${{ vars.VERBOSE }}
|
verbose: ${{ vars.VERBOSE }}
|
||||||
|
|
||||||
- name: upgrade v*.next.forgejo.org
|
|
||||||
run: |
|
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
|
||||||
apt-get update -qq
|
|
||||||
apt-get -q install -y -qq curl
|
|
||||||
version="${{ github.ref_name }}"
|
|
||||||
version=${version##*v}
|
|
||||||
major=$(echo $version | sed -E -e 's/^([0-9]+).*/\1/')
|
|
||||||
# https://forgejo.org/docs/next/developer/infrastructure
|
|
||||||
curl -o /dev/null -sS https://v$major.next.forgejo.org/.well-known/wakeup-on-logs/forgejo-v$major
|
|
||||||
|
|
||||||
- name: set up go for the DNS update below
|
- name: set up go for the DNS update below
|
||||||
if: vars.ROLE == 'forgejo-experimental' && secrets.OVH_APP_KEY != ''
|
if: vars.ROLE == 'forgejo-experimental' && secrets.OVH_APP_KEY != ''
|
||||||
uses: https://code.forgejo.org/actions/setup-go@v5
|
uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version-file: "go.mod"
|
go-version: ">=1.21"
|
||||||
|
check-latest: true
|
||||||
- name: update the _release.experimental DNS record
|
- name: update the _release.experimental DNS record
|
||||||
if: vars.ROLE == 'forgejo-experimental' && secrets.OVH_APP_KEY != ''
|
if: vars.ROLE == 'forgejo-experimental' && secrets.OVH_APP_KEY != ''
|
||||||
uses: https://code.forgejo.org/actions/ovh-dns-update@v1
|
uses: https://code.forgejo.org/actions/ovh-dns-update@v1
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
schedule:
|
|
||||||
- cron: '@daily'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release-notes:
|
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-')
|
|
||||||
runs-on: docker
|
|
||||||
container:
|
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
|
||||||
steps:
|
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: https://code.forgejo.org/actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: "go.mod"
|
|
||||||
cache: false
|
|
||||||
|
|
||||||
- name: apt install jq
|
|
||||||
run: |
|
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
|
||||||
apt-get update -qq
|
|
||||||
apt-get -q install -y -qq jq
|
|
||||||
|
|
||||||
- name: update open milestones
|
|
||||||
run: |
|
|
||||||
set -x
|
|
||||||
curl -sS $GITHUB_SERVER_URL/api/v1/repos/$GITHUB_REPOSITORY/milestones?state=open | jq -r '.[] | .title' | while read forgejo version ; do
|
|
||||||
milestone="$forgejo $version"
|
|
||||||
go run code.forgejo.org/forgejo/release-notes-assistant@v1.1.1 --config .release-notes-assistant.yaml --storage milestone --storage-location "$milestone" --forgejo-url $GITHUB_SERVER_URL --repository $GITHUB_REPOSITORY --token ${{ secrets.RELEASE_NOTES_ASSISTANT_TOKEN }} release $version
|
|
||||||
done
|
|
|
@ -1,39 +0,0 @@
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
types:
|
|
||||||
- edited
|
|
||||||
- synchronize
|
|
||||||
- labeled
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release-notes:
|
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') && contains(github.event.pull_request.labels.*.name, 'worth a release-note') }}
|
|
||||||
runs-on: docker
|
|
||||||
container:
|
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
|
||||||
steps:
|
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
|
|
||||||
- name: event
|
|
||||||
run: |
|
|
||||||
cat <<'EOF'
|
|
||||||
${{ toJSON(github.event.pull_request.labels.*.name) }}
|
|
||||||
EOF
|
|
||||||
cat <<'EOF'
|
|
||||||
${{ toJSON(github.event) }}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
- uses: https://code.forgejo.org/actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: "go.mod"
|
|
||||||
cache: false
|
|
||||||
|
|
||||||
- name: apt install jq
|
|
||||||
run: |
|
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
|
||||||
apt-get update -qq
|
|
||||||
apt-get -q install -y -qq jq
|
|
||||||
|
|
||||||
- name: release-notes-assistant preview
|
|
||||||
run: |
|
|
||||||
go run code.forgejo.org/forgejo/release-notes-assistant@v1.1.1 --config .release-notes-assistant.yaml --storage pr --storage-location ${{ github.event.pull_request.number }} --forgejo-url $GITHUB_SERVER_URL --repository $GITHUB_REPOSITORY --token ${{ secrets.RELEASE_NOTES_ASSISTANT_TOKEN }} preview ${{ github.event.pull_request.number }}
|
|
|
@ -1,69 +0,0 @@
|
||||||
#
|
|
||||||
# Runs every 2 hours, but Renovate is limited to create new PR before 4am.
|
|
||||||
# See renovate.json for more settings.
|
|
||||||
# Automerge is enabled for Renovate PR's but need to be approved before.
|
|
||||||
#
|
|
||||||
name: renovate
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- 'renovate/**' # self-test updates
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0/2 * * *'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
RENOVATE_DRY_RUN: ${{ (github.event_name != 'schedule' && github.ref_name != github.event.repository.default_branch) && 'full' || '' }}
|
|
||||||
RENOVATE_REPOSITORIES: ${{ github.repository }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
renovate:
|
|
||||||
if: ${{ secrets.RENOVATE_TOKEN != '' }}
|
|
||||||
|
|
||||||
runs-on: docker
|
|
||||||
container:
|
|
||||||
image: code.forgejo.org/forgejo-contrib/renovate:38.110.2
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Load renovate repo cache
|
|
||||||
uses: https://code.forgejo.org/actions/cache/restore@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
.tmp/cache/renovate/repository
|
|
||||||
.tmp/cache/renovate/renovate-cache-sqlite
|
|
||||||
.tmp/osv
|
|
||||||
key: repo-cache-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
repo-cache-
|
|
||||||
|
|
||||||
- name: Run renovate
|
|
||||||
run: renovate
|
|
||||||
env:
|
|
||||||
GITHUB_COM_TOKEN: ${{ secrets.RENOVATE_GITHUB_COM_TOKEN }}
|
|
||||||
LOG_LEVEL: debug
|
|
||||||
RENOVATE_BASE_DIR: ${{ github.workspace }}/.tmp
|
|
||||||
RENOVATE_ENDPOINT: ${{ github.server_url }}
|
|
||||||
RENOVATE_PLATFORM: gitea
|
|
||||||
RENOVATE_REPOSITORY_CACHE: 'enabled'
|
|
||||||
RENOVATE_TOKEN: ${{ secrets.RENOVATE_TOKEN }}
|
|
||||||
RENOVATE_GIT_AUTHOR: 'Renovate Bot <forgejo-renovate-action@forgejo.org>'
|
|
||||||
|
|
||||||
RENOVATE_X_SQLITE_PACKAGE_CACHE: true
|
|
||||||
|
|
||||||
GIT_AUTHOR_NAME: 'Renovate Bot'
|
|
||||||
GIT_AUTHOR_EMAIL: 'forgejo-renovate-action@forgejo.org'
|
|
||||||
GIT_COMMITTER_NAME: 'Renovate Bot'
|
|
||||||
GIT_COMMITTER_EMAIL: 'forgejo-renovate-action@forgejo.org'
|
|
||||||
|
|
||||||
OSV_OFFLINE_ROOT_DIR: ${{ github.workspace }}/.tmp/osv
|
|
||||||
|
|
||||||
- name: Save renovate repo cache
|
|
||||||
if: always() && env.RENOVATE_DRY_RUN != 'full'
|
|
||||||
uses: https://code.forgejo.org/actions/cache/save@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
.tmp/cache/renovate/repository
|
|
||||||
.tmp/cache/renovate/renovate-cache-sqlite
|
|
||||||
.tmp/osv
|
|
||||||
key: repo-cache-${{ github.run_id }}
|
|
|
@ -8,255 +8,204 @@ on:
|
||||||
- 'v*/forgejo*'
|
- 'v*/forgejo*'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
backend-checks:
|
lint-backend:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'docker.io/node:20-bookworm'
|
||||||
steps:
|
steps:
|
||||||
- name: event info
|
- uses: https://code.forgejo.org/actions/checkout@v3
|
||||||
run: |
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
cat <<'EOF'
|
|
||||||
${{ toJSON(github) }}
|
|
||||||
EOF
|
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
- uses: ./.forgejo/workflows-composite/setup-env
|
|
||||||
- run: su forgejo -c 'make deps-backend deps-tools'
|
|
||||||
- run: su forgejo -c 'make --always-make -j$(nproc) lint-backend tidy-check swagger-check fmt-check swagger-validate' # ensure the "go-licenses" make target runs
|
|
||||||
- uses: ./.forgejo/workflows-composite/build-backend
|
|
||||||
frontend-checks:
|
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
|
||||||
runs-on: docker
|
|
||||||
container:
|
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
|
||||||
steps:
|
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
- run: make deps-frontend
|
|
||||||
- run: make lint-frontend
|
|
||||||
- run: make checks-frontend
|
|
||||||
- run: make test-frontend-coverage
|
|
||||||
- run: make frontend
|
|
||||||
- name: Install zstd for cache saving
|
|
||||||
# works around https://github.com/actions/cache/issues/1169, because the
|
|
||||||
# consuming job has zstd and doesn't restore the cache otherwise
|
|
||||||
run: |
|
|
||||||
apt-get update -qq
|
|
||||||
apt-get -q install -qq -y zstd
|
|
||||||
- name: "Cache frontend build for playwright testing"
|
|
||||||
uses: actions/cache/save@v4
|
|
||||||
with:
|
with:
|
||||||
path: ${{github.workspace}}/public/assets
|
go-version: ">=1.21"
|
||||||
key: frontend-build-${{ github.sha }}
|
check-latest: true
|
||||||
|
- run: make deps-backend deps-tools
|
||||||
|
- run: make lint-backend
|
||||||
|
env:
|
||||||
|
TAGS: bindata sqlite sqlite_unlock_notify
|
||||||
|
checks-backend:
|
||||||
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: 'docker.io/node:20-bookworm'
|
||||||
|
steps:
|
||||||
|
- uses: https://code.forgejo.org/actions/checkout@v3
|
||||||
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: ">=1.21"
|
||||||
|
check-latest: true
|
||||||
|
- run: make deps-backend deps-tools
|
||||||
|
- run: make --always-make checks-backend # ensure the "go-licenses" make target runs
|
||||||
test-unit:
|
test-unit:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [backend-checks, frontend-checks]
|
needs: [lint-backend, checks-backend]
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'docker.io/node:20-bookworm'
|
||||||
services:
|
services:
|
||||||
elasticsearch:
|
|
||||||
image: docker.io/bitnami/elasticsearch:7
|
|
||||||
env:
|
|
||||||
discovery.type: single-node
|
|
||||||
ES_JAVA_OPTS: "-Xms512m -Xmx512m"
|
|
||||||
minio:
|
minio:
|
||||||
image: docker.io/bitnami/minio:2024.8.17
|
image: 'docker.io/bitnami/minio:2023.8.31'
|
||||||
options: >-
|
|
||||||
--hostname gitea.minio
|
|
||||||
env:
|
env:
|
||||||
MINIO_DOMAIN: minio
|
|
||||||
MINIO_ROOT_USER: 123456
|
MINIO_ROOT_USER: 123456
|
||||||
MINIO_ROOT_PASSWORD: 12345678
|
MINIO_ROOT_PASSWORD: 12345678
|
||||||
steps:
|
steps:
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v4
|
- uses: https://code.forgejo.org/actions/checkout@v3
|
||||||
- uses: ./.forgejo/workflows-composite/setup-env
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
- name: install git >= 2.42
|
|
||||||
uses: ./.forgejo/workflows-composite/apt-install-from
|
|
||||||
with:
|
with:
|
||||||
packages: git
|
go-version: ">=1.21"
|
||||||
- name: test release-notes-assistant.sh
|
- run: |
|
||||||
|
git config --add safe.directory '*'
|
||||||
|
adduser --quiet --comment forgejo --disabled-password forgejo
|
||||||
|
chown -R forgejo:forgejo .
|
||||||
|
- name: install git >= 2.42
|
||||||
run: |
|
run: |
|
||||||
apt-get -q install -qq -y jq
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
./release-notes-assistant.sh test_main
|
echo deb http://deb.debian.org/debian/ testing main > /etc/apt/sources.list.d/testing.list
|
||||||
- uses: ./.forgejo/workflows-composite/build-backend
|
apt-get update -qq
|
||||||
|
apt-get -q install -qq -y git
|
||||||
|
rm /etc/apt/sources.list.d/testing.list
|
||||||
|
apt-get update -qq
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make deps-backend'
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make backend'
|
||||||
|
env:
|
||||||
|
TAGS: bindata
|
||||||
- run: |
|
- run: |
|
||||||
su forgejo -c 'make test-backend test-check'
|
su forgejo -c 'make test-backend test-check'
|
||||||
timeout-minutes: 50
|
timeout-minutes: 50
|
||||||
env:
|
env:
|
||||||
RACE_ENABLED: 'true'
|
RACE_ENABLED: 'true'
|
||||||
TAGS: bindata
|
TAGS: bindata
|
||||||
TEST_ELASTICSEARCH_URL: http://elasticsearch:9200
|
|
||||||
test-e2e:
|
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
|
||||||
runs-on: docker
|
|
||||||
needs: [backend-checks, frontend-checks]
|
|
||||||
container:
|
|
||||||
image: 'code.forgejo.org/oci/playwright:latest'
|
|
||||||
steps:
|
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 20
|
|
||||||
- uses: ./.forgejo/workflows-composite/setup-env
|
|
||||||
- name: "Restore frontend build"
|
|
||||||
uses: actions/cache/restore@v4
|
|
||||||
id: cache-frontend
|
|
||||||
with:
|
|
||||||
path: ${{github.workspace}}/public/assets
|
|
||||||
key: frontend-build-${{ github.sha }}
|
|
||||||
- name: "Build frontend (if not cached)"
|
|
||||||
if: steps.cache-frontend.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
su forgejo -c 'make deps-frontend frontend'
|
|
||||||
- uses: ./.forgejo/workflows-composite/build-backend
|
|
||||||
- name: Get changed files
|
|
||||||
id: changed-files
|
|
||||||
uses: https://code.forgejo.org/tj-actions/changed-files@v45
|
|
||||||
with:
|
|
||||||
separator: '\n'
|
|
||||||
- run: |
|
|
||||||
su forgejo -c 'make generate test-e2e-sqlite'
|
|
||||||
timeout-minutes: 40
|
|
||||||
env:
|
|
||||||
USE_REPO_TEST_DIR: 1
|
|
||||||
CHANGED_FILES: ${{steps.changed-files.outputs.all_changed_files}}
|
|
||||||
test-remote-cacher:
|
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
|
||||||
runs-on: docker
|
|
||||||
needs: [backend-checks, frontend-checks, test-unit]
|
|
||||||
container:
|
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
cacher:
|
|
||||||
# redis
|
|
||||||
- image: docker.io/bitnami/redis:7.2
|
|
||||||
port: 6379
|
|
||||||
# redict
|
|
||||||
- image: registry.redict.io/redict:7.3.0-scratch
|
|
||||||
port: 6379
|
|
||||||
# valkey
|
|
||||||
- image: docker.io/bitnami/valkey:7.2
|
|
||||||
port: 6379
|
|
||||||
# garnet
|
|
||||||
- image: ghcr.io/microsoft/garnet-alpine:1.0.14
|
|
||||||
port: 6379
|
|
||||||
services:
|
|
||||||
cacher:
|
|
||||||
image: ${{ matrix.cacher.image }}
|
|
||||||
options: ${{ matrix.cacher.options }}
|
|
||||||
steps:
|
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
- uses: ./.forgejo/workflows-composite/setup-env
|
|
||||||
- name: install git >= 2.42
|
|
||||||
uses: ./.forgejo/workflows-composite/apt-install-from
|
|
||||||
with:
|
|
||||||
packages: git
|
|
||||||
- uses: ./.forgejo/workflows-composite/build-backend
|
|
||||||
- run: |
|
|
||||||
su forgejo -c 'make test-remote-cacher test-check'
|
|
||||||
timeout-minutes: 50
|
|
||||||
env:
|
|
||||||
RACE_ENABLED: 'true'
|
|
||||||
TAGS: bindata
|
|
||||||
TEST_REDIS_SERVER: cacher:${{ matrix.cacher.port }}
|
|
||||||
test-mysql:
|
test-mysql:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [backend-checks, frontend-checks]
|
needs: [lint-backend, checks-backend]
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'docker.io/node:20-bookworm'
|
||||||
services:
|
services:
|
||||||
mysql:
|
mysql:
|
||||||
image: 'docker.io/bitnami/mysql:8.4'
|
image: 'docker.io/mysql:8-debian'
|
||||||
env:
|
env:
|
||||||
ALLOW_EMPTY_PASSWORD: yes
|
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
||||||
MYSQL_DATABASE: testgitea
|
MYSQL_DATABASE: testgitea
|
||||||
#
|
#
|
||||||
# See also https://codeberg.org/forgejo/forgejo/issues/976
|
# See also https://codeberg.org/forgejo/forgejo/issues/976
|
||||||
#
|
#
|
||||||
MYSQL_EXTRA_FLAGS: --innodb-adaptive-flushing=OFF --innodb-buffer-pool-size=4G --innodb-log-buffer-size=128M --innodb-flush-log-at-trx-commit=0 --innodb-flush-log-at-timeout=30 --innodb-flush-method=nosync --innodb-fsync-threshold=1000000000
|
cmd: ['mysqld', '--innodb-adaptive-flushing=OFF', '--innodb-buffer-pool-size=4G', '--innodb-log-buffer-size=128M', '--innodb-flush-log-at-trx-commit=0', '--innodb-flush-log-at-timeout=30', '--innodb-flush-method=nosync', '--innodb-fsync-threshold=1000000000']
|
||||||
steps:
|
steps:
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v4
|
- uses: https://code.forgejo.org/actions/checkout@v3
|
||||||
- uses: ./.forgejo/workflows-composite/setup-env
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
- name: install dependencies & git >= 2.42
|
|
||||||
uses: ./.forgejo/workflows-composite/apt-install-from
|
|
||||||
with:
|
with:
|
||||||
packages: git git-lfs
|
go-version: "1.21"
|
||||||
- uses: ./.forgejo/workflows-composite/build-backend
|
- name: install dependencies & git >= 2.42
|
||||||
|
run: |
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
echo deb http://deb.debian.org/debian/ testing main > /etc/apt/sources.list.d/testing.list
|
||||||
|
apt-get update -qq
|
||||||
|
apt-get install --no-install-recommends -qq -y git git-lfs
|
||||||
|
rm /etc/apt/sources.list.d/testing.list
|
||||||
|
apt-get update -qq
|
||||||
|
- name: setup user and permissions
|
||||||
|
run: |
|
||||||
|
git config --add safe.directory '*'
|
||||||
|
adduser --quiet --comment forgejo --disabled-password forgejo
|
||||||
|
chown -R forgejo:forgejo .
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make deps-backend'
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make backend'
|
||||||
|
env:
|
||||||
|
TAGS: bindata
|
||||||
- run: |
|
- run: |
|
||||||
su forgejo -c 'make test-mysql-migration test-mysql'
|
su forgejo -c 'make test-mysql-migration test-mysql'
|
||||||
timeout-minutes: 50
|
timeout-minutes: 50
|
||||||
env:
|
env:
|
||||||
|
TAGS: bindata
|
||||||
USE_REPO_TEST_DIR: 1
|
USE_REPO_TEST_DIR: 1
|
||||||
test-pgsql:
|
test-pgsql:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [backend-checks, frontend-checks]
|
needs: [lint-backend, checks-backend]
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'docker.io/node:20-bookworm'
|
||||||
services:
|
services:
|
||||||
minio:
|
minio:
|
||||||
image: docker.io/bitnami/minio:2024.8.17
|
image: bitnami/minio:2021.3.17
|
||||||
env:
|
env:
|
||||||
MINIO_ROOT_USER: 123456
|
MINIO_ACCESS_KEY: 123456
|
||||||
MINIO_ROOT_PASSWORD: 12345678
|
MINIO_SECRET_KEY: 12345678
|
||||||
ldap:
|
|
||||||
image: docker.io/gitea/test-openldap:latest
|
|
||||||
pgsql:
|
pgsql:
|
||||||
image: 'code.forgejo.org/oci/postgres:15'
|
image: 'docker.io/postgres:15'
|
||||||
env:
|
env:
|
||||||
POSTGRES_DB: test
|
POSTGRES_DB: test
|
||||||
POSTGRES_PASSWORD: postgres
|
POSTGRES_PASSWORD: postgres
|
||||||
steps:
|
steps:
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v4
|
- uses: https://code.forgejo.org/actions/checkout@v3
|
||||||
- uses: ./.forgejo/workflows-composite/setup-env
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
- name: install dependencies & git >= 2.42
|
|
||||||
uses: ./.forgejo/workflows-composite/apt-install-from
|
|
||||||
with:
|
with:
|
||||||
packages: git git-lfs
|
go-version: "1.21"
|
||||||
- uses: ./.forgejo/workflows-composite/build-backend
|
- name: install dependencies & git >= 2.42
|
||||||
|
run: |
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
echo deb http://deb.debian.org/debian/ testing main > /etc/apt/sources.list.d/testing.list
|
||||||
|
apt-get update -qq
|
||||||
|
apt-get install --no-install-recommends -qq -y git git-lfs
|
||||||
|
rm /etc/apt/sources.list.d/testing.list
|
||||||
|
apt-get update -qq
|
||||||
|
- name: setup user and permissions
|
||||||
|
run: |
|
||||||
|
git config --add safe.directory '*'
|
||||||
|
adduser --quiet --comment forgejo --disabled-password forgejo
|
||||||
|
chown -R forgejo:forgejo .
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make deps-backend'
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make backend'
|
||||||
|
env:
|
||||||
|
TAGS: bindata
|
||||||
- run: |
|
- run: |
|
||||||
su forgejo -c 'make test-pgsql-migration test-pgsql'
|
su forgejo -c 'make test-pgsql-migration test-pgsql'
|
||||||
timeout-minutes: 50
|
timeout-minutes: 50
|
||||||
env:
|
env:
|
||||||
|
TAGS: bindata
|
||||||
RACE_ENABLED: true
|
RACE_ENABLED: true
|
||||||
USE_REPO_TEST_DIR: 1
|
USE_REPO_TEST_DIR: 1
|
||||||
TEST_LDAP: 1
|
|
||||||
test-sqlite:
|
test-sqlite:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [backend-checks, frontend-checks]
|
needs: [lint-backend, checks-backend]
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'docker.io/node:20-bookworm'
|
||||||
steps:
|
steps:
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v4
|
- uses: https://code.forgejo.org/actions/checkout@v3
|
||||||
- uses: ./.forgejo/workflows-composite/setup-env
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
- name: install dependencies & git >= 2.42
|
|
||||||
uses: ./.forgejo/workflows-composite/apt-install-from
|
|
||||||
with:
|
with:
|
||||||
packages: git git-lfs
|
go-version: "1.21"
|
||||||
- uses: ./.forgejo/workflows-composite/build-backend
|
- name: install dependencies & git >= 2.42
|
||||||
|
run: |
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
echo deb http://deb.debian.org/debian/ testing main > /etc/apt/sources.list.d/testing.list
|
||||||
|
apt-get update -qq
|
||||||
|
apt-get install --no-install-recommends -qq -y git git-lfs
|
||||||
|
rm /etc/apt/sources.list.d/testing.list
|
||||||
|
apt-get update -qq
|
||||||
|
- name: setup user and permissions
|
||||||
|
run: |
|
||||||
|
git config --add safe.directory '*'
|
||||||
|
adduser --quiet --comment forgejo --disabled-password forgejo
|
||||||
|
chown -R forgejo:forgejo .
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make deps-backend'
|
||||||
|
- run: |
|
||||||
|
su forgejo -c 'make backend'
|
||||||
|
env:
|
||||||
|
TAGS: bindata sqlite sqlite_unlock_notify
|
||||||
- run: |
|
- run: |
|
||||||
su forgejo -c 'make test-sqlite-migration test-sqlite'
|
su forgejo -c 'make test-sqlite-migration test-sqlite'
|
||||||
timeout-minutes: 50
|
timeout-minutes: 50
|
||||||
env:
|
env:
|
||||||
TAGS: sqlite sqlite_unlock_notify
|
TAGS: bindata sqlite sqlite_unlock_notify
|
||||||
RACE_ENABLED: true
|
RACE_ENABLED: true
|
||||||
TEST_TAGS: sqlite sqlite_unlock_notify
|
TEST_TAGS: sqlite sqlite_unlock_notify
|
||||||
USE_REPO_TEST_DIR: 1
|
USE_REPO_TEST_DIR: 1
|
||||||
security-check:
|
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
|
||||||
runs-on: docker
|
|
||||||
needs:
|
|
||||||
- test-sqlite
|
|
||||||
- test-pgsql
|
|
||||||
- test-mysql
|
|
||||||
- test-remote-cacher
|
|
||||||
- test-unit
|
|
||||||
container:
|
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
|
||||||
steps:
|
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
- uses: ./.forgejo/workflows-composite/setup-env
|
|
||||||
- run: su forgejo -c 'make deps-backend deps-tools'
|
|
||||||
- run: su forgejo -c 'make security-check'
|
|
||||||
|
|
1
.gitattributes
vendored
1
.gitattributes
vendored
|
@ -1,6 +1,5 @@
|
||||||
* text=auto eol=lf
|
* text=auto eol=lf
|
||||||
*.tmpl linguist-language=go-html-template
|
*.tmpl linguist-language=go-html-template
|
||||||
*.pb.go linguist-generated
|
|
||||||
/assets/*.json linguist-generated
|
/assets/*.json linguist-generated
|
||||||
/public/assets/img/svg/*.svg linguist-generated
|
/public/assets/img/svg/*.svg linguist-generated
|
||||||
/templates/swagger/v1_json.tmpl linguist-generated
|
/templates/swagger/v1_json.tmpl linguist-generated
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
name: 🦋 Bug Report (web interface / frontend)
|
name: 🦋 Bug Report (web interface / frontend)
|
||||||
description: Something doesn't look quite as it should? Report it here!
|
description: Something doesn't look quite as it should? Report it here!
|
||||||
title: "bug: "
|
title: "[BUG] "
|
||||||
labels: ["bug/new-report", "forgejo/ui"]
|
labels: ["bug", "forgejo/ui"]
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
|
@ -13,29 +13,16 @@ body:
|
||||||
- Please speak English, as this is the language all maintainers can speak and write.
|
- Please speak English, as this is the language all maintainers can speak and write.
|
||||||
- Be as clear and concise as possible. A very verbose report is harder to interpret in a concrete way.
|
- Be as clear and concise as possible. A very verbose report is harder to interpret in a concrete way.
|
||||||
- Be civil, and follow the [Forgejo Code of Conduct](https://codeberg.org/forgejo/code-of-conduct).
|
- Be civil, and follow the [Forgejo Code of Conduct](https://codeberg.org/forgejo/code-of-conduct).
|
||||||
- Take a moment to [check that your issue hasn't been reported before](https://codeberg.org/forgejo/forgejo/issues?q=&type=all&labels=78137).
|
- Please make sure you are using the latest release of Forgejo and take a moment to [check that your issue hasn't been reported before](https://codeberg.org/forgejo/forgejo/issues?q=&type=all&labels=78137).
|
||||||
- type: dropdown
|
- Please give all relevant information below for bug reports, as incomplete details may result in the issue not being considered.
|
||||||
id: can-reproduce
|
|
||||||
attributes:
|
|
||||||
label: Can you reproduce the bug on the Forgejo test instance?
|
|
||||||
description: |
|
|
||||||
Please try reproducing your issue at https://dev.next.forgejo.org.
|
|
||||||
It is running the latest development branch and will confirm the problem is not already fixed.
|
|
||||||
If you can reproduce it, provide a URL in the description.
|
|
||||||
options:
|
|
||||||
- "Yes"
|
|
||||||
- "No"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: description
|
id: description
|
||||||
attributes:
|
attributes:
|
||||||
label: Description
|
label: Description
|
||||||
description: |
|
description: |
|
||||||
Please provide a description of your issue here, with a URL if you were able to reproduce the issue (see above).
|
Please provide a description of your issue here, with a URL if you were able to reproduce the issue (see below).
|
||||||
If you think this is a JavaScript error, include a copy of the JavaScript console.
|
If you think this is a JavaScript error, show us the JavaScript console.
|
||||||
validations:
|
If the error appears to relate to Forgejo the server, please also give us `DEBUG` level logs. (See https://forgejo.org/docs/latest/admin/logging-documentation/)
|
||||||
required: true
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: screenshots
|
id: screenshots
|
||||||
attributes:
|
attributes:
|
||||||
|
@ -48,6 +35,20 @@ body:
|
||||||
attributes:
|
attributes:
|
||||||
label: Forgejo Version
|
label: Forgejo Version
|
||||||
description: Forgejo version (or commit reference) your instance is running
|
description: Forgejo version (or commit reference) your instance is running
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: can-reproduce
|
||||||
|
attributes:
|
||||||
|
label: Can you reproduce the bug on Forgejo Next?
|
||||||
|
description: |
|
||||||
|
Please try reproducing your issue at [Forgejo Next](https://next.forgejo.org).
|
||||||
|
If you can reproduce it, please provide a URL in the Description field.
|
||||||
|
options:
|
||||||
|
- "Yes"
|
||||||
|
- "No"
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
id: browser-ver
|
id: browser-ver
|
||||||
attributes:
|
attributes:
|
||||||
|
@ -55,3 +56,8 @@ body:
|
||||||
description: The browser and version that you are using to access Forgejo
|
description: The browser and version that you are using to access Forgejo
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: os-ver
|
||||||
|
attributes:
|
||||||
|
label: Operating System
|
||||||
|
description: The operating system you are using to access Forgejo
|
|
@ -1,7 +1,7 @@
|
||||||
name: 🐛 Bug Report (server / backend)
|
name: 🐛 Bug Report (server / backend)
|
||||||
description: Found something you weren't expecting? Report it here!
|
description: Found something you weren't expecting? Report it here!
|
||||||
title: "bug: "
|
title: "[BUG] "
|
||||||
labels: bug/new-report
|
labels: bug
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
|
@ -13,26 +13,14 @@ body:
|
||||||
- Please speak English, as this is the language all maintainers can speak and write.
|
- Please speak English, as this is the language all maintainers can speak and write.
|
||||||
- Be as clear and concise as possible. A very verbose report is harder to interpret in a concrete way.
|
- Be as clear and concise as possible. A very verbose report is harder to interpret in a concrete way.
|
||||||
- Be civil, and follow the [Forgejo Code of Conduct](https://codeberg.org/forgejo/code-of-conduct).
|
- Be civil, and follow the [Forgejo Code of Conduct](https://codeberg.org/forgejo/code-of-conduct).
|
||||||
- Take a moment to [check that your issue hasn't been reported before](https://codeberg.org/forgejo/forgejo/issues?q=&type=all&labels=78137).
|
- Please make sure you are using the latest release of Forgejo and take a moment to [check that your issue hasn't been reported before](https://codeberg.org/forgejo/forgejo/issues?q=&type=all&labels=78137).
|
||||||
- type: dropdown
|
- Please give all relevant information below for bug reports, as incomplete details may result in the issue not being considered.
|
||||||
id: can-reproduce
|
|
||||||
attributes:
|
|
||||||
label: Can you reproduce the bug on the Forgejo test instance?
|
|
||||||
description: |
|
|
||||||
Please try reproducing your issue at https://dev.next.forgejo.org.
|
|
||||||
It is running the latest development branch and will confirm the problem is not already fixed.
|
|
||||||
If you can reproduce it, provide a URL in the description.
|
|
||||||
options:
|
|
||||||
- "Yes"
|
|
||||||
- "No"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: description
|
id: description
|
||||||
attributes:
|
attributes:
|
||||||
label: Description
|
label: Description
|
||||||
description: |
|
description: |
|
||||||
Please provide a description of your issue here, with a URL if you were able to reproduce the issue (see above).
|
Please provide a description of your issue here, with a URL if you were able to reproduce the issue (see below).
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
|
@ -40,14 +28,18 @@ body:
|
||||||
attributes:
|
attributes:
|
||||||
label: Forgejo Version
|
label: Forgejo Version
|
||||||
description: Forgejo version (or commit reference) of your instance
|
description: Forgejo version (or commit reference) of your instance
|
||||||
- type: textarea
|
validations:
|
||||||
id: run-info
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: can-reproduce
|
||||||
attributes:
|
attributes:
|
||||||
label: How are you running Forgejo?
|
label: Can you reproduce the bug on Forgejo Next?
|
||||||
description: |
|
description: |
|
||||||
Please include information on whether you built Forgejo yourself, used one of our downloads, or are using some other package.
|
Please try reproducing your issue at [Forgejo Next](https://next.forgejo.org).
|
||||||
Please also tell us how you are running Forgejo, e.g. if it is being run from a container, a command-line, systemd etc.
|
If you can reproduce it, please provide a URL in the Description field.
|
||||||
If you are using a package or systemd tell us what distribution you are using.
|
options:
|
||||||
|
- "Yes"
|
||||||
|
- "No"
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
|
@ -61,6 +53,31 @@ body:
|
||||||
|
|
||||||
Please copy and paste your logs here, with any sensitive information (e.g. API keys) removed/hidden.
|
Please copy and paste your logs here, with any sensitive information (e.g. API keys) removed/hidden.
|
||||||
You can wrap your logs in `<details>...</details>` tags so it doesn't take up too much space in the issue.
|
You can wrap your logs in `<details>...</details>` tags so it doesn't take up too much space in the issue.
|
||||||
|
- type: textarea
|
||||||
|
id: screenshots
|
||||||
|
attributes:
|
||||||
|
label: Screenshots
|
||||||
|
description: If this issue involves the Web Interface, please provide one or more screenshots
|
||||||
|
- type: input
|
||||||
|
id: git-ver
|
||||||
|
attributes:
|
||||||
|
label: Git Version
|
||||||
|
description: The version of git running on the server
|
||||||
|
- type: input
|
||||||
|
id: os-ver
|
||||||
|
attributes:
|
||||||
|
label: Operating System
|
||||||
|
description: The operating system you are using to run Forgejo
|
||||||
|
- type: textarea
|
||||||
|
id: run-info
|
||||||
|
attributes:
|
||||||
|
label: How are you running Forgejo?
|
||||||
|
description: |
|
||||||
|
Please include information on whether you built Forgejo yourself, used one of our downloads, or are using some other package.
|
||||||
|
Please also tell us how you are running Forgejo, e.g. if it is being run from docker, a command-line, systemd etc.
|
||||||
|
If you are using a package or systemd tell us what distribution you are using.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
- type: dropdown
|
- type: dropdown
|
||||||
id: database
|
id: database
|
||||||
attributes:
|
attributes:
|
||||||
|
@ -70,3 +87,4 @@ body:
|
||||||
- SQLite
|
- SQLite
|
||||||
- PostgreSQL
|
- PostgreSQL
|
||||||
- MySQL
|
- MySQL
|
||||||
|
- MSSQL
|
|
@ -1,6 +1,6 @@
|
||||||
name: 💡 Feature Request
|
name: 💡 Feature Request
|
||||||
description: Got an idea for a feature that Forgejo doesn't have yet? Suggest it here!
|
description: Got an idea for a feature that Forgejo doesn't have yet? Suggest it here!
|
||||||
title: "feat: "
|
title: "[FEAT] "
|
||||||
labels: ["enhancement/feature"]
|
labels: ["enhancement/feature"]
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
4
.gitea/pull_request_template.md
Normal file
4
.gitea/pull_request_template.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<!--
|
||||||
|
Before submitting a PR, please read the contributing guidelines:
|
||||||
|
https://codeberg.org/forgejo/forgejo/src/branch/forgejo/CONTRIBUTING.md
|
||||||
|
-->
|
11
.gitignore
vendored
11
.gitignore
vendored
|
@ -18,7 +18,7 @@ _test
|
||||||
|
|
||||||
# MS VSCode
|
# MS VSCode
|
||||||
.vscode
|
.vscode
|
||||||
__debug_bin*
|
__debug_bin
|
||||||
|
|
||||||
*.cgo1.go
|
*.cgo1.go
|
||||||
*.cgo2.c
|
*.cgo2.c
|
||||||
|
@ -64,7 +64,7 @@ cpu.out
|
||||||
/data
|
/data
|
||||||
/indexers
|
/indexers
|
||||||
/log
|
/log
|
||||||
/public/assets/img/avatar
|
/public/img/avatar
|
||||||
/tests/integration/gitea-integration-*
|
/tests/integration/gitea-integration-*
|
||||||
/tests/integration/indexers-*
|
/tests/integration/indexers-*
|
||||||
/tests/e2e/gitea-e2e-*
|
/tests/e2e/gitea-e2e-*
|
||||||
|
@ -83,6 +83,7 @@ cpu.out
|
||||||
/public/assets/css
|
/public/assets/css
|
||||||
/public/assets/fonts
|
/public/assets/fonts
|
||||||
/public/assets/licenses.txt
|
/public/assets/licenses.txt
|
||||||
|
/public/assets/img/webpack
|
||||||
/vendor
|
/vendor
|
||||||
/web_src/fomantic/node_modules
|
/web_src/fomantic/node_modules
|
||||||
/web_src/fomantic/build/*
|
/web_src/fomantic/build/*
|
||||||
|
@ -101,9 +102,6 @@ cpu.out
|
||||||
/.go-licenses
|
/.go-licenses
|
||||||
/.cur-deadcode-out
|
/.cur-deadcode-out
|
||||||
|
|
||||||
# Files and folders that were previously generated
|
|
||||||
/public/assets/img/webpack
|
|
||||||
|
|
||||||
# Snapcraft
|
# Snapcraft
|
||||||
/gitea_a*.txt
|
/gitea_a*.txt
|
||||||
snap/.snapcraft/
|
snap/.snapcraft/
|
||||||
|
@ -115,9 +113,6 @@ prime/
|
||||||
*_source.tar.bz2
|
*_source.tar.bz2
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# nix-direnv generated files
|
|
||||||
.direnv/
|
|
||||||
|
|
||||||
# Make evidence files
|
# Make evidence files
|
||||||
/.make_evidence
|
/.make_evidence
|
||||||
|
|
||||||
|
|
19
.gitpod.yml
19
.gitpod.yml
|
@ -10,19 +10,10 @@ tasks:
|
||||||
- name: Run backend
|
- name: Run backend
|
||||||
command: |
|
command: |
|
||||||
gp sync-await setup
|
gp sync-await setup
|
||||||
|
if [ ! -f custom/conf/app.ini ]
|
||||||
# Get the URL and extract the domain
|
then
|
||||||
url=$(gp url 3000)
|
|
||||||
domain=$(echo $url | awk -F[/:] '{print $4}')
|
|
||||||
|
|
||||||
if [ -f custom/conf/app.ini ]; then
|
|
||||||
sed -i "s|^ROOT_URL =.*|ROOT_URL = ${url}/|" custom/conf/app.ini
|
|
||||||
sed -i "s|^DOMAIN =.*|DOMAIN = ${domain}|" custom/conf/app.ini
|
|
||||||
sed -i "s|^SSH_DOMAIN =.*|SSH_DOMAIN = ${domain}|" custom/conf/app.ini
|
|
||||||
sed -i "s|^NO_REPLY_ADDRESS =.*|SSH_DOMAIN = noreply.${domain}|" custom/conf/app.ini
|
|
||||||
else
|
|
||||||
mkdir -p custom/conf/
|
mkdir -p custom/conf/
|
||||||
echo -e "[server]\nROOT_URL = ${url}/" > custom/conf/app.ini
|
echo -e "[server]\nROOT_URL=$(gp url 3000)/" > custom/conf/app.ini
|
||||||
echo -e "\n[database]\nDB_TYPE = sqlite3\nPATH = $GITPOD_REPO_ROOT/data/gitea.db" >> custom/conf/app.ini
|
echo -e "\n[database]\nDB_TYPE = sqlite3\nPATH = $GITPOD_REPO_ROOT/data/gitea.db" >> custom/conf/app.ini
|
||||||
fi
|
fi
|
||||||
export TAGS="sqlite sqlite_unlock_notify"
|
export TAGS="sqlite sqlite_unlock_notify"
|
||||||
|
@ -42,8 +33,8 @@ vscode:
|
||||||
- DavidAnson.vscode-markdownlint
|
- DavidAnson.vscode-markdownlint
|
||||||
- Vue.volar
|
- Vue.volar
|
||||||
- ms-azuretools.vscode-docker
|
- ms-azuretools.vscode-docker
|
||||||
- vitest.explorer
|
- zixuanchen.vitest-explorer
|
||||||
- cweijan.vscode-database-client2
|
- qwtel.sqlite-viewer
|
||||||
- GitHub.vscode-pull-request-github
|
- GitHub.vscode-pull-request-github
|
||||||
|
|
||||||
ports:
|
ports:
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
linters:
|
linters:
|
||||||
enable-all: false
|
|
||||||
disable-all: true
|
|
||||||
fast: false
|
|
||||||
enable:
|
enable:
|
||||||
- bidichk
|
- bidichk
|
||||||
|
# - deadcode # deprecated - https://github.com/golangci/golangci-lint/issues/1841
|
||||||
- depguard
|
- depguard
|
||||||
- dupl
|
- dupl
|
||||||
- errcheck
|
- errcheck
|
||||||
- forbidigo
|
- forbidigo
|
||||||
- gocritic
|
- gocritic
|
||||||
|
# - gocyclo # The cyclomatic complexety of a lot of functions is too high, we should refactor those another time.
|
||||||
- gofmt
|
- gofmt
|
||||||
- gofumpt
|
- gofumpt
|
||||||
- gosimple
|
- gosimple
|
||||||
|
@ -18,22 +17,23 @@ linters:
|
||||||
- nolintlint
|
- nolintlint
|
||||||
- revive
|
- revive
|
||||||
- staticcheck
|
- staticcheck
|
||||||
|
# - structcheck # deprecated - https://github.com/golangci/golangci-lint/issues/1841
|
||||||
- stylecheck
|
- stylecheck
|
||||||
- tenv
|
|
||||||
- testifylint
|
|
||||||
- typecheck
|
- typecheck
|
||||||
- unconvert
|
- unconvert
|
||||||
- unused
|
- unused
|
||||||
- unparam
|
# - varcheck # deprecated - https://github.com/golangci/golangci-lint/issues/1841
|
||||||
- wastedassign
|
- wastedassign
|
||||||
|
enable-all: false
|
||||||
|
disable-all: true
|
||||||
|
fast: false
|
||||||
|
|
||||||
run:
|
run:
|
||||||
timeout: 10m
|
timeout: 10m
|
||||||
|
skip-dirs:
|
||||||
output:
|
- node_modules
|
||||||
sort-results: true
|
- public
|
||||||
sort-order: [file]
|
- web_src
|
||||||
show-stats: true
|
|
||||||
|
|
||||||
linters-settings:
|
linters-settings:
|
||||||
stylecheck:
|
stylecheck:
|
||||||
|
@ -43,40 +43,35 @@ linters-settings:
|
||||||
gocritic:
|
gocritic:
|
||||||
disabled-checks:
|
disabled-checks:
|
||||||
- ifElseChain
|
- ifElseChain
|
||||||
|
- singleCaseSwitch # Every time this occurred in the code, there was no other way.
|
||||||
revive:
|
revive:
|
||||||
severity: error
|
ignore-generated-header: false
|
||||||
|
severity: warning
|
||||||
|
confidence: 0.8
|
||||||
|
errorCode: 1
|
||||||
|
warningCode: 1
|
||||||
rules:
|
rules:
|
||||||
- name: atomic
|
|
||||||
- name: bare-return
|
|
||||||
- name: blank-imports
|
- name: blank-imports
|
||||||
- name: constant-logical-expr
|
|
||||||
- name: context-as-argument
|
- name: context-as-argument
|
||||||
- name: context-keys-type
|
- name: context-keys-type
|
||||||
- name: dot-imports
|
- name: dot-imports
|
||||||
- name: duplicated-imports
|
|
||||||
- name: empty-lines
|
|
||||||
- name: error-naming
|
|
||||||
- name: error-return
|
- name: error-return
|
||||||
- name: error-strings
|
- name: error-strings
|
||||||
- name: errorf
|
- name: error-naming
|
||||||
- name: exported
|
- name: exported
|
||||||
- name: identical-branches
|
|
||||||
- name: if-return
|
- name: if-return
|
||||||
- name: increment-decrement
|
- name: increment-decrement
|
||||||
- name: indent-error-flow
|
- name: var-naming
|
||||||
- name: modifies-value-receiver
|
- name: var-declaration
|
||||||
- name: package-comments
|
- name: package-comments
|
||||||
- name: range
|
- name: range
|
||||||
- name: receiver-naming
|
- name: receiver-naming
|
||||||
- name: redefines-builtin-id
|
|
||||||
- name: string-of-int
|
|
||||||
- name: superfluous-else
|
|
||||||
- name: time-naming
|
- name: time-naming
|
||||||
- name: unconditional-recursion
|
|
||||||
- name: unexported-return
|
- name: unexported-return
|
||||||
- name: unreachable-code
|
- name: indent-error-flow
|
||||||
- name: var-declaration
|
- name: errorf
|
||||||
- name: var-naming
|
- name: duplicated-imports
|
||||||
|
- name: modifies-value-receiver
|
||||||
gofumpt:
|
gofumpt:
|
||||||
extra-rules: true
|
extra-rules: true
|
||||||
depguard:
|
depguard:
|
||||||
|
@ -95,21 +90,12 @@ linters-settings:
|
||||||
desc: do not use the internal package, use AddXxx function instead
|
desc: do not use the internal package, use AddXxx function instead
|
||||||
- pkg: gopkg.in/ini.v1
|
- pkg: gopkg.in/ini.v1
|
||||||
desc: do not use the ini package, use gitea's config system instead
|
desc: do not use the ini package, use gitea's config system instead
|
||||||
- pkg: github.com/minio/sha256-simd
|
|
||||||
desc: use crypto/sha256 instead, see https://codeberg.org/forgejo/forgejo/pulls/1528
|
|
||||||
testifylint:
|
|
||||||
disable:
|
|
||||||
- go-require
|
|
||||||
|
|
||||||
issues:
|
issues:
|
||||||
max-issues-per-linter: 0
|
max-issues-per-linter: 0
|
||||||
max-same-issues: 0
|
max-same-issues: 0
|
||||||
exclude-dirs: [node_modules, public, web_src]
|
|
||||||
exclude-case-sensitive: true
|
|
||||||
exclude-rules:
|
exclude-rules:
|
||||||
- path: models/db/sql_postgres_with_schema.go
|
# Exclude some linters from running on tests files.
|
||||||
linters:
|
|
||||||
- nolintlint
|
|
||||||
- path: _test\.go
|
- path: _test\.go
|
||||||
linters:
|
linters:
|
||||||
- gocyclo
|
- gocyclo
|
||||||
|
@ -127,19 +113,19 @@ issues:
|
||||||
- path: cmd
|
- path: cmd
|
||||||
linters:
|
linters:
|
||||||
- forbidigo
|
- forbidigo
|
||||||
- text: "webhook"
|
- linters:
|
||||||
linters:
|
|
||||||
- dupl
|
- dupl
|
||||||
- text: "`ID' should not be capitalized"
|
text: "webhook"
|
||||||
linters:
|
- linters:
|
||||||
- gocritic
|
- gocritic
|
||||||
- text: "swagger"
|
text: "`ID' should not be capitalized"
|
||||||
linters:
|
- linters:
|
||||||
- unused
|
- unused
|
||||||
- deadcode
|
- deadcode
|
||||||
- text: "argument x is overwritten before first use"
|
text: "swagger"
|
||||||
linters:
|
- linters:
|
||||||
- staticcheck
|
- staticcheck
|
||||||
|
text: "argument x is overwritten before first use"
|
||||||
- text: "commentFormatting: put a space between `//` and comment text"
|
- text: "commentFormatting: put a space between `//` and comment text"
|
||||||
linters:
|
linters:
|
||||||
- gocritic
|
- gocritic
|
||||||
|
|
4
.ignore
4
.ignore
|
@ -4,8 +4,6 @@
|
||||||
/modules/options/bindata.go
|
/modules/options/bindata.go
|
||||||
/modules/public/bindata.go
|
/modules/public/bindata.go
|
||||||
/modules/templates/bindata.go
|
/modules/templates/bindata.go
|
||||||
/options/gitignore
|
|
||||||
/options/license
|
|
||||||
/public/assets
|
|
||||||
/vendor
|
/vendor
|
||||||
|
/public/assets
|
||||||
node_modules
|
node_modules
|
||||||
|
|
2
.mailmap
2
.mailmap
|
@ -1,2 +0,0 @@
|
||||||
Unknwon <u@gogs.io> <joe2010xtmf@163.com>
|
|
||||||
Unknwon <u@gogs.io> 无闻 <u@gogs.io>
|
|
|
@ -1,27 +0,0 @@
|
||||||
categorize: './release-notes-assistant.sh'
|
|
||||||
branch-development: 'forgejo'
|
|
||||||
branch-pattern: 'v*/forgejo'
|
|
||||||
branch-find-version: 'v(?P<version>\d+\.\d+)/forgejo'
|
|
||||||
branch-to-version: '${version}.0'
|
|
||||||
branch-from-version: 'v%[1]d.%[2]d/forgejo'
|
|
||||||
tag-from-version: 'v%[1]d.%[2]d.%[3]d'
|
|
||||||
branch-known:
|
|
||||||
- 'v7.0/forgejo'
|
|
||||||
cleanup-line: 'sed -Ee "s/^(feat|fix):\s*//g" -e "s/^\[WIP\] //" -e "s/^WIP: //" -e "s;\[(UI|BUG|FEAT|v.*?/forgejo)\]\s*;;g"'
|
|
||||||
render-header: |
|
|
||||||
|
|
||||||
## Draft release notes
|
|
||||||
comment: |
|
|
||||||
<details>
|
|
||||||
<summary>Where does that come from?</summary>
|
|
||||||
The following is a preview of the release notes for this pull request, as they will appear in the upcoming release. They are derived from the content of the `%[2]s/%[3]s.md` file, if it exists, or the title of the pull request. They were also added at the bottom of the description of this pull request for easier reference.
|
|
||||||
|
|
||||||
This message and the release notes originate from a call to the [release-notes-assistant](https://code.forgejo.org/forgejo/release-notes-assistant).
|
|
||||||
|
|
||||||
```diff
|
|
||||||
%[4]s
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
%[1]s
|
|
221
.stylelintrc.yaml
Normal file
221
.stylelintrc.yaml
Normal file
|
@ -0,0 +1,221 @@
|
||||||
|
plugins:
|
||||||
|
- stylelint-declaration-strict-value
|
||||||
|
- stylelint-declaration-block-no-ignored-properties
|
||||||
|
- stylelint-stylistic
|
||||||
|
|
||||||
|
ignoreFiles:
|
||||||
|
- "**/*.go"
|
||||||
|
|
||||||
|
overrides:
|
||||||
|
- files: ["**/chroma/*", "**/codemirror/*", "**/standalone/*", "**/console.css", "font_i18n.css"]
|
||||||
|
rules:
|
||||||
|
scale-unlimited/declaration-strict-value: null
|
||||||
|
- files: ["**/chroma/*", "**/codemirror/*"]
|
||||||
|
rules:
|
||||||
|
block-no-empty: null
|
||||||
|
- files: ["**/*.vue"]
|
||||||
|
customSyntax: postcss-html
|
||||||
|
|
||||||
|
rules:
|
||||||
|
alpha-value-notation: null
|
||||||
|
annotation-no-unknown: true
|
||||||
|
at-rule-allowed-list: null
|
||||||
|
at-rule-disallowed-list: null
|
||||||
|
at-rule-empty-line-before: null
|
||||||
|
at-rule-no-unknown: true
|
||||||
|
at-rule-no-vendor-prefix: true
|
||||||
|
at-rule-property-required-list: null
|
||||||
|
block-no-empty: true
|
||||||
|
color-function-notation: null
|
||||||
|
color-hex-alpha: null
|
||||||
|
color-hex-length: null
|
||||||
|
color-named: null
|
||||||
|
color-no-hex: null
|
||||||
|
color-no-invalid-hex: true
|
||||||
|
comment-empty-line-before: null
|
||||||
|
comment-no-empty: true
|
||||||
|
comment-pattern: null
|
||||||
|
comment-whitespace-inside: null
|
||||||
|
comment-word-disallowed-list: null
|
||||||
|
custom-media-pattern: null
|
||||||
|
custom-property-empty-line-before: null
|
||||||
|
custom-property-no-missing-var-function: true
|
||||||
|
custom-property-pattern: null
|
||||||
|
declaration-block-no-duplicate-custom-properties: true
|
||||||
|
declaration-block-no-duplicate-properties: [true, {ignore: [consecutive-duplicates-with-different-values]}]
|
||||||
|
declaration-block-no-redundant-longhand-properties: null
|
||||||
|
declaration-block-no-shorthand-property-overrides: null
|
||||||
|
declaration-block-single-line-max-declarations: null
|
||||||
|
declaration-empty-line-before: null
|
||||||
|
declaration-no-important: null
|
||||||
|
declaration-property-max-values: null
|
||||||
|
declaration-property-unit-allowed-list: null
|
||||||
|
declaration-property-unit-disallowed-list: {line-height: [em]}
|
||||||
|
declaration-property-value-allowed-list: null
|
||||||
|
declaration-property-value-disallowed-list: null
|
||||||
|
declaration-property-value-no-unknown: true
|
||||||
|
font-family-name-quotes: always-where-recommended
|
||||||
|
font-family-no-duplicate-names: true
|
||||||
|
font-family-no-missing-generic-family-keyword: true
|
||||||
|
font-weight-notation: null
|
||||||
|
function-allowed-list: null
|
||||||
|
function-calc-no-unspaced-operator: true
|
||||||
|
function-disallowed-list: null
|
||||||
|
function-linear-gradient-no-nonstandard-direction: true
|
||||||
|
function-name-case: lower
|
||||||
|
function-no-unknown: null
|
||||||
|
function-url-no-scheme-relative: null
|
||||||
|
function-url-quotes: always
|
||||||
|
function-url-scheme-allowed-list: null
|
||||||
|
function-url-scheme-disallowed-list: null
|
||||||
|
hue-degree-notation: null
|
||||||
|
import-notation: string
|
||||||
|
keyframe-block-no-duplicate-selectors: true
|
||||||
|
keyframe-declaration-no-important: true
|
||||||
|
keyframe-selector-notation: null
|
||||||
|
keyframes-name-pattern: null
|
||||||
|
length-zero-no-unit: [true, ignore: [custom-properties], ignoreFunctions: [var]]
|
||||||
|
max-nesting-depth: null
|
||||||
|
media-feature-name-allowed-list: null
|
||||||
|
media-feature-name-disallowed-list: null
|
||||||
|
media-feature-name-no-unknown: true
|
||||||
|
media-feature-name-no-vendor-prefix: true
|
||||||
|
media-feature-name-unit-allowed-list: null
|
||||||
|
media-feature-name-value-allowed-list: null
|
||||||
|
media-feature-name-value-no-unknown: true
|
||||||
|
media-feature-range-notation: null
|
||||||
|
media-query-no-invalid: true
|
||||||
|
named-grid-areas-no-invalid: true
|
||||||
|
no-descending-specificity: null
|
||||||
|
no-duplicate-at-import-rules: true
|
||||||
|
no-duplicate-selectors: true
|
||||||
|
no-empty-source: true
|
||||||
|
no-invalid-double-slash-comments: true
|
||||||
|
no-invalid-position-at-import-rule: null
|
||||||
|
no-irregular-whitespace: true
|
||||||
|
no-unknown-animations: null
|
||||||
|
no-unknown-custom-properties: null
|
||||||
|
number-max-precision: null
|
||||||
|
plugin/declaration-block-no-ignored-properties: true
|
||||||
|
property-allowed-list: null
|
||||||
|
property-disallowed-list: null
|
||||||
|
property-no-unknown: true
|
||||||
|
property-no-vendor-prefix: null
|
||||||
|
rule-empty-line-before: null
|
||||||
|
rule-selector-property-disallowed-list: null
|
||||||
|
scale-unlimited/declaration-strict-value: [[/color$/, font-weight], {ignoreValues: /^(inherit|transparent|unset|initial|currentcolor|none)$/, ignoreFunctions: false, disableFix: true, expandShorthand: true}]
|
||||||
|
selector-attribute-name-disallowed-list: null
|
||||||
|
selector-attribute-operator-allowed-list: null
|
||||||
|
selector-attribute-operator-disallowed-list: null
|
||||||
|
selector-attribute-quotes: always
|
||||||
|
selector-class-pattern: null
|
||||||
|
selector-combinator-allowed-list: null
|
||||||
|
selector-combinator-disallowed-list: null
|
||||||
|
selector-disallowed-list: null
|
||||||
|
selector-id-pattern: null
|
||||||
|
selector-max-attribute: null
|
||||||
|
selector-max-class: null
|
||||||
|
selector-max-combinators: null
|
||||||
|
selector-max-compound-selectors: null
|
||||||
|
selector-max-id: null
|
||||||
|
selector-max-pseudo-class: null
|
||||||
|
selector-max-specificity: null
|
||||||
|
selector-max-type: null
|
||||||
|
selector-max-universal: null
|
||||||
|
selector-nested-pattern: null
|
||||||
|
selector-no-qualifying-type: null
|
||||||
|
selector-no-vendor-prefix: true
|
||||||
|
selector-not-notation: null
|
||||||
|
selector-pseudo-class-allowed-list: null
|
||||||
|
selector-pseudo-class-disallowed-list: null
|
||||||
|
selector-pseudo-class-no-unknown: true
|
||||||
|
selector-pseudo-element-allowed-list: null
|
||||||
|
selector-pseudo-element-colon-notation: double
|
||||||
|
selector-pseudo-element-disallowed-list: null
|
||||||
|
selector-pseudo-element-no-unknown: true
|
||||||
|
selector-type-case: lower
|
||||||
|
selector-type-no-unknown: [true, {ignore: [custom-elements]}]
|
||||||
|
shorthand-property-no-redundant-values: true
|
||||||
|
string-no-newline: true
|
||||||
|
stylistic/at-rule-name-case: null
|
||||||
|
stylistic/at-rule-name-newline-after: null
|
||||||
|
stylistic/at-rule-name-space-after: null
|
||||||
|
stylistic/at-rule-semicolon-newline-after: null
|
||||||
|
stylistic/at-rule-semicolon-space-before: null
|
||||||
|
stylistic/block-closing-brace-empty-line-before: null
|
||||||
|
stylistic/block-closing-brace-newline-after: null
|
||||||
|
stylistic/block-closing-brace-newline-before: null
|
||||||
|
stylistic/block-closing-brace-space-after: null
|
||||||
|
stylistic/block-closing-brace-space-before: null
|
||||||
|
stylistic/block-opening-brace-newline-after: null
|
||||||
|
stylistic/block-opening-brace-newline-before: null
|
||||||
|
stylistic/block-opening-brace-space-after: null
|
||||||
|
stylistic/block-opening-brace-space-before: null
|
||||||
|
stylistic/color-hex-case: lower
|
||||||
|
stylistic/declaration-bang-space-after: never
|
||||||
|
stylistic/declaration-bang-space-before: null
|
||||||
|
stylistic/declaration-block-semicolon-newline-after: null
|
||||||
|
stylistic/declaration-block-semicolon-newline-before: null
|
||||||
|
stylistic/declaration-block-semicolon-space-after: null
|
||||||
|
stylistic/declaration-block-semicolon-space-before: never
|
||||||
|
stylistic/declaration-block-trailing-semicolon: null
|
||||||
|
stylistic/declaration-colon-newline-after: null
|
||||||
|
stylistic/declaration-colon-space-after: null
|
||||||
|
stylistic/declaration-colon-space-before: never
|
||||||
|
stylistic/function-comma-newline-after: null
|
||||||
|
stylistic/function-comma-newline-before: null
|
||||||
|
stylistic/function-comma-space-after: null
|
||||||
|
stylistic/function-comma-space-before: null
|
||||||
|
stylistic/function-max-empty-lines: 0
|
||||||
|
stylistic/function-parentheses-newline-inside: never-multi-line
|
||||||
|
stylistic/function-parentheses-space-inside: null
|
||||||
|
stylistic/function-whitespace-after: null
|
||||||
|
stylistic/indentation: 2
|
||||||
|
stylistic/linebreaks: null
|
||||||
|
stylistic/max-empty-lines: 1
|
||||||
|
stylistic/max-line-length: null
|
||||||
|
stylistic/media-feature-colon-space-after: null
|
||||||
|
stylistic/media-feature-colon-space-before: never
|
||||||
|
stylistic/media-feature-name-case: null
|
||||||
|
stylistic/media-feature-parentheses-space-inside: null
|
||||||
|
stylistic/media-feature-range-operator-space-after: always
|
||||||
|
stylistic/media-feature-range-operator-space-before: always
|
||||||
|
stylistic/media-query-list-comma-newline-after: null
|
||||||
|
stylistic/media-query-list-comma-newline-before: null
|
||||||
|
stylistic/media-query-list-comma-space-after: null
|
||||||
|
stylistic/media-query-list-comma-space-before: null
|
||||||
|
stylistic/no-empty-first-line: null
|
||||||
|
stylistic/no-eol-whitespace: true
|
||||||
|
stylistic/no-extra-semicolons: true
|
||||||
|
stylistic/no-missing-end-of-source-newline: null
|
||||||
|
stylistic/number-leading-zero: null
|
||||||
|
stylistic/number-no-trailing-zeros: null
|
||||||
|
stylistic/property-case: lower
|
||||||
|
stylistic/selector-attribute-brackets-space-inside: null
|
||||||
|
stylistic/selector-attribute-operator-space-after: null
|
||||||
|
stylistic/selector-attribute-operator-space-before: null
|
||||||
|
stylistic/selector-combinator-space-after: null
|
||||||
|
stylistic/selector-combinator-space-before: null
|
||||||
|
stylistic/selector-descendant-combinator-no-non-space: null
|
||||||
|
stylistic/selector-list-comma-newline-after: null
|
||||||
|
stylistic/selector-list-comma-newline-before: null
|
||||||
|
stylistic/selector-list-comma-space-after: always-single-line
|
||||||
|
stylistic/selector-list-comma-space-before: never-single-line
|
||||||
|
stylistic/selector-max-empty-lines: 0
|
||||||
|
stylistic/selector-pseudo-class-case: lower
|
||||||
|
stylistic/selector-pseudo-class-parentheses-space-inside: never
|
||||||
|
stylistic/selector-pseudo-element-case: lower
|
||||||
|
stylistic/string-quotes: double
|
||||||
|
stylistic/unicode-bom: null
|
||||||
|
stylistic/unit-case: lower
|
||||||
|
stylistic/value-list-comma-newline-after: null
|
||||||
|
stylistic/value-list-comma-newline-before: null
|
||||||
|
stylistic/value-list-comma-space-after: null
|
||||||
|
stylistic/value-list-comma-space-before: null
|
||||||
|
stylistic/value-list-max-empty-lines: 0
|
||||||
|
time-min-milliseconds: null
|
||||||
|
unit-allowed-list: null
|
||||||
|
unit-disallowed-list: null
|
||||||
|
unit-no-unknown: true
|
||||||
|
value-keyword-case: null
|
||||||
|
value-no-vendor-prefix: [true, {ignoreValues: [box, inline-box]}]
|
8355
CHANGELOG.md
Normal file
8355
CHANGELOG.md
Normal file
File diff suppressed because it is too large
Load diff
20
CODEOWNERS
20
CODEOWNERS
|
@ -6,6 +6,9 @@
|
||||||
|
|
||||||
# Please mind the alphabetic order of reviewers.
|
# Please mind the alphabetic order of reviewers.
|
||||||
|
|
||||||
|
# Files related to the CI of the Forgejo project.
|
||||||
|
.forgejo/.* @dachary @earl-warren
|
||||||
|
|
||||||
# Files related to frontend development.
|
# Files related to frontend development.
|
||||||
|
|
||||||
# Javascript and CSS code.
|
# Javascript and CSS code.
|
||||||
|
@ -13,28 +16,17 @@ web_src/.* @caesar @crystal @gusted
|
||||||
|
|
||||||
# HTML templates used by the backend.
|
# HTML templates used by the backend.
|
||||||
templates/.* @caesar @crystal @gusted
|
templates/.* @caesar @crystal @gusted
|
||||||
## the issue sidebar was touched by fnetx
|
|
||||||
templates/repo/issue/view_content/sidebar.* @fnetx
|
|
||||||
|
|
||||||
# Playwright tests
|
|
||||||
tests/e2e/.* @fnetx
|
|
||||||
|
|
||||||
# Files related to Go development.
|
# Files related to Go development.
|
||||||
|
|
||||||
# The modules usually don't require much knowledge about Forgejo and could
|
# The modules usually don't require much knowledge about Forgejo and could
|
||||||
# be reviewed by Go developers.
|
# be reviewed by Go developers.
|
||||||
modules/.* @gusted
|
modules/.* @dachary @earl-warren @gusted
|
||||||
|
|
||||||
# Models has code related to SQL queries, general database knowledge and XORM.
|
# Models has code related to SQL queries, general database knowledge and XORM.
|
||||||
models/.* @gusted
|
models/.* @dachary @earl-warren @gusted
|
||||||
|
|
||||||
# The routers directory contains the most amount code that requires a good grasp
|
# The routers directory contains the most amount code that requires a good grasp
|
||||||
# of how Forgejo comes together. It's tedious to write good integration testing
|
# of how Forgejo comes together. It's tedious to write good integration testing
|
||||||
# for code that lives in here.
|
# for code that lives in here.
|
||||||
routers/.* @gusted
|
routers/.* @dachary @earl-warren @gusted
|
||||||
|
|
||||||
# Let new strings be checked by the translation team.
|
|
||||||
options/locale/locale_en-US.ini @0ko
|
|
||||||
|
|
||||||
# Personal interest
|
|
||||||
.*/webhook.* @oliverpool
|
|
||||||
|
|
|
@ -4,4 +4,21 @@ The Forgejo project is run by a community of people who are expected to follow t
|
||||||
|
|
||||||
Sensitive security-related issues should be reported to [security@forgejo.org](mailto:security@forgejo.org) using [encryption](https://keyoxide.org/security@forgejo.org).
|
Sensitive security-related issues should be reported to [security@forgejo.org](mailto:security@forgejo.org) using [encryption](https://keyoxide.org/security@forgejo.org).
|
||||||
|
|
||||||
You can find links to the different aspects of Developer documentation on this page: [Forgejo Contributor Guide](https://forgejo.org/docs/next/contributor/).
|
## For everyone involved
|
||||||
|
|
||||||
|
- [Documentation](https://forgejo.org/docs/next/)
|
||||||
|
- [Code of Conduct](https://forgejo.org/docs/latest/developer/coc/)
|
||||||
|
- [Bugs, features, security and others discussions](https://forgejo.org/docs/latest/developer/discussions/)
|
||||||
|
- [Governance](https://forgejo.org/docs/latest/developer/governance/)
|
||||||
|
- [Sustainability and funding](https://codeberg.org/forgejo/sustainability/src/branch/main/README.md)
|
||||||
|
|
||||||
|
## For contributors
|
||||||
|
|
||||||
|
- [Developer Certificate of Origin (DCO)](https://forgejo.org/docs/latest/developer/dco/)
|
||||||
|
- [Development workflow](https://forgejo.org/docs/latest/developer/workflow/)
|
||||||
|
- [Compiling from source](https://forgejo.org/docs/latest/developer/from-source/)
|
||||||
|
|
||||||
|
## For maintainers
|
||||||
|
|
||||||
|
- [Release management](https://forgejo.org/docs/latest/developer/release/)
|
||||||
|
- [Secrets](https://forgejo.org/docs/latest/developer/secrets/)
|
||||||
|
|
31
Dockerfile
31
Dockerfile
|
@ -1,13 +1,13 @@
|
||||||
FROM --platform=$BUILDPLATFORM docker.io/tonistiigi/xx AS xx
|
FROM --platform=$BUILDPLATFORM docker.io/tonistiigi/xx AS xx
|
||||||
|
|
||||||
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.23-alpine3.20 as build-env
|
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.21-alpine3.19 as build-env
|
||||||
|
|
||||||
ARG GOPROXY
|
ARG GOPROXY
|
||||||
ENV GOPROXY=${GOPROXY:-direct}
|
ENV GOPROXY ${GOPROXY:-direct}
|
||||||
|
|
||||||
ARG RELEASE_VERSION
|
ARG GITEA_VERSION
|
||||||
ARG TAGS="sqlite sqlite_unlock_notify"
|
ARG TAGS="sqlite sqlite_unlock_notify"
|
||||||
ENV TAGS="bindata timetzdata $TAGS"
|
ENV TAGS "bindata timetzdata $TAGS"
|
||||||
ARG CGO_EXTRA_CFLAGS
|
ARG CGO_EXTRA_CFLAGS
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -33,10 +33,10 @@ RUN apk --no-cache add build-base git nodejs npm
|
||||||
COPY . ${GOPATH}/src/code.gitea.io/gitea
|
COPY . ${GOPATH}/src/code.gitea.io/gitea
|
||||||
WORKDIR ${GOPATH}/src/code.gitea.io/gitea
|
WORKDIR ${GOPATH}/src/code.gitea.io/gitea
|
||||||
|
|
||||||
RUN make clean
|
RUN make clean-all
|
||||||
RUN make frontend
|
RUN make frontend
|
||||||
RUN go build contrib/environment-to-ini/environment-to-ini.go && xx-verify environment-to-ini
|
RUN go build contrib/environment-to-ini/environment-to-ini.go && xx-verify environment-to-ini
|
||||||
RUN LDFLAGS="-buildid=" make RELEASE_VERSION=$RELEASE_VERSION GOFLAGS="-trimpath" go-check generate-backend static-executable && xx-verify gitea
|
RUN make go-check generate-backend static-executable && xx-verify gitea
|
||||||
|
|
||||||
# Copy local files
|
# Copy local files
|
||||||
COPY docker/root /tmp/local
|
COPY docker/root /tmp/local
|
||||||
|
@ -51,18 +51,8 @@ RUN chmod 755 /tmp/local/usr/bin/entrypoint \
|
||||||
/go/src/code.gitea.io/gitea/environment-to-ini
|
/go/src/code.gitea.io/gitea/environment-to-ini
|
||||||
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
||||||
|
|
||||||
FROM code.forgejo.org/oci/golang:1.23-alpine3.20
|
FROM docker.io/library/alpine:3.19
|
||||||
ARG RELEASE_VERSION
|
LABEL maintainer="contact@forgejo.org"
|
||||||
LABEL maintainer="contact@forgejo.org" \
|
|
||||||
org.opencontainers.image.authors="Forgejo" \
|
|
||||||
org.opencontainers.image.url="https://forgejo.org" \
|
|
||||||
org.opencontainers.image.documentation="https://forgejo.org/download/#container-image" \
|
|
||||||
org.opencontainers.image.source="https://codeberg.org/forgejo/forgejo" \
|
|
||||||
org.opencontainers.image.version="${RELEASE_VERSION}" \
|
|
||||||
org.opencontainers.image.vendor="Forgejo" \
|
|
||||||
org.opencontainers.image.licenses="GPL-3.0-or-later" \
|
|
||||||
org.opencontainers.image.title="Forgejo. Beyond coding. We forge." \
|
|
||||||
org.opencontainers.image.description="Forgejo is a self-hosted lightweight software forge. Easy to install and low maintenance, it just does the job."
|
|
||||||
|
|
||||||
EXPOSE 22 3000
|
EXPOSE 22 3000
|
||||||
|
|
||||||
|
@ -92,8 +82,8 @@ RUN addgroup \
|
||||||
git && \
|
git && \
|
||||||
echo "git:*" | chpasswd -e
|
echo "git:*" | chpasswd -e
|
||||||
|
|
||||||
ENV USER=git
|
ENV USER git
|
||||||
ENV GITEA_CUSTOM=/data/gitea
|
ENV GITEA_CUSTOM /data/gitea
|
||||||
|
|
||||||
VOLUME ["/data"]
|
VOLUME ["/data"]
|
||||||
|
|
||||||
|
@ -103,6 +93,5 @@ CMD ["/bin/s6-svscan", "/etc/s6"]
|
||||||
COPY --from=build-env /tmp/local /
|
COPY --from=build-env /tmp/local /
|
||||||
RUN cd /usr/local/bin ; ln -s gitea forgejo
|
RUN cd /usr/local/bin ; ln -s gitea forgejo
|
||||||
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
||||||
RUN ln /app/gitea/gitea /app/gitea/forgejo-cli
|
|
||||||
COPY --from=build-env /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
|
COPY --from=build-env /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
|
||||||
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh
|
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
FROM --platform=$BUILDPLATFORM docker.io/tonistiigi/xx AS xx
|
FROM --platform=$BUILDPLATFORM docker.io/tonistiigi/xx AS xx
|
||||||
|
|
||||||
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.23-alpine3.20 as build-env
|
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.21-alpine3.19 as build-env
|
||||||
|
|
||||||
ARG GOPROXY
|
ARG GOPROXY
|
||||||
ENV GOPROXY=${GOPROXY:-direct}
|
ENV GOPROXY ${GOPROXY:-direct}
|
||||||
|
|
||||||
ARG RELEASE_VERSION
|
ARG GITEA_VERSION
|
||||||
ARG TAGS="sqlite sqlite_unlock_notify"
|
ARG TAGS="sqlite sqlite_unlock_notify"
|
||||||
ENV TAGS="bindata timetzdata $TAGS"
|
ENV TAGS "bindata timetzdata $TAGS"
|
||||||
ARG CGO_EXTRA_CFLAGS
|
ARG CGO_EXTRA_CFLAGS
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -33,10 +33,10 @@ RUN apk --no-cache add build-base git nodejs npm
|
||||||
COPY . ${GOPATH}/src/code.gitea.io/gitea
|
COPY . ${GOPATH}/src/code.gitea.io/gitea
|
||||||
WORKDIR ${GOPATH}/src/code.gitea.io/gitea
|
WORKDIR ${GOPATH}/src/code.gitea.io/gitea
|
||||||
|
|
||||||
RUN make clean
|
RUN make clean-all
|
||||||
RUN make frontend
|
RUN make frontend
|
||||||
RUN go build contrib/environment-to-ini/environment-to-ini.go && xx-verify environment-to-ini
|
RUN go build contrib/environment-to-ini/environment-to-ini.go && xx-verify environment-to-ini
|
||||||
RUN make RELEASE_VERSION=$RELEASE_VERSION go-check generate-backend static-executable && xx-verify gitea
|
RUN make go-check generate-backend static-executable && xx-verify gitea
|
||||||
|
|
||||||
# Copy local files
|
# Copy local files
|
||||||
COPY docker/rootless /tmp/local
|
COPY docker/rootless /tmp/local
|
||||||
|
@ -49,17 +49,8 @@ RUN chmod 755 /tmp/local/usr/local/bin/docker-entrypoint.sh \
|
||||||
/go/src/code.gitea.io/gitea/environment-to-ini
|
/go/src/code.gitea.io/gitea/environment-to-ini
|
||||||
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
||||||
|
|
||||||
FROM code.forgejo.org/oci/golang:1.23-alpine3.20
|
FROM docker.io/library/alpine:3.19
|
||||||
LABEL maintainer="contact@forgejo.org" \
|
LABEL maintainer="contact@forgejo.org"
|
||||||
org.opencontainers.image.authors="Forgejo" \
|
|
||||||
org.opencontainers.image.url="https://forgejo.org" \
|
|
||||||
org.opencontainers.image.documentation="https://forgejo.org/download/#container-image" \
|
|
||||||
org.opencontainers.image.source="https://codeberg.org/forgejo/forgejo" \
|
|
||||||
org.opencontainers.image.version="${RELEASE_VERSION}" \
|
|
||||||
org.opencontainers.image.vendor="Forgejo" \
|
|
||||||
org.opencontainers.image.licenses="GPL-3.0-or-later" \
|
|
||||||
org.opencontainers.image.title="Forgejo. Beyond coding. We forge." \
|
|
||||||
org.opencontainers.image.description="Forgejo is a self-hosted lightweight software forge. Easy to install and low maintenance, it just does the job."
|
|
||||||
|
|
||||||
EXPOSE 2222 3000
|
EXPOSE 2222 3000
|
||||||
|
|
||||||
|
@ -90,25 +81,22 @@ RUN chown git:git /var/lib/gitea /etc/gitea
|
||||||
COPY --from=build-env /tmp/local /
|
COPY --from=build-env /tmp/local /
|
||||||
RUN cd /usr/local/bin ; ln -s gitea forgejo
|
RUN cd /usr/local/bin ; ln -s gitea forgejo
|
||||||
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
||||||
RUN ln /app/gitea/gitea /app/gitea/forgejo-cli
|
|
||||||
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
|
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
|
||||||
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh
|
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh
|
||||||
|
|
||||||
#git:git
|
#git:git
|
||||||
USER 1000:1000
|
USER 1000:1000
|
||||||
ENV GITEA_WORK_DIR=/var/lib/gitea
|
ENV GITEA_WORK_DIR /var/lib/gitea
|
||||||
ENV GITEA_CUSTOM=/var/lib/gitea/custom
|
ENV GITEA_CUSTOM /var/lib/gitea/custom
|
||||||
ENV GITEA_TEMP=/tmp/gitea
|
ENV GITEA_TEMP /tmp/gitea
|
||||||
ENV TMPDIR=/tmp/gitea
|
ENV TMPDIR /tmp/gitea
|
||||||
|
|
||||||
# Legacy config file for backwards compatibility
|
#TODO add to docs the ability to define the ini to load (useful to test and revert a config)
|
||||||
# TODO: remove on next major version release
|
ENV GITEA_APP_INI /etc/gitea/app.ini
|
||||||
ENV GITEA_APP_INI_LEGACY=/etc/gitea/app.ini
|
ENV HOME "/var/lib/gitea/git"
|
||||||
|
|
||||||
ENV GITEA_APP_INI=${GITEA_CUSTOM}/conf/app.ini
|
|
||||||
ENV HOME="/var/lib/gitea/git"
|
|
||||||
VOLUME ["/var/lib/gitea", "/etc/gitea"]
|
VOLUME ["/var/lib/gitea", "/etc/gitea"]
|
||||||
WORKDIR /var/lib/gitea
|
WORKDIR /var/lib/gitea
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/usr/local/bin/docker-entrypoint.sh"]
|
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/usr/local/bin/docker-entrypoint.sh"]
|
||||||
CMD []
|
CMD []
|
||||||
|
|
||||||
|
|
695
LICENSE
695
LICENSE
|
@ -1,674 +1,21 @@
|
||||||
GNU GENERAL PUBLIC LICENSE
|
Copyright (c) 2022 The Forgejo Authors
|
||||||
Version 3, 29 June 2007
|
Copyright (c) 2016 The Gitea Authors
|
||||||
|
Copyright (c) 2015 The Gogs Authors
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this license document, but changing it is not allowed.
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
Preamble
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
The GNU General Public License is a free, copyleft license for
|
furnished to do so, subject to the following conditions:
|
||||||
software and other kinds of works.
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
The licenses for most software and other practical works are designed
|
all copies or substantial portions of the Software.
|
||||||
to take away your freedom to share and change the works. By contrast,
|
|
||||||
the GNU General Public License is intended to guarantee your freedom to
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
share and change all versions of a program--to make sure it remains free
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
software for all its users. We, the Free Software Foundation, use the
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
GNU General Public License for most of our software; it applies also to
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
any other work released this way by its authors. You can apply it to
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
your programs, too.
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
them if you wish), that you receive source code or can get it if you
|
|
||||||
want it, that you can change the software or use pieces of it in new
|
|
||||||
free programs, and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to prevent others from denying you
|
|
||||||
these rights or asking you to surrender the rights. Therefore, you have
|
|
||||||
certain responsibilities if you distribute copies of the software, or if
|
|
||||||
you modify it: responsibilities to respect the freedom of others.
|
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
|
||||||
gratis or for a fee, you must pass on to the recipients the same
|
|
||||||
freedoms that you received. You must make sure that they, too, receive
|
|
||||||
or can get the source code. And you must show them these terms so they
|
|
||||||
know their rights.
|
|
||||||
|
|
||||||
Developers that use the GNU GPL protect your rights with two steps:
|
|
||||||
(1) assert copyright on the software, and (2) offer you this License
|
|
||||||
giving you legal permission to copy, distribute and/or modify it.
|
|
||||||
|
|
||||||
For the developers' and authors' protection, the GPL clearly explains
|
|
||||||
that there is no warranty for this free software. For both users' and
|
|
||||||
authors' sake, the GPL requires that modified versions be marked as
|
|
||||||
changed, so that their problems will not be attributed erroneously to
|
|
||||||
authors of previous versions.
|
|
||||||
|
|
||||||
Some devices are designed to deny users access to install or run
|
|
||||||
modified versions of the software inside them, although the manufacturer
|
|
||||||
can do so. This is fundamentally incompatible with the aim of
|
|
||||||
protecting users' freedom to change the software. The systematic
|
|
||||||
pattern of such abuse occurs in the area of products for individuals to
|
|
||||||
use, which is precisely where it is most unacceptable. Therefore, we
|
|
||||||
have designed this version of the GPL to prohibit the practice for those
|
|
||||||
products. If such problems arise substantially in other domains, we
|
|
||||||
stand ready to extend this provision to those domains in future versions
|
|
||||||
of the GPL, as needed to protect the freedom of users.
|
|
||||||
|
|
||||||
Finally, every program is threatened constantly by software patents.
|
|
||||||
States should not allow patents to restrict development and use of
|
|
||||||
software on general-purpose computers, but in those that do, we wish to
|
|
||||||
avoid the special danger that patents applied to a free program could
|
|
||||||
make it effectively proprietary. To prevent this, the GPL assures that
|
|
||||||
patents cannot be used to render the program non-free.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
0. Definitions.
|
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU General Public License.
|
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
|
||||||
works, such as semiconductor masks.
|
|
||||||
|
|
||||||
"The Program" refers to any copyrightable work licensed under this
|
|
||||||
License. Each licensee is addressed as "you". "Licensees" and
|
|
||||||
"recipients" may be individuals or organizations.
|
|
||||||
|
|
||||||
To "modify" a work means to copy from or adapt all or part of the work
|
|
||||||
in a fashion requiring copyright permission, other than the making of an
|
|
||||||
exact copy. The resulting work is called a "modified version" of the
|
|
||||||
earlier work or a work "based on" the earlier work.
|
|
||||||
|
|
||||||
A "covered work" means either the unmodified Program or a work based
|
|
||||||
on the Program.
|
|
||||||
|
|
||||||
To "propagate" a work means to do anything with it that, without
|
|
||||||
permission, would make you directly or secondarily liable for
|
|
||||||
infringement under applicable copyright law, except executing it on a
|
|
||||||
computer or modifying a private copy. Propagation includes copying,
|
|
||||||
distribution (with or without modification), making available to the
|
|
||||||
public, and in some countries other activities as well.
|
|
||||||
|
|
||||||
To "convey" a work means any kind of propagation that enables other
|
|
||||||
parties to make or receive copies. Mere interaction with a user through
|
|
||||||
a computer network, with no transfer of a copy, is not conveying.
|
|
||||||
|
|
||||||
An interactive user interface displays "Appropriate Legal Notices"
|
|
||||||
to the extent that it includes a convenient and prominently visible
|
|
||||||
feature that (1) displays an appropriate copyright notice, and (2)
|
|
||||||
tells the user that there is no warranty for the work (except to the
|
|
||||||
extent that warranties are provided), that licensees may convey the
|
|
||||||
work under this License, and how to view a copy of this License. If
|
|
||||||
the interface presents a list of user commands or options, such as a
|
|
||||||
menu, a prominent item in the list meets this criterion.
|
|
||||||
|
|
||||||
1. Source Code.
|
|
||||||
|
|
||||||
The "source code" for a work means the preferred form of the work
|
|
||||||
for making modifications to it. "Object code" means any non-source
|
|
||||||
form of a work.
|
|
||||||
|
|
||||||
A "Standard Interface" means an interface that either is an official
|
|
||||||
standard defined by a recognized standards body, or, in the case of
|
|
||||||
interfaces specified for a particular programming language, one that
|
|
||||||
is widely used among developers working in that language.
|
|
||||||
|
|
||||||
The "System Libraries" of an executable work include anything, other
|
|
||||||
than the work as a whole, that (a) is included in the normal form of
|
|
||||||
packaging a Major Component, but which is not part of that Major
|
|
||||||
Component, and (b) serves only to enable use of the work with that
|
|
||||||
Major Component, or to implement a Standard Interface for which an
|
|
||||||
implementation is available to the public in source code form. A
|
|
||||||
"Major Component", in this context, means a major essential component
|
|
||||||
(kernel, window system, and so on) of the specific operating system
|
|
||||||
(if any) on which the executable work runs, or a compiler used to
|
|
||||||
produce the work, or an object code interpreter used to run it.
|
|
||||||
|
|
||||||
The "Corresponding Source" for a work in object code form means all
|
|
||||||
the source code needed to generate, install, and (for an executable
|
|
||||||
work) run the object code and to modify the work, including scripts to
|
|
||||||
control those activities. However, it does not include the work's
|
|
||||||
System Libraries, or general-purpose tools or generally available free
|
|
||||||
programs which are used unmodified in performing those activities but
|
|
||||||
which are not part of the work. For example, Corresponding Source
|
|
||||||
includes interface definition files associated with source files for
|
|
||||||
the work, and the source code for shared libraries and dynamically
|
|
||||||
linked subprograms that the work is specifically designed to require,
|
|
||||||
such as by intimate data communication or control flow between those
|
|
||||||
subprograms and other parts of the work.
|
|
||||||
|
|
||||||
The Corresponding Source need not include anything that users
|
|
||||||
can regenerate automatically from other parts of the Corresponding
|
|
||||||
Source.
|
|
||||||
|
|
||||||
The Corresponding Source for a work in source code form is that
|
|
||||||
same work.
|
|
||||||
|
|
||||||
2. Basic Permissions.
|
|
||||||
|
|
||||||
All rights granted under this License are granted for the term of
|
|
||||||
copyright on the Program, and are irrevocable provided the stated
|
|
||||||
conditions are met. This License explicitly affirms your unlimited
|
|
||||||
permission to run the unmodified Program. The output from running a
|
|
||||||
covered work is covered by this License only if the output, given its
|
|
||||||
content, constitutes a covered work. This License acknowledges your
|
|
||||||
rights of fair use or other equivalent, as provided by copyright law.
|
|
||||||
|
|
||||||
You may make, run and propagate covered works that you do not
|
|
||||||
convey, without conditions so long as your license otherwise remains
|
|
||||||
in force. You may convey covered works to others for the sole purpose
|
|
||||||
of having them make modifications exclusively for you, or provide you
|
|
||||||
with facilities for running those works, provided that you comply with
|
|
||||||
the terms of this License in conveying all material for which you do
|
|
||||||
not control copyright. Those thus making or running the covered works
|
|
||||||
for you must do so exclusively on your behalf, under your direction
|
|
||||||
and control, on terms that prohibit them from making any copies of
|
|
||||||
your copyrighted material outside their relationship with you.
|
|
||||||
|
|
||||||
Conveying under any other circumstances is permitted solely under
|
|
||||||
the conditions stated below. Sublicensing is not allowed; section 10
|
|
||||||
makes it unnecessary.
|
|
||||||
|
|
||||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
|
||||||
|
|
||||||
No covered work shall be deemed part of an effective technological
|
|
||||||
measure under any applicable law fulfilling obligations under article
|
|
||||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
|
||||||
similar laws prohibiting or restricting circumvention of such
|
|
||||||
measures.
|
|
||||||
|
|
||||||
When you convey a covered work, you waive any legal power to forbid
|
|
||||||
circumvention of technological measures to the extent such circumvention
|
|
||||||
is effected by exercising rights under this License with respect to
|
|
||||||
the covered work, and you disclaim any intention to limit operation or
|
|
||||||
modification of the work as a means of enforcing, against the work's
|
|
||||||
users, your or third parties' legal rights to forbid circumvention of
|
|
||||||
technological measures.
|
|
||||||
|
|
||||||
4. Conveying Verbatim Copies.
|
|
||||||
|
|
||||||
You may convey verbatim copies of the Program's source code as you
|
|
||||||
receive it, in any medium, provided that you conspicuously and
|
|
||||||
appropriately publish on each copy an appropriate copyright notice;
|
|
||||||
keep intact all notices stating that this License and any
|
|
||||||
non-permissive terms added in accord with section 7 apply to the code;
|
|
||||||
keep intact all notices of the absence of any warranty; and give all
|
|
||||||
recipients a copy of this License along with the Program.
|
|
||||||
|
|
||||||
You may charge any price or no price for each copy that you convey,
|
|
||||||
and you may offer support or warranty protection for a fee.
|
|
||||||
|
|
||||||
5. Conveying Modified Source Versions.
|
|
||||||
|
|
||||||
You may convey a work based on the Program, or the modifications to
|
|
||||||
produce it from the Program, in the form of source code under the
|
|
||||||
terms of section 4, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) The work must carry prominent notices stating that you modified
|
|
||||||
it, and giving a relevant date.
|
|
||||||
|
|
||||||
b) The work must carry prominent notices stating that it is
|
|
||||||
released under this License and any conditions added under section
|
|
||||||
7. This requirement modifies the requirement in section 4 to
|
|
||||||
"keep intact all notices".
|
|
||||||
|
|
||||||
c) You must license the entire work, as a whole, under this
|
|
||||||
License to anyone who comes into possession of a copy. This
|
|
||||||
License will therefore apply, along with any applicable section 7
|
|
||||||
additional terms, to the whole of the work, and all its parts,
|
|
||||||
regardless of how they are packaged. This License gives no
|
|
||||||
permission to license the work in any other way, but it does not
|
|
||||||
invalidate such permission if you have separately received it.
|
|
||||||
|
|
||||||
d) If the work has interactive user interfaces, each must display
|
|
||||||
Appropriate Legal Notices; however, if the Program has interactive
|
|
||||||
interfaces that do not display Appropriate Legal Notices, your
|
|
||||||
work need not make them do so.
|
|
||||||
|
|
||||||
A compilation of a covered work with other separate and independent
|
|
||||||
works, which are not by their nature extensions of the covered work,
|
|
||||||
and which are not combined with it such as to form a larger program,
|
|
||||||
in or on a volume of a storage or distribution medium, is called an
|
|
||||||
"aggregate" if the compilation and its resulting copyright are not
|
|
||||||
used to limit the access or legal rights of the compilation's users
|
|
||||||
beyond what the individual works permit. Inclusion of a covered work
|
|
||||||
in an aggregate does not cause this License to apply to the other
|
|
||||||
parts of the aggregate.
|
|
||||||
|
|
||||||
6. Conveying Non-Source Forms.
|
|
||||||
|
|
||||||
You may convey a covered work in object code form under the terms
|
|
||||||
of sections 4 and 5, provided that you also convey the
|
|
||||||
machine-readable Corresponding Source under the terms of this License,
|
|
||||||
in one of these ways:
|
|
||||||
|
|
||||||
a) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by the
|
|
||||||
Corresponding Source fixed on a durable physical medium
|
|
||||||
customarily used for software interchange.
|
|
||||||
|
|
||||||
b) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by a
|
|
||||||
written offer, valid for at least three years and valid for as
|
|
||||||
long as you offer spare parts or customer support for that product
|
|
||||||
model, to give anyone who possesses the object code either (1) a
|
|
||||||
copy of the Corresponding Source for all the software in the
|
|
||||||
product that is covered by this License, on a durable physical
|
|
||||||
medium customarily used for software interchange, for a price no
|
|
||||||
more than your reasonable cost of physically performing this
|
|
||||||
conveying of source, or (2) access to copy the
|
|
||||||
Corresponding Source from a network server at no charge.
|
|
||||||
|
|
||||||
c) Convey individual copies of the object code with a copy of the
|
|
||||||
written offer to provide the Corresponding Source. This
|
|
||||||
alternative is allowed only occasionally and noncommercially, and
|
|
||||||
only if you received the object code with such an offer, in accord
|
|
||||||
with subsection 6b.
|
|
||||||
|
|
||||||
d) Convey the object code by offering access from a designated
|
|
||||||
place (gratis or for a charge), and offer equivalent access to the
|
|
||||||
Corresponding Source in the same way through the same place at no
|
|
||||||
further charge. You need not require recipients to copy the
|
|
||||||
Corresponding Source along with the object code. If the place to
|
|
||||||
copy the object code is a network server, the Corresponding Source
|
|
||||||
may be on a different server (operated by you or a third party)
|
|
||||||
that supports equivalent copying facilities, provided you maintain
|
|
||||||
clear directions next to the object code saying where to find the
|
|
||||||
Corresponding Source. Regardless of what server hosts the
|
|
||||||
Corresponding Source, you remain obligated to ensure that it is
|
|
||||||
available for as long as needed to satisfy these requirements.
|
|
||||||
|
|
||||||
e) Convey the object code using peer-to-peer transmission, provided
|
|
||||||
you inform other peers where the object code and Corresponding
|
|
||||||
Source of the work are being offered to the general public at no
|
|
||||||
charge under subsection 6d.
|
|
||||||
|
|
||||||
A separable portion of the object code, whose source code is excluded
|
|
||||||
from the Corresponding Source as a System Library, need not be
|
|
||||||
included in conveying the object code work.
|
|
||||||
|
|
||||||
A "User Product" is either (1) a "consumer product", which means any
|
|
||||||
tangible personal property which is normally used for personal, family,
|
|
||||||
or household purposes, or (2) anything designed or sold for incorporation
|
|
||||||
into a dwelling. In determining whether a product is a consumer product,
|
|
||||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
|
||||||
product received by a particular user, "normally used" refers to a
|
|
||||||
typical or common use of that class of product, regardless of the status
|
|
||||||
of the particular user or of the way in which the particular user
|
|
||||||
actually uses, or expects or is expected to use, the product. A product
|
|
||||||
is a consumer product regardless of whether the product has substantial
|
|
||||||
commercial, industrial or non-consumer uses, unless such uses represent
|
|
||||||
the only significant mode of use of the product.
|
|
||||||
|
|
||||||
"Installation Information" for a User Product means any methods,
|
|
||||||
procedures, authorization keys, or other information required to install
|
|
||||||
and execute modified versions of a covered work in that User Product from
|
|
||||||
a modified version of its Corresponding Source. The information must
|
|
||||||
suffice to ensure that the continued functioning of the modified object
|
|
||||||
code is in no case prevented or interfered with solely because
|
|
||||||
modification has been made.
|
|
||||||
|
|
||||||
If you convey an object code work under this section in, or with, or
|
|
||||||
specifically for use in, a User Product, and the conveying occurs as
|
|
||||||
part of a transaction in which the right of possession and use of the
|
|
||||||
User Product is transferred to the recipient in perpetuity or for a
|
|
||||||
fixed term (regardless of how the transaction is characterized), the
|
|
||||||
Corresponding Source conveyed under this section must be accompanied
|
|
||||||
by the Installation Information. But this requirement does not apply
|
|
||||||
if neither you nor any third party retains the ability to install
|
|
||||||
modified object code on the User Product (for example, the work has
|
|
||||||
been installed in ROM).
|
|
||||||
|
|
||||||
The requirement to provide Installation Information does not include a
|
|
||||||
requirement to continue to provide support service, warranty, or updates
|
|
||||||
for a work that has been modified or installed by the recipient, or for
|
|
||||||
the User Product in which it has been modified or installed. Access to a
|
|
||||||
network may be denied when the modification itself materially and
|
|
||||||
adversely affects the operation of the network or violates the rules and
|
|
||||||
protocols for communication across the network.
|
|
||||||
|
|
||||||
Corresponding Source conveyed, and Installation Information provided,
|
|
||||||
in accord with this section must be in a format that is publicly
|
|
||||||
documented (and with an implementation available to the public in
|
|
||||||
source code form), and must require no special password or key for
|
|
||||||
unpacking, reading or copying.
|
|
||||||
|
|
||||||
7. Additional Terms.
|
|
||||||
|
|
||||||
"Additional permissions" are terms that supplement the terms of this
|
|
||||||
License by making exceptions from one or more of its conditions.
|
|
||||||
Additional permissions that are applicable to the entire Program shall
|
|
||||||
be treated as though they were included in this License, to the extent
|
|
||||||
that they are valid under applicable law. If additional permissions
|
|
||||||
apply only to part of the Program, that part may be used separately
|
|
||||||
under those permissions, but the entire Program remains governed by
|
|
||||||
this License without regard to the additional permissions.
|
|
||||||
|
|
||||||
When you convey a copy of a covered work, you may at your option
|
|
||||||
remove any additional permissions from that copy, or from any part of
|
|
||||||
it. (Additional permissions may be written to require their own
|
|
||||||
removal in certain cases when you modify the work.) You may place
|
|
||||||
additional permissions on material, added by you to a covered work,
|
|
||||||
for which you have or can give appropriate copyright permission.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, for material you
|
|
||||||
add to a covered work, you may (if authorized by the copyright holders of
|
|
||||||
that material) supplement the terms of this License with terms:
|
|
||||||
|
|
||||||
a) Disclaiming warranty or limiting liability differently from the
|
|
||||||
terms of sections 15 and 16 of this License; or
|
|
||||||
|
|
||||||
b) Requiring preservation of specified reasonable legal notices or
|
|
||||||
author attributions in that material or in the Appropriate Legal
|
|
||||||
Notices displayed by works containing it; or
|
|
||||||
|
|
||||||
c) Prohibiting misrepresentation of the origin of that material, or
|
|
||||||
requiring that modified versions of such material be marked in
|
|
||||||
reasonable ways as different from the original version; or
|
|
||||||
|
|
||||||
d) Limiting the use for publicity purposes of names of licensors or
|
|
||||||
authors of the material; or
|
|
||||||
|
|
||||||
e) Declining to grant rights under trademark law for use of some
|
|
||||||
trade names, trademarks, or service marks; or
|
|
||||||
|
|
||||||
f) Requiring indemnification of licensors and authors of that
|
|
||||||
material by anyone who conveys the material (or modified versions of
|
|
||||||
it) with contractual assumptions of liability to the recipient, for
|
|
||||||
any liability that these contractual assumptions directly impose on
|
|
||||||
those licensors and authors.
|
|
||||||
|
|
||||||
All other non-permissive additional terms are considered "further
|
|
||||||
restrictions" within the meaning of section 10. If the Program as you
|
|
||||||
received it, or any part of it, contains a notice stating that it is
|
|
||||||
governed by this License along with a term that is a further
|
|
||||||
restriction, you may remove that term. If a license document contains
|
|
||||||
a further restriction but permits relicensing or conveying under this
|
|
||||||
License, you may add to a covered work material governed by the terms
|
|
||||||
of that license document, provided that the further restriction does
|
|
||||||
not survive such relicensing or conveying.
|
|
||||||
|
|
||||||
If you add terms to a covered work in accord with this section, you
|
|
||||||
must place, in the relevant source files, a statement of the
|
|
||||||
additional terms that apply to those files, or a notice indicating
|
|
||||||
where to find the applicable terms.
|
|
||||||
|
|
||||||
Additional terms, permissive or non-permissive, may be stated in the
|
|
||||||
form of a separately written license, or stated as exceptions;
|
|
||||||
the above requirements apply either way.
|
|
||||||
|
|
||||||
8. Termination.
|
|
||||||
|
|
||||||
You may not propagate or modify a covered work except as expressly
|
|
||||||
provided under this License. Any attempt otherwise to propagate or
|
|
||||||
modify it is void, and will automatically terminate your rights under
|
|
||||||
this License (including any patent licenses granted under the third
|
|
||||||
paragraph of section 11).
|
|
||||||
|
|
||||||
However, if you cease all violation of this License, then your
|
|
||||||
license from a particular copyright holder is reinstated (a)
|
|
||||||
provisionally, unless and until the copyright holder explicitly and
|
|
||||||
finally terminates your license, and (b) permanently, if the copyright
|
|
||||||
holder fails to notify you of the violation by some reasonable means
|
|
||||||
prior to 60 days after the cessation.
|
|
||||||
|
|
||||||
Moreover, your license from a particular copyright holder is
|
|
||||||
reinstated permanently if the copyright holder notifies you of the
|
|
||||||
violation by some reasonable means, this is the first time you have
|
|
||||||
received notice of violation of this License (for any work) from that
|
|
||||||
copyright holder, and you cure the violation prior to 30 days after
|
|
||||||
your receipt of the notice.
|
|
||||||
|
|
||||||
Termination of your rights under this section does not terminate the
|
|
||||||
licenses of parties who have received copies or rights from you under
|
|
||||||
this License. If your rights have been terminated and not permanently
|
|
||||||
reinstated, you do not qualify to receive new licenses for the same
|
|
||||||
material under section 10.
|
|
||||||
|
|
||||||
9. Acceptance Not Required for Having Copies.
|
|
||||||
|
|
||||||
You are not required to accept this License in order to receive or
|
|
||||||
run a copy of the Program. Ancillary propagation of a covered work
|
|
||||||
occurring solely as a consequence of using peer-to-peer transmission
|
|
||||||
to receive a copy likewise does not require acceptance. However,
|
|
||||||
nothing other than this License grants you permission to propagate or
|
|
||||||
modify any covered work. These actions infringe copyright if you do
|
|
||||||
not accept this License. Therefore, by modifying or propagating a
|
|
||||||
covered work, you indicate your acceptance of this License to do so.
|
|
||||||
|
|
||||||
10. Automatic Licensing of Downstream Recipients.
|
|
||||||
|
|
||||||
Each time you convey a covered work, the recipient automatically
|
|
||||||
receives a license from the original licensors, to run, modify and
|
|
||||||
propagate that work, subject to this License. You are not responsible
|
|
||||||
for enforcing compliance by third parties with this License.
|
|
||||||
|
|
||||||
An "entity transaction" is a transaction transferring control of an
|
|
||||||
organization, or substantially all assets of one, or subdividing an
|
|
||||||
organization, or merging organizations. If propagation of a covered
|
|
||||||
work results from an entity transaction, each party to that
|
|
||||||
transaction who receives a copy of the work also receives whatever
|
|
||||||
licenses to the work the party's predecessor in interest had or could
|
|
||||||
give under the previous paragraph, plus a right to possession of the
|
|
||||||
Corresponding Source of the work from the predecessor in interest, if
|
|
||||||
the predecessor has it or can get it with reasonable efforts.
|
|
||||||
|
|
||||||
You may not impose any further restrictions on the exercise of the
|
|
||||||
rights granted or affirmed under this License. For example, you may
|
|
||||||
not impose a license fee, royalty, or other charge for exercise of
|
|
||||||
rights granted under this License, and you may not initiate litigation
|
|
||||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
|
||||||
any patent claim is infringed by making, using, selling, offering for
|
|
||||||
sale, or importing the Program or any portion of it.
|
|
||||||
|
|
||||||
11. Patents.
|
|
||||||
|
|
||||||
A "contributor" is a copyright holder who authorizes use under this
|
|
||||||
License of the Program or a work on which the Program is based. The
|
|
||||||
work thus licensed is called the contributor's "contributor version".
|
|
||||||
|
|
||||||
A contributor's "essential patent claims" are all patent claims
|
|
||||||
owned or controlled by the contributor, whether already acquired or
|
|
||||||
hereafter acquired, that would be infringed by some manner, permitted
|
|
||||||
by this License, of making, using, or selling its contributor version,
|
|
||||||
but do not include claims that would be infringed only as a
|
|
||||||
consequence of further modification of the contributor version. For
|
|
||||||
purposes of this definition, "control" includes the right to grant
|
|
||||||
patent sublicenses in a manner consistent with the requirements of
|
|
||||||
this License.
|
|
||||||
|
|
||||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
|
||||||
patent license under the contributor's essential patent claims, to
|
|
||||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
|
||||||
propagate the contents of its contributor version.
|
|
||||||
|
|
||||||
In the following three paragraphs, a "patent license" is any express
|
|
||||||
agreement or commitment, however denominated, not to enforce a patent
|
|
||||||
(such as an express permission to practice a patent or covenant not to
|
|
||||||
sue for patent infringement). To "grant" such a patent license to a
|
|
||||||
party means to make such an agreement or commitment not to enforce a
|
|
||||||
patent against the party.
|
|
||||||
|
|
||||||
If you convey a covered work, knowingly relying on a patent license,
|
|
||||||
and the Corresponding Source of the work is not available for anyone
|
|
||||||
to copy, free of charge and under the terms of this License, through a
|
|
||||||
publicly available network server or other readily accessible means,
|
|
||||||
then you must either (1) cause the Corresponding Source to be so
|
|
||||||
available, or (2) arrange to deprive yourself of the benefit of the
|
|
||||||
patent license for this particular work, or (3) arrange, in a manner
|
|
||||||
consistent with the requirements of this License, to extend the patent
|
|
||||||
license to downstream recipients. "Knowingly relying" means you have
|
|
||||||
actual knowledge that, but for the patent license, your conveying the
|
|
||||||
covered work in a country, or your recipient's use of the covered work
|
|
||||||
in a country, would infringe one or more identifiable patents in that
|
|
||||||
country that you have reason to believe are valid.
|
|
||||||
|
|
||||||
If, pursuant to or in connection with a single transaction or
|
|
||||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
|
||||||
covered work, and grant a patent license to some of the parties
|
|
||||||
receiving the covered work authorizing them to use, propagate, modify
|
|
||||||
or convey a specific copy of the covered work, then the patent license
|
|
||||||
you grant is automatically extended to all recipients of the covered
|
|
||||||
work and works based on it.
|
|
||||||
|
|
||||||
A patent license is "discriminatory" if it does not include within
|
|
||||||
the scope of its coverage, prohibits the exercise of, or is
|
|
||||||
conditioned on the non-exercise of one or more of the rights that are
|
|
||||||
specifically granted under this License. You may not convey a covered
|
|
||||||
work if you are a party to an arrangement with a third party that is
|
|
||||||
in the business of distributing software, under which you make payment
|
|
||||||
to the third party based on the extent of your activity of conveying
|
|
||||||
the work, and under which the third party grants, to any of the
|
|
||||||
parties who would receive the covered work from you, a discriminatory
|
|
||||||
patent license (a) in connection with copies of the covered work
|
|
||||||
conveyed by you (or copies made from those copies), or (b) primarily
|
|
||||||
for and in connection with specific products or compilations that
|
|
||||||
contain the covered work, unless you entered into that arrangement,
|
|
||||||
or that patent license was granted, prior to 28 March 2007.
|
|
||||||
|
|
||||||
Nothing in this License shall be construed as excluding or limiting
|
|
||||||
any implied license or other defenses to infringement that may
|
|
||||||
otherwise be available to you under applicable patent law.
|
|
||||||
|
|
||||||
12. No Surrender of Others' Freedom.
|
|
||||||
|
|
||||||
If conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot convey a
|
|
||||||
covered work so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you may
|
|
||||||
not convey it at all. For example, if you agree to terms that obligate you
|
|
||||||
to collect a royalty for further conveying from those to whom you convey
|
|
||||||
the Program, the only way you could satisfy both those terms and this
|
|
||||||
License would be to refrain entirely from conveying the Program.
|
|
||||||
|
|
||||||
13. Use with the GNU Affero General Public License.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
|
||||||
permission to link or combine any covered work with a work licensed
|
|
||||||
under version 3 of the GNU Affero General Public License into a single
|
|
||||||
combined work, and to convey the resulting work. The terms of this
|
|
||||||
License will continue to apply to the part which is the covered work,
|
|
||||||
but the special requirements of the GNU Affero General Public License,
|
|
||||||
section 13, concerning interaction through a network will apply to the
|
|
||||||
combination as such.
|
|
||||||
|
|
||||||
14. Revised Versions of this License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of
|
|
||||||
the GNU General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Program specifies that a certain numbered version of the GNU General
|
|
||||||
Public License "or any later version" applies to it, you have the
|
|
||||||
option of following the terms and conditions either of that numbered
|
|
||||||
version or of any later version published by the Free Software
|
|
||||||
Foundation. If the Program does not specify a version number of the
|
|
||||||
GNU General Public License, you may choose any version ever published
|
|
||||||
by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future
|
|
||||||
versions of the GNU General Public License can be used, that proxy's
|
|
||||||
public statement of acceptance of a version permanently authorizes you
|
|
||||||
to choose that version for the Program.
|
|
||||||
|
|
||||||
Later license versions may give you additional or different
|
|
||||||
permissions. However, no additional obligations are imposed on any
|
|
||||||
author or copyright holder as a result of your choosing to follow a
|
|
||||||
later version.
|
|
||||||
|
|
||||||
15. Disclaimer of Warranty.
|
|
||||||
|
|
||||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
|
||||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
|
||||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
|
||||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
|
||||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
|
||||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
16. Limitation of Liability.
|
|
||||||
|
|
||||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
|
||||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
|
||||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
|
||||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
|
||||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
|
||||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
|
||||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
|
||||||
SUCH DAMAGES.
|
|
||||||
|
|
||||||
17. Interpretation of Sections 15 and 16.
|
|
||||||
|
|
||||||
If the disclaimer of warranty and limitation of liability provided
|
|
||||||
above cannot be given local legal effect according to their terms,
|
|
||||||
reviewing courts shall apply local law that most closely approximates
|
|
||||||
an absolute waiver of all civil liability in connection with the
|
|
||||||
Program, unless a warranty or assumption of liability accompanies a
|
|
||||||
copy of the Program in return for a fee.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
state the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If the program does terminal interaction, make it output a short
|
|
||||||
notice like this when it starts in an interactive mode:
|
|
||||||
|
|
||||||
<program> Copyright (C) <year> <name of author>
|
|
||||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
|
||||||
This is free software, and you are welcome to redistribute it
|
|
||||||
under certain conditions; type `show c' for details.
|
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, your program's commands
|
|
||||||
might be different; for a GUI interface, you would use an "about box".
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
|
||||||
For more information on this, and how to apply and follow the GNU GPL, see
|
|
||||||
<https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
The GNU General Public License does not permit incorporating your program
|
|
||||||
into proprietary programs. If your program is a subroutine library, you
|
|
||||||
may consider it more useful to permit linking proprietary applications with
|
|
||||||
the library. If this is what you want to do, use the GNU Lesser General
|
|
||||||
Public License instead of this License. But first, please read
|
|
||||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
|
||||||
|
|
61
MAINTAINERS
Normal file
61
MAINTAINERS
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
Alexey Makhov <amakhov@avito.ru> (@makhov)
|
||||||
|
Bo-Yi Wu <appleboy.tw@gmail.com> (@appleboy)
|
||||||
|
Ethan Koenig <ethantkoenig@gmail.com> (@ethantkoenig)
|
||||||
|
Kees de Vries <bouwko@gmail.com> (@Bwko)
|
||||||
|
Kim Carlbäcker <kim.carlbacker@gmail.com> (@bkcsoft)
|
||||||
|
LefsFlare <nobody@nobody.tld> (@LefsFlarey)
|
||||||
|
Lunny Xiao <xiaolunwen@gmail.com> (@lunny)
|
||||||
|
Rachid Zarouali <nobody@nobody.tld> (@xinity)
|
||||||
|
Rémy Boulanouar <admin@dblk.org> (@DblK)
|
||||||
|
Sandro Santilli <strk@kbt.io> (@strk)
|
||||||
|
Thibault Meyer <meyer.thibault@gmail.com> (@0xbaadf00d)
|
||||||
|
Thomas Boerger <thomas@webhippie.de> (@tboerger)
|
||||||
|
Patrick G <geek1011@outlook.com> (@geek1011)
|
||||||
|
Antoine Girard <sapk@sapk.fr> (@sapk)
|
||||||
|
Lauris Bukšis-Haberkorns <lauris@nix.lv> (@lafriks)
|
||||||
|
Jonas Östanbäck <jonas.ostanback@gmail.com> (@cez81)
|
||||||
|
David Schneiderbauer <dschneiderbauer@gmail.com> (@daviian)
|
||||||
|
Peter Žeby <morlinest@gmail.com> (@morlinest)
|
||||||
|
Matti Ranta <techknowlogick@gitea.io> (@techknowlogick)
|
||||||
|
Jonas Franz <info@jonasfranz.software> (@jonasfranz)
|
||||||
|
Alexey Terentyev <axifnx@gmail.com> (@axifive)
|
||||||
|
Lanre Adelowo <yo@lanre.wtf> (@adelowo)
|
||||||
|
Konrad Langenberg <k@knt.li> (@kolaente)
|
||||||
|
He-Long Zhang <outman99@hotmail.com> (@BetaCat0)
|
||||||
|
Andrew Thornton <art27@cantab.net> (@zeripath)
|
||||||
|
John Olheiser <john.olheiser@gmail.com> (@jolheiser)
|
||||||
|
Richard Mahn <rich.mahn@unfoldingword.org> (@richmahn)
|
||||||
|
Mrsdizzie <info@mrsdizzie.com> (@mrsdizzie)
|
||||||
|
silverwind <me@silverwind.io> (@silverwind)
|
||||||
|
Gary Kim <gary@garykim.dev> (@gary-kim)
|
||||||
|
Guillermo Prandi <gitea.maint@mailfilter.com.ar> (@guillep2k)
|
||||||
|
Mura Li <typeless@ctli.io> (@typeless)
|
||||||
|
6543 <6543@obermui.de> (@6543)
|
||||||
|
jaqra <jaqra@hotmail.com> (@jaqra)
|
||||||
|
David Svantesson <davidsvantesson@gmail.com> (@davidsvantesson)
|
||||||
|
a1012112796 <1012112796@qq.com> (@a1012112796)
|
||||||
|
Karl Heinz Marbaise <kama@soebes.de> (@khmarbaise)
|
||||||
|
Norwin Roosen <git@nroo.de> (@noerw)
|
||||||
|
Kyle Dumont <kdumontnu@gmail.com> (@kdumontnu)
|
||||||
|
Patrick Schratz <patrick.schratz@gmail.com> (@pat-s)
|
||||||
|
Janis Estelmann <admin@oldschoolhack.me> (@KN4CK3R)
|
||||||
|
Steven Kriegler <sk.bunsenbrenner@gmail.com> (@justusbunsi)
|
||||||
|
Jimmy Praet <jimmy.praet@telenet.be> (@jpraet)
|
||||||
|
Leon Hofmeister <dev.lh@web.de> (@delvh)
|
||||||
|
Wim <wim@42.be> (@42wim)
|
||||||
|
Jason Song <i@wolfogre.com> (@wolfogre)
|
||||||
|
Yarden Shoham <git@yardenshoham.com> (@yardenshoham)
|
||||||
|
Yu Tian <zettat123@gmail.com> (@Zettat123)
|
||||||
|
Eddie Yang <576951401@qq.com> (@yp05327)
|
||||||
|
Dong Ge <gedong_1994@163.com> (@sillyguodong)
|
||||||
|
Xinyi Gong <hestergong@gmail.com> (@HesterG)
|
||||||
|
wxiaoguang <wxiaoguang@gmail.com> (@wxiaoguang)
|
||||||
|
Gary Moon <gary@garymoon.net> (@garymoon)
|
||||||
|
Philip Peterson <philip.c.peterson@gmail.com> (@philip-peterson)
|
||||||
|
Denys Konovalov <kontakt@denyskon.de> (@denyskon)
|
||||||
|
Punit Inani <punitinani1@gmail.com> (@puni9869)
|
||||||
|
CaiCandong <1290147055@qq.com> (@caicandong)
|
||||||
|
Rui Chen <rui@chenrui.dev> (@chenrui333)
|
||||||
|
Nanguan Lin <nanguanlin6@gmail.com> (@lng2020)
|
||||||
|
kerwin612 <kerwin612@qq.com> (@kerwin612)
|
||||||
|
Gary Wang <git@blumia.net> (@BLumia)
|
529
Makefile
529
Makefile
|
@ -24,34 +24,29 @@ HAS_GO := $(shell hash $(GO) > /dev/null 2>&1 && echo yes)
|
||||||
COMMA := ,
|
COMMA := ,
|
||||||
DIFF ?= diff --unified
|
DIFF ?= diff --unified
|
||||||
|
|
||||||
ifeq ($(USE_GOTESTSUM), yes)
|
|
||||||
GOTEST ?= gotestsum --
|
|
||||||
GOTESTCOMPILEDRUNPREFIX ?= gotestsum --raw-command -- go tool test2json -t
|
|
||||||
GOTESTCOMPILEDRUNSUFFIX ?= -test.v=test2json
|
|
||||||
else
|
|
||||||
GOTEST ?= $(GO) test
|
|
||||||
GOTESTCOMPILEDRUNPREFIX ?=
|
|
||||||
GOTESTCOMPILEDRUNSUFFIX ?=
|
|
||||||
endif
|
|
||||||
|
|
||||||
XGO_VERSION := go-1.21.x
|
XGO_VERSION := go-1.21.x
|
||||||
|
|
||||||
AIR_PACKAGE ?= github.com/air-verse/air@v1 # renovate: datasource=go
|
AIR_PACKAGE ?= github.com/cosmtrek/air@v1.44.0
|
||||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.0.3 # renovate: datasource=go
|
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.7.0
|
||||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.7.0 # renovate: datasource=go
|
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.5.0
|
||||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.61.0 # renovate: datasource=go
|
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.55.0
|
||||||
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 # renovate: datasource=go
|
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11
|
||||||
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.6.0 # renovate: datasource=go
|
MISSPELL_PACKAGE ?= github.com/client9/misspell/cmd/misspell@v0.3.4
|
||||||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.31.0 # renovate: datasource=go
|
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.5
|
||||||
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
||||||
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0 # renovate: datasource=go
|
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0
|
||||||
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1 # renovate: datasource=go
|
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1.0.1
|
||||||
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.26.0 # renovate: datasource=go
|
ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1.6.25
|
||||||
GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.4.0 # renovate: datasource=go
|
DEADCODE_PACKAGE ?= golang.org/x/tools/internal/cmd/deadcode@v0.14.0
|
||||||
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.16.2 # renovate: datasource=go
|
|
||||||
RENOVATE_NPM_PACKAGE ?= renovate@38.110.2 # renovate: datasource=docker packageName=code.forgejo.org/forgejo-contrib/renovate
|
DOCKER_IMAGE ?= gitea/gitea
|
||||||
|
DOCKER_TAG ?= latest
|
||||||
|
DOCKER_REF := $(DOCKER_IMAGE):$(DOCKER_TAG)
|
||||||
|
|
||||||
ifeq ($(HAS_GO), yes)
|
ifeq ($(HAS_GO), yes)
|
||||||
|
GOPATH ?= $(shell $(GO) env GOPATH)
|
||||||
|
export PATH := $(GOPATH)/bin:$(PATH)
|
||||||
|
|
||||||
CGO_EXTRA_CFLAGS := -DSQLITE_MAX_VARIABLE_NUMBER=32766
|
CGO_EXTRA_CFLAGS := -DSQLITE_MAX_VARIABLE_NUMBER=32766
|
||||||
CGO_CFLAGS ?= $(shell $(GO) env CGO_CFLAGS) $(CGO_EXTRA_CFLAGS)
|
CGO_CFLAGS ?= $(shell $(GO) env CGO_CFLAGS) $(CGO_EXTRA_CFLAGS)
|
||||||
endif
|
endif
|
||||||
|
@ -90,56 +85,31 @@ endif
|
||||||
STORED_VERSION_FILE := VERSION
|
STORED_VERSION_FILE := VERSION
|
||||||
HUGO_VERSION ?= 0.111.3
|
HUGO_VERSION ?= 0.111.3
|
||||||
|
|
||||||
GITEA_COMPATIBILITY ?= gitea-1.22.0
|
|
||||||
|
|
||||||
STORED_VERSION=$(shell cat $(STORED_VERSION_FILE) 2>/dev/null)
|
STORED_VERSION=$(shell cat $(STORED_VERSION_FILE) 2>/dev/null)
|
||||||
ifneq ($(STORED_VERSION),)
|
ifneq ($(STORED_VERSION),)
|
||||||
FORGEJO_VERSION ?= $(STORED_VERSION)
|
GITEA_VERSION ?= $(STORED_VERSION)
|
||||||
else
|
else
|
||||||
ifneq ($(GITEA_VERSION),)
|
GITEA_VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//')
|
||||||
FORGEJO_VERSION ?= $(GITEA_VERSION)
|
|
||||||
FORGEJO_VERSION_API ?= $(GITEA_VERSION)+${GITEA_COMPATIBILITY}
|
|
||||||
else
|
|
||||||
# drop the "g" prefix prepended by git describe to the commit hash
|
|
||||||
FORGEJO_VERSION ?= $(shell git describe --exclude '*-test' --tags --always | sed 's/^v//' | sed 's/\-g/-/')+${GITEA_COMPATIBILITY}
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
FORGEJO_VERSION_MAJOR=$(shell echo $(FORGEJO_VERSION) | sed -e 's/\..*//')
|
VERSION = ${GITEA_VERSION}
|
||||||
FORGEJO_VERSION_MINOR=$(shell echo $(FORGEJO_VERSION) | sed -E -e 's/^([0-9]+\.[0-9]+).*/\1/')
|
|
||||||
|
|
||||||
show-version-full:
|
# SemVer
|
||||||
@echo ${FORGEJO_VERSION}
|
FORGEJO_VERSION := 7.0.0+0-gitea-1.22.0
|
||||||
|
|
||||||
show-version-major:
|
LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)" -X "main.ForgejoVersion=$(FORGEJO_VERSION)"
|
||||||
@echo ${FORGEJO_VERSION_MAJOR}
|
|
||||||
|
|
||||||
show-version-minor:
|
|
||||||
@echo ${FORGEJO_VERSION_MINOR}
|
|
||||||
|
|
||||||
RELEASE_VERSION ?= ${FORGEJO_VERSION}
|
|
||||||
VERSION ?= ${RELEASE_VERSION}
|
|
||||||
|
|
||||||
FORGEJO_VERSION_API ?= ${FORGEJO_VERSION}
|
|
||||||
|
|
||||||
show-version-api:
|
|
||||||
@echo ${FORGEJO_VERSION_API}
|
|
||||||
|
|
||||||
LDFLAGS := $(LDFLAGS) -X "main.ReleaseVersion=$(RELEASE_VERSION)" -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(FORGEJO_VERSION)" -X "main.Tags=$(TAGS)" -X "main.ForgejoVersion=$(FORGEJO_VERSION_API)"
|
|
||||||
|
|
||||||
LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64
|
LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64
|
||||||
|
|
||||||
ifeq ($(HAS_GO), yes)
|
GO_PACKAGES ?= $(filter-out code.gitea.io/gitea/tests/integration/migration-test code.gitea.io/gitea/tests code.gitea.io/gitea/tests/integration code.gitea.io/gitea/tests/e2e,$(shell $(GO) list ./... | grep -v /vendor/))
|
||||||
GO_TEST_PACKAGES ?= $(filter-out $(shell $(GO) list code.gitea.io/gitea/models/migrations/...) $(shell $(GO) list code.gitea.io/gitea/models/forgejo_migrations/...) code.gitea.io/gitea/tests/integration/migration-test code.gitea.io/gitea/tests code.gitea.io/gitea/tests/integration code.gitea.io/gitea/tests/e2e,$(shell $(GO) list ./...))
|
GO_TEST_PACKAGES ?= $(filter-out $(shell $(GO) list code.gitea.io/gitea/models/migrations/...) $(shell $(GO) list code.gitea.io/gitea/models/forgejo_migrations/...) code.gitea.io/gitea/tests/integration/migration-test code.gitea.io/gitea/tests code.gitea.io/gitea/tests/integration code.gitea.io/gitea/tests/e2e,$(shell $(GO) list ./... | grep -v /vendor/))
|
||||||
endif
|
|
||||||
REMOTE_CACHER_MODULES ?= cache nosql session queue
|
|
||||||
GO_TEST_REMOTE_CACHER_PACKAGES ?= $(addprefix code.gitea.io/gitea/modules/,$(REMOTE_CACHER_MODULES))
|
|
||||||
|
|
||||||
FOMANTIC_WORK_DIR := web_src/fomantic
|
FOMANTIC_WORK_DIR := web_src/fomantic
|
||||||
|
|
||||||
WEBPACK_SOURCES := $(shell find web_src/js web_src/css -type f)
|
WEBPACK_SOURCES := $(shell find web_src/js web_src/css -type f)
|
||||||
WEBPACK_CONFIGS := webpack.config.js tailwind.config.js
|
WEBPACK_CONFIGS := webpack.config.js
|
||||||
WEBPACK_DEST := public/assets/js/index.js public/assets/css/index.css
|
WEBPACK_DEST := public/assets/js/index.js public/assets/css/index.css
|
||||||
WEBPACK_DEST_ENTRIES := public/assets/js public/assets/css public/assets/fonts
|
WEBPACK_DEST_ENTRIES := public/assets/js public/assets/css public/assets/fonts public/assets/img/webpack
|
||||||
|
|
||||||
BINDATA_DEST := modules/public/bindata.go modules/options/bindata.go modules/templates/bindata.go
|
BINDATA_DEST := modules/public/bindata.go modules/options/bindata.go modules/templates/bindata.go
|
||||||
BINDATA_HASH := $(addsuffix .hash,$(BINDATA_DEST))
|
BINDATA_HASH := $(addsuffix .hash,$(BINDATA_DEST))
|
||||||
|
@ -164,18 +134,12 @@ TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(FOMAN
|
||||||
GO_DIRS := build cmd models modules routers services tests
|
GO_DIRS := build cmd models modules routers services tests
|
||||||
WEB_DIRS := web_src/js web_src/css
|
WEB_DIRS := web_src/js web_src/css
|
||||||
|
|
||||||
ESLINT_FILES := web_src/js tools *.js tests/e2e/*.js tests/e2e/shared/*.js
|
|
||||||
STYLELINT_FILES := web_src/css web_src/js/components/*.vue
|
|
||||||
SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) docs/content templates options/locale/locale_en-US.ini .github $(wildcard *.go *.js *.md *.yml *.yaml *.toml)
|
|
||||||
|
|
||||||
GO_SOURCES := $(wildcard *.go)
|
GO_SOURCES := $(wildcard *.go)
|
||||||
GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" ! -path modules/options/bindata.go ! -path modules/public/bindata.go ! -path modules/templates/bindata.go)
|
GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" ! -path modules/options/bindata.go ! -path modules/public/bindata.go ! -path modules/templates/bindata.go)
|
||||||
GO_SOURCES += $(GENERATED_GO_DEST)
|
GO_SOURCES += $(GENERATED_GO_DEST)
|
||||||
GO_SOURCES_NO_BINDATA := $(GO_SOURCES)
|
GO_SOURCES_NO_BINDATA := $(GO_SOURCES)
|
||||||
|
|
||||||
ifeq ($(HAS_GO), yes)
|
MIGRATION_PACKAGES := $(shell $(GO) list code.gitea.io/gitea/models/migrations/... code.gitea.io/gitea/models/forgejo_migrations/...)
|
||||||
MIGRATION_PACKAGES := $(shell $(GO) list code.gitea.io/gitea/models/migrations/... code.gitea.io/gitea/models/forgejo_migrations/...)
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(filter $(TAGS_SPLIT),bindata),bindata)
|
ifeq ($(filter $(TAGS_SPLIT),bindata),bindata)
|
||||||
GO_SOURCES += $(BINDATA_DEST)
|
GO_SOURCES += $(BINDATA_DEST)
|
||||||
|
@ -190,15 +154,13 @@ endif
|
||||||
FORGEJO_API_SPEC := public/assets/forgejo/api.v1.yml
|
FORGEJO_API_SPEC := public/assets/forgejo/api.v1.yml
|
||||||
|
|
||||||
SWAGGER_SPEC := templates/swagger/v1_json.tmpl
|
SWAGGER_SPEC := templates/swagger/v1_json.tmpl
|
||||||
SWAGGER_SPEC_S_TMPL := s|"basePath": *"/api/v1"|"basePath": "{{AppSubUrl \| JSEscape}}/api/v1"|g
|
SWAGGER_SPEC_S_TMPL := s|"basePath": *"/api/v1"|"basePath": "{{AppSubUrl \| JSEscape \| Safe}}/api/v1"|g
|
||||||
SWAGGER_SPEC_S_JSON := s|"basePath": *"{{AppSubUrl \| JSEscape}}/api/v1"|"basePath": "/api/v1"|g
|
SWAGGER_SPEC_S_JSON := s|"basePath": *"{{AppSubUrl \| JSEscape \| Safe}}/api/v1"|"basePath": "/api/v1"|g
|
||||||
SWAGGER_EXCLUDE := code.gitea.io/sdk
|
SWAGGER_EXCLUDE := code.gitea.io/sdk
|
||||||
SWAGGER_NEWLINE_COMMAND := -e '$$a\'
|
SWAGGER_NEWLINE_COMMAND := -e '$$a\'
|
||||||
SWAGGER_SPEC_BRANDING := s|Gitea API|Forgejo API|g
|
|
||||||
SWAGGER_SPEC_LICENSE := s|"name": "MIT"|"name": "This file is distributed under the MIT license for the purpose of interoperability"|
|
|
||||||
|
|
||||||
TEST_MYSQL_HOST ?= mysql:3306
|
TEST_MYSQL_HOST ?= mysql:3306
|
||||||
TEST_MYSQL_DBNAME ?= testgitea?multiStatements=true
|
TEST_MYSQL_DBNAME ?= testgitea
|
||||||
TEST_MYSQL_USERNAME ?= root
|
TEST_MYSQL_USERNAME ?= root
|
||||||
TEST_MYSQL_PASSWORD ?=
|
TEST_MYSQL_PASSWORD ?=
|
||||||
TEST_PGSQL_HOST ?= pgsql:5432
|
TEST_PGSQL_HOST ?= pgsql:5432
|
||||||
|
@ -206,6 +168,10 @@ TEST_PGSQL_DBNAME ?= testgitea
|
||||||
TEST_PGSQL_USERNAME ?= postgres
|
TEST_PGSQL_USERNAME ?= postgres
|
||||||
TEST_PGSQL_PASSWORD ?= postgres
|
TEST_PGSQL_PASSWORD ?= postgres
|
||||||
TEST_PGSQL_SCHEMA ?= gtestschema
|
TEST_PGSQL_SCHEMA ?= gtestschema
|
||||||
|
TEST_MSSQL_HOST ?= mssql:1433
|
||||||
|
TEST_MSSQL_DBNAME ?= gitea
|
||||||
|
TEST_MSSQL_USERNAME ?= sa
|
||||||
|
TEST_MSSQL_PASSWORD ?= MwantsaSecurePassword1
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: build
|
all: build
|
||||||
|
@ -213,7 +179,7 @@ all: build
|
||||||
.PHONY: help
|
.PHONY: help
|
||||||
help:
|
help:
|
||||||
@echo "Make Routines:"
|
@echo "Make Routines:"
|
||||||
@echo " - \"\" equivalent to \"build\""
|
@echo " - \"\" equivalent to \"build\""
|
||||||
@echo " - build build everything"
|
@echo " - build build everything"
|
||||||
@echo " - frontend build frontend files"
|
@echo " - frontend build frontend files"
|
||||||
@echo " - backend build backend files"
|
@echo " - backend build backend files"
|
||||||
|
@ -229,17 +195,14 @@ help:
|
||||||
@echo " - deps-py install python dependencies"
|
@echo " - deps-py install python dependencies"
|
||||||
@echo " - lint lint everything"
|
@echo " - lint lint everything"
|
||||||
@echo " - lint-fix lint everything and fix issues"
|
@echo " - lint-fix lint everything and fix issues"
|
||||||
|
@echo " - lint-actions lint action workflow files"
|
||||||
@echo " - lint-frontend lint frontend files"
|
@echo " - lint-frontend lint frontend files"
|
||||||
@echo " - lint-frontend-fix lint frontend files and fix issues"
|
@echo " - lint-frontend-fix lint frontend files and fix issues"
|
||||||
@echo " - lint-backend lint backend files"
|
@echo " - lint-backend lint backend files"
|
||||||
@echo " - lint-backend-fix lint backend files and fix issues"
|
@echo " - lint-backend-fix lint backend files and fix issues"
|
||||||
@echo " - lint-codespell lint typos"
|
|
||||||
@echo " - lint-codespell-fix lint typos and fix them automatically"
|
|
||||||
@echo " - lint-codespell-fix-i lint typos and fix them interactively"
|
|
||||||
@echo " - lint-go lint go files"
|
@echo " - lint-go lint go files"
|
||||||
@echo " - lint-go-fix lint go files and fix issues"
|
@echo " - lint-go-fix lint go files and fix issues"
|
||||||
@echo " - lint-go-vet lint go files with vet"
|
@echo " - lint-go-vet lint go files with vet"
|
||||||
@echo " - lint-go-gopls lint go files with gopls"
|
|
||||||
@echo " - lint-js lint js files"
|
@echo " - lint-js lint js files"
|
||||||
@echo " - lint-js-fix lint js files and fix issues"
|
@echo " - lint-js-fix lint js files and fix issues"
|
||||||
@echo " - lint-css lint css files"
|
@echo " - lint-css lint css files"
|
||||||
|
@ -247,21 +210,17 @@ help:
|
||||||
@echo " - lint-md lint markdown files"
|
@echo " - lint-md lint markdown files"
|
||||||
@echo " - lint-swagger lint swagger files"
|
@echo " - lint-swagger lint swagger files"
|
||||||
@echo " - lint-templates lint template files"
|
@echo " - lint-templates lint template files"
|
||||||
@echo " - lint-renovate lint renovate files"
|
|
||||||
@echo " - lint-yaml lint yaml files"
|
@echo " - lint-yaml lint yaml files"
|
||||||
@echo " - lint-spell lint spelling"
|
|
||||||
@echo " - lint-spell-fix lint spelling and fix issues"
|
|
||||||
@echo " - checks run various consistency checks"
|
@echo " - checks run various consistency checks"
|
||||||
@echo " - checks-frontend check frontend files"
|
@echo " - checks-frontend check frontend files"
|
||||||
@echo " - checks-backend check backend files"
|
@echo " - checks-backend check backend files"
|
||||||
@echo " - test test everything"
|
@echo " - test test everything"
|
||||||
@echo " - show-version-full show the same version as the API endpoint"
|
|
||||||
@echo " - show-version-major show major release number only"
|
|
||||||
@echo " - test-frontend test frontend files"
|
@echo " - test-frontend test frontend files"
|
||||||
@echo " - test-frontend-coverage test frontend files and display code coverage"
|
|
||||||
@echo " - test-backend test backend files"
|
@echo " - test-backend test backend files"
|
||||||
@echo " - test-remote-cacher test backend files that use a remote cache"
|
@echo " - test-e2e[\#TestSpecificName] test end to end using playwright"
|
||||||
@echo " - test-e2e-sqlite[\#name.test.e2e] test end to end using playwright and sqlite"
|
@echo " - update update js and py dependencies"
|
||||||
|
@echo " - update-js update js dependencies"
|
||||||
|
@echo " - update-py update py dependencies"
|
||||||
@echo " - webpack build webpack files"
|
@echo " - webpack build webpack files"
|
||||||
@echo " - svg build svg files"
|
@echo " - svg build svg files"
|
||||||
@echo " - fomantic build fomantic files"
|
@echo " - fomantic build fomantic files"
|
||||||
|
@ -270,20 +229,14 @@ help:
|
||||||
@echo " - generate-license update license files"
|
@echo " - generate-license update license files"
|
||||||
@echo " - generate-gitignore update gitignore files"
|
@echo " - generate-gitignore update gitignore files"
|
||||||
@echo " - generate-manpage generate manpage"
|
@echo " - generate-manpage generate manpage"
|
||||||
@echo " - generate-gomock generate gomock files"
|
|
||||||
@echo " - generate-forgejo-api generate the forgejo API from spec"
|
@echo " - generate-forgejo-api generate the forgejo API from spec"
|
||||||
@echo " - forgejo-api-validate check if the forgejo API matches the specs"
|
@echo " - forgejo-api-validate check if the forgejo API matches the specs"
|
||||||
@echo " - generate-swagger generate the swagger spec from code comments"
|
@echo " - generate-swagger generate the swagger spec from code comments"
|
||||||
@echo " - swagger-validate check if the swagger spec is valid"
|
@echo " - swagger-validate check if the swagger spec is valid"
|
||||||
@echo " - go-licenses regenerate go licenses"
|
@echo " - go-licenses regenerate go licenses"
|
||||||
@echo " - tidy run go mod tidy"
|
@echo " - tidy run go mod tidy"
|
||||||
@echo " - test[\#TestSpecificName] run unit test"
|
@echo " - test[\#TestSpecificName] run unit test"
|
||||||
@echo " - test-sqlite[\#TestSpecificName] run integration test for sqlite"
|
@echo " - test-sqlite[\#TestSpecificName] run integration test for sqlite"
|
||||||
@echo " - reproduce-build\#version build a reproducible binary for the specified release version"
|
|
||||||
|
|
||||||
###
|
|
||||||
# Check system and environment requirements
|
|
||||||
###
|
|
||||||
|
|
||||||
.PHONY: go-check
|
.PHONY: go-check
|
||||||
go-check:
|
go-check:
|
||||||
|
@ -291,14 +244,14 @@ go-check:
|
||||||
$(eval MIN_GO_VERSION := $(shell printf "%03d%03d" $(shell echo '$(MIN_GO_VERSION_STR)' | tr '.' ' ')))
|
$(eval MIN_GO_VERSION := $(shell printf "%03d%03d" $(shell echo '$(MIN_GO_VERSION_STR)' | tr '.' ' ')))
|
||||||
$(eval GO_VERSION := $(shell printf "%03d%03d" $(shell $(GO) version | grep -Eo '[0-9]+\.[0-9]+' | tr '.' ' ');))
|
$(eval GO_VERSION := $(shell printf "%03d%03d" $(shell $(GO) version | grep -Eo '[0-9]+\.[0-9]+' | tr '.' ' ');))
|
||||||
@if [ "$(GO_VERSION)" -lt "$(MIN_GO_VERSION)" ]; then \
|
@if [ "$(GO_VERSION)" -lt "$(MIN_GO_VERSION)" ]; then \
|
||||||
echo "Forgejo requires Go $(MIN_GO_VERSION_STR) or greater to build. You can get it at https://go.dev/dl/"; \
|
echo "Gitea requires Go $(MIN_GO_VERSION_STR) or greater to build. You can get it at https://go.dev/dl/"; \
|
||||||
exit 1; \
|
exit 1; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
.PHONY: git-check
|
.PHONY: git-check
|
||||||
git-check:
|
git-check:
|
||||||
@if git lfs >/dev/null 2>&1 ; then : ; else \
|
@if git lfs >/dev/null 2>&1 ; then : ; else \
|
||||||
echo "Forgejo requires git with lfs support to run tests." ; \
|
echo "Gitea requires git with lfs support to run tests." ; \
|
||||||
exit 1; \
|
exit 1; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -309,14 +262,10 @@ node-check:
|
||||||
$(eval NODE_VERSION := $(shell printf "%03d%03d%03d" $(shell node -v | cut -c2- | tr '.' ' ');))
|
$(eval NODE_VERSION := $(shell printf "%03d%03d%03d" $(shell node -v | cut -c2- | tr '.' ' ');))
|
||||||
$(eval NPM_MISSING := $(shell hash npm > /dev/null 2>&1 || echo 1))
|
$(eval NPM_MISSING := $(shell hash npm > /dev/null 2>&1 || echo 1))
|
||||||
@if [ "$(NODE_VERSION)" -lt "$(MIN_NODE_VERSION)" -o "$(NPM_MISSING)" = "1" ]; then \
|
@if [ "$(NODE_VERSION)" -lt "$(MIN_NODE_VERSION)" -o "$(NPM_MISSING)" = "1" ]; then \
|
||||||
echo "Forgejo requires Node.js $(MIN_NODE_VERSION_STR) or greater and npm to build. You can get it at https://nodejs.org/en/download/"; \
|
echo "Gitea requires Node.js $(MIN_NODE_VERSION_STR) or greater and npm to build. You can get it at https://nodejs.org/en/download/"; \
|
||||||
exit 1; \
|
exit 1; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
###
|
|
||||||
# Basic maintenance, check and lint targets
|
|
||||||
###
|
|
||||||
|
|
||||||
.PHONY: clean-all
|
.PHONY: clean-all
|
||||||
clean-all: clean
|
clean-all: clean
|
||||||
rm -rf $(WEBPACK_DEST_ENTRIES) node_modules
|
rm -rf $(WEBPACK_DEST_ENTRIES) node_modules
|
||||||
|
@ -328,14 +277,14 @@ clean:
|
||||||
e2e*.test \
|
e2e*.test \
|
||||||
tests/integration/gitea-integration-* \
|
tests/integration/gitea-integration-* \
|
||||||
tests/integration/indexers-* \
|
tests/integration/indexers-* \
|
||||||
tests/mysql.ini tests/pgsql.ini man/ \
|
tests/mysql.ini tests/pgsql.ini tests/mssql.ini man/ \
|
||||||
tests/e2e/gitea-e2e-*/ \
|
tests/e2e/gitea-e2e-*/ \
|
||||||
tests/e2e/indexers-*/ \
|
tests/e2e/indexers-*/ \
|
||||||
tests/e2e/reports/ tests/e2e/test-artifacts/ tests/e2e/test-snapshots/
|
tests/e2e/reports/ tests/e2e/test-artifacts/ tests/e2e/test-snapshots/
|
||||||
|
|
||||||
.PHONY: fmt
|
.PHONY: fmt
|
||||||
fmt:
|
fmt:
|
||||||
@GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) $(GO) run build/code-batch-process.go gitea-fmt -w '{file-list}'
|
GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) $(GO) run build/code-batch-process.go gitea-fmt -w '{file-list}'
|
||||||
$(eval TEMPLATES := $(shell find templates -type f -name '*.tmpl'))
|
$(eval TEMPLATES := $(shell find templates -type f -name '*.tmpl'))
|
||||||
@# strip whitespace after '{{' or '(' and before '}}' or ')' unless there is only
|
@# strip whitespace after '{{' or '(' and before '}}' or ')' unless there is only
|
||||||
@# whitespace before it
|
@# whitespace before it
|
||||||
|
@ -346,8 +295,16 @@ fmt:
|
||||||
|
|
||||||
.PHONY: fmt-check
|
.PHONY: fmt-check
|
||||||
fmt-check: fmt
|
fmt-check: fmt
|
||||||
@git diff --exit-code --color=always $(GO_SOURCES) templates $(WEB_DIRS) \
|
@diff=$$(git diff --color=always $(GO_SOURCES) templates $(WEB_DIRS)); \
|
||||||
|| (code=$$?; echo "Please run 'make fmt' and commit the result"; exit $${code})
|
if [ -n "$$diff" ]; then \
|
||||||
|
echo "Please run 'make fmt' and commit the result:"; \
|
||||||
|
echo "$${diff}"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
.PHONY: misspell-check
|
||||||
|
misspell-check:
|
||||||
|
go run $(MISSPELL_PACKAGE) -error $(GO_DIRS) $(WEB_DIRS)
|
||||||
|
|
||||||
.PHONY: $(TAGS_EVIDENCE)
|
.PHONY: $(TAGS_EVIDENCE)
|
||||||
$(TAGS_EVIDENCE):
|
$(TAGS_EVIDENCE):
|
||||||
|
@ -368,8 +325,12 @@ generate-forgejo-api: $(FORGEJO_API_SPEC)
|
||||||
|
|
||||||
.PHONY: forgejo-api-check
|
.PHONY: forgejo-api-check
|
||||||
forgejo-api-check: generate-forgejo-api
|
forgejo-api-check: generate-forgejo-api
|
||||||
@git diff --exit-code --color=always $(FORGEJO_API_SERVER) \
|
@diff=$$(git diff $(FORGEJO_API_SERVER) ; \
|
||||||
|| (code=$$?; echo "Please run 'make generate-forgejo-api' and commit the result"; exit $${code})
|
if [ -n "$$diff" ]; then \
|
||||||
|
echo "Please run 'make generate-forgejo-api' and commit the result:"; \
|
||||||
|
echo "$${diff}"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
.PHONY: forgejo-api-validate
|
.PHONY: forgejo-api-validate
|
||||||
forgejo-api-validate:
|
forgejo-api-validate:
|
||||||
|
@ -382,13 +343,15 @@ $(SWAGGER_SPEC): $(GO_SOURCES_NO_BINDATA)
|
||||||
$(GO) run $(SWAGGER_PACKAGE) generate spec -x "$(SWAGGER_EXCLUDE)" -o './$(SWAGGER_SPEC)'
|
$(GO) run $(SWAGGER_PACKAGE) generate spec -x "$(SWAGGER_EXCLUDE)" -o './$(SWAGGER_SPEC)'
|
||||||
$(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
|
$(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
|
||||||
$(SED_INPLACE) $(SWAGGER_NEWLINE_COMMAND) './$(SWAGGER_SPEC)'
|
$(SED_INPLACE) $(SWAGGER_NEWLINE_COMMAND) './$(SWAGGER_SPEC)'
|
||||||
$(SED_INPLACE) '$(SWAGGER_SPEC_BRANDING)' './$(SWAGGER_SPEC)'
|
|
||||||
$(SED_INPLACE) '$(SWAGGER_SPEC_LICENSE)' './$(SWAGGER_SPEC)'
|
|
||||||
|
|
||||||
.PHONY: swagger-check
|
.PHONY: swagger-check
|
||||||
swagger-check: generate-swagger
|
swagger-check: generate-swagger
|
||||||
@git diff --exit-code --color=always '$(SWAGGER_SPEC)' \
|
@diff=$$(git diff --color=always '$(SWAGGER_SPEC)'); \
|
||||||
|| (code=$$?; echo "Please run 'make generate-swagger' and commit the result"; exit $${code})
|
if [ -n "$$diff" ]; then \
|
||||||
|
echo "Please run 'make generate-swagger' and commit the result:"; \
|
||||||
|
echo "$${diff}"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
.PHONY: swagger-validate
|
.PHONY: swagger-validate
|
||||||
swagger-validate:
|
swagger-validate:
|
||||||
|
@ -403,13 +366,13 @@ checks: checks-frontend checks-backend
|
||||||
checks-frontend: lockfile-check svg-check
|
checks-frontend: lockfile-check svg-check
|
||||||
|
|
||||||
.PHONY: checks-backend
|
.PHONY: checks-backend
|
||||||
checks-backend: tidy-check swagger-check fmt-check swagger-validate security-check
|
checks-backend: tidy-check swagger-check fmt-check misspell-check forgejo-api-validate swagger-validate security-check
|
||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint: lint-frontend lint-backend lint-spell
|
lint: lint-frontend lint-backend
|
||||||
|
|
||||||
.PHONY: lint-fix
|
.PHONY: lint-fix
|
||||||
lint-fix: lint-frontend-fix lint-backend-fix lint-spell-fix
|
lint-fix: lint-frontend-fix lint-backend-fix
|
||||||
|
|
||||||
.PHONY: lint-frontend
|
.PHONY: lint-frontend
|
||||||
lint-frontend: lint-js lint-css
|
lint-frontend: lint-js lint-css
|
||||||
|
@ -418,74 +381,49 @@ lint-frontend: lint-js lint-css
|
||||||
lint-frontend-fix: lint-js-fix lint-css-fix
|
lint-frontend-fix: lint-js-fix lint-css-fix
|
||||||
|
|
||||||
.PHONY: lint-backend
|
.PHONY: lint-backend
|
||||||
lint-backend: lint-go lint-go-vet lint-editorconfig lint-renovate
|
lint-backend: lint-go lint-go-vet lint-editorconfig
|
||||||
|
|
||||||
.PHONY: lint-backend-fix
|
.PHONY: lint-backend-fix
|
||||||
lint-backend-fix: lint-go-fix lint-go-vet lint-editorconfig
|
lint-backend-fix: lint-go-fix lint-go-vet lint-editorconfig
|
||||||
|
|
||||||
.PHONY: lint-codespell
|
|
||||||
lint-codespell:
|
|
||||||
codespell
|
|
||||||
|
|
||||||
.PHONY: lint-codespell-fix
|
|
||||||
lint-codespell-fix:
|
|
||||||
codespell -w
|
|
||||||
|
|
||||||
.PHONY: lint-codespell-fix-i
|
|
||||||
lint-codespell-fix-i:
|
|
||||||
codespell -w -i 3 -C 2
|
|
||||||
|
|
||||||
.PHONY: lint-js
|
.PHONY: lint-js
|
||||||
lint-js: node_modules
|
lint-js: node_modules
|
||||||
npx eslint --color --max-warnings=0 --ext js,vue $(ESLINT_FILES)
|
npx eslint --color --max-warnings=0 --ext js,vue web_src/js build *.config.js tests/e2e
|
||||||
|
|
||||||
.PHONY: lint-js-fix
|
.PHONY: lint-js-fix
|
||||||
lint-js-fix: node_modules
|
lint-js-fix: node_modules
|
||||||
npx eslint --color --max-warnings=0 --ext js,vue $(ESLINT_FILES) --fix
|
npx eslint --color --max-warnings=0 --ext js,vue web_src/js build *.config.js tests/e2e --fix
|
||||||
|
|
||||||
.PHONY: lint-css
|
.PHONY: lint-css
|
||||||
lint-css: node_modules
|
lint-css: node_modules
|
||||||
npx stylelint --color --max-warnings=0 $(STYLELINT_FILES)
|
npx stylelint --color --max-warnings=0 web_src/css web_src/js/components/*.vue
|
||||||
|
|
||||||
.PHONY: lint-css-fix
|
.PHONY: lint-css-fix
|
||||||
lint-css-fix: node_modules
|
lint-css-fix: node_modules
|
||||||
npx stylelint --color --max-warnings=0 $(STYLELINT_FILES) --fix
|
npx stylelint --color --max-warnings=0 web_src/css web_src/js/components/*.vue --fix
|
||||||
|
|
||||||
.PHONY: lint-swagger
|
.PHONY: lint-swagger
|
||||||
lint-swagger: node_modules
|
lint-swagger: node_modules
|
||||||
npx spectral lint -q -F hint $(SWAGGER_SPEC)
|
npx spectral lint -q -F hint $(SWAGGER_SPEC)
|
||||||
|
|
||||||
.PHONY: lint-renovate
|
|
||||||
lint-renovate: node_modules
|
|
||||||
npx --yes --package $(RENOVATE_NPM_PACKAGE) -- renovate-config-validator --strict > .lint-renovate 2>&1 || true
|
|
||||||
@if grep --quiet --extended-regexp -e '^( WARN:|ERROR:)' .lint-renovate ; then cat .lint-renovate ; rm .lint-renovate ; exit 1 ; fi
|
|
||||||
@rm .lint-renovate
|
|
||||||
|
|
||||||
.PHONY: lint-md
|
.PHONY: lint-md
|
||||||
lint-md: node_modules
|
lint-md: node_modules
|
||||||
npx markdownlint docs *.md
|
npx markdownlint docs *.md
|
||||||
|
|
||||||
.PHONY: lint-spell
|
|
||||||
lint-spell: lint-codespell
|
|
||||||
@go run $(MISSPELL_PACKAGE) -error $(SPELLCHECK_FILES)
|
|
||||||
|
|
||||||
.PHONY: lint-spell-fix
|
|
||||||
lint-spell-fix: lint-codespell-fix
|
|
||||||
@go run $(MISSPELL_PACKAGE) -w $(SPELLCHECK_FILES)
|
|
||||||
|
|
||||||
RUN_DEADCODE = $(GO) run $(DEADCODE_PACKAGE) -generated=false -f='{{println .Path}}{{range .Funcs}}{{printf "\t%s\n" .Name}}{{end}}{{println}}' -test code.gitea.io/gitea
|
|
||||||
|
|
||||||
.PHONY: lint-go
|
.PHONY: lint-go
|
||||||
lint-go:
|
lint-go:
|
||||||
$(GO) run $(GOLANGCI_LINT_PACKAGE) run $(GOLANGCI_LINT_ARGS)
|
$(GO) run $(GOLANGCI_LINT_PACKAGE) run $(GOLANGCI_LINT_ARGS)
|
||||||
$(RUN_DEADCODE) > .cur-deadcode-out
|
$(GO) run $(DEADCODE_PACKAGE) -generated=false -test code.gitea.io/gitea > .cur-deadcode-out
|
||||||
@$(DIFF) .deadcode-out .cur-deadcode-out \
|
@$(DIFF) .deadcode-out .cur-deadcode-out; \
|
||||||
|| (code=$$?; echo "Please run 'make lint-go-fix' and commit the result"; exit $${code})
|
if [ $$? -eq 1 ]; then \
|
||||||
|
echo "Please run 'make lint-go-fix' and commit the result"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
.PHONY: lint-go-fix
|
.PHONY: lint-go-fix
|
||||||
lint-go-fix:
|
lint-go-fix:
|
||||||
$(GO) run $(GOLANGCI_LINT_PACKAGE) run $(GOLANGCI_LINT_ARGS) --fix
|
$(GO) run $(GOLANGCI_LINT_PACKAGE) run $(GOLANGCI_LINT_ARGS) --fix
|
||||||
$(RUN_DEADCODE) > .deadcode-out
|
$(GO) run $(DEADCODE_PACKAGE) -generated=false -test code.gitea.io/gitea > .deadcode-out
|
||||||
|
|
||||||
# workaround step for the lint-go-windows CI task because 'go run' can not
|
# workaround step for the lint-go-windows CI task because 'go run' can not
|
||||||
# have distinct GOOS/GOARCH for its build and run steps
|
# have distinct GOOS/GOARCH for its build and run steps
|
||||||
|
@ -497,37 +435,27 @@ lint-go-windows:
|
||||||
.PHONY: lint-go-vet
|
.PHONY: lint-go-vet
|
||||||
lint-go-vet:
|
lint-go-vet:
|
||||||
@echo "Running go vet..."
|
@echo "Running go vet..."
|
||||||
@$(GO) vet ./...
|
@$(GO) vet $(GO_PACKAGES)
|
||||||
|
|
||||||
.PHONY: lint-go-gopls
|
|
||||||
lint-go-gopls:
|
|
||||||
@echo "Running gopls check..."
|
|
||||||
@GO=$(GO) GOPLS_PACKAGE=$(GOPLS_PACKAGE) tools/lint-go-gopls.sh $(GO_SOURCES_NO_BINDATA)
|
|
||||||
|
|
||||||
.PHONY: lint-editorconfig
|
.PHONY: lint-editorconfig
|
||||||
lint-editorconfig:
|
lint-editorconfig:
|
||||||
$(GO) run $(EDITORCONFIG_CHECKER_PACKAGE) templates .forgejo/workflows
|
$(GO) run $(EDITORCONFIG_CHECKER_PACKAGE) templates .forgejo/workflows
|
||||||
|
|
||||||
|
.PHONY: lint-actions
|
||||||
|
lint-actions:
|
||||||
|
$(GO) run $(ACTIONLINT_PACKAGE)
|
||||||
|
|
||||||
.PHONY: lint-templates
|
.PHONY: lint-templates
|
||||||
lint-templates: .venv node_modules
|
lint-templates: .venv
|
||||||
@node tools/lint-templates-svg.js
|
|
||||||
@poetry run djlint $(shell find templates -type f -iname '*.tmpl')
|
@poetry run djlint $(shell find templates -type f -iname '*.tmpl')
|
||||||
|
|
||||||
.PHONY: lint-yaml
|
.PHONY: lint-yaml
|
||||||
lint-yaml: .venv
|
lint-yaml: .venv
|
||||||
@poetry run yamllint .
|
@poetry run yamllint .
|
||||||
|
|
||||||
.PHONY: security-check
|
|
||||||
security-check:
|
|
||||||
go run $(GOVULNCHECK_PACKAGE) ./...
|
|
||||||
|
|
||||||
###
|
|
||||||
# Development and testing targets
|
|
||||||
###
|
|
||||||
|
|
||||||
.PHONY: watch
|
.PHONY: watch
|
||||||
watch:
|
watch:
|
||||||
@bash tools/watch.sh
|
@bash build/watch.sh
|
||||||
|
|
||||||
.PHONY: watch-frontend
|
.PHONY: watch-frontend
|
||||||
watch-frontend: node-check node_modules
|
watch-frontend: node-check node_modules
|
||||||
|
@ -544,21 +472,12 @@ test: test-frontend test-backend
|
||||||
.PHONY: test-backend
|
.PHONY: test-backend
|
||||||
test-backend:
|
test-backend:
|
||||||
@echo "Running go test with $(GOTESTFLAGS) -tags '$(TEST_TAGS)'..."
|
@echo "Running go test with $(GOTESTFLAGS) -tags '$(TEST_TAGS)'..."
|
||||||
@$(GOTEST) $(GOTESTFLAGS) -tags='$(TEST_TAGS)' $(GO_TEST_PACKAGES)
|
@$(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' $(GO_TEST_PACKAGES)
|
||||||
|
|
||||||
.PHONY: test-remote-cacher
|
|
||||||
test-remote-cacher:
|
|
||||||
@echo "Running go test with $(GOTESTFLAGS) -tags '$(TEST_TAGS)'..."
|
|
||||||
@$(GOTEST) $(GOTESTFLAGS) -tags='$(TEST_TAGS)' $(GO_TEST_REMOTE_CACHER_PACKAGES)
|
|
||||||
|
|
||||||
.PHONY: test-frontend
|
.PHONY: test-frontend
|
||||||
test-frontend: node_modules
|
test-frontend: node_modules
|
||||||
npx vitest
|
npx vitest
|
||||||
|
|
||||||
.PHONY: test-frontend-coverage
|
|
||||||
test-frontend-coverage: node_modules
|
|
||||||
npx vitest --coverage --coverage.include 'web_src/**'
|
|
||||||
|
|
||||||
.PHONY: test-check
|
.PHONY: test-check
|
||||||
test-check:
|
test-check:
|
||||||
@echo "Running test-check...";
|
@echo "Running test-check...";
|
||||||
|
@ -574,7 +493,7 @@ test-check:
|
||||||
.PHONY: test\#%
|
.PHONY: test\#%
|
||||||
test\#%:
|
test\#%:
|
||||||
@echo "Running go test with -tags '$(TEST_TAGS)'..."
|
@echo "Running go test with -tags '$(TEST_TAGS)'..."
|
||||||
@$(GOTEST) $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -run $(subst .,/,$*) $(GO_TEST_PACKAGES)
|
@$(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -run $(subst .,/,$*) $(GO_TEST_PACKAGES)
|
||||||
|
|
||||||
.PHONY: coverage
|
.PHONY: coverage
|
||||||
coverage:
|
coverage:
|
||||||
|
@ -585,7 +504,7 @@ coverage:
|
||||||
.PHONY: unit-test-coverage
|
.PHONY: unit-test-coverage
|
||||||
unit-test-coverage:
|
unit-test-coverage:
|
||||||
@echo "Running unit-test-coverage $(GOTESTFLAGS) -tags '$(TEST_TAGS)'..."
|
@echo "Running unit-test-coverage $(GOTESTFLAGS) -tags '$(TEST_TAGS)'..."
|
||||||
@$(GOTEST) $(GOTESTFLAGS) -timeout=20m -tags='$(TEST_TAGS)' -cover -coverprofile coverage.out $(GO_TEST_PACKAGES) && echo "\n==>\033[32m Ok\033[m\n" || exit 1
|
@$(GO) test $(GOTESTFLAGS) -timeout=20m -tags='$(TEST_TAGS)' -cover -coverprofile coverage.out $(GO_TEST_PACKAGES) && echo "\n==>\033[32m Ok\033[m\n" || exit 1
|
||||||
|
|
||||||
.PHONY: tidy
|
.PHONY: tidy
|
||||||
tidy:
|
tidy:
|
||||||
|
@ -599,14 +518,18 @@ vendor: go.mod go.sum
|
||||||
|
|
||||||
.PHONY: tidy-check
|
.PHONY: tidy-check
|
||||||
tidy-check: tidy
|
tidy-check: tidy
|
||||||
@git diff --exit-code --color=always go.mod go.sum $(GO_LICENSE_FILE) \
|
@diff=$$(git diff --color=always go.mod go.sum $(GO_LICENSE_FILE)); \
|
||||||
|| (code=$$?; echo "Please run 'make tidy' and commit the result"; exit $${code})
|
if [ -n "$$diff" ]; then \
|
||||||
|
echo "Please run 'make tidy' and commit the result:"; \
|
||||||
|
echo "$${diff}"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
.PHONY: go-licenses
|
.PHONY: go-licenses
|
||||||
go-licenses: $(GO_LICENSE_FILE)
|
go-licenses: $(GO_LICENSE_FILE)
|
||||||
|
|
||||||
$(GO_LICENSE_FILE): go.mod go.sum
|
$(GO_LICENSE_FILE): go.mod go.sum
|
||||||
-$(shell $(GO) env GOROOT)/bin/go run $(GO_LICENSES_PACKAGE) save . --force --ignore code.gitea.io/gitea --save_path=$(GO_LICENSE_TMP_DIR) 2>/dev/null
|
-$(GO) run $(GO_LICENSES_PACKAGE) save . --force --save_path=$(GO_LICENSE_TMP_DIR) 2>/dev/null
|
||||||
$(GO) run build/generate-go-licenses.go $(GO_LICENSE_TMP_DIR) $(GO_LICENSE_FILE)
|
$(GO) run build/generate-go-licenses.go $(GO_LICENSE_TMP_DIR) $(GO_LICENSE_FILE)
|
||||||
@rm -rf $(GO_LICENSE_TMP_DIR)
|
@rm -rf $(GO_LICENSE_TMP_DIR)
|
||||||
|
|
||||||
|
@ -618,11 +541,11 @@ generate-ini-sqlite:
|
||||||
|
|
||||||
.PHONY: test-sqlite
|
.PHONY: test-sqlite
|
||||||
test-sqlite: integrations.sqlite.test generate-ini-sqlite
|
test-sqlite: integrations.sqlite.test generate-ini-sqlite
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GOTESTCOMPILEDRUNPREFIX) ./integrations.sqlite.test $(GOTESTCOMPILEDRUNSUFFIX)
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.sqlite.test
|
||||||
|
|
||||||
.PHONY: test-sqlite\#%
|
.PHONY: test-sqlite\#%
|
||||||
test-sqlite\#%: integrations.sqlite.test generate-ini-sqlite
|
test-sqlite\#%: integrations.sqlite.test generate-ini-sqlite
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GOTESTCOMPILEDRUNPREFIX) ./integrations.sqlite.test $(GOTESTCOMPILEDRUNSUFFIX) -test.run $(subst .,/,$*)
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.sqlite.test -test.run $(subst .,/,$*)
|
||||||
|
|
||||||
.PHONY: test-sqlite-migration
|
.PHONY: test-sqlite-migration
|
||||||
test-sqlite-migration: migrations.sqlite.test migrations.individual.sqlite.test
|
test-sqlite-migration: migrations.sqlite.test migrations.individual.sqlite.test
|
||||||
|
@ -639,11 +562,11 @@ generate-ini-mysql:
|
||||||
|
|
||||||
.PHONY: test-mysql
|
.PHONY: test-mysql
|
||||||
test-mysql: integrations.mysql.test generate-ini-mysql
|
test-mysql: integrations.mysql.test generate-ini-mysql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GOTESTCOMPILEDRUNPREFIX) ./integrations.mysql.test $(GOTESTCOMPILEDRUNSUFFIX)
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./integrations.mysql.test
|
||||||
|
|
||||||
.PHONY: test-mysql\#%
|
.PHONY: test-mysql\#%
|
||||||
test-mysql\#%: integrations.mysql.test generate-ini-mysql
|
test-mysql\#%: integrations.mysql.test generate-ini-mysql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GOTESTCOMPILEDRUNPREFIX) ./integrations.mysql.test $(GOTESTCOMPILEDRUNSUFFIX) -test.run $(subst .,/,$*)
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./integrations.mysql.test -test.run $(subst .,/,$*)
|
||||||
|
|
||||||
.PHONY: test-mysql-migration
|
.PHONY: test-mysql-migration
|
||||||
test-mysql-migration: migrations.mysql.test migrations.individual.mysql.test
|
test-mysql-migration: migrations.mysql.test migrations.individual.mysql.test
|
||||||
|
@ -661,17 +584,39 @@ generate-ini-pgsql:
|
||||||
|
|
||||||
.PHONY: test-pgsql
|
.PHONY: test-pgsql
|
||||||
test-pgsql: integrations.pgsql.test generate-ini-pgsql
|
test-pgsql: integrations.pgsql.test generate-ini-pgsql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GOTESTCOMPILEDRUNPREFIX) ./integrations.pgsql.test $(GOTESTCOMPILEDRUNSUFFIX)
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./integrations.pgsql.test
|
||||||
|
|
||||||
.PHONY: test-pgsql\#%
|
.PHONY: test-pgsql\#%
|
||||||
test-pgsql\#%: integrations.pgsql.test generate-ini-pgsql
|
test-pgsql\#%: integrations.pgsql.test generate-ini-pgsql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GOTESTCOMPILEDRUNPREFIX) ./integrations.pgsql.test $(GOTESTCOMPILEDRUNSUFFIX) -test.run $(subst .,/,$*)
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./integrations.pgsql.test -test.run $(subst .,/,$*)
|
||||||
|
|
||||||
.PHONY: test-pgsql-migration
|
.PHONY: test-pgsql-migration
|
||||||
test-pgsql-migration: migrations.pgsql.test migrations.individual.pgsql.test
|
test-pgsql-migration: migrations.pgsql.test migrations.individual.pgsql.test
|
||||||
|
|
||||||
|
generate-ini-mssql:
|
||||||
|
sed -e 's|{{TEST_MSSQL_HOST}}|${TEST_MSSQL_HOST}|g' \
|
||||||
|
-e 's|{{TEST_MSSQL_DBNAME}}|${TEST_MSSQL_DBNAME}|g' \
|
||||||
|
-e 's|{{TEST_MSSQL_USERNAME}}|${TEST_MSSQL_USERNAME}|g' \
|
||||||
|
-e 's|{{TEST_MSSQL_PASSWORD}}|${TEST_MSSQL_PASSWORD}|g' \
|
||||||
|
-e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
|
||||||
|
-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
|
||||||
|
-e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \
|
||||||
|
tests/mssql.ini.tmpl > tests/mssql.ini
|
||||||
|
|
||||||
|
.PHONY: test-mssql
|
||||||
|
test-mssql: integrations.mssql.test generate-ini-mssql
|
||||||
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./integrations.mssql.test
|
||||||
|
|
||||||
|
.PHONY: test-mssql\#%
|
||||||
|
test-mssql\#%: integrations.mssql.test generate-ini-mssql
|
||||||
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./integrations.mssql.test -test.run $(subst .,/,$*)
|
||||||
|
|
||||||
|
.PHONY: test-mssql-migration
|
||||||
|
test-mssql-migration: migrations.mssql.test migrations.individual.mssql.test
|
||||||
|
|
||||||
.PHONY: playwright
|
.PHONY: playwright
|
||||||
playwright: deps-frontend
|
playwright: $(PLAYWRIGHT_DIR)
|
||||||
|
npm install --no-save @playwright/test
|
||||||
npx playwright install $(PLAYWRIGHT_FLAGS)
|
npx playwright install $(PLAYWRIGHT_FLAGS)
|
||||||
|
|
||||||
.PHONY: test-e2e%
|
.PHONY: test-e2e%
|
||||||
|
@ -684,36 +629,35 @@ test-e2e: test-e2e-sqlite
|
||||||
|
|
||||||
.PHONY: test-e2e-sqlite
|
.PHONY: test-e2e-sqlite
|
||||||
test-e2e-sqlite: playwright e2e.sqlite.test generate-ini-sqlite
|
test-e2e-sqlite: playwright e2e.sqlite.test generate-ini-sqlite
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GOTESTCOMPILEDRUNPREFIX) ./e2e.sqlite.test $(GOTESTCOMPILEDRUNSUFFIX) -test.run TestE2e
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./e2e.sqlite.test
|
||||||
|
|
||||||
.PHONY: test-e2e-sqlite\#%
|
.PHONY: test-e2e-sqlite\#%
|
||||||
test-e2e-sqlite\#%: playwright e2e.sqlite.test generate-ini-sqlite
|
test-e2e-sqlite\#%: playwright e2e.sqlite.test generate-ini-sqlite
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GOTESTCOMPILEDRUNPREFIX) ./e2e.sqlite.test $(GOTESTCOMPILEDRUNSUFFIX) -test.run TestE2e/$*
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./e2e.sqlite.test -test.run TestE2e/$*
|
||||||
|
|
||||||
.PHONY: test-e2e-sqlite-firefox\#%
|
|
||||||
test-e2e-sqlite-firefox\#%: playwright e2e.sqlite.test generate-ini-sqlite
|
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini PLAYWRIGHT_PROJECT=firefox $(GOTESTCOMPILEDRUNPREFIX) ./e2e.sqlite.test $(GOTESTCOMPILEDRUNSUFFIX) -test.run TestE2e/$*
|
|
||||||
|
|
||||||
.PHONY: test-e2e-mysql
|
.PHONY: test-e2e-mysql
|
||||||
test-e2e-mysql: playwright e2e.mysql.test generate-ini-mysql
|
test-e2e-mysql: playwright e2e.mysql.test generate-ini-mysql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GOTESTCOMPILEDRUNPREFIX) ./e2e.mysql.test $(GOTESTCOMPILEDRUNSUFFIX) -test.run TestE2e
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./e2e.mysql.test
|
||||||
|
|
||||||
.PHONY: test-e2e-mysql\#%
|
.PHONY: test-e2e-mysql\#%
|
||||||
test-e2e-mysql\#%: playwright e2e.mysql.test generate-ini-mysql
|
test-e2e-mysql\#%: playwright e2e.mysql.test generate-ini-mysql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GOTESTCOMPILEDRUNPREFIX) ./e2e.mysql.test $(GOTESTCOMPILEDRUNSUFFIX) -test.run TestE2e/$*
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./e2e.mysql.test -test.run TestE2e/$*
|
||||||
|
|
||||||
.PHONY: test-e2e-pgsql
|
.PHONY: test-e2e-pgsql
|
||||||
test-e2e-pgsql: playwright e2e.pgsql.test generate-ini-pgsql
|
test-e2e-pgsql: playwright e2e.pgsql.test generate-ini-pgsql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GOTESTCOMPILEDRUNPREFIX) ./e2e.pgsql.test $(GOTESTCOMPILEDRUNSUFFIX) -test.run TestE2e
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./e2e.pgsql.test
|
||||||
|
|
||||||
.PHONY: test-e2e-pgsql\#%
|
.PHONY: test-e2e-pgsql\#%
|
||||||
test-e2e-pgsql\#%: playwright e2e.pgsql.test generate-ini-pgsql
|
test-e2e-pgsql\#%: playwright e2e.pgsql.test generate-ini-pgsql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GOTESTCOMPILEDRUNPREFIX) ./e2e.pgsql.test $(GOTESTCOMPILEDRUNSUFFIX) -test.run TestE2e/$*
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./e2e.pgsql.test -test.run TestE2e/$*
|
||||||
|
|
||||||
.PHONY: test-e2e-debugserver
|
.PHONY: test-e2e-mssql
|
||||||
test-e2e-debugserver: e2e.sqlite.test generate-ini-sqlite
|
test-e2e-mssql: playwright e2e.mssql.test generate-ini-mssql
|
||||||
sed -i s/3003/3000/g tests/sqlite.ini
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./e2e.mssql.test
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./e2e.sqlite.test -test.run TestDebugserver -test.timeout 24h
|
|
||||||
|
.PHONY: test-e2e-mssql\#%
|
||||||
|
test-e2e-mssql\#%: playwright e2e.mssql.test generate-ini-mssql
|
||||||
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./e2e.mssql.test -test.run TestE2e/$*
|
||||||
|
|
||||||
.PHONY: bench-sqlite
|
.PHONY: bench-sqlite
|
||||||
bench-sqlite: integrations.sqlite.test generate-ini-sqlite
|
bench-sqlite: integrations.sqlite.test generate-ini-sqlite
|
||||||
|
@ -723,6 +667,10 @@ bench-sqlite: integrations.sqlite.test generate-ini-sqlite
|
||||||
bench-mysql: integrations.mysql.test generate-ini-mysql
|
bench-mysql: integrations.mysql.test generate-ini-mysql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./integrations.mysql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./integrations.mysql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
|
||||||
|
|
||||||
|
.PHONY: bench-mssql
|
||||||
|
bench-mssql: integrations.mssql.test generate-ini-mssql
|
||||||
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./integrations.mssql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
|
||||||
|
|
||||||
.PHONY: bench-pgsql
|
.PHONY: bench-pgsql
|
||||||
bench-pgsql: integrations.pgsql.test generate-ini-pgsql
|
bench-pgsql: integrations.pgsql.test generate-ini-pgsql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./integrations.pgsql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./integrations.pgsql.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
|
||||||
|
@ -736,81 +684,99 @@ integration-test-coverage-sqlite: integrations.cover.sqlite.test generate-ini-sq
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.cover.sqlite.test -test.coverprofile=integration.coverage.out
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.cover.sqlite.test -test.coverprofile=integration.coverage.out
|
||||||
|
|
||||||
integrations.mysql.test: git-check $(GO_SOURCES)
|
integrations.mysql.test: git-check $(GO_SOURCES)
|
||||||
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.mysql.test
|
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.mysql.test
|
||||||
|
|
||||||
integrations.pgsql.test: git-check $(GO_SOURCES)
|
integrations.pgsql.test: git-check $(GO_SOURCES)
|
||||||
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.pgsql.test
|
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.pgsql.test
|
||||||
|
|
||||||
|
integrations.mssql.test: git-check $(GO_SOURCES)
|
||||||
|
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.mssql.test
|
||||||
|
|
||||||
integrations.sqlite.test: git-check $(GO_SOURCES)
|
integrations.sqlite.test: git-check $(GO_SOURCES)
|
||||||
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.sqlite.test -tags '$(TEST_TAGS)'
|
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.sqlite.test -tags '$(TEST_TAGS)'
|
||||||
|
|
||||||
integrations.cover.test: git-check $(GO_SOURCES)
|
integrations.cover.test: git-check $(GO_SOURCES)
|
||||||
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -coverpkg $(shell echo $(GO_TEST_PACKAGES) | tr ' ' ',') -o integrations.cover.test
|
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -coverpkg $(shell echo $(GO_TEST_PACKAGES) | tr ' ' ',') -o integrations.cover.test
|
||||||
|
|
||||||
integrations.cover.sqlite.test: git-check $(GO_SOURCES)
|
integrations.cover.sqlite.test: git-check $(GO_SOURCES)
|
||||||
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -coverpkg $(shell echo $(GO_TEST_PACKAGES) | tr ' ' ',') -o integrations.cover.sqlite.test -tags '$(TEST_TAGS)'
|
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -coverpkg $(shell echo $(GO_TEST_PACKAGES) | tr ' ' ',') -o integrations.cover.sqlite.test -tags '$(TEST_TAGS)'
|
||||||
|
|
||||||
.PHONY: migrations.mysql.test
|
.PHONY: migrations.mysql.test
|
||||||
migrations.mysql.test: $(GO_SOURCES) generate-ini-mysql
|
migrations.mysql.test: $(GO_SOURCES) generate-ini-mysql
|
||||||
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mysql.test
|
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mysql.test
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GOTESTCOMPILEDRUNPREFIX) ./migrations.mysql.test $(GOTESTCOMPILEDRUNSUFFIX)
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./migrations.mysql.test
|
||||||
|
|
||||||
.PHONY: migrations.pgsql.test
|
.PHONY: migrations.pgsql.test
|
||||||
migrations.pgsql.test: $(GO_SOURCES) generate-ini-pgsql
|
migrations.pgsql.test: $(GO_SOURCES) generate-ini-pgsql
|
||||||
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.pgsql.test
|
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.pgsql.test
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GOTESTCOMPILEDRUNPREFIX) ./migrations.pgsql.test $(GOTESTCOMPILEDRUNSUFFIX)
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./migrations.pgsql.test
|
||||||
|
|
||||||
|
.PHONY: migrations.mssql.test
|
||||||
|
migrations.mssql.test: $(GO_SOURCES) generate-ini-mssql
|
||||||
|
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mssql.test
|
||||||
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini ./migrations.mssql.test
|
||||||
|
|
||||||
.PHONY: migrations.sqlite.test
|
.PHONY: migrations.sqlite.test
|
||||||
migrations.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
|
migrations.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
|
||||||
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.sqlite.test -tags '$(TEST_TAGS)'
|
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.sqlite.test -tags '$(TEST_TAGS)'
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GOTESTCOMPILEDRUNPREFIX) ./migrations.sqlite.test $(GOTESTCOMPILEDRUNSUFFIX)
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./migrations.sqlite.test
|
||||||
|
|
||||||
.PHONY: migrations.individual.mysql.test
|
.PHONY: migrations.individual.mysql.test
|
||||||
migrations.individual.mysql.test: $(GO_SOURCES)
|
migrations.individual.mysql.test: $(GO_SOURCES)
|
||||||
for pkg in $(MIGRATION_PACKAGES); do \
|
for pkg in $(MIGRATION_PACKAGES); do \
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GOTEST) $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg || exit 1; \
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg || exit 1; \
|
||||||
done
|
done
|
||||||
|
|
||||||
.PHONY: migrations.individual.sqlite.test\#%
|
.PHONY: migrations.individual.sqlite.test\#%
|
||||||
migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite
|
migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GOTEST) $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
|
||||||
|
|
||||||
.PHONY: migrations.individual.pgsql.test
|
.PHONY: migrations.individual.pgsql.test
|
||||||
migrations.individual.pgsql.test: $(GO_SOURCES)
|
migrations.individual.pgsql.test: $(GO_SOURCES)
|
||||||
for pkg in $(MIGRATION_PACKAGES); do \
|
for pkg in $(MIGRATION_PACKAGES); do \
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GOTEST) $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg || exit 1;\
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg || exit 1;\
|
||||||
done
|
done
|
||||||
|
|
||||||
.PHONY: migrations.individual.pgsql.test\#%
|
.PHONY: migrations.individual.pgsql.test\#%
|
||||||
migrations.individual.pgsql.test\#%: $(GO_SOURCES) generate-ini-pgsql
|
migrations.individual.pgsql.test\#%: $(GO_SOURCES) generate-ini-pgsql
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GOTEST) $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: migrations.individual.mssql.test
|
||||||
|
migrations.individual.mssql.test: $(GO_SOURCES) generate-ini-mssql
|
||||||
|
for pkg in $(MIGRATION_PACKAGES); do \
|
||||||
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' -test.failfast $$pkg || exit 1; \
|
||||||
|
done
|
||||||
|
|
||||||
|
.PHONY: migrations.individual.mssql.test\#%
|
||||||
|
migrations.individual.mssql.test\#%: $(GO_SOURCES) generate-ini-mssql
|
||||||
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
|
||||||
|
|
||||||
.PHONY: migrations.individual.sqlite.test
|
.PHONY: migrations.individual.sqlite.test
|
||||||
migrations.individual.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
|
migrations.individual.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
|
||||||
for pkg in $(MIGRATION_PACKAGES); do \
|
for pkg in $(MIGRATION_PACKAGES); do \
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GOTEST) $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg || exit 1; \
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg || exit 1; \
|
||||||
done
|
done
|
||||||
|
|
||||||
.PHONY: migrations.individual.sqlite.test\#%
|
.PHONY: migrations.individual.sqlite.test\#%
|
||||||
migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite
|
migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GOTEST) $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
|
||||||
|
|
||||||
e2e.mysql.test: $(GO_SOURCES)
|
e2e.mysql.test: $(GO_SOURCES)
|
||||||
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.mysql.test
|
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.mysql.test
|
||||||
|
|
||||||
e2e.pgsql.test: $(GO_SOURCES)
|
e2e.pgsql.test: $(GO_SOURCES)
|
||||||
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.pgsql.test
|
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.pgsql.test
|
||||||
|
|
||||||
|
e2e.mssql.test: $(GO_SOURCES)
|
||||||
|
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.mssql.test
|
||||||
|
|
||||||
e2e.sqlite.test: $(GO_SOURCES)
|
e2e.sqlite.test: $(GO_SOURCES)
|
||||||
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.sqlite.test -tags '$(TEST_TAGS)'
|
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.sqlite.test -tags '$(TEST_TAGS)'
|
||||||
|
|
||||||
.PHONY: check
|
.PHONY: check
|
||||||
check: test
|
check: test
|
||||||
|
|
||||||
###
|
|
||||||
# Production / build targets
|
|
||||||
###
|
|
||||||
|
|
||||||
.PHONY: install $(TAGS_PREREQ)
|
.PHONY: install $(TAGS_PREREQ)
|
||||||
install: $(wildcard *.go)
|
install: $(wildcard *.go)
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) install -v -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)'
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) install -v -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)'
|
||||||
|
@ -834,18 +800,15 @@ generate-backend: $(TAGS_PREREQ) generate-go
|
||||||
.PHONY: generate-go
|
.PHONY: generate-go
|
||||||
generate-go: $(TAGS_PREREQ)
|
generate-go: $(TAGS_PREREQ)
|
||||||
@echo "Running go generate..."
|
@echo "Running go generate..."
|
||||||
@CC= GOOS= GOARCH= CGO_ENABLED=0 $(GO) generate -tags '$(TAGS)' ./...
|
@CC= GOOS= GOARCH= $(GO) generate -tags '$(TAGS)' $(GO_PACKAGES)
|
||||||
|
|
||||||
.PHONY: merge-locales
|
.PHONY: security-check
|
||||||
merge-locales:
|
security-check:
|
||||||
@echo "NOT NEEDED: THIS IS A NOOP AS OF Forgejo 7.0 BUT KEPT FOR BACKWARD COMPATIBILITY"
|
go run $(GOVULNCHECK_PACKAGE) ./...
|
||||||
|
|
||||||
$(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ)
|
$(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ)
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
|
||||||
|
|
||||||
forgejo: $(EXECUTABLE)
|
|
||||||
ln -f $(EXECUTABLE) forgejo
|
|
||||||
|
|
||||||
static-executable: $(GO_SOURCES) $(TAGS_PREREQ)
|
static-executable: $(GO_SOURCES) $(TAGS_PREREQ)
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags 'netgo osusergo $(TAGS)' -ldflags '-s -w -linkmode external -extldflags "-static" $(LDFLAGS)' -o $(EXECUTABLE)
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags 'netgo osusergo $(TAGS)' -ldflags '-s -w -linkmode external -extldflags "-static" $(LDFLAGS)' -o $(EXECUTABLE)
|
||||||
|
|
||||||
|
@ -861,6 +824,9 @@ $(DIST_DIRS):
|
||||||
.PHONY: release-windows
|
.PHONY: release-windows
|
||||||
release-windows: | $(DIST_DIRS)
|
release-windows: | $(DIST_DIRS)
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION) .
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION) .
|
||||||
|
ifeq (,$(findstring gogit,$(TAGS)))
|
||||||
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'osusergo gogit $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION)-gogit .
|
||||||
|
endif
|
||||||
|
|
||||||
.PHONY: release-linux
|
.PHONY: release-linux
|
||||||
release-linux: | $(DIST_DIRS)
|
release-linux: | $(DIST_DIRS)
|
||||||
|
@ -903,29 +869,9 @@ release-sources: | $(DIST_DIRS)
|
||||||
release-docs: | $(DIST_DIRS) docs
|
release-docs: | $(DIST_DIRS) docs
|
||||||
tar -czf $(DIST)/release/gitea-docs-$(VERSION).tar.gz -C ./docs .
|
tar -czf $(DIST)/release/gitea-docs-$(VERSION).tar.gz -C ./docs .
|
||||||
|
|
||||||
.PHONY: reproduce-build
|
.PHONY: docs
|
||||||
reproduce-build:
|
docs:
|
||||||
# Start building the Dockerfile with the RELEASE_VERSION tag set. GOPROXY is set
|
cd docs; bash scripts/trans-copy.sh;
|
||||||
# for convience, because the default of the Dockerfile is `direct` which can be
|
|
||||||
# quite slow.
|
|
||||||
@docker build --build-arg="RELEASE_VERSION=$(RELEASE_VERSION)" --build-arg="GOPROXY=$(shell $(GO) env GOPROXY)" --tag "forgejo-reproducibility" .
|
|
||||||
@id=$$(docker create forgejo-reproducibility); \
|
|
||||||
docker cp $$id:/app/gitea/gitea ./forgejo; \
|
|
||||||
docker rm -v $$id; \
|
|
||||||
docker image rm forgejo-reproducibility:latest
|
|
||||||
|
|
||||||
.PHONY: reproduce-build\#%
|
|
||||||
reproduce-build\#%:
|
|
||||||
@git switch -d "$*"
|
|
||||||
# All the current variables are based on information before the git checkout happened.
|
|
||||||
# Call the makefile again, so these variables are correct and can be used for building
|
|
||||||
# a reproducible binary. Always execute git switch -, to go back to the previous branch.
|
|
||||||
@make reproduce-build; \
|
|
||||||
(code=$$?; git switch -; exit $${code})
|
|
||||||
|
|
||||||
###
|
|
||||||
# Dependency management
|
|
||||||
###
|
|
||||||
|
|
||||||
.PHONY: deps
|
.PHONY: deps
|
||||||
deps: deps-frontend deps-backend deps-tools deps-py
|
deps: deps-frontend deps-backend deps-tools deps-py
|
||||||
|
@ -952,15 +898,31 @@ deps-tools:
|
||||||
$(GO) install $(XGO_PACKAGE)
|
$(GO) install $(XGO_PACKAGE)
|
||||||
$(GO) install $(GO_LICENSES_PACKAGE)
|
$(GO) install $(GO_LICENSES_PACKAGE)
|
||||||
$(GO) install $(GOVULNCHECK_PACKAGE)
|
$(GO) install $(GOVULNCHECK_PACKAGE)
|
||||||
$(GO) install $(GOMOCK_PACKAGE)
|
$(GO) install $(ACTIONLINT_PACKAGE)
|
||||||
$(GO) install $(GOPLS_PACKAGE)
|
|
||||||
|
|
||||||
node_modules: package-lock.json
|
node_modules: package-lock.json
|
||||||
npm install --no-save
|
npm install --no-save
|
||||||
@touch node_modules
|
@touch node_modules
|
||||||
|
|
||||||
.venv: poetry.lock
|
.venv: poetry.lock
|
||||||
poetry install
|
poetry install --no-root
|
||||||
|
@touch .venv
|
||||||
|
|
||||||
|
.PHONY: update
|
||||||
|
update: update-js update-py
|
||||||
|
|
||||||
|
.PHONY: update-js
|
||||||
|
update-js: node-check | node_modules
|
||||||
|
npx updates -u -f package.json
|
||||||
|
rm -rf node_modules package-lock.json
|
||||||
|
npm install --package-lock
|
||||||
|
@touch node_modules
|
||||||
|
|
||||||
|
.PHONY: update-py
|
||||||
|
update-py: node-check | node_modules
|
||||||
|
npx updates -u -f pyproject.toml
|
||||||
|
rm -rf .venv poetry.lock
|
||||||
|
poetry install --no-root
|
||||||
@touch .venv
|
@touch .venv
|
||||||
|
|
||||||
.PHONY: fomantic
|
.PHONY: fomantic
|
||||||
|
@ -969,7 +931,6 @@ fomantic:
|
||||||
cd $(FOMANTIC_WORK_DIR) && npm install --no-save
|
cd $(FOMANTIC_WORK_DIR) && npm install --no-save
|
||||||
cp -f $(FOMANTIC_WORK_DIR)/theme.config.less $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/src/theme.config
|
cp -f $(FOMANTIC_WORK_DIR)/theme.config.less $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/src/theme.config
|
||||||
cp -rf $(FOMANTIC_WORK_DIR)/_site $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/src/
|
cp -rf $(FOMANTIC_WORK_DIR)/_site $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/src/
|
||||||
$(SED_INPLACE) -e 's/ overrideBrowserslist\r/ overrideBrowserslist: ["defaults"]\r/g' $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/tasks/config/tasks.js
|
|
||||||
cd $(FOMANTIC_WORK_DIR) && npx gulp -f node_modules/fomantic-ui/gulpfile.js build
|
cd $(FOMANTIC_WORK_DIR) && npx gulp -f node_modules/fomantic-ui/gulpfile.js build
|
||||||
# fomantic uses "touchstart" as click event for some browsers, it's not ideal, so we force fomantic to always use "click" as click event
|
# fomantic uses "touchstart" as click event for some browsers, it's not ideal, so we force fomantic to always use "click" as click event
|
||||||
$(SED_INPLACE) -e 's/clickEvent[ \t]*=/clickEvent = "click", unstableClickEvent =/g' $(FOMANTIC_WORK_DIR)/build/semantic.js
|
$(SED_INPLACE) -e 's/clickEvent[ \t]*=/clickEvent = "click", unstableClickEvent =/g' $(FOMANTIC_WORK_DIR)/build/semantic.js
|
||||||
|
@ -981,27 +942,45 @@ webpack: $(WEBPACK_DEST)
|
||||||
|
|
||||||
$(WEBPACK_DEST): $(WEBPACK_SOURCES) $(WEBPACK_CONFIGS) package-lock.json
|
$(WEBPACK_DEST): $(WEBPACK_SOURCES) $(WEBPACK_CONFIGS) package-lock.json
|
||||||
@$(MAKE) -s node-check node_modules
|
@$(MAKE) -s node-check node_modules
|
||||||
@rm -rf $(WEBPACK_DEST_ENTRIES)
|
rm -rf $(WEBPACK_DEST_ENTRIES)
|
||||||
@echo "Running webpack..."
|
npx webpack
|
||||||
@BROWSERSLIST_IGNORE_OLD_DATA=true npx webpack
|
|
||||||
@touch $(WEBPACK_DEST)
|
@touch $(WEBPACK_DEST)
|
||||||
|
|
||||||
.PHONY: svg
|
.PHONY: svg
|
||||||
svg: node-check | node_modules
|
svg: node-check | node_modules
|
||||||
rm -rf $(SVG_DEST_DIR)
|
rm -rf $(SVG_DEST_DIR)
|
||||||
node tools/generate-svg.js
|
node build/generate-svg.js
|
||||||
|
|
||||||
.PHONY: svg-check
|
.PHONY: svg-check
|
||||||
svg-check: svg
|
svg-check: svg
|
||||||
@git add $(SVG_DEST_DIR)
|
@git add $(SVG_DEST_DIR)
|
||||||
@git diff --exit-code --color=always --cached $(SVG_DEST_DIR) \
|
@diff=$$(git diff --color=always --cached $(SVG_DEST_DIR)); \
|
||||||
|| (code=$$?; echo "Please run 'make svg' and commit the result"; exit $${code})
|
if [ -n "$$diff" ]; then \
|
||||||
|
echo "Please run 'make svg' and 'git add $(SVG_DEST_DIR)' and commit the result:"; \
|
||||||
|
echo "$${diff}"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
.PHONY: lockfile-check
|
.PHONY: lockfile-check
|
||||||
lockfile-check:
|
lockfile-check:
|
||||||
npm install --package-lock-only
|
npm install --package-lock-only
|
||||||
@git diff --exit-code --color=always package-lock.json \
|
@diff=$$(git diff --color=always package-lock.json); \
|
||||||
|| (code=$$?; echo "Please run 'npm install --package-lock-only' and commit the result"; exit $${code})
|
if [ -n "$$diff" ]; then \
|
||||||
|
echo "package-lock.json is inconsistent with package.json"; \
|
||||||
|
echo "Please run 'npm install --package-lock-only' and commit the result:"; \
|
||||||
|
echo "$${diff}"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
.PHONY: update-translations
|
||||||
|
update-translations:
|
||||||
|
mkdir -p ./translations
|
||||||
|
cd ./translations && curl -L https://crowdin.com/download/project/gitea.zip > gitea.zip && unzip gitea.zip
|
||||||
|
rm ./translations/gitea.zip
|
||||||
|
$(SED_INPLACE) -e 's/="/=/g' -e 's/"$$//g' ./translations/*.ini
|
||||||
|
$(SED_INPLACE) -e 's/\\"/"/g' ./translations/*.ini
|
||||||
|
mv ./translations/*.ini ./options/locale/
|
||||||
|
rmdir ./translations
|
||||||
|
|
||||||
.PHONY: generate-license
|
.PHONY: generate-license
|
||||||
generate-license:
|
generate-license:
|
||||||
|
@ -1011,14 +990,10 @@ generate-license:
|
||||||
generate-gitignore:
|
generate-gitignore:
|
||||||
$(GO) run build/generate-gitignores.go
|
$(GO) run build/generate-gitignores.go
|
||||||
|
|
||||||
.PHONY: generate-gomock
|
|
||||||
generate-gomock:
|
|
||||||
$(GO) run $(GOMOCK_PACKAGE) -package mock -destination ./modules/queue/mock/redisuniversalclient.go code.gitea.io/gitea/modules/nosql RedisClient
|
|
||||||
|
|
||||||
.PHONY: generate-images
|
.PHONY: generate-images
|
||||||
generate-images: | node_modules
|
generate-images: | node_modules
|
||||||
npm install --no-save fabric@6 imagemin-zopfli@7
|
npm install --no-save --no-package-lock fabric@5 imagemin-zopfli@7
|
||||||
node tools/generate-images.js $(TAGS)
|
node build/generate-images.js $(TAGS)
|
||||||
|
|
||||||
.PHONY: generate-manpage
|
.PHONY: generate-manpage
|
||||||
generate-manpage:
|
generate-manpage:
|
||||||
|
@ -1028,10 +1003,10 @@ generate-manpage:
|
||||||
@gzip -9 man/man1/gitea.1 && echo man/man1/gitea.1.gz created
|
@gzip -9 man/man1/gitea.1 && echo man/man1/gitea.1.gz created
|
||||||
@#TODO A small script that formats config-cheat-sheet.en-us.md nicely for use as a config man page
|
@#TODO A small script that formats config-cheat-sheet.en-us.md nicely for use as a config man page
|
||||||
|
|
||||||
|
.PHONY: docker
|
||||||
|
docker:
|
||||||
|
docker build --disable-content-trust=false -t $(DOCKER_REF) .
|
||||||
|
# support also build args docker build --build-arg GITEA_VERSION=v1.2.3 --build-arg TAGS="bindata sqlite sqlite_unlock_notify" .
|
||||||
|
|
||||||
# This endif closes the if at the top of the file
|
# This endif closes the if at the top of the file
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Disable parallel execution because it would break some targets that don't
|
|
||||||
# specify exact dependencies like 'backend' which does currently not depend
|
|
||||||
# on 'frontend' to enable Node.js-less builds from source tarballs.
|
|
||||||
.NOTPARALLEL:
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<img src="./assets/logo.svg" alt="" width="192" align="center" />
|
<img src="https://codeberg.org/forgejo/meta/raw/branch/readme/logo/forgejo.svg" alt="" width="192" align="center" />
|
||||||
<h1 align="center">Welcome to Forgejo</h1>
|
<h1 align="center">Welcome to Forgejo</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -40,11 +40,6 @@ If you like any of the following, Forgejo is literally meant for you:
|
||||||
|
|
||||||
Dive into the [documentation](https://forgejo.org/docs/latest/), subscribe to releases and blog post on [our website](https://forgejo.org), <a href="https://floss.social/@forgejo" rel="me">find us on the Fediverse</a> or hop into [our Matrix room](https://matrix.to/#/#forgejo-chat:matrix.org) if you have any questions or want to get involved.
|
Dive into the [documentation](https://forgejo.org/docs/latest/), subscribe to releases and blog post on [our website](https://forgejo.org), <a href="https://floss.social/@forgejo" rel="me">find us on the Fediverse</a> or hop into [our Matrix room](https://matrix.to/#/#forgejo-chat:matrix.org) if you have any questions or want to get involved.
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
Forgejo is distributed under the terms of the [GPL version 3.0](LICENSE) or any later version.
|
|
||||||
|
|
||||||
The agreement for this license [was documented in June 2023](https://codeberg.org/forgejo/governance/pulls/24) and implemented during the development of Forgejo v9.0. All Forgejo versions before v9.0 are distributed under the MIT license.
|
|
||||||
|
|
||||||
## Get involved
|
## Get involved
|
||||||
|
|
||||||
|
|
1040
RELEASE-NOTES.md
1040
RELEASE-NOTES.md
File diff suppressed because it is too large
Load diff
|
@ -1,27 +1,31 @@
|
||||||
<svg viewBox="0 0 212 212" xmlns="http://www.w3.org/2000/svg">
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<style type="text/css">
|
<svg version="1.1" id="main_outline" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||||
circle {
|
y="0px" viewBox="0 0 640 640" style="enable-background:new 0 0 640 640;" xml:space="preserve">
|
||||||
fill: none;
|
<g>
|
||||||
stroke: #000;
|
<path id="teabag" style="fill:#FFFFFF" d="M395.9,484.2l-126.9-61c-12.5-6-17.9-21.2-11.8-33.8l61-126.9c6-12.5,21.2-17.9,33.8-11.8
|
||||||
stroke-width: 15;
|
c17.2,8.3,27.1,13,27.1,13l-0.1-109.2l16.7-0.1l0.1,117.1c0,0,57.4,24.2,83.1,40.1c3.7,2.3,10.2,6.8,12.9,14.4
|
||||||
}
|
c2.1,6.1,2,13.1-1,19.3l-61,126.9C423.6,484.9,408.4,490.3,395.9,484.2z"/>
|
||||||
path {
|
<g>
|
||||||
fill: none;
|
<g>
|
||||||
stroke: #000;
|
<path style="fill:#609926" d="M622.7,149.8c-4.1-4.1-9.6-4-9.6-4s-117.2,6.6-177.9,8c-13.3,0.3-26.5,0.6-39.6,0.7c0,39.1,0,78.2,0,117.2
|
||||||
stroke-width: 25;
|
c-5.5-2.6-11.1-5.3-16.6-7.9c0-36.4-0.1-109.2-0.1-109.2c-29,0.4-89.2-2.2-89.2-2.2s-141.4-7.1-156.8-8.5
|
||||||
}
|
c-9.8-0.6-22.5-2.1-39,1.5c-8.7,1.8-33.5,7.4-53.8,26.9C-4.9,212.4,6.6,276.2,8,285.8c1.7,11.7,6.9,44.2,31.7,72.5
|
||||||
.orange {
|
c45.8,56.1,144.4,54.8,144.4,54.8s12.1,28.9,30.6,55.5c25,33.1,50.7,58.9,75.7,62c63,0,188.9-0.1,188.9-0.1s12,0.1,28.3-10.3
|
||||||
stroke:#ff6600;
|
c14-8.5,26.5-23.4,26.5-23.4s12.9-13.8,30.9-45.3c5.5-9.7,10.1-19.1,14.1-28c0,0,55.2-117.1,55.2-231.1
|
||||||
}
|
C633.2,157.9,624.7,151.8,622.7,149.8z M125.6,353.9c-25.9-8.5-36.9-18.7-36.9-18.7S69.6,321.8,60,295.4
|
||||||
.red {
|
c-16.5-44.2-1.4-71.2-1.4-71.2s8.4-22.5,38.5-30c13.8-3.7,31-3.1,31-3.1s7.1,59.4,15.7,94.2c7.2,29.2,24.8,77.7,24.8,77.7
|
||||||
stroke:#d40000;
|
S142.5,359.9,125.6,353.9z M425.9,461.5c0,0-6.1,14.5-19.6,15.4c-5.8,0.4-10.3-1.2-10.3-1.2s-0.3-0.1-5.3-2.1l-112.9-55
|
||||||
}
|
c0,0-10.9-5.7-12.8-15.6c-2.2-8.1,2.7-18.1,2.7-18.1L322,273c0,0,4.8-9.7,12.2-13c0.6-0.3,2.3-1,4.5-1.5c8.1-2.1,18,2.8,18,2.8
|
||||||
</style>
|
l110.7,53.7c0,0,12.6,5.7,15.3,16.2c1.9,7.4-0.5,14-1.8,17.2C474.6,363.8,425.9,461.5,425.9,461.5z"/>
|
||||||
<g transform="translate(6,6)">
|
<path style="fill:#609926" d="M326.8,380.1c-8.2,0.1-15.4,5.8-17.3,13.8c-1.9,8,2,16.3,9.1,20c7.7,4,17.5,1.8,22.7-5.4
|
||||||
<path d="M58 168 v-98 a50 50 0 0 1 50-50 h20" class="orange" />
|
c5.1-7.1,4.3-16.9-1.8-23.1l24-49.1c1.5,0.1,3.7,0.2,6.2-0.5c4.1-0.9,7.1-3.6,7.1-3.6c4.2,1.8,8.6,3.8,13.2,6.1
|
||||||
<path d="M58 168 v-30 a50 50 0 0 1 50-50 h20" class="red" />
|
c4.8,2.4,9.3,4.9,13.4,7.3c0.9,0.5,1.8,1.1,2.8,1.9c1.6,1.3,3.4,3.1,4.7,5.5c1.9,5.5-1.9,14.9-1.9,14.9
|
||||||
<circle cx="142" cy="20" r="18" class="orange" />
|
c-2.3,7.6-18.4,40.6-18.4,40.6c-8.1-0.2-15.3,5-17.7,12.5c-2.6,8.1,1.1,17.3,8.9,21.3c7.8,4,17.4,1.7,22.5-5.3
|
||||||
<circle cx="142" cy="88" r="18" class="red" />
|
c5-6.8,4.6-16.3-1.1-22.6c1.9-3.7,3.7-7.4,5.6-11.3c5-10.4,13.5-30.4,13.5-30.4c0.9-1.7,5.7-10.3,2.7-21.3
|
||||||
<circle cx="58" cy="180" r="18" class="red" />
|
c-2.5-11.4-12.6-16.7-12.6-16.7c-12.2-7.9-29.2-15.2-29.2-15.2s0-4.1-1.1-7.1c-1.1-3.1-2.8-5.1-3.9-6.3c4.7-9.7,9.4-19.3,14.1-29
|
||||||
</g>
|
c-4.1-2-8.1-4-12.2-6.1c-4.8,9.8-9.7,19.7-14.5,29.5c-6.7-0.1-12.9,3.5-16.1,9.4c-3.4,6.3-2.7,14.1,1.9,19.8
|
||||||
|
C343.2,346.5,335,363.3,326.8,380.1z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 677 B After Width: | Height: | Size: 2.5 KiB |
285
assets/go-licenses.json
generated
285
assets/go-licenses.json
generated
File diff suppressed because one or more lines are too long
|
@ -1,27 +1,31 @@
|
||||||
<svg viewBox="0 0 212 212" xmlns="http://www.w3.org/2000/svg">
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<style type="text/css">
|
<svg version="1.1" id="main_outline" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||||
circle {
|
y="0px" viewBox="0 0 640 640" style="enable-background:new 0 0 640 640;" xml:space="preserve">
|
||||||
fill: none;
|
<g>
|
||||||
stroke: #000;
|
<path id="teabag" style="fill:#FFFFFF" d="M395.9,484.2l-126.9-61c-12.5-6-17.9-21.2-11.8-33.8l61-126.9c6-12.5,21.2-17.9,33.8-11.8
|
||||||
stroke-width: 15;
|
c17.2,8.3,27.1,13,27.1,13l-0.1-109.2l16.7-0.1l0.1,117.1c0,0,57.4,24.2,83.1,40.1c3.7,2.3,10.2,6.8,12.9,14.4
|
||||||
}
|
c2.1,6.1,2,13.1-1,19.3l-61,126.9C423.6,484.9,408.4,490.3,395.9,484.2z"/>
|
||||||
path {
|
<g>
|
||||||
fill: none;
|
<g>
|
||||||
stroke: #000;
|
<path style="fill:#609926" d="M622.7,149.8c-4.1-4.1-9.6-4-9.6-4s-117.2,6.6-177.9,8c-13.3,0.3-26.5,0.6-39.6,0.7c0,39.1,0,78.2,0,117.2
|
||||||
stroke-width: 25;
|
c-5.5-2.6-11.1-5.3-16.6-7.9c0-36.4-0.1-109.2-0.1-109.2c-29,0.4-89.2-2.2-89.2-2.2s-141.4-7.1-156.8-8.5
|
||||||
}
|
c-9.8-0.6-22.5-2.1-39,1.5c-8.7,1.8-33.5,7.4-53.8,26.9C-4.9,212.4,6.6,276.2,8,285.8c1.7,11.7,6.9,44.2,31.7,72.5
|
||||||
.orange {
|
c45.8,56.1,144.4,54.8,144.4,54.8s12.1,28.9,30.6,55.5c25,33.1,50.7,58.9,75.7,62c63,0,188.9-0.1,188.9-0.1s12,0.1,28.3-10.3
|
||||||
stroke:#ff6600;
|
c14-8.5,26.5-23.4,26.5-23.4s12.9-13.8,30.9-45.3c5.5-9.7,10.1-19.1,14.1-28c0,0,55.2-117.1,55.2-231.1
|
||||||
}
|
C633.2,157.9,624.7,151.8,622.7,149.8z M125.6,353.9c-25.9-8.5-36.9-18.7-36.9-18.7S69.6,321.8,60,295.4
|
||||||
.red {
|
c-16.5-44.2-1.4-71.2-1.4-71.2s8.4-22.5,38.5-30c13.8-3.7,31-3.1,31-3.1s7.1,59.4,15.7,94.2c7.2,29.2,24.8,77.7,24.8,77.7
|
||||||
stroke:#d40000;
|
S142.5,359.9,125.6,353.9z M425.9,461.5c0,0-6.1,14.5-19.6,15.4c-5.8,0.4-10.3-1.2-10.3-1.2s-0.3-0.1-5.3-2.1l-112.9-55
|
||||||
}
|
c0,0-10.9-5.7-12.8-15.6c-2.2-8.1,2.7-18.1,2.7-18.1L322,273c0,0,4.8-9.7,12.2-13c0.6-0.3,2.3-1,4.5-1.5c8.1-2.1,18,2.8,18,2.8
|
||||||
</style>
|
l110.7,53.7c0,0,12.6,5.7,15.3,16.2c1.9,7.4-0.5,14-1.8,17.2C474.6,363.8,425.9,461.5,425.9,461.5z"/>
|
||||||
<g transform="translate(6,6)">
|
<path style="fill:#609926" d="M326.8,380.1c-8.2,0.1-15.4,5.8-17.3,13.8c-1.9,8,2,16.3,9.1,20c7.7,4,17.5,1.8,22.7-5.4
|
||||||
<path d="M58 168 v-98 a50 50 0 0 1 50-50 h20" class="orange" />
|
c5.1-7.1,4.3-16.9-1.8-23.1l24-49.1c1.5,0.1,3.7,0.2,6.2-0.5c4.1-0.9,7.1-3.6,7.1-3.6c4.2,1.8,8.6,3.8,13.2,6.1
|
||||||
<path d="M58 168 v-30 a50 50 0 0 1 50-50 h20" class="red" />
|
c4.8,2.4,9.3,4.9,13.4,7.3c0.9,0.5,1.8,1.1,2.8,1.9c1.6,1.3,3.4,3.1,4.7,5.5c1.9,5.5-1.9,14.9-1.9,14.9
|
||||||
<circle cx="142" cy="20" r="18" class="orange" />
|
c-2.3,7.6-18.4,40.6-18.4,40.6c-8.1-0.2-15.3,5-17.7,12.5c-2.6,8.1,1.1,17.3,8.9,21.3c7.8,4,17.4,1.7,22.5-5.3
|
||||||
<circle cx="142" cy="88" r="18" class="red" />
|
c5-6.8,4.6-16.3-1.1-22.6c1.9-3.7,3.7-7.4,5.6-11.3c5-10.4,13.5-30.4,13.5-30.4c0.9-1.7,5.7-10.3,2.7-21.3
|
||||||
<circle cx="58" cy="180" r="18" class="red" />
|
c-2.5-11.4-12.6-16.7-12.6-16.7c-12.2-7.9-29.2-15.2-29.2-15.2s0-4.1-1.1-7.1c-1.1-3.1-2.8-5.1-3.9-6.3c4.7-9.7,9.4-19.3,14.1-29
|
||||||
</g>
|
c-4.1-2-8.1-4-12.2-6.1c-4.8,9.8-9.7,19.7-14.5,29.5c-6.7-0.1-12.9,3.5-16.1,9.4c-3.4,6.3-2.7,14.1,1.9,19.8
|
||||||
|
C343.2,346.5,335,363.3,326.8,380.1z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 677 B After Width: | Height: | Size: 2.5 KiB |
|
@ -18,8 +18,8 @@ import (
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if len(os.Args) != 2 {
|
if len(os.Args) != 2 {
|
||||||
fmt.Println("usage: backport-locales <to-ref>")
|
println("usage: backport-locales <to-ref>")
|
||||||
fmt.Println("eg: backport-locales release/v1.19")
|
println("eg: backport-locales release/v1.19")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,6 @@ func newFileCollector(fileFilter string, batchSize int) (*fileCollector, error)
|
||||||
co.includePatterns = append(co.includePatterns, regexp.MustCompile(`.*\.go$`))
|
co.includePatterns = append(co.includePatterns, regexp.MustCompile(`.*\.go$`))
|
||||||
|
|
||||||
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`.*\bbindata\.go$`))
|
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`.*\bbindata\.go$`))
|
||||||
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`\.pb\.go$`))
|
|
||||||
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`tests/gitea-repositories-meta`))
|
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`tests/gitea-repositories-meta`))
|
||||||
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`tests/integration/migration-test`))
|
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`tests/integration/migration-test`))
|
||||||
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`modules/git/tests`))
|
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`modules/git/tests`))
|
||||||
|
@ -204,6 +203,17 @@ Example:
|
||||||
`, "file-batch-exec")
|
`, "file-batch-exec")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getGoVersion() string {
|
||||||
|
goModFile, err := os.ReadFile("go.mod")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf(`Faild to read "go.mod": %v`, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
goModVersionRegex := regexp.MustCompile(`go \d+\.\d+`)
|
||||||
|
goModVersionLine := goModVersionRegex.Find(goModFile)
|
||||||
|
return string(goModVersionLine[3:])
|
||||||
|
}
|
||||||
|
|
||||||
func newFileCollectorFromMainOptions(mainOptions map[string]string) (fc *fileCollector, err error) {
|
func newFileCollectorFromMainOptions(mainOptions map[string]string) (fc *fileCollector, err error) {
|
||||||
fileFilter := mainOptions["file-filter"]
|
fileFilter := mainOptions["file-filter"]
|
||||||
if fileFilter == "" {
|
if fileFilter == "" {
|
||||||
|
@ -268,8 +278,7 @@ func main() {
|
||||||
log.Print("the -d option is not supported by gitea-fmt")
|
log.Print("the -d option is not supported by gitea-fmt")
|
||||||
}
|
}
|
||||||
cmdErrors = append(cmdErrors, giteaFormatGoImports(files, containsString(subArgs, "-w")))
|
cmdErrors = append(cmdErrors, giteaFormatGoImports(files, containsString(subArgs, "-w")))
|
||||||
cmdErrors = append(cmdErrors, passThroughCmd("gofmt", append([]string{"-w", "-r", "interface{} -> any"}, substArgs...)))
|
cmdErrors = append(cmdErrors, passThroughCmd("go", append([]string{"run", os.Getenv("GOFUMPT_PACKAGE"), "-extra", "-lang", getGoVersion()}, substArgs...)))
|
||||||
cmdErrors = append(cmdErrors, passThroughCmd("go", append([]string{"run", os.Getenv("GOFUMPT_PACKAGE"), "-extra"}, substArgs...)))
|
|
||||||
default:
|
default:
|
||||||
log.Fatalf("unknown cmd: %s %v", subCmd, subArgs)
|
log.Fatalf("unknown cmd: %s %v", subCmd, subArgs)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFormatImportsSimple(t *testing.T) {
|
func TestFormatImportsSimple(t *testing.T) {
|
||||||
|
@ -30,7 +29,7 @@ import (
|
||||||
)
|
)
|
||||||
`
|
`
|
||||||
|
|
||||||
require.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, expected, string(formatted))
|
assert.Equal(t, expected, string(formatted))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +92,7 @@ import (
|
||||||
)
|
)
|
||||||
`
|
`
|
||||||
|
|
||||||
require.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, expected, string(formatted))
|
assert.Equal(t, expected, string(formatted))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,5 +120,5 @@ import (
|
||||||
"image/gif"
|
"image/gif"
|
||||||
)
|
)
|
||||||
`))
|
`))
|
||||||
require.ErrorIs(t, err, errInvalidCommentBetweenImports)
|
assert.ErrorIs(t, err, errInvalidCommentBetweenImports)
|
||||||
}
|
}
|
||||||
|
|
27
build/crowdin-to-weblate.sh
Executable file
27
build/crowdin-to-weblate.sh
Executable file
|
@ -0,0 +1,27 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Copyright 2024 The Forgejo Authors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
D=/tmp/crowdin-to-weblate
|
||||||
|
mkdir -p $D
|
||||||
|
|
||||||
|
function checkout() {
|
||||||
|
if test -d $D/gitea ; then
|
||||||
|
git -C $D/gitea reset --hard
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
git clone --depth 1 https://github.com/go-gitea/gitea $D/gitea
|
||||||
|
}
|
||||||
|
|
||||||
|
function replace() {
|
||||||
|
go run build/merge-forgejo-locales.go $D/gitea/options/locale
|
||||||
|
cp -a $D/gitea/options/locale/* options/locale
|
||||||
|
}
|
||||||
|
|
||||||
|
function run() {
|
||||||
|
checkout
|
||||||
|
replace
|
||||||
|
}
|
||||||
|
|
||||||
|
"$@"
|
|
@ -142,7 +142,7 @@ func generate() ([]byte, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forgejo customizations
|
// gitea customizations
|
||||||
i, ok := aliasMap["tada"]
|
i, ok := aliasMap["tada"]
|
||||||
if ok {
|
if ok {
|
||||||
data[i].Aliases = append(data[i].Aliases, "hooray")
|
data[i].Aliases = append(data[i].Aliases, "hooray")
|
||||||
|
|
|
@ -77,20 +77,6 @@ func main() {
|
||||||
sort.Strings(paths)
|
sort.Strings(paths)
|
||||||
|
|
||||||
var entries []LicenseEntry
|
var entries []LicenseEntry
|
||||||
|
|
||||||
{
|
|
||||||
licenseText, err := os.ReadFile("LICENSE")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
entries = append(entries, LicenseEntry{
|
|
||||||
Name: "codeberg.org/forgejo/forgejo",
|
|
||||||
Path: "codeberg.org/forgejo/forgejo/GPL-3.0-or-later",
|
|
||||||
LicenseText: string(licenseText),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, filePath := range paths {
|
for _, filePath := range paths {
|
||||||
licenseText, err := os.ReadFile(filePath)
|
licenseText, err := os.ReadFile(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,13 +1,20 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
import imageminZopfli from 'imagemin-zopfli'; // eslint-disable-line i/no-unresolved
|
import imageminZopfli from 'imagemin-zopfli';
|
||||||
import {loadSVGFromString, Canvas, Rect, util} from 'fabric/node'; // eslint-disable-line i/no-unresolved
|
|
||||||
import {optimize} from 'svgo';
|
import {optimize} from 'svgo';
|
||||||
|
import {fabric} from 'fabric';
|
||||||
import {readFile, writeFile} from 'node:fs/promises';
|
import {readFile, writeFile} from 'node:fs/promises';
|
||||||
import {argv, exit} from 'node:process';
|
|
||||||
|
|
||||||
function doExit(err) {
|
function exit(err) {
|
||||||
if (err) console.error(err);
|
if (err) console.error(err);
|
||||||
exit(err ? 1 : 0);
|
process.exit(err ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadSvg(svg) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
fabric.loadSVGFromString(svg, (objects, options) => {
|
||||||
|
resolve({objects, options});
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generate(svg, path, {size, bg}) {
|
async function generate(svg, path, {size, bg}) {
|
||||||
|
@ -20,7 +27,7 @@ async function generate(svg, path, {size, bg}) {
|
||||||
'removeDimensions',
|
'removeDimensions',
|
||||||
{
|
{
|
||||||
name: 'addAttributesToSVGElement',
|
name: 'addAttributesToSVGElement',
|
||||||
params: {attributes: [{width: size}, {height: size}]},
|
params: {attributes: [{width: size}, {height: size}]}
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
@ -28,14 +35,14 @@ async function generate(svg, path, {size, bg}) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const {objects, options} = await loadSVGFromString(svg);
|
const {objects, options} = await loadSvg(svg);
|
||||||
const canvas = new Canvas();
|
const canvas = new fabric.Canvas();
|
||||||
canvas.setDimensions({width: size, height: size});
|
canvas.setDimensions({width: size, height: size});
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
ctx.scale(options.width ? (size / options.width) : 1, options.height ? (size / options.height) : 1);
|
ctx.scale(options.width ? (size / options.width) : 1, options.height ? (size / options.height) : 1);
|
||||||
|
|
||||||
if (bg) {
|
if (bg) {
|
||||||
canvas.add(new Rect({
|
canvas.add(new fabric.Rect({
|
||||||
left: 0,
|
left: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
height: size * (1 / (size / options.height)),
|
height: size * (1 / (size / options.height)),
|
||||||
|
@ -44,7 +51,7 @@ async function generate(svg, path, {size, bg}) {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.add(util.groupSVGElements(objects, options));
|
canvas.add(fabric.util.groupSVGElements(objects, options));
|
||||||
canvas.renderAll();
|
canvas.renderAll();
|
||||||
|
|
||||||
let png = Buffer.from([]);
|
let png = Buffer.from([]);
|
||||||
|
@ -57,7 +64,7 @@ async function generate(svg, path, {size, bg}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const gitea = argv.slice(2).includes('gitea');
|
const gitea = process.argv.slice(2).includes('gitea');
|
||||||
const logoSvg = await readFile(new URL('../assets/logo.svg', import.meta.url), 'utf8');
|
const logoSvg = await readFile(new URL('../assets/logo.svg', import.meta.url), 'utf8');
|
||||||
const faviconSvg = await readFile(new URL('../assets/favicon.svg', import.meta.url), 'utf8');
|
const faviconSvg = await readFile(new URL('../assets/favicon.svg', import.meta.url), 'utf8');
|
||||||
|
|
||||||
|
@ -72,8 +79,4 @@ async function main() {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
main().then(exit).catch(exit);
|
||||||
doExit(await main());
|
|
||||||
} catch (err) {
|
|
||||||
doExit(err);
|
|
||||||
}
|
|
|
@ -4,16 +4,15 @@ import {optimize} from 'svgo';
|
||||||
import {parse} from 'node:path';
|
import {parse} from 'node:path';
|
||||||
import {readFile, writeFile, mkdir} from 'node:fs/promises';
|
import {readFile, writeFile, mkdir} from 'node:fs/promises';
|
||||||
import {fileURLToPath} from 'node:url';
|
import {fileURLToPath} from 'node:url';
|
||||||
import {exit} from 'node:process';
|
|
||||||
|
|
||||||
const glob = (pattern) => fastGlob.sync(pattern, {
|
const glob = (pattern) => fastGlob.sync(pattern, {
|
||||||
cwd: fileURLToPath(new URL('..', import.meta.url)),
|
cwd: fileURLToPath(new URL('..', import.meta.url)),
|
||||||
absolute: true,
|
absolute: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
function doExit(err) {
|
function exit(err) {
|
||||||
if (err) console.error(err);
|
if (err) console.error(err);
|
||||||
exit(err ? 1 : 0);
|
process.exit(err ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function processFile(file, {prefix, fullName} = {}) {
|
async function processFile(file, {prefix, fullName} = {}) {
|
||||||
|
@ -39,8 +38,8 @@ async function processFile(file, {prefix, fullName} = {}) {
|
||||||
attributes: [
|
attributes: [
|
||||||
{'xmlns': 'http://www.w3.org/2000/svg'},
|
{'xmlns': 'http://www.w3.org/2000/svg'},
|
||||||
{'width': '16'}, {'height': '16'}, {'aria-hidden': 'true'},
|
{'width': '16'}, {'height': '16'}, {'aria-hidden': 'true'},
|
||||||
],
|
]
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
@ -60,11 +59,8 @@ async function main() {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
...processFiles('node_modules/@primer/octicons/build/svg/*-16.svg', {prefix: 'octicon'}),
|
...processFiles('node_modules/@primer/octicons/build/svg/*-16.svg', {prefix: 'octicon'}),
|
||||||
...processFiles('web_src/svg/*.svg'),
|
...processFiles('web_src/svg/*.svg'),
|
||||||
|
...processFiles('public/assets/img/gitea.svg', {fullName: 'gitea-gitea'}),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
main().then(exit).catch(exit);
|
||||||
doExit(await main());
|
|
||||||
} catch (err) {
|
|
||||||
doExit(err);
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2024 The Forgejo Authors c/o Codeberg e.V.. All rights reserved.
|
// Copyright 2022 The Forgejo Authors c/o Codeberg e.V.. All rights reserved.
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
@ -7,9 +7,103 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"bufio"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
const (
|
||||||
fmt.Println("NOT NEEDED: THIS IS A NOOP AS OF Forgejo 7.0 BUT KEPT FOR BACKWARD COMPATIBILITY")
|
trimPrefix = "gitea_"
|
||||||
|
sourceFolder = "options/locales/"
|
||||||
|
)
|
||||||
|
|
||||||
|
// returns list of locales, still containing the file extension!
|
||||||
|
func generate_locale_list() []string {
|
||||||
|
localeFiles, _ := os.ReadDir(sourceFolder)
|
||||||
|
locales := []string{}
|
||||||
|
for _, localeFile := range localeFiles {
|
||||||
|
if !localeFile.IsDir() && strings.HasPrefix(localeFile.Name(), trimPrefix) {
|
||||||
|
locales = append(locales, strings.TrimPrefix(localeFile.Name(), trimPrefix))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return locales
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace all occurrences of Gitea with Forgejo
|
||||||
|
func renameGiteaForgejo(filename string) []byte {
|
||||||
|
file, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
replacements := []string{
|
||||||
|
"Gitea", "Forgejo",
|
||||||
|
"https://docs.gitea.com/installation/install-from-binary", "https://forgejo.org/download/#installation-from-binary",
|
||||||
|
"https://github.com/go-gitea/gitea/tree/master/docker", "https://forgejo.org/download/#container-image",
|
||||||
|
"https://docs.gitea.com/installation/install-from-package", "https://forgejo.org/download",
|
||||||
|
"https://code.gitea.io/gitea", "https://forgejo.org/download",
|
||||||
|
"code.gitea.io/gitea", "Forgejo",
|
||||||
|
`<a href="https://github.com/go-gitea/gitea/issues" target="_blank">GitHub</a>`, `<a href="https://codeberg.org/forgejo/forgejo/issues" target="_blank">Codeberg</a>`,
|
||||||
|
"https://github.com/go-gitea/gitea", "https://codeberg.org/forgejo/forgejo",
|
||||||
|
"https://blog.gitea.io", "https://forgejo.org/news",
|
||||||
|
"https://docs.gitea.com/usage/protected-tags", "https://forgejo.org/docs/latest/user/protection/#protected-tags",
|
||||||
|
"https://docs.gitea.com/usage/webhooks", "https://forgejo.org/docs/latest/user/webhooks/",
|
||||||
|
}
|
||||||
|
replacer := strings.NewReplacer(replacements...)
|
||||||
|
replaced := make(map[string]bool, len(replacements)/2)
|
||||||
|
count_replaced := func(original string) {
|
||||||
|
for i := 0; i < len(replacements); i += 2 {
|
||||||
|
if strings.Contains(original, replacements[i]) {
|
||||||
|
replaced[replacements[i]] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out := make([]byte, 0, 1024)
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
scanner.Split(bufio.ScanLines)
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
|
||||||
|
if strings.HasPrefix(line, "license_desc=") {
|
||||||
|
line = strings.Replace(line, "GitHub", "Forgejo", 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
|
||||||
|
out = append(out, []byte(line+"\n")...)
|
||||||
|
} else if strings.HasPrefix(line, "settings.web_hook_name_gitea") {
|
||||||
|
out = append(out, []byte(line+"\n")...)
|
||||||
|
out = append(out, []byte("settings.web_hook_name_forgejo = Forgejo\n")...)
|
||||||
|
} else if strings.HasPrefix(line, "migrate.gitea.description") {
|
||||||
|
re := regexp.MustCompile(`(.*Gitea)`)
|
||||||
|
out = append(out, []byte(re.ReplaceAllString(line, "${1}/Forgejo")+"\n")...)
|
||||||
|
} else {
|
||||||
|
count_replaced(line)
|
||||||
|
out = append(out, []byte(replacer.Replace(line)+"\n")...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file.Close()
|
||||||
|
if strings.HasSuffix(filename, "gitea_en-US.ini") {
|
||||||
|
for i := 0; i < len(replacements); i += 2 {
|
||||||
|
if replaced[replacements[i]] == false {
|
||||||
|
log.Fatalf("%s was never used to replace something in %s, it is obsolete and must be updated", replacements[i], filename)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
d := os.Args[1]
|
||||||
|
files, err := os.ReadDir(d)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, f := range files {
|
||||||
|
p := d + "/" + f.Name()
|
||||||
|
os.WriteFile(p, renameGiteaForgejo(p), 0o644)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ var (
|
||||||
// CmdActions represents the available actions sub-commands.
|
// CmdActions represents the available actions sub-commands.
|
||||||
CmdActions = &cli.Command{
|
CmdActions = &cli.Command{
|
||||||
Name: "actions",
|
Name: "actions",
|
||||||
Usage: "Manage Forgejo Actions",
|
Usage: "Manage Gitea Actions",
|
||||||
Subcommands: []*cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
subcmdActionsGenRunnerToken,
|
subcmdActionsGenRunnerToken,
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
@ -92,7 +91,7 @@ func runListAuth(c *cli.Context) error {
|
||||||
|
|
||||||
func runDeleteAuth(c *cli.Context) error {
|
func runDeleteAuth(c *cli.Context) error {
|
||||||
if !c.IsSet("id") {
|
if !c.IsSet("id") {
|
||||||
return errors.New("--id flag is missing")
|
return fmt.Errorf("--id flag is missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
"code.gitea.io/gitea/services/auth/source/ldap"
|
"code.gitea.io/gitea/services/auth/source/ldap"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -235,7 +234,7 @@ func TestAddLdapBindDn(t *testing.T) {
|
||||||
if c.errMsg != "" {
|
if c.errMsg != "" {
|
||||||
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
||||||
} else {
|
} else {
|
||||||
require.NoError(t, err, "case %d: should have no errors", n)
|
assert.NoError(t, err, "case %d: should have no errors", n)
|
||||||
assert.Equal(t, c.source, createdAuthSource, "case %d: wrong authSource", n)
|
assert.Equal(t, c.source, createdAuthSource, "case %d: wrong authSource", n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -466,7 +465,7 @@ func TestAddLdapSimpleAuth(t *testing.T) {
|
||||||
if c.errMsg != "" {
|
if c.errMsg != "" {
|
||||||
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
||||||
} else {
|
} else {
|
||||||
require.NoError(t, err, "case %d: should have no errors", n)
|
assert.NoError(t, err, "case %d: should have no errors", n)
|
||||||
assert.Equal(t, c.authSource, createdAuthSource, "case %d: wrong authSource", n)
|
assert.Equal(t, c.authSource, createdAuthSource, "case %d: wrong authSource", n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -929,7 +928,7 @@ func TestUpdateLdapBindDn(t *testing.T) {
|
||||||
if c.errMsg != "" {
|
if c.errMsg != "" {
|
||||||
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
||||||
} else {
|
} else {
|
||||||
require.NoError(t, err, "case %d: should have no errors", n)
|
assert.NoError(t, err, "case %d: should have no errors", n)
|
||||||
assert.Equal(t, c.authSource, updatedAuthSource, "case %d: wrong authSource", n)
|
assert.Equal(t, c.authSource, updatedAuthSource, "case %d: wrong authSource", n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1319,7 +1318,7 @@ func TestUpdateLdapSimpleAuth(t *testing.T) {
|
||||||
if c.errMsg != "" {
|
if c.errMsg != "" {
|
||||||
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
||||||
} else {
|
} else {
|
||||||
require.NoError(t, err, "case %d: should have no errors", n)
|
assert.NoError(t, err, "case %d: should have no errors", n)
|
||||||
assert.Equal(t, c.authSource, updatedAuthSource, "case %d: wrong authSource", n)
|
assert.Equal(t, c.authSource, updatedAuthSource, "case %d: wrong authSource", n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
|
@ -194,7 +193,7 @@ func runAddOauth(c *cli.Context) error {
|
||||||
|
|
||||||
func runUpdateOauth(c *cli.Context) error {
|
func runUpdateOauth(c *cli.Context) error {
|
||||||
if !c.IsSet("id") {
|
if !c.IsSet("id") {
|
||||||
return errors.New("--id flag is missing")
|
return fmt.Errorf("--id flag is missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
|
|
|
@ -5,6 +5,7 @@ package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
auth_model "code.gitea.io/gitea/models/auth"
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
|
@ -165,7 +166,7 @@ func runAddSMTP(c *cli.Context) error {
|
||||||
|
|
||||||
func runUpdateSMTP(c *cli.Context) error {
|
func runUpdateSMTP(c *cli.Context) error {
|
||||||
if !c.IsSet("id") {
|
if !c.IsSet("id") {
|
||||||
return errors.New("--id flag is missing")
|
return fmt.Errorf("--id flag is missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
|
|
|
@ -4,14 +4,13 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/auth/password"
|
pwd "code.gitea.io/gitea/modules/auth/password"
|
||||||
"code.gitea.io/gitea/modules/optional"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
user_service "code.gitea.io/gitea/services/user"
|
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
@ -33,11 +32,6 @@ var microcmdUserChangePassword = &cli.Command{
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "New password to set for user",
|
Usage: "New password to set for user",
|
||||||
},
|
},
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "must-change-password",
|
|
||||||
Usage: "User must change password",
|
|
||||||
Value: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,27 +46,31 @@ func runChangePassword(c *cli.Context) error {
|
||||||
if err := initDB(ctx); err != nil {
|
if err := initDB(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if len(c.String("password")) < setting.MinPasswordLength {
|
||||||
|
return fmt.Errorf("Password is not long enough. Needs to be at least %d", setting.MinPasswordLength)
|
||||||
|
}
|
||||||
|
|
||||||
user, err := user_model.GetUserByName(ctx, c.String("username"))
|
if !pwd.IsComplexEnough(c.String("password")) {
|
||||||
|
return errors.New("Password does not meet complexity requirements")
|
||||||
|
}
|
||||||
|
pwned, err := pwd.IsPwned(context.Background(), c.String("password"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if pwned {
|
||||||
opts := &user_service.UpdateAuthOptions{
|
return errors.New("The password you chose is on a list of stolen passwords previously exposed in public data breaches. Please try again with a different password.\nFor more details, see https://haveibeenpwned.com/Passwords")
|
||||||
Password: optional.Some(c.String("password")),
|
|
||||||
MustChangePassword: optional.Some(c.Bool("must-change-password")),
|
|
||||||
}
|
}
|
||||||
if err := user_service.UpdateAuth(ctx, user, opts); err != nil {
|
uname := c.String("username")
|
||||||
switch {
|
user, err := user_model.GetUserByName(ctx, uname)
|
||||||
case errors.Is(err, password.ErrMinLength):
|
if err != nil {
|
||||||
return fmt.Errorf("password is not long enough, needs to be at least %d characters", setting.MinPasswordLength)
|
return err
|
||||||
case errors.Is(err, password.ErrComplexity):
|
}
|
||||||
return errors.New("password does not meet complexity requirements")
|
if err = user.SetPassword(c.String("password")); err != nil {
|
||||||
case errors.Is(err, password.ErrIsPwned):
|
return err
|
||||||
return errors.New("the password is in a list of stolen passwords previously exposed in public data breaches, please try again with a different password, to see more details: https://haveibeenpwned.com/Passwords")
|
}
|
||||||
default:
|
|
||||||
return err
|
if err = user_model.UpdateUserCols(ctx, user, "passwd", "passwd_hash_algo", "salt"); err != nil {
|
||||||
}
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("%s's password has been successfully updated!\n", user.Name)
|
fmt.Printf("%s's password has been successfully updated!\n", user.Name)
|
||||||
|
|
|
@ -8,11 +8,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
auth_model "code.gitea.io/gitea/models/auth"
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
"code.gitea.io/gitea/models/db"
|
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
pwd "code.gitea.io/gitea/modules/auth/password"
|
pwd "code.gitea.io/gitea/modules/auth/password"
|
||||||
"code.gitea.io/gitea/modules/optional"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
@ -47,10 +46,8 @@ var microcmdUserCreate = &cli.Command{
|
||||||
Usage: "Generate a random password for the user",
|
Usage: "Generate a random password for the user",
|
||||||
},
|
},
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "must-change-password",
|
Name: "must-change-password",
|
||||||
Usage: "Set this option to false to prevent forcing the user to change their password after initial login",
|
Usage: "Set this option to false to prevent forcing the user to change their password after initial login, (Default: true)",
|
||||||
Value: true,
|
|
||||||
DisableDefaultText: true,
|
|
||||||
},
|
},
|
||||||
&cli.IntFlag{
|
&cli.IntFlag{
|
||||||
Name: "random-password-length",
|
Name: "random-password-length",
|
||||||
|
@ -74,10 +71,10 @@ func runCreateUser(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.IsSet("name") && c.IsSet("username") {
|
if c.IsSet("name") && c.IsSet("username") {
|
||||||
return errors.New("cannot set both --name and --username flags")
|
return errors.New("Cannot set both --name and --username flags")
|
||||||
}
|
}
|
||||||
if !c.IsSet("name") && !c.IsSet("username") {
|
if !c.IsSet("name") && !c.IsSet("username") {
|
||||||
return errors.New("one of --name or --username flags must be set")
|
return errors.New("One of --name or --username flags must be set")
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.IsSet("password") && c.IsSet("random-password") {
|
if c.IsSet("password") && c.IsSet("random-password") {
|
||||||
|
@ -113,27 +110,23 @@ func runCreateUser(c *cli.Context) error {
|
||||||
return errors.New("must set either password or random-password flag")
|
return errors.New("must set either password or random-password flag")
|
||||||
}
|
}
|
||||||
|
|
||||||
isAdmin := c.Bool("admin")
|
// always default to true
|
||||||
mustChangePassword := true // always default to true
|
changePassword := true
|
||||||
if c.IsSet("must-change-password") {
|
|
||||||
// if the flag is set, use the value provided by the user
|
// If this is the first user being created.
|
||||||
mustChangePassword = c.Bool("must-change-password")
|
// Take it as the admin and don't force a password update.
|
||||||
} else {
|
if n := user_model.CountUsers(ctx, nil); n == 0 {
|
||||||
// check whether there are users in the database
|
changePassword = false
|
||||||
hasUserRecord, err := db.IsTableNotEmpty(&user_model.User{})
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("IsTableNotEmpty: %w", err)
|
|
||||||
}
|
|
||||||
if !hasUserRecord {
|
|
||||||
// if this is the first admin being created, don't force to change password (keep the old behavior)
|
|
||||||
mustChangePassword = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
restricted := optional.None[bool]()
|
if c.IsSet("must-change-password") {
|
||||||
|
changePassword = c.Bool("must-change-password")
|
||||||
|
}
|
||||||
|
|
||||||
|
restricted := util.OptionalBoolNone
|
||||||
|
|
||||||
if c.IsSet("restricted") {
|
if c.IsSet("restricted") {
|
||||||
restricted = optional.Some(c.Bool("restricted"))
|
restricted = util.OptionalBoolOf(c.Bool("restricted"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// default user visibility in app.ini
|
// default user visibility in app.ini
|
||||||
|
@ -143,13 +136,13 @@ func runCreateUser(c *cli.Context) error {
|
||||||
Name: username,
|
Name: username,
|
||||||
Email: c.String("email"),
|
Email: c.String("email"),
|
||||||
Passwd: password,
|
Passwd: password,
|
||||||
IsAdmin: isAdmin,
|
IsAdmin: c.Bool("admin"),
|
||||||
MustChangePassword: mustChangePassword,
|
MustChangePassword: changePassword,
|
||||||
Visibility: visibility,
|
Visibility: visibility,
|
||||||
}
|
}
|
||||||
|
|
||||||
overwriteDefault := &user_model.CreateUserOverwriteOptions{
|
overwriteDefault := &user_model.CreateUserOverwriteOptions{
|
||||||
IsActive: optional.Some(true),
|
IsActive: util.OptionalBoolTrue,
|
||||||
IsRestricted: restricted,
|
IsRestricted: restricted,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -43,7 +42,7 @@ var microcmdUserDelete = &cli.Command{
|
||||||
|
|
||||||
func runDeleteUser(c *cli.Context) error {
|
func runDeleteUser(c *cli.Context) error {
|
||||||
if !c.IsSet("id") && !c.IsSet("username") && !c.IsSet("email") {
|
if !c.IsSet("id") && !c.IsSet("username") && !c.IsSet("email") {
|
||||||
return errors.New("You must provide the id, username or email of a user to delete")
|
return fmt.Errorf("You must provide the id, username or email of a user to delete")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
auth_model "code.gitea.io/gitea/models/auth"
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
|
@ -43,7 +42,7 @@ var microcmdUserGenerateAccessToken = &cli.Command{
|
||||||
|
|
||||||
func runGenerateAccessToken(c *cli.Context) error {
|
func runGenerateAccessToken(c *cli.Context) error {
|
||||||
if !c.IsSet("username") {
|
if !c.IsSet("username") {
|
||||||
return errors.New("You must provide a username to generate a token for")
|
return fmt.Errorf("You must provide a username to generate a token for")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
|
@ -69,7 +68,7 @@ func runGenerateAccessToken(c *cli.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if exist {
|
if exist {
|
||||||
return errors.New("access token name has been used already")
|
return fmt.Errorf("access token name has been used already")
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure the scopes are valid
|
// make sure the scopes are valid
|
||||||
|
|
|
@ -136,7 +136,7 @@ func runCert(c *cli.Context) error {
|
||||||
SerialNumber: serialNumber,
|
SerialNumber: serialNumber,
|
||||||
Subject: pkix.Name{
|
Subject: pkix.Name{
|
||||||
Organization: []string{"Acme Co"},
|
Organization: []string{"Acme Co"},
|
||||||
CommonName: "Forgejo",
|
CommonName: "Gitea",
|
||||||
},
|
},
|
||||||
NotBefore: notBefore,
|
NotBefore: notBefore,
|
||||||
NotAfter: notAfter,
|
NotAfter: notAfter,
|
||||||
|
|
|
@ -15,7 +15,7 @@ import (
|
||||||
var CmdDocs = &cli.Command{
|
var CmdDocs = &cli.Command{
|
||||||
Name: "docs",
|
Name: "docs",
|
||||||
Usage: "Output CLI documentation",
|
Usage: "Output CLI documentation",
|
||||||
Description: "A command to output Forgejo's CLI documentation, optionally to a file.",
|
Description: "A command to output Gitea's CLI documentation, optionally to a file.",
|
||||||
Action: runDocs,
|
Action: runDocs,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
|
|
|
@ -27,7 +27,7 @@ import (
|
||||||
var CmdDoctor = &cli.Command{
|
var CmdDoctor = &cli.Command{
|
||||||
Name: "doctor",
|
Name: "doctor",
|
||||||
Usage: "Diagnose and optionally fix problems, convert or re-create database tables",
|
Usage: "Diagnose and optionally fix problems, convert or re-create database tables",
|
||||||
Description: "A command to diagnose problems with the current Forgejo instance according to the given configuration. Some problems can optionally be fixed by modifying the database or data storage.",
|
Description: "A command to diagnose problems with the current Gitea instance according to the given configuration. Some problems can optionally be fixed by modifying the database or data storage.",
|
||||||
|
|
||||||
Subcommands: []*cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
cmdDoctorCheck,
|
cmdDoctorCheck,
|
||||||
|
@ -39,7 +39,7 @@ var CmdDoctor = &cli.Command{
|
||||||
var cmdDoctorCheck = &cli.Command{
|
var cmdDoctorCheck = &cli.Command{
|
||||||
Name: "check",
|
Name: "check",
|
||||||
Usage: "Diagnose and optionally fix problems",
|
Usage: "Diagnose and optionally fix problems",
|
||||||
Description: "A command to diagnose problems with the current Forgejo instance according to the given configuration. Some problems can optionally be fixed by modifying the database or data storage.",
|
Description: "A command to diagnose problems with the current Gitea instance according to the given configuration. Some problems can optionally be fixed by modifying the database or data storage.",
|
||||||
Action: runDoctorCheck,
|
Action: runDoctorCheck,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
|
@ -84,7 +84,7 @@ var cmdRecreateTable = &cli.Command{
|
||||||
Usage: "Print SQL commands sent",
|
Usage: "Print SQL commands sent",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Description: `The database definitions Forgejo uses change across versions, sometimes changing default values and leaving old unused columns.
|
Description: `The database definitions Gitea uses change across versions, sometimes changing default values and leaving old unused columns.
|
||||||
|
|
||||||
This command will cause Xorm to recreate tables, copying over the data and deleting the old table.
|
This command will cause Xorm to recreate tables, copying over the data and deleting the old table.
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
var cmdDoctorConvert = &cli.Command{
|
var cmdDoctorConvert = &cli.Command{
|
||||||
Name: "convert",
|
Name: "convert",
|
||||||
Usage: "Convert the database",
|
Usage: "Convert the database",
|
||||||
Description: "A command to convert an existing MySQL database from utf8 to utf8mb4",
|
Description: "A command to convert an existing MySQL database from utf8 to utf8mb4 or MSSQL database from varchar to nvarchar",
|
||||||
Action: runDoctorConvert,
|
Action: runDoctorConvert,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,14 +35,21 @@ func runDoctorConvert(ctx *cli.Context) error {
|
||||||
log.Info("Log path: %s", setting.Log.RootPath)
|
log.Info("Log path: %s", setting.Log.RootPath)
|
||||||
log.Info("Configuration file: %s", setting.CustomConf)
|
log.Info("Configuration file: %s", setting.CustomConf)
|
||||||
|
|
||||||
if setting.Database.Type.IsMySQL() {
|
switch {
|
||||||
|
case setting.Database.Type.IsMySQL():
|
||||||
if err := db.ConvertDatabaseTable(); err != nil {
|
if err := db.ConvertDatabaseTable(); err != nil {
|
||||||
log.Fatal("Failed to convert database & table: %v", err)
|
log.Fatal("Failed to convert database & table: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Println("Converted successfully, please confirm your database's character set is now utf8mb4")
|
fmt.Println("Converted successfully, please confirm your database's character set is now utf8mb4")
|
||||||
} else {
|
case setting.Database.Type.IsMSSQL():
|
||||||
fmt.Println("This command can only be used with a MySQL database")
|
if err := db.ConvertVarcharToNVarchar(); err != nil {
|
||||||
|
log.Fatal("Failed to convert database from varchar to nvarchar: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println("Converted successfully, please confirm your database's all columns character is NVARCHAR now")
|
||||||
|
default:
|
||||||
|
fmt.Println("This command can only be used with a MySQL or MSSQL database")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/services/doctor"
|
"code.gitea.io/gitea/services/doctor"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,9 +25,9 @@ func TestDoctorRun(t *testing.T) {
|
||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
app.Commands = []*cli.Command{cmdDoctorCheck}
|
app.Commands = []*cli.Command{cmdDoctorCheck}
|
||||||
err := app.Run([]string{"./gitea", "check", "--run", "test-check"})
|
err := app.Run([]string{"./gitea", "check", "--run", "test-check"})
|
||||||
require.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
err = app.Run([]string{"./gitea", "check", "--run", "no-such"})
|
err = app.Run([]string{"./gitea", "check", "--run", "no-such"})
|
||||||
require.ErrorContains(t, err, `unknown checks: "no-such"`)
|
assert.ErrorContains(t, err, `unknown checks: "no-such"`)
|
||||||
err = app.Run([]string{"./gitea", "check", "--run", "test-check,no-such"})
|
err = app.Run([]string{"./gitea", "check", "--run", "test-check,no-such"})
|
||||||
require.ErrorContains(t, err, `unknown checks: "no-such"`)
|
assert.ErrorContains(t, err, `unknown checks: "no-such"`)
|
||||||
}
|
}
|
||||||
|
|
36
cmd/dump.go
36
cmd/dump.go
|
@ -20,7 +20,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"code.forgejo.org/go-chi/session"
|
"gitea.com/go-chi/session"
|
||||||
"github.com/mholt/archiver/v3"
|
"github.com/mholt/archiver/v3"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
@ -98,15 +98,15 @@ var outputTypeEnum = &outputType{
|
||||||
// CmdDump represents the available dump sub-command.
|
// CmdDump represents the available dump sub-command.
|
||||||
var CmdDump = &cli.Command{
|
var CmdDump = &cli.Command{
|
||||||
Name: "dump",
|
Name: "dump",
|
||||||
Usage: "Dump Forgejo files and database",
|
Usage: "Dump Gitea files and database",
|
||||||
Description: `Dump compresses all related files and database into zip file.
|
Description: `Dump compresses all related files and database into zip file.
|
||||||
It can be used for backup and capture Forgejo server image to send to maintainer`,
|
It can be used for backup and capture Gitea server image to send to maintainer`,
|
||||||
Action: runDump,
|
Action: runDump,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "file",
|
Name: "file",
|
||||||
Aliases: []string{"f"},
|
Aliases: []string{"f"},
|
||||||
Value: fmt.Sprintf("forgejo-dump-%d.zip", time.Now().Unix()),
|
Value: fmt.Sprintf("gitea-dump-%d.zip", time.Now().Unix()),
|
||||||
Usage: "Name of the dump file which will be created. Supply '-' for stdout. See type for available types.",
|
Usage: "Name of the dump file which will be created. Supply '-' for stdout. See type for available types.",
|
||||||
},
|
},
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
|
@ -128,7 +128,7 @@ It can be used for backup and capture Forgejo server image to send to maintainer
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "database",
|
Name: "database",
|
||||||
Aliases: []string{"d"},
|
Aliases: []string{"d"},
|
||||||
Usage: "Specify the database SQL syntax: sqlite3, mysql, postgres",
|
Usage: "Specify the database SQL syntax: sqlite3, mysql, mssql, postgres",
|
||||||
},
|
},
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "skip-repository",
|
Name: "skip-repository",
|
||||||
|
@ -209,7 +209,7 @@ func runDump(ctx *cli.Context) error {
|
||||||
|
|
||||||
if !setting.InstallLock {
|
if !setting.InstallLock {
|
||||||
log.Error("Is '%s' really the right config path?\n", setting.CustomConf)
|
log.Error("Is '%s' really the right config path?\n", setting.CustomConf)
|
||||||
return fmt.Errorf("forgejo is not initialized")
|
return fmt.Errorf("gitea is not initialized")
|
||||||
}
|
}
|
||||||
setting.LoadSettings() // cannot access session settings otherwise
|
setting.LoadSettings() // cannot access session settings otherwise
|
||||||
|
|
||||||
|
@ -288,7 +288,7 @@ func runDump(ctx *cli.Context) error {
|
||||||
fatal("Path does not exist: %s", tmpDir)
|
fatal("Path does not exist: %s", tmpDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
dbDump, err := os.CreateTemp(tmpDir, "forgejo-db.sql")
|
dbDump, err := os.CreateTemp(tmpDir, "gitea-db.sql")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatal("Failed to create tmp file: %v", err)
|
fatal("Failed to create tmp file: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -310,8 +310,8 @@ func runDump(ctx *cli.Context) error {
|
||||||
fatal("Failed to dump database: %v", err)
|
fatal("Failed to dump database: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := addFile(w, "forgejo-db.sql", dbDump.Name(), verbose); err != nil {
|
if err := addFile(w, "gitea-db.sql", dbDump.Name(), verbose); err != nil {
|
||||||
fatal("Failed to include forgejo-db.sql: %v", err)
|
fatal("Failed to include gitea-db.sql: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(setting.CustomConf) > 0 {
|
if len(setting.CustomConf) > 0 {
|
||||||
|
@ -454,18 +454,14 @@ func addRecursiveExclude(w archiver.Writer, insidePath, absPath string, excludeA
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
currentAbsPath := filepath.Join(absPath, file.Name())
|
currentAbsPath := filepath.Join(absPath, file.Name())
|
||||||
currentInsidePath := path.Join(insidePath, file.Name())
|
currentInsidePath := path.Join(insidePath, file.Name())
|
||||||
|
|
||||||
if util.SliceContainsString(excludeAbsPath, currentAbsPath) {
|
|
||||||
log.Debug("Skipping %q because matched an excluded path.", currentAbsPath)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if file.IsDir() {
|
if file.IsDir() {
|
||||||
if err := addFile(w, currentInsidePath, currentAbsPath, false); err != nil {
|
if !util.SliceContainsString(excludeAbsPath, currentAbsPath) {
|
||||||
return err
|
if err := addFile(w, currentInsidePath, currentAbsPath, false); err != nil {
|
||||||
}
|
return err
|
||||||
if err = addRecursiveExclude(w, currentInsidePath, currentAbsPath, excludeAbsPath, verbose); err != nil {
|
}
|
||||||
return err
|
if err = addRecursiveExclude(w, currentInsidePath, currentAbsPath, excludeAbsPath, verbose); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// only copy regular files and symlink regular files, skip non-regular files like socket/pipe/...
|
// only copy regular files and symlink regular files, skip non-regular files like socket/pipe/...
|
||||||
|
|
118
cmd/dump_test.go
118
cmd/dump_test.go
|
@ -1,118 +0,0 @@
|
||||||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/mholt/archiver/v3"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
type mockArchiver struct {
|
|
||||||
addedFiles []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mockArchiver) Create(out io.Writer) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockArchiver) Write(f archiver.File) error {
|
|
||||||
m.addedFiles = append(m.addedFiles, f.Name())
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mockArchiver) Close() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddRecursiveExclude(t *testing.T) {
|
|
||||||
t.Run("Empty", func(t *testing.T) {
|
|
||||||
dir := t.TempDir()
|
|
||||||
archiver := &mockArchiver{}
|
|
||||||
|
|
||||||
err := addRecursiveExclude(archiver, "", dir, []string{}, false)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Empty(t, archiver.addedFiles)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Single file", func(t *testing.T) {
|
|
||||||
dir := t.TempDir()
|
|
||||||
err := os.WriteFile(dir+"/example", nil, 0o666)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
t.Run("No exclude", func(t *testing.T) {
|
|
||||||
archiver := &mockArchiver{}
|
|
||||||
|
|
||||||
err = addRecursiveExclude(archiver, "", dir, nil, false)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Len(t, archiver.addedFiles, 1)
|
|
||||||
assert.Contains(t, archiver.addedFiles, "example")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("With exclude", func(t *testing.T) {
|
|
||||||
archiver := &mockArchiver{}
|
|
||||||
|
|
||||||
err = addRecursiveExclude(archiver, "", dir, []string{dir + "/example"}, false)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Empty(t, archiver.addedFiles)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("File inside directory", func(t *testing.T) {
|
|
||||||
dir := t.TempDir()
|
|
||||||
err := os.MkdirAll(dir+"/deep/nested/folder", 0o750)
|
|
||||||
require.NoError(t, err)
|
|
||||||
err = os.WriteFile(dir+"/deep/nested/folder/example", nil, 0o666)
|
|
||||||
require.NoError(t, err)
|
|
||||||
err = os.WriteFile(dir+"/deep/nested/folder/another-file", nil, 0o666)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
t.Run("No exclude", func(t *testing.T) {
|
|
||||||
archiver := &mockArchiver{}
|
|
||||||
|
|
||||||
err = addRecursiveExclude(archiver, "", dir, nil, false)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Len(t, archiver.addedFiles, 5)
|
|
||||||
assert.Contains(t, archiver.addedFiles, "deep")
|
|
||||||
assert.Contains(t, archiver.addedFiles, "deep/nested")
|
|
||||||
assert.Contains(t, archiver.addedFiles, "deep/nested/folder")
|
|
||||||
assert.Contains(t, archiver.addedFiles, "deep/nested/folder/example")
|
|
||||||
assert.Contains(t, archiver.addedFiles, "deep/nested/folder/another-file")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Exclude first directory", func(t *testing.T) {
|
|
||||||
archiver := &mockArchiver{}
|
|
||||||
|
|
||||||
err = addRecursiveExclude(archiver, "", dir, []string{dir + "/deep"}, false)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Empty(t, archiver.addedFiles)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Exclude nested directory", func(t *testing.T) {
|
|
||||||
archiver := &mockArchiver{}
|
|
||||||
|
|
||||||
err = addRecursiveExclude(archiver, "", dir, []string{dir + "/deep/nested/folder"}, false)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Len(t, archiver.addedFiles, 2)
|
|
||||||
assert.Contains(t, archiver.addedFiles, "deep")
|
|
||||||
assert.Contains(t, archiver.addedFiles, "deep/nested")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Exclude file", func(t *testing.T) {
|
|
||||||
archiver := &mockArchiver{}
|
|
||||||
|
|
||||||
err = addRecursiveExclude(archiver, "", dir, []string{dir + "/deep/nested/folder/example"}, false)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Len(t, archiver.addedFiles, 4)
|
|
||||||
assert.Contains(t, archiver.addedFiles, "deep")
|
|
||||||
assert.Contains(t, archiver.addedFiles, "deep/nested")
|
|
||||||
assert.Contains(t, archiver.addedFiles, "deep/nested/folder")
|
|
||||||
assert.Contains(t, archiver.addedFiles, "deep/nested/folder/another-file")
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -157,9 +157,9 @@ func runViewDo(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(matchedAssetFiles) == 0 {
|
if len(matchedAssetFiles) == 0 {
|
||||||
return errors.New("no files matched the given pattern")
|
return fmt.Errorf("no files matched the given pattern")
|
||||||
} else if len(matchedAssetFiles) > 1 {
|
} else if len(matchedAssetFiles) > 1 {
|
||||||
return errors.New("too many files matched the given pattern, try to be more specific")
|
return fmt.Errorf("too many files matched the given pattern, try to be more specific")
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := matchedAssetFiles[0].fs.ReadFile(matchedAssetFiles[0].name)
|
data, err := matchedAssetFiles[0].fs.ReadFile(matchedAssetFiles[0].name)
|
||||||
|
@ -180,7 +180,7 @@ func runExtractDo(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.NArg() == 0 {
|
if c.NArg() == 0 {
|
||||||
return errors.New("a list of pattern of files to extract is mandatory (e.g. '**' for all)")
|
return fmt.Errorf("a list of pattern of files to extract is mandatory (e.g. '**' for all)")
|
||||||
}
|
}
|
||||||
|
|
||||||
destdir := "."
|
destdir := "."
|
||||||
|
|
|
@ -35,8 +35,7 @@ func SubcmdActionsGenerateRunnerToken(ctx context.Context) *cli.Command {
|
||||||
return &cli.Command{
|
return &cli.Command{
|
||||||
Name: "generate-runner-token",
|
Name: "generate-runner-token",
|
||||||
Usage: "Generate a new token for a runner to use to register with the server",
|
Usage: "Generate a new token for a runner to use to register with the server",
|
||||||
Before: prepareWorkPathAndCustomConf(ctx),
|
Action: prepareWorkPathAndCustomConf(ctx, func(cliCtx *cli.Context) error { return RunGenerateActionsRunnerToken(ctx, cliCtx) }),
|
||||||
Action: func(cliCtx *cli.Context) error { return RunGenerateActionsRunnerToken(ctx, cliCtx) },
|
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "scope",
|
Name: "scope",
|
||||||
|
@ -60,8 +59,7 @@ func SubcmdActionsRegister(ctx context.Context) *cli.Command {
|
||||||
return &cli.Command{
|
return &cli.Command{
|
||||||
Name: "register",
|
Name: "register",
|
||||||
Usage: "Idempotent registration of a runner using a shared secret",
|
Usage: "Idempotent registration of a runner using a shared secret",
|
||||||
Before: prepareWorkPathAndCustomConf(ctx),
|
Action: prepareWorkPathAndCustomConf(ctx, func(cliCtx *cli.Context) error { return RunRegister(ctx, cliCtx) }),
|
||||||
Action: func(cliCtx *cli.Context) error { return RunRegister(ctx, cliCtx) },
|
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "secret",
|
Name: "secret",
|
||||||
|
@ -86,11 +84,6 @@ func SubcmdActionsRegister(ctx context.Context) *cli.Command {
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "comma separated list of labels supported by the runner (e.g. docker,ubuntu-latest,self-hosted) (not required since v1.21)",
|
Usage: "comma separated list of labels supported by the runner (e.g. docker,ubuntu-latest,self-hosted) (not required since v1.21)",
|
||||||
},
|
},
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "keep-labels",
|
|
||||||
Value: false,
|
|
||||||
Usage: "do not affect the labels when updating an existing runner",
|
|
||||||
},
|
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "name",
|
Name: "name",
|
||||||
Value: "runner",
|
Value: "runner",
|
||||||
|
@ -138,20 +131,9 @@ func validateSecret(secret string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getLabels(cliCtx *cli.Context) (*[]string, error) {
|
|
||||||
if !cliCtx.Bool("keep-labels") {
|
|
||||||
lblValue := strings.Split(cliCtx.String("labels"), ",")
|
|
||||||
return &lblValue, nil
|
|
||||||
}
|
|
||||||
if cliCtx.String("labels") != "" {
|
|
||||||
return nil, fmt.Errorf("--labels and --keep-labels should not be used together")
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func RunRegister(ctx context.Context, cliCtx *cli.Context) error {
|
func RunRegister(ctx context.Context, cliCtx *cli.Context) error {
|
||||||
var cancel context.CancelFunc
|
|
||||||
if !ContextGetNoInit(ctx) {
|
if !ContextGetNoInit(ctx) {
|
||||||
|
var cancel context.CancelFunc
|
||||||
ctx, cancel = installSignals(ctx)
|
ctx, cancel = installSignals(ctx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
|
@ -169,12 +151,9 @@ func RunRegister(ctx context.Context, cliCtx *cli.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
scope := cliCtx.String("scope")
|
scope := cliCtx.String("scope")
|
||||||
|
labels := cliCtx.String("labels")
|
||||||
name := cliCtx.String("name")
|
name := cliCtx.String("name")
|
||||||
version := cliCtx.String("version")
|
version := cliCtx.String("version")
|
||||||
labels, err := getLabels(cliCtx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// There are two kinds of tokens
|
// There are two kinds of tokens
|
||||||
|
@ -198,7 +177,7 @@ func RunRegister(ctx context.Context, cliCtx *cli.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
runner, err := actions_model.RegisterRunner(ctx, owner, repo, secret, labels, name, version)
|
runner, err := actions_model.RegisterRunner(ctx, owner, repo, secret, strings.Split(labels, ","), name, version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error while registering runner: %v", err)
|
return fmt.Errorf("error while registering runner: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -240,3 +219,25 @@ func RunGenerateActionsRunnerToken(ctx context.Context, cliCtx *cli.Context) err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func prepareWorkPathAndCustomConf(ctx context.Context, action cli.ActionFunc) func(cliCtx *cli.Context) error {
|
||||||
|
return func(cliCtx *cli.Context) error {
|
||||||
|
if !ContextGetNoInit(ctx) {
|
||||||
|
var args setting.ArgWorkPathAndCustomConf
|
||||||
|
// from children to parent, check the global flags
|
||||||
|
for _, curCtx := range cliCtx.Lineage() {
|
||||||
|
if curCtx.IsSet("work-path") && args.WorkPath == "" {
|
||||||
|
args.WorkPath = curCtx.String("work-path")
|
||||||
|
}
|
||||||
|
if curCtx.IsSet("custom-path") && args.CustomPath == "" {
|
||||||
|
args.CustomPath = curCtx.String("custom-path")
|
||||||
|
}
|
||||||
|
if curCtx.IsSet("config") && args.CustomConf == "" {
|
||||||
|
args.CustomConf = curCtx.String("config")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setting.InitWorkPathAndCommonConfig(os.Getenv, args)
|
||||||
|
}
|
||||||
|
return action(cliCtx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,88 +0,0 @@
|
||||||
// Copyright The Forgejo Authors.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package forgejo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/services/context"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestActions_getLabels(t *testing.T) {
|
|
||||||
type testCase struct {
|
|
||||||
args []string
|
|
||||||
hasLabels bool
|
|
||||||
hasError bool
|
|
||||||
labels []string
|
|
||||||
}
|
|
||||||
type resultType struct {
|
|
||||||
labels *[]string
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
cases := []testCase{
|
|
||||||
{
|
|
||||||
args: []string{"x"},
|
|
||||||
hasLabels: true,
|
|
||||||
hasError: false,
|
|
||||||
labels: []string{""},
|
|
||||||
}, {
|
|
||||||
args: []string{"x", "--labels", "a,b"},
|
|
||||||
hasLabels: true,
|
|
||||||
hasError: false,
|
|
||||||
labels: []string{"a", "b"},
|
|
||||||
}, {
|
|
||||||
args: []string{"x", "--keep-labels"},
|
|
||||||
hasLabels: false,
|
|
||||||
hasError: false,
|
|
||||||
}, {
|
|
||||||
args: []string{"x", "--keep-labels", "--labels", "a,b"},
|
|
||||||
hasLabels: false,
|
|
||||||
hasError: true,
|
|
||||||
}, {
|
|
||||||
// this edge-case exists because that's what actually happens
|
|
||||||
// when no '--labels ...' options are present
|
|
||||||
args: []string{"x", "--keep-labels", "--labels", ""},
|
|
||||||
hasLabels: false,
|
|
||||||
hasError: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
flags := SubcmdActionsRegister(context.Context{}).Flags
|
|
||||||
for _, c := range cases {
|
|
||||||
t.Run(fmt.Sprintf("args: %v", c.args), func(t *testing.T) {
|
|
||||||
// Create a copy of command to test
|
|
||||||
var result *resultType
|
|
||||||
app := cli.NewApp()
|
|
||||||
app.Flags = flags
|
|
||||||
app.Action = func(ctx *cli.Context) error {
|
|
||||||
labels, err := getLabels(ctx)
|
|
||||||
result = &resultType{labels, err}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run it
|
|
||||||
_ = app.Run(c.args)
|
|
||||||
|
|
||||||
// Test the results
|
|
||||||
require.NotNil(t, result)
|
|
||||||
if c.hasLabels {
|
|
||||||
assert.NotNil(t, result.labels)
|
|
||||||
assert.Equal(t, c.labels, *result.labels)
|
|
||||||
} else {
|
|
||||||
assert.Nil(t, result.labels)
|
|
||||||
}
|
|
||||||
if c.hasError {
|
|
||||||
require.Error(t, result.err)
|
|
||||||
} else {
|
|
||||||
assert.NoError(t, result.err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
// Copyright Earl Warren <contact@earl-warren.org>
|
|
||||||
// Copyright Loïc Dachary <loic@dachary.org>
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package forgejo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
"code.gitea.io/gitea/modules/git"
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
"code.gitea.io/gitea/modules/storage"
|
|
||||||
"code.gitea.io/gitea/services/f3/util"
|
|
||||||
|
|
||||||
_ "code.gitea.io/gitea/services/f3/driver" // register the driver
|
|
||||||
|
|
||||||
f3_cmd "code.forgejo.org/f3/gof3/v3/cmd"
|
|
||||||
f3_logger "code.forgejo.org/f3/gof3/v3/logger"
|
|
||||||
f3_util "code.forgejo.org/f3/gof3/v3/util"
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
func CmdF3(ctx context.Context) *cli.Command {
|
|
||||||
ctx = f3_logger.ContextSetLogger(ctx, util.NewF3Logger(nil, log.GetLogger(log.DEFAULT)))
|
|
||||||
return &cli.Command{
|
|
||||||
Name: "f3",
|
|
||||||
Usage: "F3",
|
|
||||||
Subcommands: []*cli.Command{
|
|
||||||
SubcmdF3Mirror(ctx),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func SubcmdF3Mirror(ctx context.Context) *cli.Command {
|
|
||||||
mirrorCmd := f3_cmd.CreateCmdMirror(ctx)
|
|
||||||
mirrorCmd.Before = prepareWorkPathAndCustomConf(ctx)
|
|
||||||
f3Action := mirrorCmd.Action
|
|
||||||
mirrorCmd.Action = func(c *cli.Context) error { return runMirror(ctx, c, f3Action) }
|
|
||||||
return mirrorCmd
|
|
||||||
}
|
|
||||||
|
|
||||||
func runMirror(ctx context.Context, c *cli.Context, action cli.ActionFunc) error {
|
|
||||||
setting.LoadF3Setting()
|
|
||||||
if !setting.F3.Enabled {
|
|
||||||
return errors.New("F3 is disabled, it is not ready to be used and is only present for development purposes")
|
|
||||||
}
|
|
||||||
|
|
||||||
var cancel context.CancelFunc
|
|
||||||
if !ContextGetNoInit(ctx) {
|
|
||||||
ctx, cancel = installSignals(ctx)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
if err := initDB(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := storage.Init(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := git.InitSimple(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := models.Init(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err := action(c)
|
|
||||||
if panicError, ok := err.(f3_util.PanicError); ok {
|
|
||||||
log.Debug("F3 Stack trace\n%s", panicError.Stack())
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
|
@ -36,7 +36,6 @@ func CmdForgejo(ctx context.Context) *cli.Command {
|
||||||
Flags: []cli.Flag{},
|
Flags: []cli.Flag{},
|
||||||
Subcommands: []*cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
CmdActions(ctx),
|
CmdActions(ctx),
|
||||||
CmdF3(ctx),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,25 +145,3 @@ func handleCliResponseExtra(ctx context.Context, extra private.ResponseExtra) er
|
||||||
}
|
}
|
||||||
return cli.Exit(extra.Error, 1)
|
return cli.Exit(extra.Error, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareWorkPathAndCustomConf(ctx context.Context) func(c *cli.Context) error {
|
|
||||||
return func(c *cli.Context) error {
|
|
||||||
if !ContextGetNoInit(ctx) {
|
|
||||||
var args setting.ArgWorkPathAndCustomConf
|
|
||||||
// from children to parent, check the global flags
|
|
||||||
for _, curCtx := range c.Lineage() {
|
|
||||||
if curCtx.IsSet("work-path") && args.WorkPath == "" {
|
|
||||||
args.WorkPath = curCtx.String("work-path")
|
|
||||||
}
|
|
||||||
if curCtx.IsSet("custom-path") && args.CustomPath == "" {
|
|
||||||
args.CustomPath = curCtx.String("custom-path")
|
|
||||||
}
|
|
||||||
if curCtx.IsSet("config") && args.CustomConf == "" {
|
|
||||||
args.CustomConf = curCtx.String("config")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setting.InitWorkPathAndCommonConfig(os.Getenv, args)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ func runGenerateInternalToken(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func runGenerateLfsJwtSecret(c *cli.Context) error {
|
func runGenerateLfsJwtSecret(c *cli.Context) error {
|
||||||
_, jwtSecretBase64, err := generate.NewJwtSecret()
|
_, jwtSecretBase64, err := generate.NewJwtSecretBase64()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
152
cmd/hook.go
152
cmd/hook.go
|
@ -15,7 +15,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/git/pushoptions"
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/private"
|
"code.gitea.io/gitea/modules/private"
|
||||||
repo_module "code.gitea.io/gitea/modules/repository"
|
repo_module "code.gitea.io/gitea/modules/repository"
|
||||||
|
@ -140,10 +139,11 @@ func (d *delayWriter) WriteString(s string) (n int, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *delayWriter) Close() error {
|
func (d *delayWriter) Close() error {
|
||||||
if d.timer.Stop() {
|
if d == nil {
|
||||||
d.buf = nil
|
return nil
|
||||||
}
|
}
|
||||||
if d.buf == nil {
|
stopped := d.timer.Stop()
|
||||||
|
if stopped || d.buf == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
_, err := d.internal.Write(d.buf.Bytes())
|
_, err := d.internal.Write(d.buf.Bytes())
|
||||||
|
@ -172,9 +172,9 @@ func runHookPreReceive(c *cli.Context) error {
|
||||||
|
|
||||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||||
if setting.OnlyAllowPushIfGiteaEnvironmentSet {
|
if setting.OnlyAllowPushIfGiteaEnvironmentSet {
|
||||||
return fail(ctx, `Rejecting changes as Forgejo environment not set.
|
return fail(ctx, `Rejecting changes as Gitea environment not set.
|
||||||
If you are pushing over SSH you must push with a key managed by
|
If you are pushing over SSH you must push with a key managed by
|
||||||
Forgejo or set your environment appropriately.`, "")
|
Gitea or set your environment appropriately.`, "")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,7 @@ Forgejo or set your environment appropriately.`, "")
|
||||||
GitAlternativeObjectDirectories: os.Getenv(private.GitAlternativeObjectDirectories),
|
GitAlternativeObjectDirectories: os.Getenv(private.GitAlternativeObjectDirectories),
|
||||||
GitObjectDirectory: os.Getenv(private.GitObjectDirectory),
|
GitObjectDirectory: os.Getenv(private.GitObjectDirectory),
|
||||||
GitQuarantinePath: os.Getenv(private.GitQuarantinePath),
|
GitQuarantinePath: os.Getenv(private.GitQuarantinePath),
|
||||||
GitPushOptions: pushoptions.New().ReadEnv().Map(),
|
GitPushOptions: pushOptions(),
|
||||||
PullRequestID: prID,
|
PullRequestID: prID,
|
||||||
DeployKeyID: deployKeyID,
|
DeployKeyID: deployKeyID,
|
||||||
ActionPerm: int(actionPerm),
|
ActionPerm: int(actionPerm),
|
||||||
|
@ -293,35 +293,8 @@ Forgejo or set your environment appropriately.`, "")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// runHookUpdate process the update hook: https://git-scm.com/docs/githooks#update
|
|
||||||
func runHookUpdate(c *cli.Context) error {
|
func runHookUpdate(c *cli.Context) error {
|
||||||
// Now if we're an internal don't do anything else
|
// Update is empty and is kept only for backwards compatibility
|
||||||
if isInternal, _ := strconv.ParseBool(os.Getenv(repo_module.EnvIsInternal)); isInternal {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, cancel := installSignals()
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
if c.NArg() != 3 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
args := c.Args().Slice()
|
|
||||||
|
|
||||||
// The arguments given to the hook are in order: reference name, old commit ID and new commit ID.
|
|
||||||
refFullName := git.RefName(args[0])
|
|
||||||
newCommitID := args[2]
|
|
||||||
|
|
||||||
// Only process pull references.
|
|
||||||
if !refFullName.IsPull() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Empty new commit ID means deletion.
|
|
||||||
if git.IsEmptyCommitID(newCommitID, nil) {
|
|
||||||
return fail(ctx, fmt.Sprintf("The deletion of %s is skipped as it's an internal reference.", refFullName), "")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,18 +316,19 @@ func runHookPostReceive(c *cli.Context) error {
|
||||||
|
|
||||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||||
if setting.OnlyAllowPushIfGiteaEnvironmentSet {
|
if setting.OnlyAllowPushIfGiteaEnvironmentSet {
|
||||||
return fail(ctx, `Rejecting changes as Forgejo environment not set.
|
return fail(ctx, `Rejecting changes as Gitea environment not set.
|
||||||
If you are pushing over SSH you must push with a key managed by
|
If you are pushing over SSH you must push with a key managed by
|
||||||
Forgejo or set your environment appropriately.`, "")
|
Gitea or set your environment appropriately.`, "")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var out io.Writer
|
var out io.Writer
|
||||||
|
var dWriter *delayWriter
|
||||||
out = &nilWriter{}
|
out = &nilWriter{}
|
||||||
if setting.Git.VerbosePush {
|
if setting.Git.VerbosePush {
|
||||||
if setting.Git.VerbosePushDelay > 0 {
|
if setting.Git.VerbosePushDelay > 0 {
|
||||||
dWriter := newDelayWriter(os.Stdout, setting.Git.VerbosePushDelay)
|
dWriter = newDelayWriter(os.Stdout, setting.Git.VerbosePushDelay)
|
||||||
defer dWriter.Close()
|
defer dWriter.Close()
|
||||||
out = dWriter
|
out = dWriter
|
||||||
} else {
|
} else {
|
||||||
|
@ -367,7 +341,6 @@ Forgejo or set your environment appropriately.`, "")
|
||||||
isWiki, _ := strconv.ParseBool(os.Getenv(repo_module.EnvRepoIsWiki))
|
isWiki, _ := strconv.ParseBool(os.Getenv(repo_module.EnvRepoIsWiki))
|
||||||
repoName := os.Getenv(repo_module.EnvRepoName)
|
repoName := os.Getenv(repo_module.EnvRepoName)
|
||||||
pusherID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPusherID), 10, 64)
|
pusherID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPusherID), 10, 64)
|
||||||
prID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPRID), 10, 64)
|
|
||||||
pusherName := os.Getenv(repo_module.EnvPusherName)
|
pusherName := os.Getenv(repo_module.EnvPusherName)
|
||||||
|
|
||||||
hookOptions := private.HookOptions{
|
hookOptions := private.HookOptions{
|
||||||
|
@ -376,9 +349,7 @@ Forgejo or set your environment appropriately.`, "")
|
||||||
GitAlternativeObjectDirectories: os.Getenv(private.GitAlternativeObjectDirectories),
|
GitAlternativeObjectDirectories: os.Getenv(private.GitAlternativeObjectDirectories),
|
||||||
GitObjectDirectory: os.Getenv(private.GitObjectDirectory),
|
GitObjectDirectory: os.Getenv(private.GitObjectDirectory),
|
||||||
GitQuarantinePath: os.Getenv(private.GitQuarantinePath),
|
GitQuarantinePath: os.Getenv(private.GitQuarantinePath),
|
||||||
GitPushOptions: pushoptions.New().ReadEnv().Map(),
|
GitPushOptions: pushOptions(),
|
||||||
PullRequestID: prID,
|
|
||||||
PushTrigger: repo_module.PushTrigger(os.Getenv(repo_module.EnvPushTrigger)),
|
|
||||||
}
|
}
|
||||||
oldCommitIDs := make([]string, hookBatchSize)
|
oldCommitIDs := make([]string, hookBatchSize)
|
||||||
newCommitIDs := make([]string, hookBatchSize)
|
newCommitIDs := make([]string, hookBatchSize)
|
||||||
|
@ -406,7 +377,8 @@ Forgejo or set your environment appropriately.`, "")
|
||||||
newCommitIDs[count] = string(fields[1])
|
newCommitIDs[count] = string(fields[1])
|
||||||
refFullNames[count] = git.RefName(fields[2])
|
refFullNames[count] = git.RefName(fields[2])
|
||||||
|
|
||||||
if refFullNames[count] == git.BranchPrefix+"master" && !git.IsEmptyCommitID(newCommitIDs[count], nil) && count == total {
|
commitID, _ := git.NewIDFromString(newCommitIDs[count])
|
||||||
|
if refFullNames[count] == git.BranchPrefix+"master" && !commitID.IsZero() && count == total {
|
||||||
masterPushed = true
|
masterPushed = true
|
||||||
}
|
}
|
||||||
count++
|
count++
|
||||||
|
@ -419,6 +391,7 @@ Forgejo or set your environment appropriately.`, "")
|
||||||
hookOptions.RefFullNames = refFullNames
|
hookOptions.RefFullNames = refFullNames
|
||||||
resp, extra := private.HookPostReceive(ctx, repoUser, repoName, hookOptions)
|
resp, extra := private.HookPostReceive(ctx, repoUser, repoName, hookOptions)
|
||||||
if extra.HasError() {
|
if extra.HasError() {
|
||||||
|
_ = dWriter.Close()
|
||||||
hookPrintResults(results)
|
hookPrintResults(results)
|
||||||
return fail(ctx, extra.UserMsg, "HookPostReceive failed: %v", extra.Error)
|
return fail(ctx, extra.UserMsg, "HookPostReceive failed: %v", extra.Error)
|
||||||
}
|
}
|
||||||
|
@ -438,6 +411,7 @@ Forgejo or set your environment appropriately.`, "")
|
||||||
}
|
}
|
||||||
fmt.Fprintf(out, "Processed %d references in total\n", total)
|
fmt.Fprintf(out, "Processed %d references in total\n", total)
|
||||||
|
|
||||||
|
_ = dWriter.Close()
|
||||||
hookPrintResults(results)
|
hookPrintResults(results)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -450,6 +424,7 @@ Forgejo or set your environment appropriately.`, "")
|
||||||
|
|
||||||
resp, extra := private.HookPostReceive(ctx, repoUser, repoName, hookOptions)
|
resp, extra := private.HookPostReceive(ctx, repoUser, repoName, hookOptions)
|
||||||
if resp == nil {
|
if resp == nil {
|
||||||
|
_ = dWriter.Close()
|
||||||
hookPrintResults(results)
|
hookPrintResults(results)
|
||||||
return fail(ctx, extra.UserMsg, "HookPostReceive failed: %v", extra.Error)
|
return fail(ctx, extra.UserMsg, "HookPostReceive failed: %v", extra.Error)
|
||||||
}
|
}
|
||||||
|
@ -465,8 +440,9 @@ Forgejo or set your environment appropriately.`, "")
|
||||||
return fail(ctx, extra.UserMsg, "SetDefaultBranch failed: %v", extra.Error)
|
return fail(ctx, extra.UserMsg, "SetDefaultBranch failed: %v", extra.Error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ = dWriter.Close()
|
||||||
hookPrintResults(results)
|
hookPrintResults(results)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,10 +461,24 @@ func hookPrintResults(results []private.HookPostReceiveBranchResult) {
|
||||||
fmt.Fprintf(os.Stderr, " %s\n", res.URL)
|
fmt.Fprintf(os.Stderr, " %s\n", res.URL)
|
||||||
}
|
}
|
||||||
fmt.Fprintln(os.Stderr, "")
|
fmt.Fprintln(os.Stderr, "")
|
||||||
_ = os.Stderr.Sync()
|
os.Stderr.Sync()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pushOptions() map[string]string {
|
||||||
|
opts := make(map[string]string)
|
||||||
|
if pushCount, err := strconv.Atoi(os.Getenv(private.GitPushOptionCount)); err == nil {
|
||||||
|
for idx := 0; idx < pushCount; idx++ {
|
||||||
|
opt := os.Getenv(fmt.Sprintf("GIT_PUSH_OPTION_%d", idx))
|
||||||
|
kv := strings.SplitN(opt, "=", 2)
|
||||||
|
if len(kv) == 2 {
|
||||||
|
opts[kv[0]] = kv[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return opts
|
||||||
|
}
|
||||||
|
|
||||||
func runHookProcReceive(c *cli.Context) error {
|
func runHookProcReceive(c *cli.Context) error {
|
||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
@ -497,9 +487,9 @@ func runHookProcReceive(c *cli.Context) error {
|
||||||
|
|
||||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||||
if setting.OnlyAllowPushIfGiteaEnvironmentSet {
|
if setting.OnlyAllowPushIfGiteaEnvironmentSet {
|
||||||
return fail(ctx, `Rejecting changes as Forgejo environment not set.
|
return fail(ctx, `Rejecting changes as Gitea environment not set.
|
||||||
If you are pushing over SSH you must push with a key managed by
|
If you are pushing over SSH you must push with a key managed by
|
||||||
Forgejo or set your environment appropriately.`, "")
|
Gitea or set your environment appropriately.`, "")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -535,14 +525,14 @@ Forgejo or set your environment appropriately.`, "")
|
||||||
|
|
||||||
index := bytes.IndexByte(rs.Data, byte(0))
|
index := bytes.IndexByte(rs.Data, byte(0))
|
||||||
if index >= len(rs.Data) {
|
if index >= len(rs.Data) {
|
||||||
return fail(ctx, "Protocol: format error", "pkt-line: format error %s", rs.Data)
|
return fail(ctx, "Protocol: format error", "pkt-line: format error "+fmt.Sprint(rs.Data))
|
||||||
}
|
}
|
||||||
|
|
||||||
if index < 0 {
|
if index < 0 {
|
||||||
if len(rs.Data) == 10 && rs.Data[9] == '\n' {
|
if len(rs.Data) == 10 && rs.Data[9] == '\n' {
|
||||||
index = 9
|
index = 9
|
||||||
} else {
|
} else {
|
||||||
return fail(ctx, "Protocol: format error", "pkt-line: format error %s", rs.Data)
|
return fail(ctx, "Protocol: format error", "pkt-line: format error "+fmt.Sprint(rs.Data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -593,7 +583,7 @@ Forgejo or set your environment appropriately.`, "")
|
||||||
|
|
||||||
for {
|
for {
|
||||||
// note: pktLineTypeUnknow means pktLineTypeFlush and pktLineTypeData all allowed
|
// note: pktLineTypeUnknow means pktLineTypeFlush and pktLineTypeData all allowed
|
||||||
rs, err = readPktLine(ctx, reader, pktLineTypeUnknown)
|
rs, err = readPktLine(ctx, reader, pktLineTypeUnknow)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -613,9 +603,8 @@ Forgejo or set your environment appropriately.`, "")
|
||||||
hookOptions.GitPushOptions = make(map[string]string)
|
hookOptions.GitPushOptions = make(map[string]string)
|
||||||
|
|
||||||
if hasPushOptions {
|
if hasPushOptions {
|
||||||
pushOptions := pushoptions.NewFromMap(&hookOptions.GitPushOptions)
|
|
||||||
for {
|
for {
|
||||||
rs, err = readPktLine(ctx, reader, pktLineTypeUnknown)
|
rs, err = readPktLine(ctx, reader, pktLineTypeUnknow)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -623,7 +612,11 @@ Forgejo or set your environment appropriately.`, "")
|
||||||
if rs.Type == pktLineTypeFlush {
|
if rs.Type == pktLineTypeFlush {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
pushOptions.Parse(string(rs.Data))
|
|
||||||
|
kv := strings.SplitN(string(rs.Data), "=", 2)
|
||||||
|
if len(kv) == 2 {
|
||||||
|
hookOptions.GitPushOptions[kv[0]] = kv[1]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,7 +671,8 @@ Forgejo or set your environment appropriately.`, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !git.IsEmptyCommitID(rs.OldOID, nil) {
|
commitID, _ := git.NewIDFromString(rs.OldOID)
|
||||||
|
if !commitID.IsZero() {
|
||||||
err = writeDataPktLine(ctx, os.Stdout, []byte("option old-oid "+rs.OldOID))
|
err = writeDataPktLine(ctx, os.Stdout, []byte("option old-oid "+rs.OldOID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -705,8 +699,8 @@ Forgejo or set your environment appropriately.`, "")
|
||||||
type pktLineType int64
|
type pktLineType int64
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Unknown type
|
// UnKnow type
|
||||||
pktLineTypeUnknown pktLineType = 0
|
pktLineTypeUnknow pktLineType = 0
|
||||||
// flush-pkt "0000"
|
// flush-pkt "0000"
|
||||||
pktLineTypeFlush pktLineType = iota
|
pktLineTypeFlush pktLineType = iota
|
||||||
// data line
|
// data line
|
||||||
|
@ -720,16 +714,22 @@ type gitPktLine struct {
|
||||||
Data []byte
|
Data []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reads an Pkt-Line from `in`. If requestType is not unknown, it will a
|
|
||||||
func readPktLine(ctx context.Context, in *bufio.Reader, requestType pktLineType) (*gitPktLine, error) {
|
func readPktLine(ctx context.Context, in *bufio.Reader, requestType pktLineType) (*gitPktLine, error) {
|
||||||
// Read length prefix
|
var (
|
||||||
|
err error
|
||||||
|
r *gitPktLine
|
||||||
|
)
|
||||||
|
|
||||||
|
// read prefix
|
||||||
lengthBytes := make([]byte, 4)
|
lengthBytes := make([]byte, 4)
|
||||||
if n, err := in.Read(lengthBytes); n != 4 || err != nil {
|
for i := 0; i < 4; i++ {
|
||||||
return nil, fail(ctx, "Protocol: stdin error", "Pkt-Line: read stdin failed : %v", err)
|
lengthBytes[i], err = in.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fail(ctx, "Protocol: stdin error", "Pkt-Line: read stdin failed : %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
r = new(gitPktLine)
|
||||||
r := &gitPktLine{}
|
|
||||||
r.Length, err = strconv.ParseUint(string(lengthBytes), 16, 32)
|
r.Length, err = strconv.ParseUint(string(lengthBytes), 16, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fail(ctx, "Protocol: format parse error", "Pkt-Line format is wrong :%v", err)
|
return nil, fail(ctx, "Protocol: format parse error", "Pkt-Line format is wrong :%v", err)
|
||||||
|
@ -748,8 +748,11 @@ func readPktLine(ctx context.Context, in *bufio.Reader, requestType pktLineType)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.Data = make([]byte, r.Length-4)
|
r.Data = make([]byte, r.Length-4)
|
||||||
if n, err := io.ReadFull(in, r.Data); uint64(n) != r.Length-4 || err != nil {
|
for i := range r.Data {
|
||||||
return nil, fail(ctx, "Protocol: stdin error", "Pkt-Line: read stdin failed : %v", err)
|
r.Data[i], err = in.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fail(ctx, "Protocol: data error", "Pkt-Line: read stdin failed : %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r.Type = pktLineTypeData
|
r.Type = pktLineTypeData
|
||||||
|
@ -765,23 +768,20 @@ func writeFlushPktLine(ctx context.Context, out io.Writer) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write an Pkt-Line based on `data` to `out` according to the specification.
|
|
||||||
// https://git-scm.com/docs/protocol-common
|
|
||||||
func writeDataPktLine(ctx context.Context, out io.Writer, data []byte) error {
|
func writeDataPktLine(ctx context.Context, out io.Writer, data []byte) error {
|
||||||
// Implementations SHOULD NOT send an empty pkt-line ("0004").
|
hexchar := []byte("0123456789abcdef")
|
||||||
if len(data) == 0 {
|
hex := func(n uint64) byte {
|
||||||
return fail(ctx, "Protocol: write error", "Not allowed to write empty Pkt-Line")
|
return hexchar[(n)&15]
|
||||||
}
|
}
|
||||||
|
|
||||||
length := uint64(len(data) + 4)
|
length := uint64(len(data) + 4)
|
||||||
|
tmp := make([]byte, 4)
|
||||||
|
tmp[0] = hex(length >> 12)
|
||||||
|
tmp[1] = hex(length >> 8)
|
||||||
|
tmp[2] = hex(length >> 4)
|
||||||
|
tmp[3] = hex(length)
|
||||||
|
|
||||||
// The maximum length of a pkt-line’s data component is 65516 bytes.
|
lr, err := out.Write(tmp)
|
||||||
// Implementations MUST NOT send pkt-line whose length exceeds 65520 (65516 bytes of payload + 4 bytes of length data).
|
|
||||||
if length > 65520 {
|
|
||||||
return fail(ctx, "Protocol: write error", "Pkt-Line exceeds maximum of 65520 bytes")
|
|
||||||
}
|
|
||||||
|
|
||||||
lr, err := fmt.Fprintf(out, "%04x", length)
|
|
||||||
if err != nil || lr != 4 {
|
if err != nil || lr != 4 {
|
||||||
return fail(ctx, "Protocol: write error", "Pkt-Line response failed: %v", err)
|
return fail(ctx, "Protocol: write error", "Pkt-Line response failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
196
cmd/hook_test.go
196
cmd/hook_test.go
|
@ -7,190 +7,36 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
"code.gitea.io/gitea/modules/test"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Capture what's being written into a standard file descriptor.
|
|
||||||
func captureOutput(t *testing.T, stdFD *os.File) (finish func() (output string)) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
r, w, err := os.Pipe()
|
|
||||||
require.NoError(t, err)
|
|
||||||
resetStdout := test.MockVariableValue(stdFD, *w)
|
|
||||||
|
|
||||||
return func() (output string) {
|
|
||||||
w.Close()
|
|
||||||
resetStdout()
|
|
||||||
|
|
||||||
out, err := io.ReadAll(r)
|
|
||||||
require.NoError(t, err)
|
|
||||||
return string(out)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPktLine(t *testing.T) {
|
func TestPktLine(t *testing.T) {
|
||||||
|
// test read
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
s := strings.NewReader("0000")
|
||||||
|
r := bufio.NewReader(s)
|
||||||
|
result, err := readPktLine(ctx, r, pktLineTypeFlush)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, pktLineTypeFlush, result.Type)
|
||||||
|
|
||||||
t.Run("Read", func(t *testing.T) {
|
s = strings.NewReader("0006a\n")
|
||||||
s := strings.NewReader("0000")
|
r = bufio.NewReader(s)
|
||||||
r := bufio.NewReader(s)
|
result, err = readPktLine(ctx, r, pktLineTypeData)
|
||||||
result, err := readPktLine(ctx, r, pktLineTypeFlush)
|
assert.NoError(t, err)
|
||||||
require.NoError(t, err)
|
assert.Equal(t, pktLineTypeData, result.Type)
|
||||||
assert.Equal(t, pktLineTypeFlush, result.Type)
|
assert.Equal(t, []byte("a\n"), result.Data)
|
||||||
|
|
||||||
s = strings.NewReader("0006a\n")
|
// test write
|
||||||
r = bufio.NewReader(s)
|
w := bytes.NewBuffer([]byte{})
|
||||||
result, err = readPktLine(ctx, r, pktLineTypeData)
|
err = writeFlushPktLine(ctx, w)
|
||||||
require.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, pktLineTypeData, result.Type)
|
assert.Equal(t, []byte("0000"), w.Bytes())
|
||||||
assert.Equal(t, []byte("a\n"), result.Data)
|
|
||||||
|
|
||||||
s = strings.NewReader("0004")
|
w.Reset()
|
||||||
r = bufio.NewReader(s)
|
err = writeDataPktLine(ctx, w, []byte("a\nb"))
|
||||||
result, err = readPktLine(ctx, r, pktLineTypeData)
|
assert.NoError(t, err)
|
||||||
require.Error(t, err)
|
assert.Equal(t, []byte("0007a\nb"), w.Bytes())
|
||||||
assert.Nil(t, result)
|
|
||||||
|
|
||||||
data := strings.Repeat("x", 65516)
|
|
||||||
r = bufio.NewReader(strings.NewReader("fff0" + data))
|
|
||||||
result, err = readPktLine(ctx, r, pktLineTypeData)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Equal(t, pktLineTypeData, result.Type)
|
|
||||||
assert.Equal(t, []byte(data), result.Data)
|
|
||||||
|
|
||||||
r = bufio.NewReader(strings.NewReader("fff1a"))
|
|
||||||
result, err = readPktLine(ctx, r, pktLineTypeData)
|
|
||||||
require.Error(t, err)
|
|
||||||
assert.Nil(t, result)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Write", func(t *testing.T) {
|
|
||||||
w := bytes.NewBuffer([]byte{})
|
|
||||||
err := writeFlushPktLine(ctx, w)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Equal(t, []byte("0000"), w.Bytes())
|
|
||||||
|
|
||||||
w.Reset()
|
|
||||||
err = writeDataPktLine(ctx, w, []byte("a\nb"))
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Equal(t, []byte("0007a\nb"), w.Bytes())
|
|
||||||
|
|
||||||
w.Reset()
|
|
||||||
data := bytes.Repeat([]byte{0x05}, 288)
|
|
||||||
err = writeDataPktLine(ctx, w, data)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Equal(t, append([]byte("0124"), data...), w.Bytes())
|
|
||||||
|
|
||||||
w.Reset()
|
|
||||||
err = writeDataPktLine(ctx, w, nil)
|
|
||||||
require.Error(t, err)
|
|
||||||
assert.Empty(t, w.Bytes())
|
|
||||||
|
|
||||||
w.Reset()
|
|
||||||
data = bytes.Repeat([]byte{0x64}, 65516)
|
|
||||||
err = writeDataPktLine(ctx, w, data)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Equal(t, append([]byte("fff0"), data...), w.Bytes())
|
|
||||||
|
|
||||||
w.Reset()
|
|
||||||
err = writeDataPktLine(ctx, w, bytes.Repeat([]byte{0x64}, 65516+1))
|
|
||||||
require.Error(t, err)
|
|
||||||
assert.Empty(t, w.Bytes())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDelayWriter(t *testing.T) {
|
|
||||||
// Setup the environment.
|
|
||||||
defer test.MockVariableValue(&setting.InternalToken, "Random")()
|
|
||||||
defer test.MockVariableValue(&setting.InstallLock, true)()
|
|
||||||
defer test.MockVariableValue(&setting.Git.VerbosePush, true)()
|
|
||||||
t.Setenv("SSH_ORIGINAL_COMMAND", "true")
|
|
||||||
|
|
||||||
// Setup the Stdin.
|
|
||||||
f, err := os.OpenFile(t.TempDir()+"/stdin", os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o666)
|
|
||||||
require.NoError(t, err)
|
|
||||||
_, err = f.Write([]byte("00000000000000000000 00000000000000000001 refs/head/main\n"))
|
|
||||||
require.NoError(t, err)
|
|
||||||
_, err = f.Seek(0, 0)
|
|
||||||
require.NoError(t, err)
|
|
||||||
defer test.MockVariableValue(os.Stdin, *f)()
|
|
||||||
|
|
||||||
// Setup the server that processes the hooks.
|
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
time.Sleep(time.Millisecond * 600)
|
|
||||||
}))
|
|
||||||
defer ts.Close()
|
|
||||||
defer test.MockVariableValue(&setting.LocalURL, ts.URL+"/")()
|
|
||||||
|
|
||||||
app := cli.NewApp()
|
|
||||||
app.Commands = []*cli.Command{subcmdHookPreReceive}
|
|
||||||
|
|
||||||
t.Run("Should delay", func(t *testing.T) {
|
|
||||||
defer test.MockVariableValue(&setting.Git.VerbosePushDelay, time.Millisecond*500)()
|
|
||||||
finish := captureOutput(t, os.Stdout)
|
|
||||||
|
|
||||||
err = app.Run([]string{"./forgejo", "pre-receive"})
|
|
||||||
require.NoError(t, err)
|
|
||||||
out := finish()
|
|
||||||
|
|
||||||
require.Contains(t, out, "* Checking 1 references")
|
|
||||||
require.Contains(t, out, "Checked 1 references in total")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Shouldn't delay", func(t *testing.T) {
|
|
||||||
defer test.MockVariableValue(&setting.Git.VerbosePushDelay, time.Second*5)()
|
|
||||||
finish := captureOutput(t, os.Stdout)
|
|
||||||
|
|
||||||
err = app.Run([]string{"./forgejo", "pre-receive"})
|
|
||||||
require.NoError(t, err)
|
|
||||||
out := finish()
|
|
||||||
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Empty(t, out)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRunHookUpdate(t *testing.T) {
|
|
||||||
app := cli.NewApp()
|
|
||||||
app.Commands = []*cli.Command{subcmdHookUpdate}
|
|
||||||
|
|
||||||
t.Run("Removal of internal reference", func(t *testing.T) {
|
|
||||||
defer test.MockVariableValue(&cli.OsExiter, func(code int) {})()
|
|
||||||
defer test.MockVariableValue(&setting.IsProd, false)()
|
|
||||||
finish := captureOutput(t, os.Stderr)
|
|
||||||
|
|
||||||
err := app.Run([]string{"./forgejo", "update", "refs/pull/1/head", "0a51ae26bc73c47e2f754560c40904cf14ed51a9", "0000000000000000000000000000000000000000"})
|
|
||||||
out := finish()
|
|
||||||
require.Error(t, err)
|
|
||||||
|
|
||||||
assert.Contains(t, out, "The deletion of refs/pull/1/head is skipped as it's an internal reference.")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Update of internal reference", func(t *testing.T) {
|
|
||||||
err := app.Run([]string{"./forgejo", "update", "refs/pull/1/head", "0a51ae26bc73c47e2f754560c40904cf14ed51a9", "0000000000000000000000000000000000000001"})
|
|
||||||
require.NoError(t, err)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Removal of branch", func(t *testing.T) {
|
|
||||||
err := app.Run([]string{"./forgejo", "update", "refs/head/main", "0a51ae26bc73c47e2f754560c40904cf14ed51a9", "0000000000000000000000000000000000000000"})
|
|
||||||
require.NoError(t, err)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Not enough arguments", func(t *testing.T) {
|
|
||||||
err := app.Run([]string{"./forgejo", "update"})
|
|
||||||
require.NoError(t, err)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ import (
|
||||||
var CmdKeys = &cli.Command{
|
var CmdKeys = &cli.Command{
|
||||||
Name: "keys",
|
Name: "keys",
|
||||||
Usage: "(internal) Should only be called by SSH server",
|
Usage: "(internal) Should only be called by SSH server",
|
||||||
Description: "Queries the Forgejo database to get the authorized command for a given ssh key fingerprint",
|
Description: "Queries the Gitea database to get the authorized command for a given ssh key fingerprint",
|
||||||
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||||
Action: runKeys,
|
Action: runKeys,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
|
@ -71,7 +71,7 @@ func runKeys(c *cli.Context) error {
|
||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
setup(ctx, c.Bool("debug"))
|
setup(ctx, false)
|
||||||
|
|
||||||
authorizedString, extra := private.AuthorizedPublicKeyByContent(ctx, content)
|
authorizedString, extra := private.AuthorizedPublicKeyByContent(ctx, content)
|
||||||
// do not use handleCliResponseExtra or cli.NewExitError, if it exists immediately, it breaks some tests like Test_CmdKeys
|
// do not use handleCliResponseExtra or cli.NewExitError, if it exists immediately, it breaks some tests like Test_CmdKeys
|
||||||
|
|
25
cmd/main.go
25
cmd/main.go
|
@ -72,7 +72,7 @@ func appGlobalFlags() []cli.Flag {
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "work-path",
|
Name: "work-path",
|
||||||
Aliases: []string{"w"},
|
Aliases: []string{"w"},
|
||||||
Usage: "Set Forgejo's working path (defaults to the directory of the Forgejo binary)",
|
Usage: "Set Gitea's working path (defaults to the Gitea's binary directory)",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,6 @@ func NewMainApp(version, versionExtra string) *cli.App {
|
||||||
|
|
||||||
var subCmdsStandalone []*cli.Command = make([]*cli.Command, 0, 10)
|
var subCmdsStandalone []*cli.Command = make([]*cli.Command, 0, 10)
|
||||||
var subCmdWithConfig []*cli.Command = make([]*cli.Command, 0, 10)
|
var subCmdWithConfig []*cli.Command = make([]*cli.Command, 0, 10)
|
||||||
var globalFlags []cli.Flag = make([]cli.Flag, 0, 10)
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// If the executable is forgejo-cli, provide a Forgejo specific CLI
|
// If the executable is forgejo-cli, provide a Forgejo specific CLI
|
||||||
|
@ -132,15 +131,6 @@ func NewMainApp(version, versionExtra string) *cli.App {
|
||||||
//
|
//
|
||||||
if executable == "forgejo-cli" {
|
if executable == "forgejo-cli" {
|
||||||
subCmdsStandalone = append(subCmdsStandalone, forgejo.CmdActions(context.Background()))
|
subCmdsStandalone = append(subCmdsStandalone, forgejo.CmdActions(context.Background()))
|
||||||
subCmdWithConfig = append(subCmdWithConfig, forgejo.CmdF3(context.Background()))
|
|
||||||
globalFlags = append(globalFlags, []cli.Flag{
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "quiet",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "verbose",
|
|
||||||
},
|
|
||||||
}...)
|
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
// Otherwise provide a Gitea compatible CLI which includes Forgejo
|
// Otherwise provide a Gitea compatible CLI which includes Forgejo
|
||||||
|
@ -152,15 +142,15 @@ func NewMainApp(version, versionExtra string) *cli.App {
|
||||||
subCmdWithConfig = append(subCmdWithConfig, CmdActions)
|
subCmdWithConfig = append(subCmdWithConfig, CmdActions)
|
||||||
}
|
}
|
||||||
|
|
||||||
return innerNewMainApp(version, versionExtra, subCmdsStandalone, subCmdWithConfig, globalFlags)
|
return innerNewMainApp(version, versionExtra, subCmdsStandalone, subCmdWithConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
func innerNewMainApp(version, versionExtra string, subCmdsStandaloneArgs, subCmdWithConfigArgs []*cli.Command, globalFlagsArgs []cli.Flag) *cli.App {
|
func innerNewMainApp(version, versionExtra string, subCmdsStandaloneArgs, subCmdWithConfigArgs []*cli.Command) *cli.App {
|
||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
app.HelpName = "forgejo"
|
app.Name = "Gitea"
|
||||||
app.Name = "Forgejo"
|
app.HelpName = "gitea"
|
||||||
app.Usage = "Beyond coding. We forge."
|
app.Usage = "A painless self-hosted Git service"
|
||||||
app.Description = `By default, forgejo will start serving using the web-server with no argument, which can alternatively be run by running the subcommand "web".`
|
app.Description = `Gitea program contains "web" and other subcommands. If no subcommand is given, it starts the web server by default. Use "web" subcommand for more web server arguments, use other subcommands for other purposes.`
|
||||||
app.Version = version + versionExtra
|
app.Version = version + versionExtra
|
||||||
app.EnableBashCompletion = true
|
app.EnableBashCompletion = true
|
||||||
|
|
||||||
|
@ -195,7 +185,6 @@ func innerNewMainApp(version, versionExtra string, subCmdsStandaloneArgs, subCmd
|
||||||
app.DefaultCommand = CmdWeb.Name
|
app.DefaultCommand = CmdWeb.Name
|
||||||
|
|
||||||
globalFlags := appGlobalFlags()
|
globalFlags := appGlobalFlags()
|
||||||
globalFlags = append(globalFlags, globalFlagsArgs...)
|
|
||||||
app.Flags = append(app.Flags, cli.VersionFlag)
|
app.Flags = append(app.Flags, cli.VersionFlag)
|
||||||
app.Flags = append(app.Flags, globalFlags...)
|
app.Flags = append(app.Flags, globalFlags...)
|
||||||
app.HideHelp = true // use our own help action to show helps (with more information like default config)
|
app.HideHelp = true // use our own help action to show helps (with more information like default config)
|
||||||
|
|
|
@ -16,7 +16,6 @@ import (
|
||||||
"code.gitea.io/gitea/modules/test"
|
"code.gitea.io/gitea/modules/test"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -142,7 +141,7 @@ func TestCliCmd(t *testing.T) {
|
||||||
}
|
}
|
||||||
args := strings.Split(c.cmd, " ") // for test only, "split" is good enough
|
args := strings.Split(c.cmd, " ") // for test only, "split" is good enough
|
||||||
r, err := runTestApp(app, args...)
|
r, err := runTestApp(app, args...)
|
||||||
require.NoError(t, err, c.cmd)
|
assert.NoError(t, err, c.cmd)
|
||||||
assert.NotEmpty(t, c.exp, c.cmd)
|
assert.NotEmpty(t, c.exp, c.cmd)
|
||||||
assert.Contains(t, r.Stdout, c.exp, c.cmd)
|
assert.Contains(t, r.Stdout, c.exp, c.cmd)
|
||||||
}
|
}
|
||||||
|
@ -151,28 +150,28 @@ func TestCliCmd(t *testing.T) {
|
||||||
func TestCliCmdError(t *testing.T) {
|
func TestCliCmdError(t *testing.T) {
|
||||||
app := newTestApp(func(ctx *cli.Context) error { return fmt.Errorf("normal error") })
|
app := newTestApp(func(ctx *cli.Context) error { return fmt.Errorf("normal error") })
|
||||||
r, err := runTestApp(app, "./gitea", "test-cmd")
|
r, err := runTestApp(app, "./gitea", "test-cmd")
|
||||||
require.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Equal(t, 1, r.ExitCode)
|
assert.Equal(t, 1, r.ExitCode)
|
||||||
assert.Equal(t, "", r.Stdout)
|
assert.Equal(t, "", r.Stdout)
|
||||||
assert.Equal(t, "Command error: normal error\n", r.Stderr)
|
assert.Equal(t, "Command error: normal error\n", r.Stderr)
|
||||||
|
|
||||||
app = newTestApp(func(ctx *cli.Context) error { return cli.Exit("exit error", 2) })
|
app = newTestApp(func(ctx *cli.Context) error { return cli.Exit("exit error", 2) })
|
||||||
r, err = runTestApp(app, "./gitea", "test-cmd")
|
r, err = runTestApp(app, "./gitea", "test-cmd")
|
||||||
require.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Equal(t, 2, r.ExitCode)
|
assert.Equal(t, 2, r.ExitCode)
|
||||||
assert.Equal(t, "", r.Stdout)
|
assert.Equal(t, "", r.Stdout)
|
||||||
assert.Equal(t, "exit error\n", r.Stderr)
|
assert.Equal(t, "exit error\n", r.Stderr)
|
||||||
|
|
||||||
app = newTestApp(func(ctx *cli.Context) error { return nil })
|
app = newTestApp(func(ctx *cli.Context) error { return nil })
|
||||||
r, err = runTestApp(app, "./gitea", "test-cmd", "--no-such")
|
r, err = runTestApp(app, "./gitea", "test-cmd", "--no-such")
|
||||||
require.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Equal(t, 1, r.ExitCode)
|
assert.Equal(t, 1, r.ExitCode)
|
||||||
assert.Equal(t, "Incorrect Usage: flag provided but not defined: -no-such\n\n", r.Stdout)
|
assert.Equal(t, "Incorrect Usage: flag provided but not defined: -no-such\n\n", r.Stdout)
|
||||||
assert.Equal(t, "", r.Stderr) // the cli package's strange behavior, the error message is not in stderr ....
|
assert.Equal(t, "", r.Stderr) // the cli package's strange behavior, the error message is not in stderr ....
|
||||||
|
|
||||||
app = newTestApp(func(ctx *cli.Context) error { return nil })
|
app = newTestApp(func(ctx *cli.Context) error { return nil })
|
||||||
r, err = runTestApp(app, "./gitea", "test-cmd")
|
r, err = runTestApp(app, "./gitea", "test-cmd")
|
||||||
require.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, -1, r.ExitCode) // the cli.OsExiter is not called
|
assert.Equal(t, -1, r.ExitCode) // the cli.OsExiter is not called
|
||||||
assert.Equal(t, "", r.Stdout)
|
assert.Equal(t, "", r.Stdout)
|
||||||
assert.Equal(t, "", r.Stderr)
|
assert.Equal(t, "", r.Stderr)
|
||||||
|
|
|
@ -16,8 +16,8 @@ var (
|
||||||
// CmdManager represents the manager command
|
// CmdManager represents the manager command
|
||||||
CmdManager = &cli.Command{
|
CmdManager = &cli.Command{
|
||||||
Name: "manager",
|
Name: "manager",
|
||||||
Usage: "Manage the running forgejo process",
|
Usage: "Manage the running gitea process",
|
||||||
Description: "This is a command for managing the running forgejo process",
|
Description: "This is a command for managing the running gitea process",
|
||||||
Subcommands: []*cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
subcmdShutdown,
|
subcmdShutdown,
|
||||||
subcmdRestart,
|
subcmdRestart,
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
@ -63,7 +62,7 @@ var (
|
||||||
Subcommands: []*cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
{
|
{
|
||||||
Name: "pause",
|
Name: "pause",
|
||||||
Usage: "Pause logging (Forgejo will buffer logs up to a certain point and will drop them after that point)",
|
Usage: "Pause logging (Gitea will buffer logs up to a certain point and will drop them after that point)",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
|
@ -81,7 +80,7 @@ var (
|
||||||
Action: runResumeLogging,
|
Action: runResumeLogging,
|
||||||
}, {
|
}, {
|
||||||
Name: "release-and-reopen",
|
Name: "release-and-reopen",
|
||||||
Usage: "Cause Forgejo to release and re-open files used for logging",
|
Usage: "Cause Gitea to release and re-open files used for logging",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
|
@ -250,7 +249,7 @@ func runAddFileLogger(c *cli.Context) error {
|
||||||
if c.IsSet("filename") {
|
if c.IsSet("filename") {
|
||||||
vals["filename"] = c.String("filename")
|
vals["filename"] = c.String("filename")
|
||||||
} else {
|
} else {
|
||||||
return errors.New("filename must be set when creating a file logger")
|
return fmt.Errorf("filename must be set when creating a file logger")
|
||||||
}
|
}
|
||||||
if c.IsSet("rotate") {
|
if c.IsSet("rotate") {
|
||||||
vals["rotate"] = c.Bool("rotate")
|
vals["rotate"] = c.Bool("rotate")
|
||||||
|
|
|
@ -18,7 +18,7 @@ import (
|
||||||
var CmdMigrate = &cli.Command{
|
var CmdMigrate = &cli.Command{
|
||||||
Name: "migrate",
|
Name: "migrate",
|
||||||
Usage: "Migrate the database",
|
Usage: "Migrate the database",
|
||||||
Description: "This is a command for migrating the database, so that you can run gitea admin user create before starting the server.",
|
Description: "This is a command for migrating the database, so that you can run gitea admin create-user before starting the server.",
|
||||||
Action: runMigrate,
|
Action: runMigrate,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,7 @@ package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
actions_model "code.gitea.io/gitea/models/actions"
|
actions_model "code.gitea.io/gitea/models/actions"
|
||||||
|
@ -36,7 +34,7 @@ var CmdMigrateStorage = &cli.Command{
|
||||||
Name: "type",
|
Name: "type",
|
||||||
Aliases: []string{"t"},
|
Aliases: []string{"t"},
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Type of stored files to copy. Allowed types: 'attachments', 'lfs', 'avatars', 'repo-avatars', 'repo-archivers', 'packages', 'actions-log', 'actions-artifacts'",
|
Usage: "Type of stored files to copy. Allowed types: 'attachments', 'lfs', 'avatars', 'repo-avatars', 'repo-archivers', 'packages', 'actions-log'",
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "storage",
|
Name: "storage",
|
||||||
|
@ -162,25 +160,6 @@ func migrateActionsLog(ctx context.Context, dstStorage storage.ObjectStorage) er
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func migrateActionsArtifacts(ctx context.Context, dstStorage storage.ObjectStorage) error {
|
|
||||||
return db.Iterate(ctx, nil, func(ctx context.Context, artifact *actions_model.ActionArtifact) error {
|
|
||||||
if artifact.Status == int64(actions_model.ArtifactStatusExpired) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := storage.Copy(dstStorage, artifact.StoragePath, storage.ActionsArtifacts, artifact.StoragePath)
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, fs.ErrNotExist) {
|
|
||||||
log.Warn("ignored: actions artifact %s exists in the database but not in storage", artifact.StoragePath)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func runMigrateStorage(ctx *cli.Context) error {
|
func runMigrateStorage(ctx *cli.Context) error {
|
||||||
stdCtx, cancel := installSignals()
|
stdCtx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
@ -244,14 +223,13 @@ func runMigrateStorage(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
migratedMethods := map[string]func(context.Context, storage.ObjectStorage) error{
|
migratedMethods := map[string]func(context.Context, storage.ObjectStorage) error{
|
||||||
"attachments": migrateAttachments,
|
"attachments": migrateAttachments,
|
||||||
"lfs": migrateLFS,
|
"lfs": migrateLFS,
|
||||||
"avatars": migrateAvatars,
|
"avatars": migrateAvatars,
|
||||||
"repo-avatars": migrateRepoAvatars,
|
"repo-avatars": migrateRepoAvatars,
|
||||||
"repo-archivers": migrateRepoArchivers,
|
"repo-archivers": migrateRepoArchivers,
|
||||||
"packages": migratePackages,
|
"packages": migratePackages,
|
||||||
"actions-log": migrateActionsLog,
|
"actions-log": migrateActionsLog,
|
||||||
"actions-artifacts": migrateActionsArtifacts,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tp := strings.ToLower(ctx.String("type"))
|
tp := strings.ToLower(ctx.String("type"))
|
||||||
|
|
|
@ -5,12 +5,10 @@ package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/actions"
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/packages"
|
"code.gitea.io/gitea/models/packages"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
@ -18,36 +16,19 @@ import (
|
||||||
packages_module "code.gitea.io/gitea/modules/packages"
|
packages_module "code.gitea.io/gitea/modules/packages"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
"code.gitea.io/gitea/modules/test"
|
|
||||||
packages_service "code.gitea.io/gitea/services/packages"
|
packages_service "code.gitea.io/gitea/services/packages"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func createLocalStorage(t *testing.T) (storage.ObjectStorage, string) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
p := t.TempDir()
|
|
||||||
|
|
||||||
storage, err := storage.NewLocalStorage(
|
|
||||||
context.Background(),
|
|
||||||
&setting.Storage{
|
|
||||||
Path: p,
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
return storage, p
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMigratePackages(t *testing.T) {
|
func TestMigratePackages(t *testing.T) {
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
creator := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
creator := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
|
|
||||||
content := "package main\n\nfunc main() {\nfmt.Println(\"hi\")\n}\n"
|
content := "package main\n\nfunc main() {\nfmt.Println(\"hi\")\n}\n"
|
||||||
buf, err := packages_module.CreateHashedBufferFromReaderWithSize(strings.NewReader(content), 1024)
|
buf, err := packages_module.CreateHashedBufferFromReaderWithSize(strings.NewReader(content), 1024)
|
||||||
require.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer buf.Close()
|
defer buf.Close()
|
||||||
|
|
||||||
v, f, err := packages_service.CreatePackageAndAddFile(db.DefaultContext, &packages_service.PackageCreationInfo{
|
v, f, err := packages_service.CreatePackageAndAddFile(db.DefaultContext, &packages_service.PackageCreationInfo{
|
||||||
|
@ -68,67 +49,27 @@ func TestMigratePackages(t *testing.T) {
|
||||||
Data: buf,
|
Data: buf,
|
||||||
IsLead: true,
|
IsLead: true,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, v)
|
assert.NotNil(t, v)
|
||||||
assert.NotNil(t, f)
|
assert.NotNil(t, f)
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
dstStorage, p := createLocalStorage(t)
|
p := t.TempDir()
|
||||||
|
|
||||||
|
dstStorage, err := storage.NewLocalStorage(
|
||||||
|
ctx,
|
||||||
|
&setting.Storage{
|
||||||
|
Path: p,
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = migratePackages(ctx, dstStorage)
|
err = migratePackages(ctx, dstStorage)
|
||||||
require.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
entries, err := os.ReadDir(p)
|
entries, err := os.ReadDir(p)
|
||||||
require.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, entries, 2)
|
assert.Len(t, entries, 2)
|
||||||
assert.EqualValues(t, "01", entries[0].Name())
|
assert.EqualValues(t, "01", entries[0].Name())
|
||||||
assert.EqualValues(t, "tmp", entries[1].Name())
|
assert.EqualValues(t, "tmp", entries[1].Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMigrateActionsArtifacts(t *testing.T) {
|
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
srcStorage, _ := createLocalStorage(t)
|
|
||||||
defer test.MockVariableValue(&storage.ActionsArtifacts, srcStorage)()
|
|
||||||
id := int64(0)
|
|
||||||
|
|
||||||
addArtifact := func(storagePath string, status actions.ArtifactStatus) {
|
|
||||||
id++
|
|
||||||
artifact := &actions.ActionArtifact{
|
|
||||||
ID: id,
|
|
||||||
ArtifactName: storagePath,
|
|
||||||
StoragePath: storagePath,
|
|
||||||
Status: int64(status),
|
|
||||||
}
|
|
||||||
_, err := db.GetEngine(db.DefaultContext).Insert(artifact)
|
|
||||||
require.NoError(t, err)
|
|
||||||
srcStorage.Save(storagePath, strings.NewReader(storagePath), -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
exists := "/exists"
|
|
||||||
addArtifact(exists, actions.ArtifactStatusUploadConfirmed)
|
|
||||||
|
|
||||||
expired := "/expired"
|
|
||||||
addArtifact(expired, actions.ArtifactStatusExpired)
|
|
||||||
|
|
||||||
notFound := "/notfound"
|
|
||||||
addArtifact(notFound, actions.ArtifactStatusUploadConfirmed)
|
|
||||||
srcStorage.Delete(notFound)
|
|
||||||
|
|
||||||
dstStorage, _ := createLocalStorage(t)
|
|
||||||
|
|
||||||
require.NoError(t, migrateActionsArtifacts(db.DefaultContext, dstStorage))
|
|
||||||
|
|
||||||
object, err := dstStorage.Open(exists)
|
|
||||||
require.NoError(t, err)
|
|
||||||
buf, err := io.ReadAll(object)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Equal(t, exists, string(buf))
|
|
||||||
|
|
||||||
_, err = dstStorage.Stat(expired)
|
|
||||||
require.Error(t, err)
|
|
||||||
|
|
||||||
_, err = dstStorage.Stat(notFound)
|
|
||||||
require.Error(t, err)
|
|
||||||
}
|
|
||||||
|
|
56
cmd/serv.go
56
cmd/serv.go
|
@ -14,7 +14,6 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
|
@ -64,10 +63,21 @@ func setup(ctx context.Context, debug bool) {
|
||||||
setupConsoleLogger(log.FATAL, false, os.Stderr)
|
setupConsoleLogger(log.FATAL, false, os.Stderr)
|
||||||
}
|
}
|
||||||
setting.MustInstalled()
|
setting.MustInstalled()
|
||||||
|
if debug {
|
||||||
|
setting.RunMode = "dev"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if setting.RepoRootPath exists. It could be the case that it doesn't exist, this can happen when
|
||||||
|
// `[repository]` `ROOT` is a relative path and $GITEA_WORK_DIR isn't passed to the SSH connection.
|
||||||
if _, err := os.Stat(setting.RepoRootPath); err != nil {
|
if _, err := os.Stat(setting.RepoRootPath); err != nil {
|
||||||
_ = fail(ctx, "Unable to access repository path", "Unable to access repository path %q, err: %v", setting.RepoRootPath, err)
|
if os.IsNotExist(err) {
|
||||||
|
_ = fail(ctx, "Incorrect configuration, no repository directory.", "Directory `[repository].ROOT` %q was not found, please check if $GITEA_WORK_DIR is passed to the SSH connection or make `[repository].ROOT` an absolute value.", setting.RepoRootPath)
|
||||||
|
} else {
|
||||||
|
_ = fail(ctx, "Incorrect configuration, repository directory is inaccessible", "Directory `[repository].ROOT` %q is inaccessible. err: %v", setting.RepoRootPath, err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := git.InitSimple(context.Background()); err != nil {
|
if err := git.InitSimple(context.Background()); err != nil {
|
||||||
_ = fail(ctx, "Failed to init git", "Failed to init git, err: %v", err)
|
_ = fail(ctx, "Failed to init git", "Failed to init git, err: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -93,12 +103,12 @@ func fail(ctx context.Context, userMessage, logMsgFmt string, args ...any) error
|
||||||
// There appears to be a chance to cause a zombie process and failure to read the Exit status
|
// There appears to be a chance to cause a zombie process and failure to read the Exit status
|
||||||
// if nothing is outputted on stdout.
|
// if nothing is outputted on stdout.
|
||||||
_, _ = fmt.Fprintln(os.Stdout, "")
|
_, _ = fmt.Fprintln(os.Stdout, "")
|
||||||
_, _ = fmt.Fprintln(os.Stderr, "Forgejo:", userMessage)
|
_, _ = fmt.Fprintln(os.Stderr, "Gitea:", userMessage)
|
||||||
|
|
||||||
if logMsgFmt != "" {
|
if logMsgFmt != "" {
|
||||||
logMsg := fmt.Sprintf(logMsgFmt, args...)
|
logMsg := fmt.Sprintf(logMsgFmt, args...)
|
||||||
if !setting.IsProd {
|
if !setting.IsProd {
|
||||||
_, _ = fmt.Fprintln(os.Stderr, "Forgejo:", logMsg)
|
_, _ = fmt.Fprintln(os.Stderr, "Gitea:", logMsg)
|
||||||
}
|
}
|
||||||
if userMessage != "" {
|
if userMessage != "" {
|
||||||
if unicode.IsPunct(rune(userMessage[len(userMessage)-1])) {
|
if unicode.IsPunct(rune(userMessage[len(userMessage)-1])) {
|
||||||
|
@ -107,10 +117,7 @@ func fail(ctx context.Context, userMessage, logMsgFmt string, args ...any) error
|
||||||
logMsg = userMessage + ". " + logMsg
|
logMsg = userMessage + ". " + logMsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Don't send an log if this is done in a test and no InternalToken is set.
|
_ = private.SSHLog(ctx, true, logMsg)
|
||||||
if !testing.Testing() || setting.InternalToken != "" {
|
|
||||||
_ = private.SSHLog(ctx, true, logMsg)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return cli.Exit("", 1)
|
return cli.Exit("", 1)
|
||||||
}
|
}
|
||||||
|
@ -136,7 +143,7 @@ func runServ(c *cli.Context) error {
|
||||||
setup(ctx, c.Bool("debug"))
|
setup(ctx, c.Bool("debug"))
|
||||||
|
|
||||||
if setting.SSH.Disabled {
|
if setting.SSH.Disabled {
|
||||||
fmt.Println("Forgejo: SSH has been disabled")
|
println("Gitea: SSH has been disabled")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,12 +154,6 @@ func runServ(c *cli.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
_ = fail(ctx, "Internal Server Error", "Panic: %v\n%s", err, log.Stack(2))
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
keys := strings.Split(c.Args().First(), "-")
|
keys := strings.Split(c.Args().First(), "-")
|
||||||
if len(keys) != 2 || keys[0] != "key" {
|
if len(keys) != 2 || keys[0] != "key" {
|
||||||
return fail(ctx, "Key ID format error", "Invalid key argument: %s", c.Args().First())
|
return fail(ctx, "Key ID format error", "Invalid key argument: %s", c.Args().First())
|
||||||
|
@ -170,13 +171,13 @@ func runServ(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
switch key.Type {
|
switch key.Type {
|
||||||
case asymkey_model.KeyTypeDeploy:
|
case asymkey_model.KeyTypeDeploy:
|
||||||
fmt.Println("Hi there! You've successfully authenticated with the deploy key named " + key.Name + ", but Forgejo does not provide shell access.")
|
println("Hi there! You've successfully authenticated with the deploy key named " + key.Name + ", but Gitea does not provide shell access.")
|
||||||
case asymkey_model.KeyTypePrincipal:
|
case asymkey_model.KeyTypePrincipal:
|
||||||
fmt.Println("Hi there! You've successfully authenticated with the principal " + key.Content + ", but Forgejo does not provide shell access.")
|
println("Hi there! You've successfully authenticated with the principal " + key.Content + ", but Gitea does not provide shell access.")
|
||||||
default:
|
default:
|
||||||
fmt.Println("Hi there, " + user.Name + "! You've successfully authenticated with the key named " + key.Name + ", but Forgejo does not provide shell access.")
|
println("Hi there, " + user.Name + "! You've successfully authenticated with the key named " + key.Name + ", but Gitea does not provide shell access.")
|
||||||
}
|
}
|
||||||
fmt.Println("If this is unexpected, please log in with password and setup Forgejo under another user.")
|
println("If this is unexpected, please log in with password and setup Gitea under another user.")
|
||||||
return nil
|
return nil
|
||||||
} else if c.Bool("debug") {
|
} else if c.Bool("debug") {
|
||||||
log.Debug("SSH_ORIGINAL_COMMAND: %s", os.Getenv("SSH_ORIGINAL_COMMAND"))
|
log.Debug("SSH_ORIGINAL_COMMAND: %s", os.Getenv("SSH_ORIGINAL_COMMAND"))
|
||||||
|
@ -199,7 +200,10 @@ func runServ(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
verb := words[0]
|
verb := words[0]
|
||||||
repoPath := strings.TrimPrefix(words[1], "/")
|
repoPath := words[1]
|
||||||
|
if repoPath[0] == '/' {
|
||||||
|
repoPath = repoPath[1:]
|
||||||
|
}
|
||||||
|
|
||||||
var lfsVerb string
|
var lfsVerb string
|
||||||
if verb == lfsAuthenticateVerb {
|
if verb == lfsAuthenticateVerb {
|
||||||
|
@ -212,18 +216,16 @@ func runServ(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LowerCase and trim the repoPath as that's how they are stored.
|
||||||
|
repoPath = strings.ToLower(strings.TrimSpace(repoPath))
|
||||||
|
|
||||||
rr := strings.SplitN(repoPath, "/", 2)
|
rr := strings.SplitN(repoPath, "/", 2)
|
||||||
if len(rr) != 2 {
|
if len(rr) != 2 {
|
||||||
return fail(ctx, "Invalid repository path", "Invalid repository path: %v", repoPath)
|
return fail(ctx, "Invalid repository path", "Invalid repository path: %v", repoPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
username := rr[0]
|
username := strings.ToLower(rr[0])
|
||||||
reponame := strings.TrimSuffix(rr[1], ".git")
|
reponame := strings.ToLower(strings.TrimSuffix(rr[1], ".git"))
|
||||||
|
|
||||||
// LowerCase and trim the repoPath as that's how they are stored.
|
|
||||||
// This should be done after splitting the repoPath into username and reponame
|
|
||||||
// so that username and reponame are not affected.
|
|
||||||
repoPath = strings.ToLower(strings.TrimSpace(repoPath))
|
|
||||||
|
|
||||||
if alphaDashDotPattern.MatchString(reponame) {
|
if alphaDashDotPattern.MatchString(reponame) {
|
||||||
return fail(ctx, "Invalid repo name", "Invalid repo name: %s", reponame)
|
return fail(ctx, "Invalid repo name", "Invalid repo name: %s", reponame)
|
||||||
|
|
20
cmd/web.go
20
cmd/web.go
|
@ -34,8 +34,8 @@ var PIDFile = "/run/gitea.pid"
|
||||||
// CmdWeb represents the available web sub-command.
|
// CmdWeb represents the available web sub-command.
|
||||||
var CmdWeb = &cli.Command{
|
var CmdWeb = &cli.Command{
|
||||||
Name: "web",
|
Name: "web",
|
||||||
Usage: "Start the Forgejo web server",
|
Usage: "Start Gitea web server",
|
||||||
Description: `The Forgejo web server is the only thing you need to run,
|
Description: `Gitea web server is the only thing you need to run,
|
||||||
and it takes care of all the other things for you`,
|
and it takes care of all the other things for you`,
|
||||||
Before: PrepareConsoleLoggerLevel(log.INFO),
|
Before: PrepareConsoleLoggerLevel(log.INFO),
|
||||||
Action: runWeb,
|
Action: runWeb,
|
||||||
|
@ -108,13 +108,13 @@ func createPIDFile(pidPath string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func showWebStartupMessage(msg string) {
|
func showWebStartupMessage(msg string) {
|
||||||
log.Info("Forgejo version: %s%s", setting.AppVer, setting.AppBuiltWith)
|
log.Info("Gitea version: %s%s", setting.AppVer, setting.AppBuiltWith)
|
||||||
log.Info("* RunMode: %s", setting.RunMode)
|
log.Info("* RunMode: %s", setting.RunMode)
|
||||||
log.Info("* AppPath: %s", setting.AppPath)
|
log.Info("* AppPath: %s", setting.AppPath)
|
||||||
log.Info("* WorkPath: %s", setting.AppWorkPath)
|
log.Info("* WorkPath: %s", setting.AppWorkPath)
|
||||||
log.Info("* CustomPath: %s", setting.CustomPath)
|
log.Info("* CustomPath: %s", setting.CustomPath)
|
||||||
log.Info("* ConfigFile: %s", setting.CustomConf)
|
log.Info("* ConfigFile: %s", setting.CustomConf)
|
||||||
log.Info("%s", msg) // show startup message
|
log.Info("%s", msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func serveInstall(ctx *cli.Context) error {
|
func serveInstall(ctx *cli.Context) error {
|
||||||
|
@ -136,13 +136,13 @@ func serveInstall(ctx *cli.Context) error {
|
||||||
c := install.Routes()
|
c := install.Routes()
|
||||||
err := listen(c, false)
|
err := listen(c, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Critical("Unable to open listener for installer. Is Forgejo already running?")
|
log.Critical("Unable to open listener for installer. Is Gitea already running?")
|
||||||
graceful.GetManager().DoGracefulShutdown()
|
graceful.GetManager().DoGracefulShutdown()
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
case <-graceful.GetManager().IsShutdown():
|
case <-graceful.GetManager().IsShutdown():
|
||||||
<-graceful.GetManager().Done()
|
<-graceful.GetManager().Done()
|
||||||
log.Info("PID: %d Forgejo Web Finished", os.Getpid())
|
log.Info("PID: %d Gitea Web Finished", os.Getpid())
|
||||||
log.GetManager().Close()
|
log.GetManager().Close()
|
||||||
return err
|
return err
|
||||||
default:
|
default:
|
||||||
|
@ -211,7 +211,7 @@ func serveInstalled(ctx *cli.Context) error {
|
||||||
webRoutes := routers.NormalRoutes()
|
webRoutes := routers.NormalRoutes()
|
||||||
err := listen(webRoutes, true)
|
err := listen(webRoutes, true)
|
||||||
<-graceful.GetManager().Done()
|
<-graceful.GetManager().Done()
|
||||||
log.Info("PID: %d Forgejo Web Finished", os.Getpid())
|
log.Info("PID: %d Gitea Web Finished", os.Getpid())
|
||||||
log.GetManager().Close()
|
log.GetManager().Close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -237,9 +237,9 @@ func runWeb(ctx *cli.Context) error {
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if os.Getppid() > 1 && len(os.Getenv("LISTEN_FDS")) > 0 {
|
if os.Getppid() > 1 && len(os.Getenv("LISTEN_FDS")) > 0 {
|
||||||
log.Info("Restarting Forgejo on PID: %d from parent PID: %d", os.Getpid(), os.Getppid())
|
log.Info("Restarting Gitea on PID: %d from parent PID: %d", os.Getpid(), os.Getppid())
|
||||||
} else {
|
} else {
|
||||||
log.Info("Starting Forgejo on PID: %d", os.Getpid())
|
log.Info("Starting Gitea on PID: %d", os.Getpid())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set pid file setting
|
// Set pid file setting
|
||||||
|
@ -299,7 +299,7 @@ func listen(m http.Handler, handleRedirector bool) error {
|
||||||
if setting.Protocol != setting.HTTPUnix && setting.Protocol != setting.FCGIUnix {
|
if setting.Protocol != setting.HTTPUnix && setting.Protocol != setting.FCGIUnix {
|
||||||
listenAddr = net.JoinHostPort(listenAddr, setting.HTTPPort)
|
listenAddr = net.JoinHostPort(listenAddr, setting.HTTPPort)
|
||||||
}
|
}
|
||||||
_, _, finished := process.GetManager().AddTypedContext(graceful.GetManager().HammerContext(), "Web: Forgejo Server", process.SystemProcessType, true)
|
_, _, finished := process.GetManager().AddTypedContext(graceful.GetManager().HammerContext(), "Web: Gitea Server", process.SystemProcessType, true)
|
||||||
defer finished()
|
defer finished()
|
||||||
log.Info("Listen: %v://%s%s", setting.Protocol, listenAddr, setting.AppSubURL)
|
log.Info("Listen: %v://%s%s", setting.Protocol, listenAddr, setting.AppSubURL)
|
||||||
// This can be useful for users, many users do wrong to their config and get strange behaviors behind a reverse-proxy.
|
// This can be useful for users, many users do wrong to their config and get strange behaviors behind a reverse-proxy.
|
||||||
|
|
|
@ -11,7 +11,7 @@ The default version will read from `docs/config.yml`. You can override this
|
||||||
using the option `--version`.
|
using the option `--version`.
|
||||||
|
|
||||||
The upstream branches will be fetched, using the remote `origin`. This can
|
The upstream branches will be fetched, using the remote `origin`. This can
|
||||||
be overridden using `--upstream`, and fetching can be avoided using
|
be overrided using `--upstream`, and fetching can be avoided using
|
||||||
`--no-fetch`.
|
`--no-fetch`.
|
||||||
|
|
||||||
By default the branch created will be called `backport-$PR-$VERSION`. You
|
By default the branch created will be called `backport-$PR-$VERSION`. You
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/google/go-github/v64/github"
|
"github.com/google/go-github/v57/github"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue