mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-10-02 21:33:16 +00:00
Compare commits
20 commits
b8d68505e4
...
f79d2fba07
Author | SHA1 | Date | |
---|---|---|---|
|
f79d2fba07 | ||
|
d2eac83f6a | ||
|
df0e50a08f | ||
|
d25a3709d9 | ||
|
e28a1e1d38 | ||
|
aec55ac1b6 | ||
|
9a7fc2e55e | ||
|
2099c2af7c | ||
|
502a6a4461 | ||
|
c9ea78eb1c | ||
|
8178d6eaba | ||
|
36af3348bc | ||
|
b496317b5a | ||
|
5ccf79d05c | ||
|
30b8b45e5e | ||
|
65b3136261 | ||
|
ff65d34f03 | ||
|
a226064711 | ||
|
8f0a05a7e4 | ||
|
ed656ca0f3 |
21 changed files with 629 additions and 266 deletions
|
@ -6,7 +6,7 @@
|
||||||
"ghcr.io/devcontainers/features/node:1": {
|
"ghcr.io/devcontainers/features/node:1": {
|
||||||
"version": "20"
|
"version": "20"
|
||||||
},
|
},
|
||||||
"ghcr.io/devcontainers/features/git-lfs:1.2.1": {},
|
"ghcr.io/devcontainers/features/git-lfs:1.2.3": {},
|
||||||
"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"
|
"version": "3.12"
|
||||||
|
|
|
@ -87,7 +87,7 @@ jobs:
|
||||||
|
|
||||||
- name: cache node_modules
|
- name: cache node_modules
|
||||||
id: node
|
id: node
|
||||||
uses: https://code.forgejo.org/actions/cache@v3
|
uses: https://code.forgejo.org/actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
node_modules
|
node_modules
|
||||||
|
|
11
cmd/serv.go
11
cmd/serv.go
|
@ -147,6 +147,12 @@ 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())
|
||||||
|
@ -193,10 +199,7 @@ func runServ(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
verb := words[0]
|
verb := words[0]
|
||||||
repoPath := words[1]
|
repoPath := strings.TrimPrefix(words[1], "/")
|
||||||
if repoPath[0] == '/' {
|
|
||||||
repoPath = repoPath[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
var lfsVerb string
|
var lfsVerb string
|
||||||
if verb == lfsAuthenticateVerb {
|
if verb == lfsAuthenticateVerb {
|
||||||
|
|
|
@ -18,8 +18,32 @@ func FullSteps(task *actions_model.ActionTask) []*actions_model.ActionTaskStep {
|
||||||
return fullStepsOfEmptySteps(task)
|
return fullStepsOfEmptySteps(task)
|
||||||
}
|
}
|
||||||
|
|
||||||
firstStep := task.Steps[0]
|
// firstStep is the first step that has run or running, not include preStep.
|
||||||
|
// For example,
|
||||||
|
// 1. preStep(Success) -> step1(Success) -> step2(Running) -> step3(Waiting) -> postStep(Waiting): firstStep is step1.
|
||||||
|
// 2. preStep(Success) -> step1(Skipped) -> step2(Success) -> postStep(Success): firstStep is step2.
|
||||||
|
// 3. preStep(Success) -> step1(Running) -> step2(Waiting) -> postStep(Waiting): firstStep is step1.
|
||||||
|
// 4. preStep(Success) -> step1(Skipped) -> step2(Skipped) -> postStep(Skipped): firstStep is nil.
|
||||||
|
// 5. preStep(Success) -> step1(Cancelled) -> step2(Cancelled) -> postStep(Cancelled): firstStep is nil.
|
||||||
|
var firstStep *actions_model.ActionTaskStep
|
||||||
|
// lastHasRunStep is the last step that has run.
|
||||||
|
// For example,
|
||||||
|
// 1. preStep(Success) -> step1(Success) -> step2(Running) -> step3(Waiting) -> postStep(Waiting): lastHasRunStep is step1.
|
||||||
|
// 2. preStep(Success) -> step1(Success) -> step2(Success) -> step3(Success) -> postStep(Success): lastHasRunStep is step3.
|
||||||
|
// 3. preStep(Success) -> step1(Success) -> step2(Failure) -> step3 -> postStep(Waiting): lastHasRunStep is step2.
|
||||||
|
// So its Stopped is the Started of postStep when there are no more steps to run.
|
||||||
|
var lastHasRunStep *actions_model.ActionTaskStep
|
||||||
|
|
||||||
var logIndex int64
|
var logIndex int64
|
||||||
|
for _, step := range task.Steps {
|
||||||
|
if firstStep == nil && (step.Status.HasRun() || step.Status.IsRunning()) {
|
||||||
|
firstStep = step
|
||||||
|
}
|
||||||
|
if step.Status.HasRun() {
|
||||||
|
lastHasRunStep = step
|
||||||
|
}
|
||||||
|
logIndex += step.LogLength
|
||||||
|
}
|
||||||
|
|
||||||
preStep := &actions_model.ActionTaskStep{
|
preStep := &actions_model.ActionTaskStep{
|
||||||
Name: preStepName,
|
Name: preStepName,
|
||||||
|
@ -28,32 +52,17 @@ func FullSteps(task *actions_model.ActionTask) []*actions_model.ActionTaskStep {
|
||||||
Status: actions_model.StatusRunning,
|
Status: actions_model.StatusRunning,
|
||||||
}
|
}
|
||||||
|
|
||||||
if firstStep.Status.HasRun() || firstStep.Status.IsRunning() {
|
// No step has run or is running, so preStep is equal to the task
|
||||||
|
if firstStep == nil {
|
||||||
|
preStep.Stopped = task.Stopped
|
||||||
|
preStep.Status = task.Status
|
||||||
|
} else {
|
||||||
preStep.LogLength = firstStep.LogIndex
|
preStep.LogLength = firstStep.LogIndex
|
||||||
preStep.Stopped = firstStep.Started
|
preStep.Stopped = firstStep.Started
|
||||||
preStep.Status = actions_model.StatusSuccess
|
preStep.Status = actions_model.StatusSuccess
|
||||||
} else if task.Status.IsDone() {
|
|
||||||
preStep.Stopped = task.Stopped
|
|
||||||
preStep.Status = actions_model.StatusFailure
|
|
||||||
if task.Status.IsSkipped() {
|
|
||||||
preStep.Status = actions_model.StatusSkipped
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
logIndex += preStep.LogLength
|
logIndex += preStep.LogLength
|
||||||
|
|
||||||
// lastHasRunStep is the last step that has run.
|
|
||||||
// For example,
|
|
||||||
// 1. preStep(Success) -> step1(Success) -> step2(Running) -> step3(Waiting) -> postStep(Waiting): lastHasRunStep is step1.
|
|
||||||
// 2. preStep(Success) -> step1(Success) -> step2(Success) -> step3(Success) -> postStep(Success): lastHasRunStep is step3.
|
|
||||||
// 3. preStep(Success) -> step1(Success) -> step2(Failure) -> step3 -> postStep(Waiting): lastHasRunStep is step2.
|
|
||||||
// So its Stopped is the Started of postStep when there are no more steps to run.
|
|
||||||
var lastHasRunStep *actions_model.ActionTaskStep
|
|
||||||
for _, step := range task.Steps {
|
|
||||||
if step.Status.HasRun() {
|
|
||||||
lastHasRunStep = step
|
|
||||||
}
|
|
||||||
logIndex += step.LogLength
|
|
||||||
}
|
|
||||||
if lastHasRunStep == nil {
|
if lastHasRunStep == nil {
|
||||||
lastHasRunStep = preStep
|
lastHasRunStep = preStep
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,6 +137,25 @@ func TestFullSteps(t *testing.T) {
|
||||||
{Name: postStepName, Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0},
|
{Name: postStepName, Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "first step is skipped",
|
||||||
|
task: &actions_model.ActionTask{
|
||||||
|
Steps: []*actions_model.ActionTaskStep{
|
||||||
|
{Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0},
|
||||||
|
{Status: actions_model.StatusSuccess, LogIndex: 10, LogLength: 80, Started: 10010, Stopped: 10090},
|
||||||
|
},
|
||||||
|
Status: actions_model.StatusSuccess,
|
||||||
|
Started: 10000,
|
||||||
|
Stopped: 10100,
|
||||||
|
LogLength: 100,
|
||||||
|
},
|
||||||
|
want: []*actions_model.ActionTaskStep{
|
||||||
|
{Name: preStepName, Status: actions_model.StatusSuccess, LogIndex: 0, LogLength: 10, Started: 10000, Stopped: 10010},
|
||||||
|
{Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0},
|
||||||
|
{Status: actions_model.StatusSuccess, LogIndex: 10, LogLength: 80, Started: 10010, Stopped: 10090},
|
||||||
|
{Name: postStepName, Status: actions_model.StatusSuccess, LogIndex: 90, LogLength: 10, Started: 10090, Stopped: 10100},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
|
@ -288,6 +288,8 @@ func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int
|
||||||
searchRequest.AddFacet("languages", bleve.NewFacetRequest("Language", 10))
|
searchRequest.AddFacet("languages", bleve.NewFacetRequest("Language", 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
searchRequest.SortBy([]string{"-_score", "UpdatedAt"})
|
||||||
|
|
||||||
result, err := b.inner.Indexer.SearchInContext(ctx, searchRequest)
|
result, err := b.inner.Indexer.SearchInContext(ctx, searchRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, nil, err
|
return 0, nil, nil, err
|
||||||
|
|
|
@ -318,7 +318,8 @@ func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int
|
||||||
NumOfFragments(0). // return all highting content on fragments
|
NumOfFragments(0). // return all highting content on fragments
|
||||||
HighlighterType("fvh"),
|
HighlighterType("fvh"),
|
||||||
).
|
).
|
||||||
Sort("repo_id", true).
|
Sort("_score", false).
|
||||||
|
Sort("updated_at", true).
|
||||||
From(start).Size(pageSize).
|
From(start).Size(pageSize).
|
||||||
Do(ctx)
|
Do(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -349,7 +350,8 @@ func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int
|
||||||
NumOfFragments(0). // return all highting content on fragments
|
NumOfFragments(0). // return all highting content on fragments
|
||||||
HighlighterType("fvh"),
|
HighlighterType("fvh"),
|
||||||
).
|
).
|
||||||
Sort("repo_id", true).
|
Sort("_score", false).
|
||||||
|
Sort("updated_at", true).
|
||||||
From(start).Size(pageSize).
|
From(start).Size(pageSize).
|
||||||
Do(ctx)
|
Do(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
416
package-lock.json
generated
416
package-lock.json
generated
|
@ -10,7 +10,7 @@
|
||||||
"@citation-js/plugin-software-formats": "0.6.1",
|
"@citation-js/plugin-software-formats": "0.6.1",
|
||||||
"@github/markdown-toolbar-element": "2.2.3",
|
"@github/markdown-toolbar-element": "2.2.3",
|
||||||
"@github/relative-time-element": "4.4.3",
|
"@github/relative-time-element": "4.4.3",
|
||||||
"@github/text-expander-element": "2.7.1",
|
"@github/text-expander-element": "2.7.2",
|
||||||
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
|
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
|
||||||
"@primer/octicons": "19.9.0",
|
"@primer/octicons": "19.9.0",
|
||||||
"ansi_up": "6.0.2",
|
"ansi_up": "6.0.2",
|
||||||
|
@ -78,7 +78,7 @@
|
||||||
"eslint-plugin-no-use-extend-native": "0.5.0",
|
"eslint-plugin-no-use-extend-native": "0.5.0",
|
||||||
"eslint-plugin-playwright": "1.6.2",
|
"eslint-plugin-playwright": "1.6.2",
|
||||||
"eslint-plugin-regexp": "2.6.0",
|
"eslint-plugin-regexp": "2.6.0",
|
||||||
"eslint-plugin-sonarjs": "2.0.2",
|
"eslint-plugin-sonarjs": "2.0.3",
|
||||||
"eslint-plugin-unicorn": "55.0.0",
|
"eslint-plugin-unicorn": "55.0.0",
|
||||||
"eslint-plugin-vitest-globals": "1.5.0",
|
"eslint-plugin-vitest-globals": "1.5.0",
|
||||||
"eslint-plugin-vue": "9.28.0",
|
"eslint-plugin-vue": "9.28.0",
|
||||||
|
@ -195,22 +195,22 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/core": {
|
"node_modules/@babel/core": {
|
||||||
"version": "7.24.3",
|
"version": "7.25.2",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz",
|
||||||
"integrity": "sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==",
|
"integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ampproject/remapping": "^2.2.0",
|
"@ampproject/remapping": "^2.2.0",
|
||||||
"@babel/code-frame": "^7.24.2",
|
"@babel/code-frame": "^7.24.7",
|
||||||
"@babel/generator": "^7.24.1",
|
"@babel/generator": "^7.25.0",
|
||||||
"@babel/helper-compilation-targets": "^7.23.6",
|
"@babel/helper-compilation-targets": "^7.25.2",
|
||||||
"@babel/helper-module-transforms": "^7.23.3",
|
"@babel/helper-module-transforms": "^7.25.2",
|
||||||
"@babel/helpers": "^7.24.1",
|
"@babel/helpers": "^7.25.0",
|
||||||
"@babel/parser": "^7.24.1",
|
"@babel/parser": "^7.25.0",
|
||||||
"@babel/template": "^7.24.0",
|
"@babel/template": "^7.25.0",
|
||||||
"@babel/traverse": "^7.24.1",
|
"@babel/traverse": "^7.25.2",
|
||||||
"@babel/types": "^7.24.0",
|
"@babel/types": "^7.25.2",
|
||||||
"convert-source-map": "^2.0.0",
|
"convert-source-map": "^2.0.0",
|
||||||
"debug": "^4.1.0",
|
"debug": "^4.1.0",
|
||||||
"gensync": "^1.0.0-beta.2",
|
"gensync": "^1.0.0-beta.2",
|
||||||
|
@ -236,9 +236,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/eslint-parser": {
|
"node_modules/@babel/eslint-parser": {
|
||||||
"version": "7.24.1",
|
"version": "7.25.1",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.24.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.1.tgz",
|
||||||
"integrity": "sha512-d5guuzMlPeDfZIbpQ8+g1NaCNuAGBBGNECh0HVqz1sjOeVLh2CEaifuOysCH18URW6R7pqXINvf5PaR/dC6jLQ==",
|
"integrity": "sha512-Y956ghgTT4j7rKesabkh5WeqgSFZVFwaPR0IWFm7KFHFmmJ4afbG49SmfW4S+GyRPx0Dy5jxEWA5t0rpxfElWg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -251,7 +251,7 @@
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@babel/core": "^7.11.0",
|
"@babel/core": "^7.11.0",
|
||||||
"eslint": "^7.5.0 || ^8.0.0"
|
"eslint": "^7.5.0 || ^8.0.0 || ^9.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": {
|
"node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": {
|
||||||
|
@ -713,6 +713,39 @@
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": {
|
||||||
|
"version": "7.25.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz",
|
||||||
|
"integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-plugin-utils": "^7.24.8",
|
||||||
|
"@babel/traverse": "^7.25.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/core": "^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": {
|
||||||
|
"version": "7.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz",
|
||||||
|
"integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-plugin-utils": "^7.24.8"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/core": "^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
|
"node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
|
||||||
"version": "7.25.0",
|
"version": "7.25.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz",
|
||||||
|
@ -765,15 +798,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/plugin-proposal-decorators": {
|
"node_modules/@babel/plugin-proposal-decorators": {
|
||||||
"version": "7.24.1",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.24.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.24.7.tgz",
|
||||||
"integrity": "sha512-zPEvzFijn+hRvJuX2Vu3KbEBN39LN3f7tW3MQO2LsIs57B26KU+kUc82BdAktS1VCM6libzh45eKGI65lg0cpA==",
|
"integrity": "sha512-RL9GR0pUG5Kc8BUWLNDm2T5OpYwSX15r98I0IkgmRQTXuELq/OynH8xtMTMvTJFjXbMWFVTKtYkTaYQsuAwQlQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-create-class-features-plugin": "^7.24.1",
|
"@babel/helper-create-class-features-plugin": "^7.24.7",
|
||||||
"@babel/helper-plugin-utils": "^7.24.0",
|
"@babel/helper-plugin-utils": "^7.24.7",
|
||||||
"@babel/plugin-syntax-decorators": "^7.24.1"
|
"@babel/plugin-syntax-decorators": "^7.24.7"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
|
@ -1313,6 +1346,23 @@
|
||||||
"@babel/core": "^7.0.0-0"
|
"@babel/core": "^7.0.0-0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": {
|
||||||
|
"version": "7.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz",
|
||||||
|
"integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-create-regexp-features-plugin": "^7.25.0",
|
||||||
|
"@babel/helper-plugin-utils": "^7.24.8"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/core": "^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@babel/plugin-transform-dynamic-import": {
|
"node_modules/@babel/plugin-transform-dynamic-import": {
|
||||||
"version": "7.24.7",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz",
|
||||||
|
@ -2010,27 +2060,29 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/preset-env": {
|
"node_modules/@babel/preset-env": {
|
||||||
"version": "7.24.3",
|
"version": "7.25.4",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.4.tgz",
|
||||||
"integrity": "sha512-fSk430k5c2ff8536JcPvPWK4tZDwehWLGlBp0wrsBUjZVdeQV6lePbwKWZaZfK2vnh/1kQX1PzAJWsnBmVgGJA==",
|
"integrity": "sha512-W9Gyo+KmcxjGahtt3t9fb14vFRWvPpu5pT6GBlovAK6BTBcxgjfVMSQCfJl4oi35ODrxP6xx2Wr8LNST57Mraw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/compat-data": "^7.24.1",
|
"@babel/compat-data": "^7.25.4",
|
||||||
"@babel/helper-compilation-targets": "^7.23.6",
|
"@babel/helper-compilation-targets": "^7.25.2",
|
||||||
"@babel/helper-plugin-utils": "^7.24.0",
|
"@babel/helper-plugin-utils": "^7.24.8",
|
||||||
"@babel/helper-validator-option": "^7.23.5",
|
"@babel/helper-validator-option": "^7.24.8",
|
||||||
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.1",
|
"@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.3",
|
||||||
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.1",
|
"@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0",
|
||||||
"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.1",
|
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0",
|
||||||
|
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7",
|
||||||
|
"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0",
|
||||||
"@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
|
"@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
|
||||||
"@babel/plugin-syntax-async-generators": "^7.8.4",
|
"@babel/plugin-syntax-async-generators": "^7.8.4",
|
||||||
"@babel/plugin-syntax-class-properties": "^7.12.13",
|
"@babel/plugin-syntax-class-properties": "^7.12.13",
|
||||||
"@babel/plugin-syntax-class-static-block": "^7.14.5",
|
"@babel/plugin-syntax-class-static-block": "^7.14.5",
|
||||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||||
"@babel/plugin-syntax-export-namespace-from": "^7.8.3",
|
"@babel/plugin-syntax-export-namespace-from": "^7.8.3",
|
||||||
"@babel/plugin-syntax-import-assertions": "^7.24.1",
|
"@babel/plugin-syntax-import-assertions": "^7.24.7",
|
||||||
"@babel/plugin-syntax-import-attributes": "^7.24.1",
|
"@babel/plugin-syntax-import-attributes": "^7.24.7",
|
||||||
"@babel/plugin-syntax-import-meta": "^7.10.4",
|
"@babel/plugin-syntax-import-meta": "^7.10.4",
|
||||||
"@babel/plugin-syntax-json-strings": "^7.8.3",
|
"@babel/plugin-syntax-json-strings": "^7.8.3",
|
||||||
"@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
|
"@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
|
||||||
|
@ -2042,59 +2094,60 @@
|
||||||
"@babel/plugin-syntax-private-property-in-object": "^7.14.5",
|
"@babel/plugin-syntax-private-property-in-object": "^7.14.5",
|
||||||
"@babel/plugin-syntax-top-level-await": "^7.14.5",
|
"@babel/plugin-syntax-top-level-await": "^7.14.5",
|
||||||
"@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
|
"@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
|
||||||
"@babel/plugin-transform-arrow-functions": "^7.24.1",
|
"@babel/plugin-transform-arrow-functions": "^7.24.7",
|
||||||
"@babel/plugin-transform-async-generator-functions": "^7.24.3",
|
"@babel/plugin-transform-async-generator-functions": "^7.25.4",
|
||||||
"@babel/plugin-transform-async-to-generator": "^7.24.1",
|
"@babel/plugin-transform-async-to-generator": "^7.24.7",
|
||||||
"@babel/plugin-transform-block-scoped-functions": "^7.24.1",
|
"@babel/plugin-transform-block-scoped-functions": "^7.24.7",
|
||||||
"@babel/plugin-transform-block-scoping": "^7.24.1",
|
"@babel/plugin-transform-block-scoping": "^7.25.0",
|
||||||
"@babel/plugin-transform-class-properties": "^7.24.1",
|
"@babel/plugin-transform-class-properties": "^7.25.4",
|
||||||
"@babel/plugin-transform-class-static-block": "^7.24.1",
|
"@babel/plugin-transform-class-static-block": "^7.24.7",
|
||||||
"@babel/plugin-transform-classes": "^7.24.1",
|
"@babel/plugin-transform-classes": "^7.25.4",
|
||||||
"@babel/plugin-transform-computed-properties": "^7.24.1",
|
"@babel/plugin-transform-computed-properties": "^7.24.7",
|
||||||
"@babel/plugin-transform-destructuring": "^7.24.1",
|
"@babel/plugin-transform-destructuring": "^7.24.8",
|
||||||
"@babel/plugin-transform-dotall-regex": "^7.24.1",
|
"@babel/plugin-transform-dotall-regex": "^7.24.7",
|
||||||
"@babel/plugin-transform-duplicate-keys": "^7.24.1",
|
"@babel/plugin-transform-duplicate-keys": "^7.24.7",
|
||||||
"@babel/plugin-transform-dynamic-import": "^7.24.1",
|
"@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0",
|
||||||
"@babel/plugin-transform-exponentiation-operator": "^7.24.1",
|
"@babel/plugin-transform-dynamic-import": "^7.24.7",
|
||||||
"@babel/plugin-transform-export-namespace-from": "^7.24.1",
|
"@babel/plugin-transform-exponentiation-operator": "^7.24.7",
|
||||||
"@babel/plugin-transform-for-of": "^7.24.1",
|
"@babel/plugin-transform-export-namespace-from": "^7.24.7",
|
||||||
"@babel/plugin-transform-function-name": "^7.24.1",
|
"@babel/plugin-transform-for-of": "^7.24.7",
|
||||||
"@babel/plugin-transform-json-strings": "^7.24.1",
|
"@babel/plugin-transform-function-name": "^7.25.1",
|
||||||
"@babel/plugin-transform-literals": "^7.24.1",
|
"@babel/plugin-transform-json-strings": "^7.24.7",
|
||||||
"@babel/plugin-transform-logical-assignment-operators": "^7.24.1",
|
"@babel/plugin-transform-literals": "^7.25.2",
|
||||||
"@babel/plugin-transform-member-expression-literals": "^7.24.1",
|
"@babel/plugin-transform-logical-assignment-operators": "^7.24.7",
|
||||||
"@babel/plugin-transform-modules-amd": "^7.24.1",
|
"@babel/plugin-transform-member-expression-literals": "^7.24.7",
|
||||||
"@babel/plugin-transform-modules-commonjs": "^7.24.1",
|
"@babel/plugin-transform-modules-amd": "^7.24.7",
|
||||||
"@babel/plugin-transform-modules-systemjs": "^7.24.1",
|
"@babel/plugin-transform-modules-commonjs": "^7.24.8",
|
||||||
"@babel/plugin-transform-modules-umd": "^7.24.1",
|
"@babel/plugin-transform-modules-systemjs": "^7.25.0",
|
||||||
"@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5",
|
"@babel/plugin-transform-modules-umd": "^7.24.7",
|
||||||
"@babel/plugin-transform-new-target": "^7.24.1",
|
"@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7",
|
||||||
"@babel/plugin-transform-nullish-coalescing-operator": "^7.24.1",
|
"@babel/plugin-transform-new-target": "^7.24.7",
|
||||||
"@babel/plugin-transform-numeric-separator": "^7.24.1",
|
"@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7",
|
||||||
"@babel/plugin-transform-object-rest-spread": "^7.24.1",
|
"@babel/plugin-transform-numeric-separator": "^7.24.7",
|
||||||
"@babel/plugin-transform-object-super": "^7.24.1",
|
"@babel/plugin-transform-object-rest-spread": "^7.24.7",
|
||||||
"@babel/plugin-transform-optional-catch-binding": "^7.24.1",
|
"@babel/plugin-transform-object-super": "^7.24.7",
|
||||||
"@babel/plugin-transform-optional-chaining": "^7.24.1",
|
"@babel/plugin-transform-optional-catch-binding": "^7.24.7",
|
||||||
"@babel/plugin-transform-parameters": "^7.24.1",
|
"@babel/plugin-transform-optional-chaining": "^7.24.8",
|
||||||
"@babel/plugin-transform-private-methods": "^7.24.1",
|
"@babel/plugin-transform-parameters": "^7.24.7",
|
||||||
"@babel/plugin-transform-private-property-in-object": "^7.24.1",
|
"@babel/plugin-transform-private-methods": "^7.25.4",
|
||||||
"@babel/plugin-transform-property-literals": "^7.24.1",
|
"@babel/plugin-transform-private-property-in-object": "^7.24.7",
|
||||||
"@babel/plugin-transform-regenerator": "^7.24.1",
|
"@babel/plugin-transform-property-literals": "^7.24.7",
|
||||||
"@babel/plugin-transform-reserved-words": "^7.24.1",
|
"@babel/plugin-transform-regenerator": "^7.24.7",
|
||||||
"@babel/plugin-transform-shorthand-properties": "^7.24.1",
|
"@babel/plugin-transform-reserved-words": "^7.24.7",
|
||||||
"@babel/plugin-transform-spread": "^7.24.1",
|
"@babel/plugin-transform-shorthand-properties": "^7.24.7",
|
||||||
"@babel/plugin-transform-sticky-regex": "^7.24.1",
|
"@babel/plugin-transform-spread": "^7.24.7",
|
||||||
"@babel/plugin-transform-template-literals": "^7.24.1",
|
"@babel/plugin-transform-sticky-regex": "^7.24.7",
|
||||||
"@babel/plugin-transform-typeof-symbol": "^7.24.1",
|
"@babel/plugin-transform-template-literals": "^7.24.7",
|
||||||
"@babel/plugin-transform-unicode-escapes": "^7.24.1",
|
"@babel/plugin-transform-typeof-symbol": "^7.24.8",
|
||||||
"@babel/plugin-transform-unicode-property-regex": "^7.24.1",
|
"@babel/plugin-transform-unicode-escapes": "^7.24.7",
|
||||||
"@babel/plugin-transform-unicode-regex": "^7.24.1",
|
"@babel/plugin-transform-unicode-property-regex": "^7.24.7",
|
||||||
"@babel/plugin-transform-unicode-sets-regex": "^7.24.1",
|
"@babel/plugin-transform-unicode-regex": "^7.24.7",
|
||||||
|
"@babel/plugin-transform-unicode-sets-regex": "^7.25.4",
|
||||||
"@babel/preset-modules": "0.1.6-no-external-plugins",
|
"@babel/preset-modules": "0.1.6-no-external-plugins",
|
||||||
"babel-plugin-polyfill-corejs2": "^0.4.10",
|
"babel-plugin-polyfill-corejs2": "^0.4.10",
|
||||||
"babel-plugin-polyfill-corejs3": "^0.10.4",
|
"babel-plugin-polyfill-corejs3": "^0.10.6",
|
||||||
"babel-plugin-polyfill-regenerator": "^0.6.1",
|
"babel-plugin-polyfill-regenerator": "^0.6.1",
|
||||||
"core-js-compat": "^3.31.0",
|
"core-js-compat": "^3.37.1",
|
||||||
"semver": "^6.3.1"
|
"semver": "^6.3.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -2115,15 +2168,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/preset-flow": {
|
"node_modules/@babel/preset-flow": {
|
||||||
"version": "7.24.1",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.24.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.24.7.tgz",
|
||||||
"integrity": "sha512-sWCV2G9pcqZf+JHyv/RyqEIpFypxdCSxWIxQjpdaQxenNog7cN1pr76hg8u0Fz8Qgg0H4ETkGcJnXL8d4j0PPA==",
|
"integrity": "sha512-NL3Lo0NorCU607zU3NwRyJbpaB6E3t0xtd3LfAQKDfkeX4/ggcDXvkmkW42QWT5owUeW/jAe4hn+2qvkV1IbfQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.24.0",
|
"@babel/helper-plugin-utils": "^7.24.7",
|
||||||
"@babel/helper-validator-option": "^7.23.5",
|
"@babel/helper-validator-option": "^7.24.7",
|
||||||
"@babel/plugin-transform-flow-strip-types": "^7.24.1"
|
"@babel/plugin-transform-flow-strip-types": "^7.24.7"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
|
@ -2148,18 +2201,18 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/preset-react": {
|
"node_modules/@babel/preset-react": {
|
||||||
"version": "7.24.1",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz",
|
||||||
"integrity": "sha512-eFa8up2/8cZXLIpkafhaADTXSnl7IsUFCYenRWrARBz0/qZwcT0RBXpys0LJU4+WfPoF2ZG6ew6s2V6izMCwRA==",
|
"integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.24.0",
|
"@babel/helper-plugin-utils": "^7.24.7",
|
||||||
"@babel/helper-validator-option": "^7.23.5",
|
"@babel/helper-validator-option": "^7.24.7",
|
||||||
"@babel/plugin-transform-react-display-name": "^7.24.1",
|
"@babel/plugin-transform-react-display-name": "^7.24.7",
|
||||||
"@babel/plugin-transform-react-jsx": "^7.23.4",
|
"@babel/plugin-transform-react-jsx": "^7.24.7",
|
||||||
"@babel/plugin-transform-react-jsx-development": "^7.22.5",
|
"@babel/plugin-transform-react-jsx-development": "^7.24.7",
|
||||||
"@babel/plugin-transform-react-pure-annotations": "^7.24.1"
|
"@babel/plugin-transform-react-pure-annotations": "^7.24.7"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
|
@ -2976,9 +3029,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint-community/regexpp": {
|
"node_modules/@eslint-community/regexpp": {
|
||||||
"version": "4.10.0",
|
"version": "4.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz",
|
||||||
"integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
|
"integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -3124,13 +3177,13 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@github/text-expander-element": {
|
"node_modules/@github/text-expander-element": {
|
||||||
"version": "2.7.1",
|
"version": "2.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/@github/text-expander-element/-/text-expander-element-2.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/@github/text-expander-element/-/text-expander-element-2.7.2.tgz",
|
||||||
"integrity": "sha512-CWxfYxJRkeWVCUhJveproLs6pHsPrWtK8TsjL8ByYVcSCs8CJmNzF8b7ZawrUgfai0F2jb4aIdw2FoBTykj9XA==",
|
"integrity": "sha512-eTIOUQKoBxe+e0yHKHQHoo4x61Erb7m0lhi2vMRHZS7TwI6OCGSj/3YydAr3obbQbZjevF9wPihLf1wADu3A9g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@github/combobox-nav": "^2.0.2",
|
"@github/combobox-nav": "^2.0.2",
|
||||||
"dom-input-range": "^1.1.6"
|
"dom-input-range": "^1.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@humanwhocodes/config-array": {
|
"node_modules/@humanwhocodes/config-array": {
|
||||||
|
@ -8560,9 +8613,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-react-hooks": {
|
"node_modules/eslint-plugin-react-hooks": {
|
||||||
"version": "4.6.0",
|
"version": "4.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz",
|
||||||
"integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
|
"integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -8660,33 +8713,33 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-sonarjs": {
|
"node_modules/eslint-plugin-sonarjs": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-2.0.3.tgz",
|
||||||
"integrity": "sha512-0JUYTlUDk/up3mS0rFP9vHCRvhIYNTy06m99IPFeyMDUWL8u0ebz+nFPYn6OWDBTIEfbvQ/Xe0PdjWO8w0WD0Q==",
|
"integrity": "sha512-Xsy+x5xNxc/h+M/B2s8XMPoKw0o4gUL0cqT8gl6SiEtA6qKX6/SlOjj4Avp7bT7UIguHbjKv/RACy3AxIGOvwA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "LGPL-3.0-only",
|
"license": "LGPL-3.0-only",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "7.24.3",
|
"@babel/core": "7.25.2",
|
||||||
"@babel/eslint-parser": "7.24.1",
|
"@babel/eslint-parser": "7.25.1",
|
||||||
"@babel/plugin-proposal-decorators": "7.24.1",
|
"@babel/plugin-proposal-decorators": "7.24.7",
|
||||||
"@babel/preset-env": "7.24.3",
|
"@babel/preset-env": "7.25.4",
|
||||||
"@babel/preset-flow": "7.24.1",
|
"@babel/preset-flow": "7.24.7",
|
||||||
"@babel/preset-react": "7.24.1",
|
"@babel/preset-react": "7.24.7",
|
||||||
"@eslint-community/regexpp": "4.10.0",
|
"@eslint-community/regexpp": "4.11.1",
|
||||||
"@typescript-eslint/eslint-plugin": "7.16.1",
|
"@typescript-eslint/eslint-plugin": "7.16.1",
|
||||||
"@typescript-eslint/utils": "^7.16.1",
|
"@typescript-eslint/utils": "^7.16.1",
|
||||||
"builtin-modules": "3.3.0",
|
"builtin-modules": "3.3.0",
|
||||||
"bytes": "3.1.2",
|
"bytes": "3.1.2",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.30.0",
|
||||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
"eslint-plugin-jsx-a11y": "^6.10.0",
|
||||||
"eslint-plugin-react": "^7.35.0",
|
"eslint-plugin-react": "^7.36.1",
|
||||||
"eslint-plugin-react-hooks": "4.6.0",
|
"eslint-plugin-react-hooks": "4.6.2",
|
||||||
"eslint-scope": "8.0.1",
|
"eslint-scope": "8.0.2",
|
||||||
"functional-red-black-tree": "1.0.1",
|
"functional-red-black-tree": "1.0.1",
|
||||||
"jsx-ast-utils": "^3.3.5",
|
"jsx-ast-utils": "^3.3.5",
|
||||||
"minimatch": "^9.0.3",
|
"minimatch": "^10.0.1",
|
||||||
"scslre": "0.3.0",
|
"scslre": "0.3.0",
|
||||||
"semver": "7.6.0",
|
"semver": "7.6.3",
|
||||||
"typescript": "*",
|
"typescript": "*",
|
||||||
"vue-eslint-parser": "9.4.3"
|
"vue-eslint-parser": "9.4.3"
|
||||||
},
|
},
|
||||||
|
@ -8899,6 +8952,22 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/type-utils/node_modules/minimatch": {
|
||||||
|
"version": "9.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
||||||
|
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"brace-expansion": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16 || 14 >=14.17"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/types": {
|
"node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/types": {
|
||||||
"version": "7.18.0",
|
"version": "7.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz",
|
||||||
|
@ -8963,6 +9032,23 @@
|
||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
|
||||||
|
"version": "9.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
||||||
|
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"brace-expansion": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16 || 14 >=14.17"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/utils": {
|
"node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/utils": {
|
||||||
"version": "7.16.1",
|
"version": "7.16.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.1.tgz",
|
||||||
|
@ -9029,6 +9115,22 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/utils/node_modules/minimatch": {
|
||||||
|
"version": "9.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
||||||
|
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"brace-expansion": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16 || 14 >=14.17"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/visitor-keys": {
|
"node_modules/eslint-plugin-sonarjs/node_modules/@typescript-eslint/visitor-keys": {
|
||||||
"version": "7.16.1",
|
"version": "7.16.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.1.tgz",
|
||||||
|
@ -9062,9 +9164,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-sonarjs/node_modules/eslint-scope": {
|
"node_modules/eslint-plugin-sonarjs/node_modules/eslint-scope": {
|
||||||
"version": "8.0.1",
|
"version": "8.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz",
|
||||||
"integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==",
|
"integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -9091,58 +9193,6 @@
|
||||||
"url": "https://opencollective.com/eslint"
|
"url": "https://opencollective.com/eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-sonarjs/node_modules/lru-cache": {
|
|
||||||
"version": "6.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
|
||||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"yallist": "^4.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/eslint-plugin-sonarjs/node_modules/minimatch": {
|
|
||||||
"version": "9.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
|
||||||
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"brace-expansion": "^2.0.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=16 || 14 >=14.17"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/isaacs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/eslint-plugin-sonarjs/node_modules/semver": {
|
|
||||||
"version": "7.6.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
|
|
||||||
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"lru-cache": "^6.0.0"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"semver": "bin/semver.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/eslint-plugin-sonarjs/node_modules/yallist": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "ISC"
|
|
||||||
},
|
|
||||||
"node_modules/eslint-plugin-unicorn": {
|
"node_modules/eslint-plugin-unicorn": {
|
||||||
"version": "55.0.0",
|
"version": "55.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-55.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-55.0.0.tgz",
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
"@citation-js/plugin-software-formats": "0.6.1",
|
"@citation-js/plugin-software-formats": "0.6.1",
|
||||||
"@github/markdown-toolbar-element": "2.2.3",
|
"@github/markdown-toolbar-element": "2.2.3",
|
||||||
"@github/relative-time-element": "4.4.3",
|
"@github/relative-time-element": "4.4.3",
|
||||||
"@github/text-expander-element": "2.7.1",
|
"@github/text-expander-element": "2.7.2",
|
||||||
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
|
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
|
||||||
"@primer/octicons": "19.9.0",
|
"@primer/octicons": "19.9.0",
|
||||||
"ansi_up": "6.0.2",
|
"ansi_up": "6.0.2",
|
||||||
|
@ -77,7 +77,7 @@
|
||||||
"eslint-plugin-no-use-extend-native": "0.5.0",
|
"eslint-plugin-no-use-extend-native": "0.5.0",
|
||||||
"eslint-plugin-playwright": "1.6.2",
|
"eslint-plugin-playwright": "1.6.2",
|
||||||
"eslint-plugin-regexp": "2.6.0",
|
"eslint-plugin-regexp": "2.6.0",
|
||||||
"eslint-plugin-sonarjs": "2.0.2",
|
"eslint-plugin-sonarjs": "2.0.3",
|
||||||
"eslint-plugin-unicorn": "55.0.0",
|
"eslint-plugin-unicorn": "55.0.0",
|
||||||
"eslint-plugin-vitest-globals": "1.5.0",
|
"eslint-plugin-vitest-globals": "1.5.0",
|
||||||
"eslint-plugin-vue": "9.28.0",
|
"eslint-plugin-vue": "9.28.0",
|
||||||
|
|
3
release-notes/5416.md
Normal file
3
release-notes/5416.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
feat: [commit](https://codeberg.org/forgejo/forgejo/commit/8178d6eaba64d05799fd3b62fa889bd13bee07c7) Code search results when using the bleve indexer are sorted by relevance.
|
||||||
|
fix: [commit](https://codeberg.org/forgejo/forgejo/commit/b496317b5a2aea970bc94ccf6fcde35cd417ec20) After migrating a repository that contains merged pull requests, the branch is missing and cannot be deleted.
|
||||||
|
fix: [commit](https://codeberg.org/forgejo/forgejo/commit/a226064711899da07d6b1455a68ef758f2f3e7e0) Forgejo Actions artifact v4 upload above 8MB.
|
|
@ -123,6 +123,54 @@ func listChunksByRunID(st storage.ObjectStorage, runID int64) (map[int64][]*chun
|
||||||
return chunksMap, nil
|
return chunksMap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func listChunksByRunIDV4(st storage.ObjectStorage, runID, artifactID int64, blist *BlockList) ([]*chunkFileItem, error) {
|
||||||
|
storageDir := fmt.Sprintf("tmpv4%d", runID)
|
||||||
|
var chunks []*chunkFileItem
|
||||||
|
chunkMap := map[string]*chunkFileItem{}
|
||||||
|
dummy := &chunkFileItem{}
|
||||||
|
for _, name := range blist.Latest {
|
||||||
|
chunkMap[name] = dummy
|
||||||
|
}
|
||||||
|
if err := st.IterateObjects(storageDir, func(fpath string, obj storage.Object) error {
|
||||||
|
baseName := filepath.Base(fpath)
|
||||||
|
if !strings.HasPrefix(baseName, "block-") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// when read chunks from storage, it only contains storage dir and basename,
|
||||||
|
// no matter the subdirectory setting in storage config
|
||||||
|
item := chunkFileItem{Path: storageDir + "/" + baseName, ArtifactID: artifactID}
|
||||||
|
var size int64
|
||||||
|
var b64chunkName string
|
||||||
|
if _, err := fmt.Sscanf(baseName, "block-%d-%d-%s", &item.RunID, &size, &b64chunkName); err != nil {
|
||||||
|
return fmt.Errorf("parse content range error: %v", err)
|
||||||
|
}
|
||||||
|
rchunkName, err := base64.URLEncoding.DecodeString(b64chunkName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to parse chunkName: %v", err)
|
||||||
|
}
|
||||||
|
chunkName := string(rchunkName)
|
||||||
|
item.End = item.Start + size - 1
|
||||||
|
if _, ok := chunkMap[chunkName]; ok {
|
||||||
|
chunkMap[chunkName] = &item
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for i, name := range blist.Latest {
|
||||||
|
chunk, ok := chunkMap[name]
|
||||||
|
if !ok || chunk.Path == "" {
|
||||||
|
return nil, fmt.Errorf("missing Chunk (%d/%d): %s", i, len(blist.Latest), name)
|
||||||
|
}
|
||||||
|
chunks = append(chunks, chunk)
|
||||||
|
if i > 0 {
|
||||||
|
chunk.Start = chunkMap[blist.Latest[i-1]].End + 1
|
||||||
|
chunk.End += chunk.Start
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return chunks, nil
|
||||||
|
}
|
||||||
|
|
||||||
func mergeChunksForRun(ctx *ArtifactContext, st storage.ObjectStorage, runID int64, artifactName string) error {
|
func mergeChunksForRun(ctx *ArtifactContext, st storage.ObjectStorage, runID int64, artifactName string) error {
|
||||||
// read all db artifacts by name
|
// read all db artifacts by name
|
||||||
artifacts, err := db.Find[actions.ActionArtifact](ctx, actions.FindArtifactsOptions{
|
artifacts, err := db.Find[actions.ActionArtifact](ctx, actions.FindArtifactsOptions{
|
||||||
|
@ -230,7 +278,7 @@ func mergeChunksForArtifact(ctx *ArtifactContext, chunks []*chunkFileItem, st st
|
||||||
rawChecksum := hash.Sum(nil)
|
rawChecksum := hash.Sum(nil)
|
||||||
actualChecksum := hex.EncodeToString(rawChecksum)
|
actualChecksum := hex.EncodeToString(rawChecksum)
|
||||||
if !strings.HasSuffix(checksum, actualChecksum) {
|
if !strings.HasSuffix(checksum, actualChecksum) {
|
||||||
return fmt.Errorf("update artifact error checksum is invalid")
|
return fmt.Errorf("update artifact error checksum is invalid %v vs %v", checksum, actualChecksum)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,15 @@ package actions
|
||||||
// PUT: http://localhost:3000/twirp/github.actions.results.api.v1.ArtifactService/UploadArtifact?sig=mO7y35r4GyjN7fwg0DTv3-Fv1NDXD84KLEgLpoPOtDI=&expires=2024-01-23+21%3A48%3A37.20833956+%2B0100+CET&artifactName=test&taskID=75&comp=block
|
// PUT: http://localhost:3000/twirp/github.actions.results.api.v1.ArtifactService/UploadArtifact?sig=mO7y35r4GyjN7fwg0DTv3-Fv1NDXD84KLEgLpoPOtDI=&expires=2024-01-23+21%3A48%3A37.20833956+%2B0100+CET&artifactName=test&taskID=75&comp=block
|
||||||
// 1.3. Continue Upload Zip Content to Blobstorage (unauthenticated request), repeat until everything is uploaded
|
// 1.3. Continue Upload Zip Content to Blobstorage (unauthenticated request), repeat until everything is uploaded
|
||||||
// PUT: http://localhost:3000/twirp/github.actions.results.api.v1.ArtifactService/UploadArtifact?sig=mO7y35r4GyjN7fwg0DTv3-Fv1NDXD84KLEgLpoPOtDI=&expires=2024-01-23+21%3A48%3A37.20833956+%2B0100+CET&artifactName=test&taskID=75&comp=appendBlock
|
// PUT: http://localhost:3000/twirp/github.actions.results.api.v1.ArtifactService/UploadArtifact?sig=mO7y35r4GyjN7fwg0DTv3-Fv1NDXD84KLEgLpoPOtDI=&expires=2024-01-23+21%3A48%3A37.20833956+%2B0100+CET&artifactName=test&taskID=75&comp=appendBlock
|
||||||
// 1.4. Unknown xml payload to Blobstorage (unauthenticated request), ignored for now
|
// 1.4. BlockList xml payload to Blobstorage (unauthenticated request)
|
||||||
|
// Files of about 800MB are parallel in parallel and / or out of order, this file is needed to enshure the correct order
|
||||||
// PUT: http://localhost:3000/twirp/github.actions.results.api.v1.ArtifactService/UploadArtifact?sig=mO7y35r4GyjN7fwg0DTv3-Fv1NDXD84KLEgLpoPOtDI=&expires=2024-01-23+21%3A48%3A37.20833956+%2B0100+CET&artifactName=test&taskID=75&comp=blockList
|
// PUT: http://localhost:3000/twirp/github.actions.results.api.v1.ArtifactService/UploadArtifact?sig=mO7y35r4GyjN7fwg0DTv3-Fv1NDXD84KLEgLpoPOtDI=&expires=2024-01-23+21%3A48%3A37.20833956+%2B0100+CET&artifactName=test&taskID=75&comp=blockList
|
||||||
|
// Request
|
||||||
|
// <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
// <BlockList>
|
||||||
|
// <Latest>blockId1</Latest>
|
||||||
|
// <Latest>blockId2</Latest>
|
||||||
|
// </BlockList>
|
||||||
// 1.5. FinalizeArtifact
|
// 1.5. FinalizeArtifact
|
||||||
// Post: /twirp/github.actions.results.api.v1.ArtifactService/FinalizeArtifact
|
// Post: /twirp/github.actions.results.api.v1.ArtifactService/FinalizeArtifact
|
||||||
// Request
|
// Request
|
||||||
|
@ -82,6 +89,7 @@ import (
|
||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -153,31 +161,34 @@ func ArtifactsV4Routes(prefix string) *web.Route {
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r artifactV4Routes) buildSignature(endp, expires, artifactName string, taskID int64) []byte {
|
func (r artifactV4Routes) buildSignature(endp, expires, artifactName string, taskID, artifactID int64) []byte {
|
||||||
mac := hmac.New(sha256.New, setting.GetGeneralTokenSigningSecret())
|
mac := hmac.New(sha256.New, setting.GetGeneralTokenSigningSecret())
|
||||||
mac.Write([]byte(endp))
|
mac.Write([]byte(endp))
|
||||||
mac.Write([]byte(expires))
|
mac.Write([]byte(expires))
|
||||||
mac.Write([]byte(artifactName))
|
mac.Write([]byte(artifactName))
|
||||||
mac.Write([]byte(fmt.Sprint(taskID)))
|
mac.Write([]byte(fmt.Sprint(taskID)))
|
||||||
|
mac.Write([]byte(fmt.Sprint(artifactID)))
|
||||||
return mac.Sum(nil)
|
return mac.Sum(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r artifactV4Routes) buildArtifactURL(endp, artifactName string, taskID int64) string {
|
func (r artifactV4Routes) buildArtifactURL(endp, artifactName string, taskID, artifactID int64) string {
|
||||||
expires := time.Now().Add(60 * time.Minute).Format("2006-01-02 15:04:05.999999999 -0700 MST")
|
expires := time.Now().Add(60 * time.Minute).Format("2006-01-02 15:04:05.999999999 -0700 MST")
|
||||||
uploadURL := strings.TrimSuffix(setting.AppURL, "/") + strings.TrimSuffix(r.prefix, "/") +
|
uploadURL := strings.TrimSuffix(setting.AppURL, "/") + strings.TrimSuffix(r.prefix, "/") +
|
||||||
"/" + endp + "?sig=" + base64.URLEncoding.EncodeToString(r.buildSignature(endp, expires, artifactName, taskID)) + "&expires=" + url.QueryEscape(expires) + "&artifactName=" + url.QueryEscape(artifactName) + "&taskID=" + fmt.Sprint(taskID)
|
"/" + endp + "?sig=" + base64.URLEncoding.EncodeToString(r.buildSignature(endp, expires, artifactName, taskID, artifactID)) + "&expires=" + url.QueryEscape(expires) + "&artifactName=" + url.QueryEscape(artifactName) + "&taskID=" + fmt.Sprint(taskID) + "&artifactID=" + fmt.Sprint(artifactID)
|
||||||
return uploadURL
|
return uploadURL
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r artifactV4Routes) verifySignature(ctx *ArtifactContext, endp string) (*actions.ActionTask, string, bool) {
|
func (r artifactV4Routes) verifySignature(ctx *ArtifactContext, endp string) (*actions.ActionTask, string, bool) {
|
||||||
rawTaskID := ctx.Req.URL.Query().Get("taskID")
|
rawTaskID := ctx.Req.URL.Query().Get("taskID")
|
||||||
|
rawArtifactID := ctx.Req.URL.Query().Get("artifactID")
|
||||||
sig := ctx.Req.URL.Query().Get("sig")
|
sig := ctx.Req.URL.Query().Get("sig")
|
||||||
expires := ctx.Req.URL.Query().Get("expires")
|
expires := ctx.Req.URL.Query().Get("expires")
|
||||||
artifactName := ctx.Req.URL.Query().Get("artifactName")
|
artifactName := ctx.Req.URL.Query().Get("artifactName")
|
||||||
dsig, _ := base64.URLEncoding.DecodeString(sig)
|
dsig, _ := base64.URLEncoding.DecodeString(sig)
|
||||||
taskID, _ := strconv.ParseInt(rawTaskID, 10, 64)
|
taskID, _ := strconv.ParseInt(rawTaskID, 10, 64)
|
||||||
|
artifactID, _ := strconv.ParseInt(rawArtifactID, 10, 64)
|
||||||
|
|
||||||
expecedsig := r.buildSignature(endp, expires, artifactName, taskID)
|
expecedsig := r.buildSignature(endp, expires, artifactName, taskID, artifactID)
|
||||||
if !hmac.Equal(dsig, expecedsig) {
|
if !hmac.Equal(dsig, expecedsig) {
|
||||||
log.Error("Error unauthorized")
|
log.Error("Error unauthorized")
|
||||||
ctx.Error(http.StatusUnauthorized, "Error unauthorized")
|
ctx.Error(http.StatusUnauthorized, "Error unauthorized")
|
||||||
|
@ -272,6 +283,8 @@ func (r *artifactV4Routes) createArtifact(ctx *ArtifactContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
artifact.ContentEncoding = ArtifactV4ContentEncoding
|
artifact.ContentEncoding = ArtifactV4ContentEncoding
|
||||||
|
artifact.FileSize = 0
|
||||||
|
artifact.FileCompressedSize = 0
|
||||||
if err := actions.UpdateArtifactByID(ctx, artifact.ID, artifact); err != nil {
|
if err := actions.UpdateArtifactByID(ctx, artifact.ID, artifact); err != nil {
|
||||||
log.Error("Error UpdateArtifactByID: %v", err)
|
log.Error("Error UpdateArtifactByID: %v", err)
|
||||||
ctx.Error(http.StatusInternalServerError, "Error UpdateArtifactByID")
|
ctx.Error(http.StatusInternalServerError, "Error UpdateArtifactByID")
|
||||||
|
@ -280,7 +293,7 @@ func (r *artifactV4Routes) createArtifact(ctx *ArtifactContext) {
|
||||||
|
|
||||||
respData := CreateArtifactResponse{
|
respData := CreateArtifactResponse{
|
||||||
Ok: true,
|
Ok: true,
|
||||||
SignedUploadUrl: r.buildArtifactURL("UploadArtifact", artifactName, ctx.ActionTask.ID),
|
SignedUploadUrl: r.buildArtifactURL("UploadArtifact", artifactName, ctx.ActionTask.ID, artifact.ID),
|
||||||
}
|
}
|
||||||
r.sendProtbufBody(ctx, &respData)
|
r.sendProtbufBody(ctx, &respData)
|
||||||
}
|
}
|
||||||
|
@ -306,6 +319,8 @@ func (r *artifactV4Routes) uploadArtifact(ctx *ArtifactContext) {
|
||||||
comp := ctx.Req.URL.Query().Get("comp")
|
comp := ctx.Req.URL.Query().Get("comp")
|
||||||
switch comp {
|
switch comp {
|
||||||
case "block", "appendBlock":
|
case "block", "appendBlock":
|
||||||
|
blockid := ctx.Req.URL.Query().Get("blockid")
|
||||||
|
if blockid == "" {
|
||||||
// get artifact by name
|
// get artifact by name
|
||||||
artifact, err := r.getArtifactByName(ctx, task.Job.RunID, artifactName)
|
artifact, err := r.getArtifactByName(ctx, task.Job.RunID, artifactName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -314,11 +329,6 @@ func (r *artifactV4Routes) uploadArtifact(ctx *ArtifactContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if comp == "block" {
|
|
||||||
artifact.FileSize = 0
|
|
||||||
artifact.FileCompressedSize = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = appendUploadChunk(r.fs, ctx, artifact, artifact.FileSize, ctx.Req.ContentLength, artifact.RunID)
|
_, err = appendUploadChunk(r.fs, ctx, artifact, artifact.FileSize, ctx.Req.ContentLength, artifact.RunID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error runner api getting task: task is not running")
|
log.Error("Error runner api getting task: task is not running")
|
||||||
|
@ -332,12 +342,54 @@ func (r *artifactV4Routes) uploadArtifact(ctx *ArtifactContext) {
|
||||||
ctx.Error(http.StatusInternalServerError, "Error UpdateArtifactByID")
|
ctx.Error(http.StatusInternalServerError, "Error UpdateArtifactByID")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
_, err := r.fs.Save(fmt.Sprintf("tmpv4%d/block-%d-%d-%s", task.Job.RunID, task.Job.RunID, ctx.Req.ContentLength, base64.URLEncoding.EncodeToString([]byte(blockid))), ctx.Req.Body, -1)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error runner api getting task: task is not running")
|
||||||
|
ctx.Error(http.StatusInternalServerError, "Error runner api getting task: task is not running")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
ctx.JSON(http.StatusCreated, "appended")
|
ctx.JSON(http.StatusCreated, "appended")
|
||||||
case "blocklist":
|
case "blocklist":
|
||||||
|
rawArtifactID := ctx.Req.URL.Query().Get("artifactID")
|
||||||
|
artifactID, _ := strconv.ParseInt(rawArtifactID, 10, 64)
|
||||||
|
_, err := r.fs.Save(fmt.Sprintf("tmpv4%d/%d-%d-blocklist", task.Job.RunID, task.Job.RunID, artifactID), ctx.Req.Body, -1)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error runner api getting task: task is not running")
|
||||||
|
ctx.Error(http.StatusInternalServerError, "Error runner api getting task: task is not running")
|
||||||
|
return
|
||||||
|
}
|
||||||
ctx.JSON(http.StatusCreated, "created")
|
ctx.JSON(http.StatusCreated, "created")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BlockList struct {
|
||||||
|
Latest []string `xml:"Latest"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Latest struct {
|
||||||
|
Value string `xml:",chardata"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *artifactV4Routes) readBlockList(runID, artifactID int64) (*BlockList, error) {
|
||||||
|
blockListName := fmt.Sprintf("tmpv4%d/%d-%d-blocklist", runID, runID, artifactID)
|
||||||
|
s, err := r.fs.Open(blockListName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
xdec := xml.NewDecoder(s)
|
||||||
|
blockList := &BlockList{}
|
||||||
|
err = xdec.Decode(blockList)
|
||||||
|
|
||||||
|
delerr := r.fs.Delete(blockListName)
|
||||||
|
if delerr != nil {
|
||||||
|
log.Warn("Failed to delete blockList %s: %v", blockListName, delerr)
|
||||||
|
}
|
||||||
|
return blockList, err
|
||||||
|
}
|
||||||
|
|
||||||
func (r *artifactV4Routes) finalizeArtifact(ctx *ArtifactContext) {
|
func (r *artifactV4Routes) finalizeArtifact(ctx *ArtifactContext) {
|
||||||
var req FinalizeArtifactRequest
|
var req FinalizeArtifactRequest
|
||||||
|
|
||||||
|
@ -356,18 +408,34 @@ func (r *artifactV4Routes) finalizeArtifact(ctx *ArtifactContext) {
|
||||||
ctx.Error(http.StatusNotFound, "Error artifact not found")
|
ctx.Error(http.StatusNotFound, "Error artifact not found")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var chunks []*chunkFileItem
|
||||||
|
blockList, err := r.readBlockList(runID, artifact.ID)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("Failed to read BlockList, fallback to old behavior: %v", err)
|
||||||
chunkMap, err := listChunksByRunID(r.fs, runID)
|
chunkMap, err := listChunksByRunID(r.fs, runID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error merge chunks: %v", err)
|
log.Error("Error merge chunks: %v", err)
|
||||||
ctx.Error(http.StatusInternalServerError, "Error merge chunks")
|
ctx.Error(http.StatusInternalServerError, "Error merge chunks")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
chunks, ok := chunkMap[artifact.ID]
|
chunks, ok = chunkMap[artifact.ID]
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Error("Error merge chunks")
|
log.Error("Error merge chunks")
|
||||||
ctx.Error(http.StatusInternalServerError, "Error merge chunks")
|
ctx.Error(http.StatusInternalServerError, "Error merge chunks")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
chunks, err = listChunksByRunIDV4(r.fs, runID, artifact.ID, blockList)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error merge chunks: %v", err)
|
||||||
|
ctx.Error(http.StatusInternalServerError, "Error merge chunks")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
artifact.FileSize = chunks[len(chunks)-1].End + 1
|
||||||
|
artifact.FileCompressedSize = chunks[len(chunks)-1].End + 1
|
||||||
|
}
|
||||||
|
|
||||||
checksum := ""
|
checksum := ""
|
||||||
if req.Hash != nil {
|
if req.Hash != nil {
|
||||||
checksum = req.Hash.Value
|
checksum = req.Hash.Value
|
||||||
|
@ -468,7 +536,7 @@ func (r *artifactV4Routes) getSignedArtifactURL(ctx *ArtifactContext) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if respData.SignedUrl == "" {
|
if respData.SignedUrl == "" {
|
||||||
respData.SignedUrl = r.buildArtifactURL("DownloadArtifact", artifactName, ctx.ActionTask.ID)
|
respData.SignedUrl = r.buildArtifactURL("DownloadArtifact", artifactName, ctx.ActionTask.ID, artifact.ID)
|
||||||
}
|
}
|
||||||
r.sendProtbufBody(ctx, &respData)
|
r.sendProtbufBody(ctx, &respData)
|
||||||
}
|
}
|
||||||
|
|
|
@ -476,6 +476,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption opt
|
||||||
ctx.Data["PosterID"] = posterID
|
ctx.Data["PosterID"] = posterID
|
||||||
ctx.Data["IsFuzzy"] = isFuzzy
|
ctx.Data["IsFuzzy"] = isFuzzy
|
||||||
ctx.Data["Keyword"] = keyword
|
ctx.Data["Keyword"] = keyword
|
||||||
|
ctx.Data["IsShowClosed"] = isShowClosed
|
||||||
switch {
|
switch {
|
||||||
case isShowClosed.Value():
|
case isShowClosed.Value():
|
||||||
ctx.Data["State"] = "closed"
|
ctx.Data["State"] = "closed"
|
||||||
|
|
|
@ -38,7 +38,6 @@ func TestCleanupSHA256(t *testing.T) {
|
||||||
Type: packages.TypeContainer,
|
Type: packages.TypeContainer,
|
||||||
}
|
}
|
||||||
_, err := db.GetEngine(ctx).Insert(&p)
|
_, err := db.GetEngine(ctx).Insert(&p)
|
||||||
// package_version").Where("version = ?", multiTag).Update(&packages_model.PackageVersion{MetadataJSON: `corrupted "manifests":[{ bad`})
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
var metadata string
|
var metadata string
|
||||||
|
|
|
@ -430,13 +430,12 @@ func DeleteBranch(ctx context.Context, doer *user_model.User, repo *repo_model.R
|
||||||
}
|
}
|
||||||
|
|
||||||
rawBranch, err := git_model.GetBranch(ctx, repo.ID, branchName)
|
rawBranch, err := git_model.GetBranch(ctx, repo.ID, branchName)
|
||||||
if err != nil {
|
if err != nil && !git_model.IsErrBranchNotExist(err) {
|
||||||
return fmt.Errorf("GetBranch: %v", err)
|
return fmt.Errorf("GetBranch: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if rawBranch.IsDeleted {
|
// database branch record not exist or it's a deleted branch
|
||||||
return nil
|
notExist := git_model.IsErrBranchNotExist(err) || rawBranch.IsDeleted
|
||||||
}
|
|
||||||
|
|
||||||
commit, err := gitRepo.GetBranchCommit(branchName)
|
commit, err := gitRepo.GetBranchCommit(branchName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -444,9 +443,11 @@ func DeleteBranch(ctx context.Context, doer *user_model.User, repo *repo_model.R
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.WithTx(ctx, func(ctx context.Context) error {
|
if err := db.WithTx(ctx, func(ctx context.Context) error {
|
||||||
|
if !notExist {
|
||||||
if err := git_model.AddDeletedBranch(ctx, repo.ID, branchName, doer.ID); err != nil {
|
if err := git_model.AddDeletedBranch(ctx, repo.ID, branchName, doer.ID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return gitRepo.DeleteBranch(branchName, git.DeleteBranchOptions{
|
return gitRepo.DeleteBranch(branchName, git.DeleteBranchOptions{
|
||||||
Force: true,
|
Force: true,
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
webhook_model "code.gitea.io/gitea/models/webhook"
|
webhook_model "code.gitea.io/gitea/models/webhook"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
@ -179,8 +180,14 @@ func (d discordConvertor) Push(p *api.PushPayload) (DiscordPayload, error) {
|
||||||
var text string
|
var text string
|
||||||
// for each commit, generate attachment text
|
// for each commit, generate attachment text
|
||||||
for i, commit := range p.Commits {
|
for i, commit := range p.Commits {
|
||||||
text += fmt.Sprintf("[%s](%s) %s - %s", commit.ID[:7], commit.URL,
|
// limit the commit message display to just the summary, otherwise it would be hard to read
|
||||||
strings.TrimRight(commit.Message, "\r\n"), commit.Author.Name)
|
message := strings.TrimRight(strings.SplitN(commit.Message, "\n", 1)[0], "\r")
|
||||||
|
|
||||||
|
// a limit of 50 is set because GitHub does the same
|
||||||
|
if utf8.RuneCountInString(message) > 50 {
|
||||||
|
message = fmt.Sprintf("%.47s...", message)
|
||||||
|
}
|
||||||
|
text += fmt.Sprintf("[%s](%s) %s - %s", commit.ID[:7], commit.URL, message, commit.Author.Name)
|
||||||
// add linebreak to each commit but the last
|
// add linebreak to each commit but the last
|
||||||
if i < len(p.Commits)-1 {
|
if i < len(p.Commits)-1 {
|
||||||
text += "\n"
|
text += "\n"
|
||||||
|
|
|
@ -80,6 +80,20 @@ func TestDiscordPayload(t *testing.T) {
|
||||||
assert.Equal(t, p.Sender.AvatarURL, pl.Embeds[0].Author.IconURL)
|
assert.Equal(t, p.Sender.AvatarURL, pl.Embeds[0].Author.IconURL)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("PushWithLongCommitMessage", func(t *testing.T) {
|
||||||
|
p := pushTestMultilineCommitMessagePayload()
|
||||||
|
|
||||||
|
pl, err := dc.Push(p)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Len(t, pl.Embeds, 1)
|
||||||
|
assert.Equal(t, "[test/repo:test] 2 new commits", pl.Embeds[0].Title)
|
||||||
|
assert.Equal(t, "[2020558](http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778) This is a commit summary ⚠️⚠️⚠️⚠️ containing ä˝ ĺĄ˝... - user1\n[2020558](http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778) This is a commit summary ⚠️⚠️⚠️⚠️ containing ä˝ ĺĄ˝... - user1", pl.Embeds[0].Description)
|
||||||
|
assert.Equal(t, p.Sender.UserName, pl.Embeds[0].Author.Name)
|
||||||
|
assert.Equal(t, setting.AppURL+p.Sender.UserName, pl.Embeds[0].Author.URL)
|
||||||
|
assert.Equal(t, p.Sender.AvatarURL, pl.Embeds[0].Author.IconURL)
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("Issue", func(t *testing.T) {
|
t.Run("Issue", func(t *testing.T) {
|
||||||
p := issueTestPayload()
|
p := issueTestPayload()
|
||||||
|
|
||||||
|
|
|
@ -64,9 +64,17 @@ func forkTestPayload() *api.ForkPayload {
|
||||||
}
|
}
|
||||||
|
|
||||||
func pushTestPayload() *api.PushPayload {
|
func pushTestPayload() *api.PushPayload {
|
||||||
|
return pushTestPayloadWithCommitMessage("commit message")
|
||||||
|
}
|
||||||
|
|
||||||
|
func pushTestMultilineCommitMessagePayload() *api.PushPayload {
|
||||||
|
return pushTestPayloadWithCommitMessage("This is a commit summary ⚠️⚠️⚠️⚠️ containing ä˝ ĺĄ˝ ⚠️⚠️️\n\nThis is the message body.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func pushTestPayloadWithCommitMessage(message string) *api.PushPayload {
|
||||||
commit := &api.PayloadCommit{
|
commit := &api.PayloadCommit{
|
||||||
ID: "2020558fe2e34debb818a514715839cabd25e778",
|
ID: "2020558fe2e34debb818a514715839cabd25e778",
|
||||||
Message: "commit message",
|
Message: message,
|
||||||
URL: "http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778",
|
URL: "http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778",
|
||||||
Author: &api.PayloadUser{
|
Author: &api.PayloadUser{
|
||||||
Name: "user1",
|
Name: "user1",
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<div class="ui secondary filter menu">
|
<div class="ui secondary filter menu">
|
||||||
{{if not .Repository.IsArchived}}
|
{{if not .Repository.IsArchived}}
|
||||||
<!-- Action Button -->
|
<!-- Action Button -->
|
||||||
{{if .IsShowClosed}}
|
{{if and .IsShowClosed.Has .IsShowClosed.Value}}
|
||||||
<button class="ui primary basic button issue-action" data-action="open" data-url="{{$.RepoLink}}/issues/status">{{ctx.Locale.Tr "repo.issues.action_open"}}</button>
|
<button class="ui primary basic button issue-action" data-action="open" data-url="{{$.RepoLink}}/issues/status">{{ctx.Locale.Tr "repo.issues.action_open"}}</button>
|
||||||
{{else}}
|
{{else if and .IsShowClosed.Has (not .IsShowClosed.Value)}}
|
||||||
<button class="ui red basic button issue-action" data-action="close" data-url="{{$.RepoLink}}/issues/status">{{ctx.Locale.Tr "repo.issues.action_close"}}</button>
|
<button class="ui red basic button issue-action" data-action="close" data-url="{{$.RepoLink}}/issues/status">{{ctx.Locale.Tr "repo.issues.action_close"}}</button>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if $.IsRepoAdmin}}
|
{{if $.IsRepoAdmin}}
|
||||||
|
|
|
@ -7,12 +7,14 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"encoding/xml"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/storage"
|
||||||
"code.gitea.io/gitea/routers/api/actions"
|
"code.gitea.io/gitea/routers/api/actions"
|
||||||
actions_service "code.gitea.io/gitea/services/actions"
|
actions_service "code.gitea.io/gitea/services/actions"
|
||||||
"code.gitea.io/gitea/tests"
|
"code.gitea.io/gitea/tests"
|
||||||
|
@ -175,6 +177,134 @@ func TestActionsArtifactV4UploadSingleFileWithRetentionDays(t *testing.T) {
|
||||||
assert.True(t, finalizeResp.Ok)
|
assert.True(t, finalizeResp.Ok)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestActionsArtifactV4UploadSingleFileWithPotentialHarmfulBlockID(t *testing.T) {
|
||||||
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
|
token, err := actions_service.CreateAuthorizationToken(48, 792, 193)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// acquire artifact upload url
|
||||||
|
req := NewRequestWithBody(t, "POST", "/twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact", toProtoJSON(&actions.CreateArtifactRequest{
|
||||||
|
Version: 4,
|
||||||
|
Name: "artifactWithPotentialHarmfulBlockID",
|
||||||
|
WorkflowRunBackendId: "792",
|
||||||
|
WorkflowJobRunBackendId: "193",
|
||||||
|
})).AddTokenAuth(token)
|
||||||
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
var uploadResp actions.CreateArtifactResponse
|
||||||
|
protojson.Unmarshal(resp.Body.Bytes(), &uploadResp)
|
||||||
|
assert.True(t, uploadResp.Ok)
|
||||||
|
assert.Contains(t, uploadResp.SignedUploadUrl, "/twirp/github.actions.results.api.v1.ArtifactService/UploadArtifact")
|
||||||
|
|
||||||
|
// get upload urls
|
||||||
|
idx := strings.Index(uploadResp.SignedUploadUrl, "/twirp/")
|
||||||
|
url := uploadResp.SignedUploadUrl[idx:] + "&comp=block&blockid=%2f..%2fmyfile"
|
||||||
|
blockListURL := uploadResp.SignedUploadUrl[idx:] + "&comp=blocklist"
|
||||||
|
|
||||||
|
// upload artifact chunk
|
||||||
|
body := strings.Repeat("A", 1024)
|
||||||
|
req = NewRequestWithBody(t, "PUT", url, strings.NewReader(body))
|
||||||
|
MakeRequest(t, req, http.StatusCreated)
|
||||||
|
|
||||||
|
// verify that the exploit didn't work
|
||||||
|
_, err = storage.Actions.Stat("myfile")
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// upload artifact blockList
|
||||||
|
blockList := &actions.BlockList{
|
||||||
|
Latest: []string{
|
||||||
|
"/../myfile",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
rawBlockList, err := xml.Marshal(blockList)
|
||||||
|
require.NoError(t, err)
|
||||||
|
req = NewRequestWithBody(t, "PUT", blockListURL, bytes.NewReader(rawBlockList))
|
||||||
|
MakeRequest(t, req, http.StatusCreated)
|
||||||
|
|
||||||
|
t.Logf("Create artifact confirm")
|
||||||
|
|
||||||
|
sha := sha256.Sum256([]byte(body))
|
||||||
|
|
||||||
|
// confirm artifact upload
|
||||||
|
req = NewRequestWithBody(t, "POST", "/twirp/github.actions.results.api.v1.ArtifactService/FinalizeArtifact", toProtoJSON(&actions.FinalizeArtifactRequest{
|
||||||
|
Name: "artifactWithPotentialHarmfulBlockID",
|
||||||
|
Size: 1024,
|
||||||
|
Hash: wrapperspb.String("sha256:" + hex.EncodeToString(sha[:])),
|
||||||
|
WorkflowRunBackendId: "792",
|
||||||
|
WorkflowJobRunBackendId: "193",
|
||||||
|
})).
|
||||||
|
AddTokenAuth(token)
|
||||||
|
resp = MakeRequest(t, req, http.StatusOK)
|
||||||
|
var finalizeResp actions.FinalizeArtifactResponse
|
||||||
|
protojson.Unmarshal(resp.Body.Bytes(), &finalizeResp)
|
||||||
|
assert.True(t, finalizeResp.Ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestActionsArtifactV4UploadSingleFileWithChunksOutOfOrder(t *testing.T) {
|
||||||
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
|
token, err := actions_service.CreateAuthorizationToken(48, 792, 193)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// acquire artifact upload url
|
||||||
|
req := NewRequestWithBody(t, "POST", "/twirp/github.actions.results.api.v1.ArtifactService/CreateArtifact", toProtoJSON(&actions.CreateArtifactRequest{
|
||||||
|
Version: 4,
|
||||||
|
Name: "artifactWithChunksOutOfOrder",
|
||||||
|
WorkflowRunBackendId: "792",
|
||||||
|
WorkflowJobRunBackendId: "193",
|
||||||
|
})).AddTokenAuth(token)
|
||||||
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
var uploadResp actions.CreateArtifactResponse
|
||||||
|
protojson.Unmarshal(resp.Body.Bytes(), &uploadResp)
|
||||||
|
assert.True(t, uploadResp.Ok)
|
||||||
|
assert.Contains(t, uploadResp.SignedUploadUrl, "/twirp/github.actions.results.api.v1.ArtifactService/UploadArtifact")
|
||||||
|
|
||||||
|
// get upload urls
|
||||||
|
idx := strings.Index(uploadResp.SignedUploadUrl, "/twirp/")
|
||||||
|
block1URL := uploadResp.SignedUploadUrl[idx:] + "&comp=block&blockid=block1"
|
||||||
|
block2URL := uploadResp.SignedUploadUrl[idx:] + "&comp=block&blockid=block2"
|
||||||
|
blockListURL := uploadResp.SignedUploadUrl[idx:] + "&comp=blocklist"
|
||||||
|
|
||||||
|
// upload artifact chunks
|
||||||
|
bodyb := strings.Repeat("B", 1024)
|
||||||
|
req = NewRequestWithBody(t, "PUT", block2URL, strings.NewReader(bodyb))
|
||||||
|
MakeRequest(t, req, http.StatusCreated)
|
||||||
|
|
||||||
|
bodya := strings.Repeat("A", 1024)
|
||||||
|
req = NewRequestWithBody(t, "PUT", block1URL, strings.NewReader(bodya))
|
||||||
|
MakeRequest(t, req, http.StatusCreated)
|
||||||
|
|
||||||
|
// upload artifact blockList
|
||||||
|
blockList := &actions.BlockList{
|
||||||
|
Latest: []string{
|
||||||
|
"block1",
|
||||||
|
"block2",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
rawBlockList, err := xml.Marshal(blockList)
|
||||||
|
require.NoError(t, err)
|
||||||
|
req = NewRequestWithBody(t, "PUT", blockListURL, bytes.NewReader(rawBlockList))
|
||||||
|
MakeRequest(t, req, http.StatusCreated)
|
||||||
|
|
||||||
|
t.Logf("Create artifact confirm")
|
||||||
|
|
||||||
|
sha := sha256.Sum256([]byte(bodya + bodyb))
|
||||||
|
|
||||||
|
// confirm artifact upload
|
||||||
|
req = NewRequestWithBody(t, "POST", "/twirp/github.actions.results.api.v1.ArtifactService/FinalizeArtifact", toProtoJSON(&actions.FinalizeArtifactRequest{
|
||||||
|
Name: "artifactWithChunksOutOfOrder",
|
||||||
|
Size: 2048,
|
||||||
|
Hash: wrapperspb.String("sha256:" + hex.EncodeToString(sha[:])),
|
||||||
|
WorkflowRunBackendId: "792",
|
||||||
|
WorkflowJobRunBackendId: "193",
|
||||||
|
})).
|
||||||
|
AddTokenAuth(token)
|
||||||
|
resp = MakeRequest(t, req, http.StatusOK)
|
||||||
|
var finalizeResp actions.FinalizeArtifactResponse
|
||||||
|
protojson.Unmarshal(resp.Body.Bytes(), &finalizeResp)
|
||||||
|
assert.True(t, finalizeResp.Ok)
|
||||||
|
}
|
||||||
|
|
||||||
func TestActionsArtifactV4DownloadSingle(t *testing.T) {
|
func TestActionsArtifactV4DownloadSingle(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,6 @@ const sfc = {
|
||||||
searchURL() {
|
searchURL() {
|
||||||
return `${this.subUrl}/repo/search?sort=updated&order=desc&uid=${this.uid}&team_id=${this.teamId}&q=${this.searchQuery
|
return `${this.subUrl}/repo/search?sort=updated&order=desc&uid=${this.uid}&team_id=${this.teamId}&q=${this.searchQuery
|
||||||
}&page=${this.page}&limit=${this.searchLimit}&mode=${this.repoTypes[this.reposFilter].searchMode
|
}&page=${this.page}&limit=${this.searchLimit}&mode=${this.repoTypes[this.reposFilter].searchMode
|
||||||
}${this.reposFilter !== 'all' ? '&exclusive=1' : ''
|
|
||||||
}${this.archivedFilter === 'archived' ? '&archived=true' : ''}${this.archivedFilter === 'unarchived' ? '&archived=false' : ''
|
}${this.archivedFilter === 'archived' ? '&archived=true' : ''}${this.archivedFilter === 'unarchived' ? '&archived=false' : ''
|
||||||
}${this.privateFilter === 'private' ? '&is_private=true' : ''}${this.privateFilter === 'public' ? '&is_private=false' : ''
|
}${this.privateFilter === 'private' ? '&is_private=true' : ''}${this.privateFilter === 'public' ? '&is_private=false' : ''
|
||||||
}`;
|
}`;
|
||||||
|
|
Loading…
Reference in a new issue