Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Jérome Perrin
gitlab-ce
Commits
ca3ea76c
Commit
ca3ea76c
authored
Jul 06, 2018
by
Alessio Caiazza
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into 11-1-stable-prepare-rc5
parents
7240d175
68d138e8
Changes
90
Hide whitespace changes
Inline
Side-by-side
Showing
90 changed files
with
1124 additions
and
235 deletions
+1124
-235
README.md
README.md
+4
-0
app/assets/javascripts/diffs/components/diff_file_header.vue
app/assets/javascripts/diffs/components/diff_file_header.vue
+9
-5
app/assets/javascripts/diffs/components/parallel_diff_view.vue
...ssets/javascripts/diffs/components/parallel_diff_view.vue
+7
-5
app/assets/javascripts/diffs/store/utils.js
app/assets/javascripts/diffs/store/utils.js
+15
-12
app/assets/javascripts/notes/components/diff_with_note.vue
app/assets/javascripts/notes/components/diff_with_note.vue
+82
-77
app/assets/javascripts/notes/stores/getters.js
app/assets/javascripts/notes/stores/getters.js
+2
-2
app/assets/javascripts/pages/projects/jobs/terminal/index.js
app/assets/javascripts/pages/projects/jobs/terminal/index.js
+3
-0
app/assets/javascripts/vue_shared/components/markdown/header.vue
...ets/javascripts/vue_shared/components/markdown/header.vue
+2
-2
app/assets/stylesheets/pages/diff.scss
app/assets/stylesheets/pages/diff.scss
+1
-1
app/controllers/concerns/preview_markdown.rb
app/controllers/concerns/preview_markdown.rb
+1
-0
app/controllers/dashboard/projects_controller.rb
app/controllers/dashboard/projects_controller.rb
+3
-2
app/controllers/projects/jobs_controller.rb
app/controllers/projects/jobs_controller.rb
+20
-2
app/helpers/projects_helper.rb
app/helpers/projects_helper.rb
+1
-0
app/helpers/users_helper.rb
app/helpers/users_helper.rb
+8
-0
app/models/board.rb
app/models/board.rb
+4
-0
app/models/ci/build.rb
app/models/ci/build.rb
+20
-0
app/models/ci/build_runner_session.rb
app/models/ci/build_runner_session.rb
+25
-0
app/models/project_services/kubernetes_service.rb
app/models/project_services/kubernetes_service.rb
+1
-1
app/models/service.rb
app/models/service.rb
+1
-1
app/policies/ci/build_policy.rb
app/policies/ci/build_policy.rb
+6
-0
app/services/ci/register_job_service.rb
app/services/ci/register_job_service.rb
+3
-1
app/services/issues/base_service.rb
app/services/issues/base_service.rb
+3
-2
app/views/layouts/header/_current_user_dropdown.html.haml
app/views/layouts/header/_current_user_dropdown.html.haml
+1
-5
app/views/projects/jobs/_sidebar.html.haml
app/views/projects/jobs/_sidebar.html.haml
+6
-2
app/views/projects/jobs/terminal.html.haml
app/views/projects/jobs/terminal.html.haml
+11
-0
app/views/projects/settings/ci_cd/_form.html.haml
app/views/projects/settings/ci_cd/_form.html.haml
+3
-0
app/views/shared/_user_dropdown_contributing_link.html.haml
app/views/shared/_user_dropdown_contributing_link.html.haml
+5
-0
app/views/shared/boards/_show.html.haml
app/views/shared/boards/_show.html.haml
+4
-3
app/views/shared/issuable/_search_bar.html.haml
app/views/shared/issuable/_search_bar.html.haml
+12
-2
app/views/shared/projects/_project.html.haml
app/views/shared/projects/_project.html.haml
+1
-1
app/workers/archive_trace_worker.rb
app/workers/archive_trace_worker.rb
+1
-1
app/workers/ci/archive_traces_cron_worker.rb
app/workers/ci/archive_traces_cron_worker.rb
+1
-0
changelogs/unreleased/20357.yml
changelogs/unreleased/20357.yml
+5
-0
changelogs/unreleased/31583-osw-gfm-complete-status-indication.yml
...s/unreleased/31583-osw-gfm-complete-status-indication.yml
+5
-0
changelogs/unreleased/44697-when-editing-a-comment-in-an-issue-the-preview-mode-is-toggled-in-the-main-textarea.yml
...ssue-the-preview-mode-is-toggled-in-the-main-textarea.yml
+6
-0
changelogs/unreleased/48825-performance.yml
changelogs/unreleased/48825-performance.yml
+8
-0
changelogs/unreleased/dm-invalid-active-service-template.yml
changelogs/unreleased/dm-invalid-active-service-template.yml
+5
-0
changelogs/unreleased/fix-trace-archive-cron-worker-race-condition.yml
...released/fix-trace-archive-cron-worker-race-condition.yml
+5
-0
changelogs/unreleased/fj-43565-wrong-role-displayed.yml
changelogs/unreleased/fj-43565-wrong-role-displayed.yml
+5
-0
changelogs/unreleased/fj-web-terminal-ci-build.yml
changelogs/unreleased/fj-web-terminal-ci-build.yml
+5
-0
changelogs/unreleased/gitaly-timeouts.yml
changelogs/unreleased/gitaly-timeouts.yml
+5
-0
changelogs/unreleased/remove-trace-efficiently.yml
changelogs/unreleased/remove-trace-efficiently.yml
+5
-0
config/routes/project.rb
config/routes/project.rb
+2
-0
db/migrate/20180613081317_create_ci_builds_runner_session.rb
db/migrate/20180613081317_create_ci_builds_runner_session.rb
+21
-0
db/schema.rb
db/schema.rb
+10
-0
doc/api/projects.md
doc/api/projects.md
+33
-0
doc/ci/examples/container_scanning.md
doc/ci/examples/container_scanning.md
+2
-2
lib/api/entities.rb
lib/api/entities.rb
+1
-0
lib/api/runner.rb
lib/api/runner.rb
+10
-3
lib/gitlab/ci/trace.rb
lib/gitlab/ci/trace.rb
+16
-10
lib/gitlab/git/commit.rb
lib/gitlab/git/commit.rb
+12
-2
lib/gitlab/git/conflict/resolver.rb
lib/gitlab/git/conflict/resolver.rb
+65
-4
lib/gitlab/git/repository.rb
lib/gitlab/git/repository.rb
+17
-2
lib/gitlab/gitaly_client/blob_service.rb
lib/gitlab/gitaly_client/blob_service.rb
+5
-5
lib/gitlab/gitaly_client/commit_service.rb
lib/gitlab/gitaly_client/commit_service.rb
+4
-4
lib/gitlab/gitaly_client/conflicts_service.rb
lib/gitlab/gitaly_client/conflicts_service.rb
+1
-1
lib/gitlab/gitaly_client/namespace_service.rb
lib/gitlab/gitaly_client/namespace_service.rb
+6
-6
lib/gitlab/gitaly_client/operation_service.rb
lib/gitlab/gitaly_client/operation_service.rb
+4
-3
lib/gitlab/gitaly_client/ref_service.rb
lib/gitlab/gitaly_client/ref_service.rb
+13
-13
lib/gitlab/gitaly_client/remote_service.rb
lib/gitlab/gitaly_client/remote_service.rb
+2
-2
lib/gitlab/gitaly_client/repository_service.rb
lib/gitlab/gitaly_client/repository_service.rb
+10
-10
lib/gitlab/gitaly_client/wiki_service.rb
lib/gitlab/gitaly_client/wiki_service.rb
+5
-5
qa/qa/runtime/browser.rb
qa/qa/runtime/browser.rb
+6
-0
spec/controllers/projects/jobs_controller_spec.rb
spec/controllers/projects/jobs_controller_spec.rb
+101
-0
spec/controllers/projects/pipelines_controller_spec.rb
spec/controllers/projects/pipelines_controller_spec.rb
+1
-1
spec/controllers/projects_controller_spec.rb
spec/controllers/projects_controller_spec.rb
+28
-1
spec/factories/ci/builds.rb
spec/factories/ci/builds.rb
+6
-0
spec/features/dashboard/projects_spec.rb
spec/features/dashboard/projects_spec.rb
+28
-0
spec/features/projects/issues/user_comments_on_issue_spec.rb
spec/features/projects/issues/user_comments_on_issue_spec.rb
+8
-0
spec/helpers/projects_helper_spec.rb
spec/helpers/projects_helper_spec.rb
+5
-0
spec/javascripts/diffs/components/diff_file_header_spec.js
spec/javascripts/diffs/components/diff_file_header_spec.js
+4
-4
spec/javascripts/diffs/store/utils_spec.js
spec/javascripts/diffs/store/utils_spec.js
+31
-0
spec/javascripts/fixtures/merge_requests.rb
spec/javascripts/fixtures/merge_requests.rb
+7
-0
spec/javascripts/notes/components/discussion_counter_spec.js
spec/javascripts/notes/components/discussion_counter_spec.js
+2
-2
spec/javascripts/notes/components/noteable_discussion_spec.js
.../javascripts/notes/components/noteable_discussion_spec.js
+11
-8
spec/javascripts/notes/mock_data.js
spec/javascripts/notes/mock_data.js
+1
-0
spec/javascripts/notes/stores/getters_spec.js
spec/javascripts/notes/stores/getters_spec.js
+18
-0
spec/javascripts/vue_shared/components/markdown/header_spec.js
...javascripts/vue_shared/components/markdown/header_spec.js
+1
-1
spec/models/ci/build_runner_session_spec.rb
spec/models/ci/build_runner_session_spec.rb
+36
-0
spec/models/ci/build_spec.rb
spec/models/ci/build_spec.rb
+88
-6
spec/models/service_spec.rb
spec/models/service_spec.rb
+1
-1
spec/requests/api/runner_spec.rb
spec/requests/api/runner_spec.rb
+1
-0
spec/services/ci/register_job_service_spec.rb
spec/services/ci/register_job_service_spec.rb
+15
-2
spec/services/ci/retry_build_service_spec.rb
spec/services/ci/retry_build_service_spec.rb
+1
-1
spec/services/merge_requests/conflicts/list_service_spec.rb
spec/services/merge_requests/conflicts/list_service_spec.rb
+18
-0
spec/services/merge_requests/conflicts/resolve_service_spec.rb
...services/merge_requests/conflicts/resolve_service_spec.rb
+11
-0
spec/spec_helper.rb
spec/spec_helper.rb
+11
-0
spec/support/helpers/wait_for_requests.rb
spec/support/helpers/wait_for_requests.rb
+3
-1
spec/support/shared_examples/ci_trace_shared_examples.rb
spec/support/shared_examples/ci_trace_shared_examples.rb
+104
-2
spec/workers/ci/archive_traces_cron_worker_spec.rb
spec/workers/ci/archive_traces_cron_worker_spec.rb
+18
-6
No files found.
README.md
View file @
ca3ea76c
...
@@ -120,6 +120,10 @@ All documentation can be found on [docs.gitlab.com/ce/](https://docs.gitlab.com/
...
@@ -120,6 +120,10 @@ All documentation can be found on [docs.gitlab.com/ce/](https://docs.gitlab.com/
Please see
[
Getting help for GitLab
](
https://about.gitlab.com/getting-help/
)
on our website for the many options to get help.
Please see
[
Getting help for GitLab
](
https://about.gitlab.com/getting-help/
)
on our website for the many options to get help.
## Why?
[
Read here
](
https://about.gitlab.com/why/
)
## Is it any good?
## Is it any good?
[
Yes
](
https://news.ycombinator.com/item?id=3067434
)
[
Yes
](
https://news.ycombinator.com/item?id=3067434
)
...
...
app/assets/javascripts/diffs/components/diff_file_header.vue
View file @
ca3ea76c
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
import
_
from
'
underscore
'
;
import
_
from
'
underscore
'
;
import
ClipboardButton
from
'
~/vue_shared/components/clipboard_button.vue
'
;
import
ClipboardButton
from
'
~/vue_shared/components/clipboard_button.vue
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
FileIcon
from
'
~/vue_shared/components/file_icon.vue
'
;
import
Tooltip
from
'
~/vue_shared/directives/tooltip
'
;
import
Tooltip
from
'
~/vue_shared/directives/tooltip
'
;
import
{
truncateSha
}
from
'
~/lib/utils/text_utility
'
;
import
{
truncateSha
}
from
'
~/lib/utils/text_utility
'
;
import
{
__
,
s__
,
sprintf
}
from
'
~/locale
'
;
import
{
__
,
s__
,
sprintf
}
from
'
~/locale
'
;
...
@@ -12,6 +13,7 @@ export default {
...
@@ -12,6 +13,7 @@ export default {
ClipboardButton
,
ClipboardButton
,
EditButton
,
EditButton
,
Icon
,
Icon
,
FileIcon
,
},
},
directives
:
{
directives
:
{
Tooltip
,
Tooltip
,
...
@@ -139,18 +141,20 @@ export default {
...
@@ -139,18 +141,20 @@ export default {
:name=
"collapseIcon"
:name=
"collapseIcon"
:size=
"16"
:size=
"16"
aria-hidden=
"true"
aria-hidden=
"true"
class=
"diff-toggle-caret"
class=
"diff-toggle-caret
append-right-5
"
@
click.stop=
"handleToggle"
@
click.stop=
"handleToggle"
/>
/>
<a
<a
ref=
"titleWrapper"
ref=
"titleWrapper"
:href=
"titleLink"
:href=
"titleLink"
class=
"append-right-4"
>
>
<
i
<
file-icon
:
class=
"`fa-$
{icon}`
"
:
file-name=
"filePath
"
class="fa fa-fw
"
:size=
"18
"
aria-hidden=
"true"
aria-hidden=
"true"
>
</i>
css-classes=
"js-file-icon append-right-5"
/>
<span
v-if=
"diffFile.renamedFile"
>
<span
v-if=
"diffFile.renamedFile"
>
<strong
<strong
v-tooltip
v-tooltip
...
...
app/assets/javascripts/diffs/components/parallel_diff_view.vue
View file @
ca3ea76c
...
@@ -24,19 +24,21 @@ export default {
...
@@ -24,19 +24,21 @@ export default {
...
mapGetters
([
'
commit
'
]),
...
mapGetters
([
'
commit
'
]),
parallelDiffLines
()
{
parallelDiffLines
()
{
return
this
.
diffLines
.
map
(
line
=>
{
return
this
.
diffLines
.
map
(
line
=>
{
const
parallelLine
=
Object
.
assign
({},
line
);
if
(
line
.
left
)
{
if
(
line
.
left
)
{
Object
.
assign
(
line
,
{
left
:
trimFirstCharOfLineContent
(
line
.
left
)
}
);
parallelLine
.
left
=
trimFirstCharOfLineContent
(
line
.
left
);
}
else
{
}
else
{
Object
.
assign
(
line
,
{
left
:
{
type
:
EMPTY_CELL_TYPE
}
})
;
parallelLine
.
left
=
{
type
:
EMPTY_CELL_TYPE
}
;
}
}
if
(
line
.
right
)
{
if
(
line
.
right
)
{
Object
.
assign
(
line
,
{
right
:
trimFirstCharOfLineContent
(
line
.
right
)
}
);
parallelLine
.
right
=
trimFirstCharOfLineContent
(
line
.
right
);
}
else
{
}
else
{
Object
.
assign
(
line
,
{
right
:
{
type
:
EMPTY_CELL_TYPE
}
})
;
parallelLine
.
right
=
{
type
:
EMPTY_CELL_TYPE
}
;
}
}
return
l
ine
;
return
parallelL
ine
;
});
});
},
},
diffLinesLength
()
{
diffLinesLength
()
{
...
...
app/assets/javascripts/diffs/store/utils.js
View file @
ca3ea76c
...
@@ -155,18 +155,21 @@ export function addContextLines(options) {
...
@@ -155,18 +155,21 @@ export function addContextLines(options) {
}
}
}
}
export
function
trimFirstCharOfLineContent
(
line
)
{
/**
if
(
!
line
.
richText
)
{
* Trims the first char of the `richText` property when it's either a space or a diff symbol.
return
line
;
* @param {Object} line
}
* @returns {Object}
*/
const
firstChar
=
line
.
richText
.
charAt
(
0
);
export
function
trimFirstCharOfLineContent
(
line
=
{})
{
const
parsedLine
=
Object
.
assign
({},
line
);
if
(
firstChar
===
'
'
||
firstChar
===
'
+
'
||
firstChar
===
'
-
'
)
{
Object
.
assign
(
line
,
{
if
(
line
.
richText
)
{
richText
:
line
.
richText
.
substring
(
1
),
const
firstChar
=
parsedLine
.
richText
.
charAt
(
0
);
});
if
(
firstChar
===
'
'
||
firstChar
===
'
+
'
||
firstChar
===
'
-
'
)
{
parsedLine
.
richText
=
line
.
richText
.
substring
(
1
);
}
}
}
return
l
ine
;
return
parsedL
ine
;
}
}
app/assets/javascripts/notes/components/diff_with_note.vue
View file @
ca3ea76c
<
script
>
<
script
>
import
{
mapState
,
mapActions
}
from
'
vuex
'
;
import
{
mapState
,
mapActions
}
from
'
vuex
'
;
import
imageDiffHelper
from
'
~/image_diff/helpers/index
'
;
import
imageDiffHelper
from
'
~/image_diff/helpers/index
'
;
import
{
convertObjectPropsToCamelCase
}
from
'
~/lib/utils/common_utils
'
;
import
{
convertObjectPropsToCamelCase
}
from
'
~/lib/utils/common_utils
'
;
import
DiffFileHeader
from
'
~/diffs/components/diff_file_header.vue
'
;
import
DiffFileHeader
from
'
~/diffs/components/diff_file_header.vue
'
;
import
SkeletonLoadingContainer
from
'
~/vue_shared/components/skeleton_loading_container.vue
'
;
import
SkeletonLoadingContainer
from
'
~/vue_shared/components/skeleton_loading_container.vue
'
;
import
{
trimFirstCharOfLineContent
}
from
'
~/diffs/store/utils
'
;
import
{
trimFirstCharOfLineContent
}
from
'
~/diffs/store/utils
'
;
export
default
{
export
default
{
components
:
{
components
:
{
DiffFileHeader
,
DiffFileHeader
,
SkeletonLoadingContainer
,
SkeletonLoadingContainer
,
},
props
:
{
discussion
:
{
type
:
Object
,
required
:
true
,
},
},
},
props
:
{
data
()
{
discussion
:
{
return
{
type
:
Object
,
error
:
false
,
required
:
true
,
};
},
},
computed
:
{
...
mapState
({
noteableData
:
state
=>
state
.
notes
.
noteableData
,
}),
hasTruncatedDiffLines
()
{
return
this
.
discussion
.
truncatedDiffLines
&&
this
.
discussion
.
truncatedDiffLines
.
length
!==
0
;
},
},
isDiscussionsExpanded
()
{
data
()
{
return
true
;
// TODO: @fatihacet - Fix this.
return
{
error
:
false
,
};
},
},
isCollapsed
()
{
computed
:
{
return
this
.
diffFile
.
collapsed
||
false
;
...
mapState
({
},
noteableData
:
state
=>
state
.
notes
.
noteableData
,
isImageDiff
()
{
}),
return
!
this
.
diffFile
.
text
;
hasTruncatedDiffLines
()
{
},
return
this
.
discussion
.
truncatedDiffLines
&&
diffFileClass
()
{
this
.
discussion
.
truncatedDiffLines
.
length
!==
0
;
const
{
text
}
=
this
.
diffFile
;
},
return
text
?
'
text-file
'
:
'
js-image-file
'
;
isDiscussionsExpanded
()
{
},
return
true
;
// TODO: @fatihacet - Fix this.
diffFile
()
{
},
return
convertObjectPropsToCamelCase
(
this
.
discussion
.
diffFile
,
{
deep
:
true
});
isCollapsed
()
{
},
return
this
.
diffFile
.
collapsed
||
false
;
imageDiffHtml
()
{
},
return
this
.
discussion
.
imageDiffHtml
;
isImageDiff
()
{
},
return
!
this
.
diffFile
.
text
;
currentUser
()
{
},
return
this
.
noteableData
.
current_user
;
diffFileClass
()
{
},
const
{
text
}
=
this
.
diffFile
;
userColorScheme
()
{
return
text
?
'
text-file
'
:
'
js-image-file
'
;
return
window
.
gon
.
user_color_scheme
;
},
},
diffFile
()
{
normalizedDiffLines
()
{
return
convertObjectPropsToCamelCase
(
this
.
discussion
.
diffFile
,
{
deep
:
true
});
const
lines
=
this
.
discussion
.
truncatedDiffLines
||
[];
},
imageDiffHtml
()
{
return
this
.
discussion
.
imageDiffHtml
;
},
currentUser
()
{
return
this
.
noteableData
.
current_user
;
},
userColorScheme
()
{
return
window
.
gon
.
user_color_scheme
;
},
normalizedDiffLines
()
{
if
(
this
.
discussion
.
truncatedDiffLines
)
{
return
this
.
discussion
.
truncatedDiffLines
.
map
(
line
=>
trimFirstCharOfLineContent
(
convertObjectPropsToCamelCase
(
line
)),
);
}
return
lines
.
map
(
line
=>
trimFirstCharOfLineContent
(
convertObjectPropsToCamelCase
(
line
)));
return
[];
},
},
},
},
mounted
()
{
mounted
()
{
if
(
this
.
isImageDiff
)
{
if
(
this
.
isImageDiff
)
{
const
canCreateNote
=
false
;
const
canCreateNote
=
false
;
const
renderCommentBadge
=
true
;
const
renderCommentBadge
=
true
;
imageDiffHelper
.
initImageDiff
(
this
.
$refs
.
fileHolder
,
canCreateNote
,
renderCommentBadge
);
imageDiffHelper
.
initImageDiff
(
this
.
$refs
.
fileHolder
,
canCreateNote
,
renderCommentBadge
);
}
else
if
(
!
this
.
hasTruncatedDiffLines
)
{
}
else
if
(
!
this
.
hasTruncatedDiffLines
)
{
this
.
fetchDiff
();
this
.
fetchDiff
();
}
}
},
methods
:
{
...
mapActions
([
'
fetchDiscussionDiffLines
'
]),
rowTag
(
html
)
{
return
html
.
outerHTML
?
'
tr
'
:
'
template
'
;
},
},
fetchDiff
()
{
methods
:
{
this
.
error
=
false
;
...
mapActions
([
'
fetchDiscussionDiffLines
'
]),
this
.
fetchDiscussionDiffLines
(
this
.
discussion
)
rowTag
(
html
)
{
.
then
(
this
.
highlight
)
return
html
.
outerHTML
?
'
tr
'
:
'
template
'
;
.
catch
(()
=>
{
},
this
.
error
=
true
;
fetchDiff
()
{
});
this
.
error
=
false
;
this
.
fetchDiscussionDiffLines
(
this
.
discussion
)
.
then
(
this
.
highlight
)
.
catch
(()
=>
{
this
.
error
=
true
;
});
},
},
},
},
};
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/notes/stores/getters.js
View file @
ca3ea76c
...
@@ -85,9 +85,9 @@ export const allDiscussions = (state, getters) => {
...
@@ -85,9 +85,9 @@ export const allDiscussions = (state, getters) => {
export
const
resolvedDiscussionsById
=
state
=>
{
export
const
resolvedDiscussionsById
=
state
=>
{
const
map
=
{};
const
map
=
{};
state
.
discussions
.
forEach
(
n
=>
{
state
.
discussions
.
f
ilter
(
d
=>
d
.
resolvable
).
f
orEach
(
n
=>
{
if
(
n
.
notes
)
{
if
(
n
.
notes
)
{
const
resolved
=
n
.
notes
.
every
(
note
=>
note
.
resolved
&&
!
note
.
system
);
const
resolved
=
n
.
notes
.
filter
(
note
=>
note
.
resolvable
).
every
(
note
=>
note
.
resolved
);
if
(
resolved
)
{
if
(
resolved
)
{
map
[
n
.
id
]
=
n
;
map
[
n
.
id
]
=
n
;
...
...
app/assets/javascripts/pages/projects/jobs/terminal/index.js
0 → 100644
View file @
ca3ea76c
import
initTerminal
from
'
~/terminal/
'
;
document
.
addEventListener
(
'
DOMContentLoaded
'
,
initTerminal
);
app/assets/javascripts/vue_shared/components/markdown/header.vue
View file @
ca3ea76c
...
@@ -29,8 +29,8 @@
...
@@ -29,8 +29,8 @@
methods
:
{
methods
:
{
isValid
(
form
)
{
isValid
(
form
)
{
return
!
form
||
return
!
form
||
form
.
find
(
'
.js-vue-markdown-field
'
).
length
||
form
.
find
(
'
.js-vue-markdown-field
'
).
length
&&
$
(
this
.
$el
).
closest
(
'
form
'
)
===
form
[
0
];
$
(
this
.
$el
).
closest
(
'
form
'
)
[
0
]
===
form
[
0
];
},
},
previewMarkdownTab
(
event
,
form
)
{
previewMarkdownTab
(
event
,
form
)
{
...
...
app/assets/stylesheets/pages/diff.scss
View file @
ca3ea76c
...
@@ -15,7 +15,7 @@
...
@@ -15,7 +15,7 @@
}
}
svg
{
svg
{
vertical-align
:
text-bottom
;
vertical-align
:
middle
;
}
}
}
}
...
...
app/controllers/concerns/preview_markdown.rb
View file @
ca3ea76c
...
@@ -10,6 +10,7 @@ module PreviewMarkdown
...
@@ -10,6 +10,7 @@ module PreviewMarkdown
when
'wikis'
then
{
pipeline: :wiki
,
project_wiki:
@project_wiki
,
page_slug:
params
[
:id
]
}
when
'wikis'
then
{
pipeline: :wiki
,
project_wiki:
@project_wiki
,
page_slug:
params
[
:id
]
}
when
'snippets'
then
{
skip_project_check:
true
}
when
'snippets'
then
{
skip_project_check:
true
}
when
'groups'
then
{
group:
group
}
when
'groups'
then
{
group:
group
}
when
'projects'
then
{
issuable_state_filter_enabled:
true
}
else
{}
else
{}
end
end
...
...
app/controllers/dashboard/projects_controller.rb
View file @
ca3ea76c
...
@@ -7,7 +7,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
...
@@ -7,7 +7,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
skip_cross_project_access_check
:index
,
:starred
skip_cross_project_access_check
:index
,
:starred
def
index
def
index
@projects
=
load_projects
(
params
.
merge
(
non_public:
true
))
.
page
(
params
[
:page
])
@projects
=
load_projects
(
params
.
merge
(
non_public:
true
))
respond_to
do
|
format
|
respond_to
do
|
format
|
format
.
html
format
.
html
...
@@ -25,7 +25,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
...
@@ -25,7 +25,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
def
starred
def
starred
@projects
=
load_projects
(
params
.
merge
(
starred:
true
))
@projects
=
load_projects
(
params
.
merge
(
starred:
true
))
.
includes
(
:forked_from_project
,
:tags
)
.
page
(
params
[
:page
])
.
includes
(
:forked_from_project
,
:tags
)
@groups
=
[]
@groups
=
[]
...
@@ -51,6 +51,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
...
@@ -51,6 +51,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
.
new
(
params:
finder_params
,
current_user:
current_user
)
.
new
(
params:
finder_params
,
current_user:
current_user
)
.
execute
.
execute
.
includes
(
:route
,
:creator
,
namespace:
[
:route
,
:owner
])
.
includes
(
:route
,
:creator
,
namespace:
[
:route
,
:owner
])
.
page
(
finder_params
[
:page
])
prepare_projects_for_rendering
(
projects
)
prepare_projects_for_rendering
(
projects
)
end
end
...
...
app/controllers/projects/jobs_controller.rb
View file @
ca3ea76c
...
@@ -2,11 +2,12 @@ class Projects::JobsController < Projects::ApplicationController
...
@@ -2,11 +2,12 @@ class Projects::JobsController < Projects::ApplicationController
include
SendFileUpload
include
SendFileUpload
before_action
:build
,
except:
[
:index
,
:cancel_all
]
before_action
:build
,
except:
[
:index
,
:cancel_all
]
before_action
:authorize_read_build!
,
before_action
:authorize_read_build!
only:
[
:index
,
:show
,
:status
,
:raw
,
:trace
]
before_action
:authorize_update_build!
,
before_action
:authorize_update_build!
,
except:
[
:index
,
:show
,
:status
,
:raw
,
:trace
,
:cancel_all
,
:erase
]
except:
[
:index
,
:show
,
:status
,
:raw
,
:trace
,
:cancel_all
,
:erase
]
before_action
:authorize_erase_build!
,
only:
[
:erase
]
before_action
:authorize_erase_build!
,
only:
[
:erase
]
before_action
:authorize_use_build_terminal!
,
only:
[
:terminal
,
:terminal_workhorse_authorize
]
before_action
:verify_api_request!
,
only: :terminal_websocket_authorize
layout
'project'
layout
'project'
...
@@ -134,6 +135,15 @@ class Projects::JobsController < Projects::ApplicationController
...
@@ -134,6 +135,15 @@ class Projects::JobsController < Projects::ApplicationController
end
end
end
end
def
terminal
end
# GET .../terminal.ws : implemented in gitlab-workhorse
def
terminal_websocket_authorize
set_workhorse_internal_api_content_type
render
json:
Gitlab
::
Workhorse
.
terminal_websocket
(
@build
.
terminal_specification
)
end
private
private
def
authorize_update_build!
def
authorize_update_build!
...
@@ -144,6 +154,14 @@ class Projects::JobsController < Projects::ApplicationController
...
@@ -144,6 +154,14 @@ class Projects::JobsController < Projects::ApplicationController
return
access_denied!
unless
can?
(
current_user
,
:erase_build
,
build
)
return
access_denied!
unless
can?
(
current_user
,
:erase_build
,
build
)
end
end
def
authorize_use_build_terminal!
return
access_denied!
unless
can?
(
current_user
,
:create_build_terminal
,
build
)
end
def
verify_api_request!
Gitlab
::
Workhorse
.
verify_api_request!
(
request
.
headers
)
end
def
raw_send_params
def
raw_send_params
{
type:
'text/plain; charset=utf-8'
,
disposition:
'inline'
}
{
type:
'text/plain; charset=utf-8'
,
disposition:
'inline'
}
end
end
...
...
app/helpers/projects_helper.rb
View file @
ca3ea76c
...
@@ -177,6 +177,7 @@ module ProjectsHelper
...
@@ -177,6 +177,7 @@ module ProjectsHelper
controller
.
action_name
,
controller
.
action_name
,
Gitlab
::
CurrentSettings
.
cache_key
,
Gitlab
::
CurrentSettings
.
cache_key
,
"cross-project:
#{
can?
(
current_user
,
:read_cross_project
)
}
"
,
"cross-project:
#{
can?
(
current_user
,
:read_cross_project
)
}
"
,
max_project_member_access_cache_key
(
project
),
'v2.6'
'v2.6'
]
]
...
...
app/helpers/users_helper.rb
View file @
ca3ea76c
...
@@ -31,6 +31,14 @@ module UsersHelper
...
@@ -31,6 +31,14 @@ module UsersHelper
current_user_menu_items
.
include?
(
item
)
current_user_menu_items
.
include?
(
item
)
end
end
def
max_project_member_access
(
project
)
current_user
&
.
max_member_access_for_project
(
project
.
id
)
||
Gitlab
::
Access
::
NO_ACCESS
end
def
max_project_member_access_cache_key
(
project
)
"access:
#{
max_project_member_access
(
project
)
}
"
end
private
private
def
get_profile_tabs
def
get_profile_tabs
...
...
app/models/board.rb
View file @
ca3ea76c
...
@@ -26,4 +26,8 @@ class Board < ActiveRecord::Base
...
@@ -26,4 +26,8 @@ class Board < ActiveRecord::Base
def
closed_list
def
closed_list
lists
.
merge
(
List
.
closed
).
take
lists
.
merge
(
List
.
closed
).
take
end
end
def
scoped?
false
end
end
end
app/models/ci/build.rb
View file @
ca3ea76c
...
@@ -27,7 +27,13 @@ module Ci
...
@@ -27,7 +27,13 @@ module Ci
has_one
:job_artifacts_trace
,
->
{
where
(
file_type:
Ci
::
JobArtifact
.
file_types
[
:trace
])
},
class_name:
'Ci::JobArtifact'
,
inverse_of: :job
,
foreign_key: :job_id
has_one
:job_artifacts_trace
,
->
{
where
(
file_type:
Ci
::
JobArtifact
.
file_types
[
:trace
])
},
class_name:
'Ci::JobArtifact'
,
inverse_of: :job
,
foreign_key: :job_id
has_one
:metadata
,
class_name:
'Ci::BuildMetadata'
has_one
:metadata
,
class_name:
'Ci::BuildMetadata'
has_one
:runner_session
,
class_name:
'Ci::BuildRunnerSession'
,
validate:
true
,
inverse_of: :build
accepts_nested_attributes_for
:runner_session
delegate
:timeout
,
to: :metadata
,
prefix:
true
,
allow_nil:
true
delegate
:timeout
,
to: :metadata
,
prefix:
true
,
allow_nil:
true
delegate
:url
,
to: :runner_session
,
prefix:
true
,
allow_nil:
true
delegate
:terminal_specification
,
to: :runner_session
,
allow_nil:
true
delegate
:gitlab_deploy_token
,
to: :project
delegate
:gitlab_deploy_token
,
to: :project
##
##
...
@@ -174,6 +180,10 @@ module Ci
...
@@ -174,6 +180,10 @@ module Ci
after_transition
pending: :running
do
|
build
|
after_transition
pending: :running
do
|
build
|
build
.
ensure_metadata
.
update_timeout_state
build
.
ensure_metadata
.
update_timeout_state
end
end
after_transition
running:
any
do
|
build
|
Ci
::
BuildRunnerSession
.
where
(
build:
build
).
delete_all
end
end
end
def
ensure_metadata
def
ensure_metadata
...
@@ -376,6 +386,10 @@ module Ci
...
@@ -376,6 +386,10 @@ module Ci
trace
.
exist?
trace
.
exist?
end
end
def
has_old_trace?
old_trace
.
present?
end
def
trace
=
(
data
)
def
trace
=
(
data
)
raise
NotImplementedError
raise
NotImplementedError
end
end
...
@@ -385,6 +399,8 @@ module Ci
...
@@ -385,6 +399,8 @@ module Ci
end
end
def
erase_old_trace!
def
erase_old_trace!
return
unless
has_old_trace?
update_column
(
:trace
,
nil
)
update_column
(
:trace
,
nil
)
end
end
...
@@ -584,6 +600,10 @@ module Ci
...
@@ -584,6 +600,10 @@ module Ci
super
(
options
).
merge
(
when:
read_attribute
(
:when
))
super
(
options
).
merge
(
when:
read_attribute
(
:when
))
end
end
def
has_terminal?
running?
&&
runner_session_url
.
present?
end
private
private
def
update_artifacts_size
def
update_artifacts_size
...
...
app/models/ci/build_runner_session.rb
0 → 100644
View file @
ca3ea76c
module
Ci
# The purpose of this class is to store Build related runner session.
# Data will be removed after transitioning from running to any state.
class
BuildRunnerSession
<
ActiveRecord
::
Base
extend
Gitlab
::
Ci
::
Model
self
.
table_name
=
'ci_builds_runner_session'
belongs_to
:build
,
class_name:
'Ci::Build'
,
inverse_of: :runner_session
validates
:build
,
presence:
true
validates
:url
,
url:
{
protocols:
%w(https)
}
def
terminal_specification
return
{}
unless
url
.
present?
{
subprotocols:
[
'terminal.gitlab.com'
].
freeze
,
url:
"
#{
url
}
/exec"
.
sub
(
"https://"
,
"wss://"
),
headers:
{
Authorization
:
authorization
.
presence
}.
compact
,
ca_pem:
certificate
.
presence
}
end
end
end
app/models/project_services/kubernetes_service.rb
View file @
ca3ea76c
...
@@ -240,7 +240,7 @@ class KubernetesService < DeploymentService
...
@@ -240,7 +240,7 @@ class KubernetesService < DeploymentService
end
end
def
deprecation_validation
def
deprecation_validation
return
if
active_changed?
(
from:
true
,
to:
false
)
return
if
active_changed?
(
from:
true
,
to:
false
)
||
(
new_record?
&&
!
active?
)
if
deprecated?
if
deprecated?
errors
[
:base
]
<<
deprecation_message
errors
[
:base
]
<<
deprecation_message
...
...
app/models/service.rb
View file @
ca3ea76c
...
@@ -281,9 +281,9 @@ class Service < ActiveRecord::Base
...
@@ -281,9 +281,9 @@ class Service < ActiveRecord::Base
def
self
.
build_from_template
(
project_id
,
template
)
def
self
.
build_from_template
(
project_id
,
template
)
service
=
template
.
dup
service
=
template
.
dup
service
.
active
=
false
unless
service
.
valid?
service
.
template
=
false
service
.
template
=
false
service
.
project_id
=
project_id
service
.
project_id
=
project_id
service
.
active
=
false
if
service
.
active?
&&
!
service
.
valid?
service
service
end
end
...
...
app/policies/ci/build_policy.rb
View file @
ca3ea76c
...
@@ -18,6 +18,10 @@ module Ci
...
@@ -18,6 +18,10 @@ module Ci
@subject
.
project
.
branch_allows_collaboration?
(
@user
,
@subject
.
ref
)
@subject
.
project
.
branch_allows_collaboration?
(
@user
,
@subject
.
ref
)
end
end
condition
(
:terminal
,
scope: :subject
)
do
@subject
.
has_terminal?
end
rule
{
protected_ref
}.
policy
do
rule
{
protected_ref
}.
policy
do
prevent
:update_build
prevent
:update_build
prevent
:erase_build
prevent
:erase_build
...
@@ -29,5 +33,7 @@ module Ci
...
@@ -29,5 +33,7 @@ module Ci
enable
:update_build
enable
:update_build
enable
:update_commit_status
enable
:update_commit_status
end
end
rule
{
can?
(
:update_build
)
&
terminal
}.
enable
:create_build_terminal
end
end
end
end
app/services/ci/register_job_service.rb
View file @
ca3ea76c
...
@@ -13,7 +13,7 @@ module Ci
...
@@ -13,7 +13,7 @@ module Ci
@runner
=
runner
@runner
=
runner
end
end
def
execute
def
execute
(
params
=
{})
builds
=
builds
=
if
runner
.
instance_type?
if
runner
.
instance_type?
builds_for_shared_runner
builds_for_shared_runner
...
@@ -41,6 +41,8 @@ module Ci
...
@@ -41,6 +41,8 @@ module Ci
# with StateMachines::InvalidTransition or StaleObjectError when doing run! or save method.
# with StateMachines::InvalidTransition or StaleObjectError when doing run! or save method.
begin
begin
build
.
runner_id
=
runner
.
id
build
.
runner_id
=
runner
.
id
build
.
runner_session_attributes
=
params
[
:session
]
if
params
[
:session
].
present?
build
.
run!
build
.
run!
register_success
(
build
)
register_success
(
build
)
...
...
app/services/issues/base_service.rb
View file @
ca3ea76c
...
@@ -32,8 +32,9 @@ module Issues
...
@@ -32,8 +32,9 @@ module Issues
def
filter_assignee
(
issuable
)
def
filter_assignee
(
issuable
)
return
if
params
[
:assignee_ids
].
blank?
return
if
params
[
:assignee_ids
].
blank?
# The number of assignees is limited by one for GitLab CE
unless
issuable
.
allows_multiple_assignees?
params
[
:assignee_ids
]
=
params
[
:assignee_ids
][
0
,
1
]
params
[
:assignee_ids
]
=
params
[
:assignee_ids
].
take
(
1
)
end
assignee_ids
=
params
[
:assignee_ids
].
select
{
|
assignee_id
|
assignee_can_read?
(
issuable
,
assignee_id
)
}
assignee_ids
=
params
[
:assignee_ids
].
select
{
|
assignee_id
|
assignee_can_read?
(
issuable
,
assignee_id
)
}
...
...
app/views/layouts/header/_current_user_dropdown.html.haml
View file @
ca3ea76c
...
@@ -17,11 +17,7 @@
...
@@ -17,11 +17,7 @@
=
link_to
_
(
"Help"
),
help_path
=
link_to
_
(
"Help"
),
help_path
-
if
current_user_menu?
(
:help
)
||
current_user_menu?
(
:settings
)
||
current_user_menu?
(
:profile
)
-
if
current_user_menu?
(
:help
)
||
current_user_menu?
(
:settings
)
||
current_user_menu?
(
:profile
)
%li
.divider
%li
.divider
%li
=
render
'shared/user_dropdown_contributing_link'
=
link_to
"https://about.gitlab.com/contributing"
,
target:
'_blank'
,
class:
'text-nowrap'
do
=
_
(
"Contribute to GitLab"
)
=
sprite_icon
(
'external-link'
,
size:
16
)
%li
.divider
-
if
current_user_menu?
(
:sign_out
)
-
if
current_user_menu?
(
:sign_out
)
%li
%li
=
link_to
_
(
"Sign out"
),
destroy_user_session_path
,
class:
"sign-out-link"
=
link_to
_
(
"Sign out"
),
destroy_user_session_path
,
class:
"sign-out-link"
app/views/projects/jobs/_sidebar.html.haml
View file @
ca3ea76c
%aside
.right-sidebar.right-sidebar-expanded.build-sidebar.js-build-sidebar.js-right-sidebar
{
data:
{
"offset-top"
=>
"101"
,
"spy"
=>
"affix"
}
}
%aside
.right-sidebar.right-sidebar-expanded.build-sidebar.js-build-sidebar.js-right-sidebar
{
data:
{
"offset-top"
=>
"101"
,
"spy"
=>
"affix"
}
}
.sidebar-container
.sidebar-container
.blocks-container
.blocks-container
-
if
can?
(
current_user
,
:create_build_terminal
,
@build
)
.block
=
link_to
terminal_project_job_path
(
@project
,
@build
),
class:
'terminal-button pull-right btn visible-md-block visible-lg-block'
,
title:
'Terminal'
do
Terminal
#js-details-block-vue
{
data:
{
can_user_retry:
can?
(
current_user
,
:update_build
,
@build
)
&&
@build
.
retryable?
}
}
#js-details-block-vue
{
data:
{
can_user_retry:
can?
(
current_user
,
:update_build
,
@build
)
&&
@build
.
retryable?
}
}
...
@@ -14,8 +18,8 @@
...
@@ -14,8 +18,8 @@
#{
time_ago_with_tooltip
(
@build
.
artifacts_expire_at
)
}
#{
time_ago_with_tooltip
(
@build
.
artifacts_expire_at
)
}
-
elsif
@build
.
has_expiring_artifacts?
-
elsif
@build
.
has_expiring_artifacts?
%p
.build-detail-row
%p
.build-detail-row
The artifacts will be removed
in
The artifacts will be removed
%span
=
time_ago_with_tooltip
@build
.
artifacts_expire_at
#{
time_ago_with_tooltip
(
@build
.
artifacts_expire_at
)
}
-
if
@build
.
artifacts?
-
if
@build
.
artifacts?
.btn-group.d-flex
{
role: :group
}
.btn-group.d-flex
{
role: :group
}
...
...
app/views/projects/jobs/terminal.html.haml
0 → 100644
View file @
ca3ea76c
-
@no_container
=
true
-
add_to_breadcrumbs
'Jobs'
,
project_jobs_path
(
@project
)
-
add_to_breadcrumbs
"#
#{
@build
.
id
}
"
,
project_job_path
(
@project
,
@build
)
-
breadcrumb_title
'Terminal'
-
page_title
'Terminal'
,
"
#{
@build
.
name
}
(#
#{
@build
.
id
}
)"
,
'Jobs'
-
content_for
:page_specific_javascripts
do
=
stylesheet_link_tag
"xterm/xterm"
.terminal-container
{
class:
container_class
}
#terminal
{
data:
{
project_path:
terminal_project_job_path
(
@project
,
@build
,
format: :ws
)
}
}
app/views/projects/settings/ci_cd/_form.html.haml
View file @
ca3ea76c
...
@@ -117,6 +117,9 @@
...
@@ -117,6 +117,9 @@
%li
%li
JaCoCo (Java/Kotlin)
JaCoCo (Java/Kotlin)
%code
Total.*?([0-9]{1,3})%
%code
Total.*?([0-9]{1,3})%
%li
go test -cover (Go)
%code
coverage: \d+.\d+% of statements
=
f
.
submit
_
(
'Save changes'
),
class:
"btn btn-save"
=
f
.
submit
_
(
'Save changes'
),
class:
"btn btn-save"
...
...
app/views/shared/_user_dropdown_contributing_link.html.haml
0 → 100644
View file @
ca3ea76c
%li
=
link_to
"https://about.gitlab.com/contributing"
,
target:
'_blank'
,
class:
'text-nowrap'
do
=
_
(
"Contribute to GitLab"
)
=
sprite_icon
(
'external-link'
,
size:
16
)
%li
.divider
app/views/shared/boards/_show.html.haml
View file @
ca3ea76c
...
@@ -2,8 +2,8 @@
...
@@ -2,8 +2,8 @@
-
group
=
local_assigns
.
fetch
(
:group
,
false
)
-
group
=
local_assigns
.
fetch
(
:group
,
false
)
-
@no_breadcrumb_container
=
true
-
@no_breadcrumb_container
=
true
-
@no_container
=
true
-
@no_container
=
true
-
@content_class
=
"issue-boards-content"
-
@content_class
=
"issue-boards-content
js-focus-mode-board
"
-
breadcrumb_title
_
(
"Issue Board"
)
-
breadcrumb_title
_
(
"Issue Board
s
"
)
-
page_title
_
(
"Boards"
)
-
page_title
_
(
"Boards"
)
-
content_for
:page_specific_javascripts
do
-
content_for
:page_specific_javascripts
do
...
@@ -11,10 +11,11 @@
...
@@ -11,10 +11,11 @@
-# haml-lint:disable InlineJavaScript
-# haml-lint:disable InlineJavaScript
%script
#js-board-template
{
type:
"text/x-template"
}=
render
"shared/boards/components/board"
%script
#js-board-template
{
type:
"text/x-template"
}=
render
"shared/boards/components/board"
%script
#js-board-modal-filter
{
type:
"text/x-template"
}=
render
"shared/issuable/search_bar"
,
type: :boards_modal
%script
#js-board-modal-filter
{
type:
"text/x-template"
}=
render
"shared/issuable/search_bar"
,
type: :boards_modal
%script
#js-board-promotion
{
type:
"text/x-template"
}=
render_if_exists
"shared/promotions/promote_issue_board"
#board-app
.boards-app
{
"v-cloak"
=>
true
,
data:
board_data
,
":class"
=>
"{ 'is-compact': detailIssueVisible }"
}
#board-app
.boards-app
{
"v-cloak"
=>
true
,
data:
board_data
,
":class"
=>
"{ 'is-compact': detailIssueVisible }"
}
.d-none.d-sm-none.d-md-block
.d-none.d-sm-none.d-md-block
=
render
'shared/issuable/search_bar'
,
type: :boards
=
render
'shared/issuable/search_bar'
,
type: :boards
,
board:
board
.boards-list
.boards-list
.boards-app-loading.text-center
{
"v-if"
=>
"loading"
}
.boards-app-loading.text-center
{
"v-if"
=>
"loading"
}
...
...
app/views/shared/issuable/_search_bar.html.haml
View file @
ca3ea76c
-
type
=
local_assigns
.
fetch
(
:type
)
-
type
=
local_assigns
.
fetch
(
:type
)
-
board
=
local_assigns
.
fetch
(
:board
,
nil
)
-
block_css_class
=
type
!=
:boards_modal
?
'row-content-block second-block'
:
''
-
block_css_class
=
type
!=
:boards_modal
?
'row-content-block second-block'
:
''
-
full_path
=
@project
.
present?
?
@project
.
full_path
:
@group
.
full_path
-
full_path
=
@project
.
present?
?
@project
.
full_path
:
@group
.
full_path
-
user_can_admin_list
=
board
&&
can?
(
current_user
,
:admin_list
,
board
.
parent
)
.issues-filters
.issues-filters
.issues-details-filters.filtered-search-block
{
class:
block_css_class
,
"v-pre"
=>
type
==
:boards_modal
}
.issues-details-filters.filtered-search-block
{
class:
block_css_class
,
"v-pre"
=>
type
==
:boards_modal
}
-
if
type
==
:boards
#js-multiple-boards-switcher
.inline.boards-switcher
{
"v-cloak"
=>
true
}
=
render_if_exists
"shared/boards/switcher"
,
board:
board
=
form_tag
page_filter_path
(
without:
[
:assignee_id
,
:author_id
,
:milestone_title
,
:label_name
,
:search
]),
method: :get
,
class:
'filter-form js-filter-form'
do
=
form_tag
page_filter_path
(
without:
[
:assignee_id
,
:author_id
,
:milestone_title
,
:label_name
,
:search
]),
method: :get
,
class:
'filter-form js-filter-form'
do
-
if
params
[
:search
].
present?
-
if
params
[
:search
].
present?
=
hidden_field_tag
:search
,
params
[
:search
]
=
hidden_field_tag
:search
,
params
[
:search
]
...
@@ -99,13 +104,18 @@
...
@@ -99,13 +104,18 @@
%gl-emoji
%gl-emoji
%span
.js-data-value.prepend-left-10
%span
.js-data-value.prepend-left-10
{{name}}
{{name}}
=
render_if_exists
'shared/issuable/filter_weight'
,
type:
type
%button
.clear-search.hidden
{
type:
'button'
}
%button
.clear-search.hidden
{
type:
'button'
}
=
icon
(
'times'
)
=
icon
(
'times'
)
.filter-dropdown-container
.filter-dropdown-container
-
if
type
==
:boards
-
if
type
==
:boards
-
if
can?
(
current_user
,
:admin_list
,
board
.
parent
)
.js-board-config
{
data:
{
can_admin_list:
user_can_admin_list
,
has_scope:
board
.
scoped?
}
}
=
render_if_exists
'shared/issuable/board_create_list_dropdown'
,
board:
board
-
if
user_can_admin_list
=
render
'shared/issuable/board_create_list_dropdown'
,
board:
board
-
if
@project
-
if
@project
#js-add-issues-btn
.prepend-left-10
{
data:
{
can_admin_list:
can?
(
current_user
,
:admin_list
,
@project
)
}
}
#js-add-issues-btn
.prepend-left-10
{
data:
{
can_admin_list:
can?
(
current_user
,
:admin_list
,
@project
)
}
}
#js-toggle-focus-btn
-
elsif
type
!=
:boards_modal
-
elsif
type
!=
:boards_modal
=
render
'shared/sort_dropdown'
=
render
'shared/sort_dropdown'
app/views/shared/projects/_project.html.haml
View file @
ca3ea76c
...
@@ -4,7 +4,7 @@
...
@@ -4,7 +4,7 @@
-
ci
=
false
unless
local_assigns
[
:ci
]
==
true
-
ci
=
false
unless
local_assigns
[
:ci
]
==
true
-
skip_namespace
=
false
unless
local_assigns
[
:skip_namespace
]
==
true
-
skip_namespace
=
false
unless
local_assigns
[
:skip_namespace
]
==
true
-
user
=
local_assigns
[
:user
]
-
user
=
local_assigns
[
:user
]
-
access
=
user
&
.
max_member_access_for_project
(
project
.
id
)
unless
user
.
nil?
-
access
=
max_project_member_access
(
project
)
-
css_class
=
''
unless
local_assigns
[
:css_class
]
-
css_class
=
''
unless
local_assigns
[
:css_class
]
-
show_last_commit_as_description
=
false
unless
local_assigns
[
:show_last_commit_as_description
]
==
true
&&
can_show_last_commit_in_list?
(
project
)
-
show_last_commit_as_description
=
false
unless
local_assigns
[
:show_last_commit_as_description
]
==
true
&&
can_show_last_commit_in_list?
(
project
)
-
css_class
+=
" no-description"
if
project
.
description
.
blank?
&&
!
show_last_commit_as_description
-
css_class
+=
" no-description"
if
project
.
description
.
blank?
&&
!
show_last_commit_as_description
...
...
app/workers/archive_trace_worker.rb
View file @
ca3ea76c
...
@@ -5,7 +5,7 @@ class ArchiveTraceWorker
...
@@ -5,7 +5,7 @@ class ArchiveTraceWorker
include
PipelineBackgroundQueue
include
PipelineBackgroundQueue
def
perform
(
job_id
)
def
perform
(
job_id
)
Ci
::
Build
.
find_by
(
id:
job_id
).
try
do
|
job
|
Ci
::
Build
.
without_archived_trace
.
find_by
(
id:
job_id
).
try
do
|
job
|
job
.
trace
.
archive!
job
.
trace
.
archive!
end
end
end
end
...
...
app/workers/ci/archive_traces_cron_worker.rb
View file @
ca3ea76c
...
@@ -12,6 +12,7 @@ module Ci
...
@@ -12,6 +12,7 @@ module Ci
Ci
::
Build
.
finished
.
with_live_trace
.
find_each
(
batch_size:
100
)
do
|
build
|
Ci
::
Build
.
finished
.
with_live_trace
.
find_each
(
batch_size:
100
)
do
|
build
|
begin
begin
build
.
trace
.
archive!
build
.
trace
.
archive!
rescue
::
Gitlab
::
Ci
::
Trace
::
AlreadyArchivedError
rescue
=>
e
rescue
=>
e
failed_archive_counter
.
increment
failed_archive_counter
.
increment
Rails
.
logger
.
error
"Failed to archive stale live trace. id:
#{
build
.
id
}
message:
#{
e
.
message
}
"
Rails
.
logger
.
error
"Failed to archive stale live trace. id:
#{
build
.
id
}
message:
#{
e
.
message
}
"
...
...
changelogs/unreleased/20357.yml
0 → 100644
View file @
ca3ea76c
---
title
:
Fix double "in" in time to artifact deletion message
merge_request
:
20357
author
:
"
@bbodenmiller"
type
:
fixed
changelogs/unreleased/31583-osw-gfm-complete-status-indication.yml
0 → 100644
View file @
ca3ea76c
---
title
:
Present state indication on GFM preview
merge_request
:
author
:
type
:
added
changelogs/unreleased/44697-when-editing-a-comment-in-an-issue-the-preview-mode-is-toggled-in-the-main-textarea.yml
0 → 100644
View file @
ca3ea76c
---
title
:
Fixed bug when editing a comment in an issue,the preview mode is toggled in
the main textarea
merge_request
:
20112
author
:
Constance Okoghenun
type
:
fixed
changelogs/unreleased/48825-performance.yml
0 → 100644
View file @
ca3ea76c
---
title
:
Improves performance of mr code, by fixing the state being mutated outside
of the store in the util function trimFirstCharOfLineContent and in map operations.
Avoids map operation in an empty array. Adds specs to the trimFirstCharOfLineContent
function
merge_request
:
20380
author
:
filipa
type
:
performance
changelogs/unreleased/dm-invalid-active-service-template.yml
0 → 100644
View file @
ca3ea76c
---
title
:
Deactivate new KubernetesService created from active template to prevent project creation from failing
merge_request
:
author
:
type
:
fixed
changelogs/unreleased/fix-trace-archive-cron-worker-race-condition.yml
0 → 100644
View file @
ca3ea76c
---
title
:
Check if archived trace exist before archive it
merge_request
:
20297
author
:
type
:
fixed
changelogs/unreleased/fj-43565-wrong-role-displayed.yml
0 → 100644
View file @
ca3ea76c
---
title
:
Fix wrong role badge displayed in projects dashboard
merge_request
:
20374
author
:
type
:
fixed
changelogs/unreleased/fj-web-terminal-ci-build.yml
0 → 100644
View file @
ca3ea76c
---
title
:
Add Web Terminal for Ci Builds
merge_request
:
author
:
Vicky Chijwani
type
:
added
changelogs/unreleased/gitaly-timeouts.yml
0 → 100644
View file @
ca3ea76c
---
title
:
Updated Gitaly fail-fast timeout values
merge_request
:
!20259
author
:
type
:
performance
changelogs/unreleased/remove-trace-efficiently.yml
0 → 100644
View file @
ca3ea76c
---
title
:
Remove redundant query when removing trace
merge_request
:
20324
author
:
type
:
performance
config/routes/project.rb
View file @
ca3ea76c
...
@@ -279,6 +279,8 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
...
@@ -279,6 +279,8 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
post
:erase
post
:erase
get
:trace
,
defaults:
{
format:
'json'
}
get
:trace
,
defaults:
{
format:
'json'
}
get
:raw
get
:raw
get
:terminal
get
'/terminal.ws/authorize'
,
to:
'jobs#terminal_websocket_authorize'
,
constraints:
{
format:
nil
}
end
end
resource
:artifacts
,
only:
[]
do
resource
:artifacts
,
only:
[]
do
...
...
db/migrate/20180613081317_create_ci_builds_runner_session.rb
0 → 100644
View file @
ca3ea76c
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class
CreateCiBuildsRunnerSession
<
ActiveRecord
::
Migration
include
Gitlab
::
Database
::
MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME
=
false
def
change
create_table
:ci_builds_runner_session
,
id: :bigserial
do
|
t
|
t
.
integer
:build_id
,
null:
false
t
.
string
:url
,
null:
false
t
.
string
:certificate
t
.
string
:authorization
t
.
foreign_key
:ci_builds
,
column: :build_id
,
on_delete: :cascade
t
.
index
:build_id
,
unique:
true
end
end
end
db/schema.rb
View file @
ca3ea76c
...
@@ -358,6 +358,15 @@ ActiveRecord::Schema.define(version: 20180629191052) do
...
@@ -358,6 +358,15 @@ ActiveRecord::Schema.define(version: 20180629191052) do
add_index
"ci_builds_metadata"
,
[
"build_id"
],
name:
"index_ci_builds_metadata_on_build_id"
,
unique:
true
,
using: :btree
add_index
"ci_builds_metadata"
,
[
"build_id"
],
name:
"index_ci_builds_metadata_on_build_id"
,
unique:
true
,
using: :btree
add_index
"ci_builds_metadata"
,
[
"project_id"
],
name:
"index_ci_builds_metadata_on_project_id"
,
using: :btree
add_index
"ci_builds_metadata"
,
[
"project_id"
],
name:
"index_ci_builds_metadata_on_project_id"
,
using: :btree
create_table
"ci_builds_runner_session"
,
id: :bigserial
,
force: :cascade
do
|
t
|
t
.
integer
"build_id"
,
null:
false
t
.
string
"url"
,
null:
false
t
.
string
"certificate"
t
.
string
"authorization"
end
add_index
"ci_builds_runner_session"
,
[
"build_id"
],
name:
"index_ci_builds_runner_session_on_build_id"
,
unique:
true
,
using: :btree
create_table
"ci_group_variables"
,
force: :cascade
do
|
t
|
create_table
"ci_group_variables"
,
force: :cascade
do
|
t
|
t
.
string
"key"
,
null:
false
t
.
string
"key"
,
null:
false
t
.
text
"value"
t
.
text
"value"
...
@@ -2191,6 +2200,7 @@ ActiveRecord::Schema.define(version: 20180629191052) do
...
@@ -2191,6 +2200,7 @@ ActiveRecord::Schema.define(version: 20180629191052) do
add_foreign_key
"ci_builds"
,
"projects"
,
name:
"fk_befce0568a"
,
on_delete: :cascade
add_foreign_key
"ci_builds"
,
"projects"
,
name:
"fk_befce0568a"
,
on_delete: :cascade
add_foreign_key
"ci_builds_metadata"
,
"ci_builds"
,
column:
"build_id"
,
on_delete: :cascade
add_foreign_key
"ci_builds_metadata"
,
"ci_builds"
,
column:
"build_id"
,
on_delete: :cascade
add_foreign_key
"ci_builds_metadata"
,
"projects"
,
on_delete: :cascade
add_foreign_key
"ci_builds_metadata"
,
"projects"
,
on_delete: :cascade
add_foreign_key
"ci_builds_runner_session"
,
"ci_builds"
,
column:
"build_id"
,
on_delete: :cascade
add_foreign_key
"ci_group_variables"
,
"namespaces"
,
column:
"group_id"
,
name:
"fk_33ae4d58d8"
,
on_delete: :cascade
add_foreign_key
"ci_group_variables"
,
"namespaces"
,
column:
"group_id"
,
name:
"fk_33ae4d58d8"
,
on_delete: :cascade
add_foreign_key
"ci_job_artifacts"
,
"ci_builds"
,
column:
"job_id"
,
on_delete: :cascade
add_foreign_key
"ci_job_artifacts"
,
"ci_builds"
,
column:
"job_id"
,
on_delete: :cascade
add_foreign_key
"ci_job_artifacts"
,
"projects"
,
on_delete: :cascade
add_foreign_key
"ci_job_artifacts"
,
"projects"
,
on_delete: :cascade
...
...
doc/api/projects.md
View file @
ca3ea76c
...
@@ -511,6 +511,39 @@ GET /projects/:id
...
@@ -511,6 +511,39 @@ GET /projects/:id
}
}
```
```
If the project is a fork, and you provide a valid token to authenticate, the
`forked_from_project`
field will appear in the response.
```
json
{
"id"
:
3
,
...
"forked_from_project"
:{
"id"
:
13083
,
"description"
:
"GitLab Community Edition"
,
"name"
:
"GitLab Community Edition"
,
"name_with_namespace"
:
"GitLab.org / GitLab Community Edition"
,
"path"
:
"gitlab-ce"
,
"path_with_namespace"
:
"gitlab-org/gitlab-ce"
,
"created_at"
:
"2013-09-26T06:02:36.000Z"
,
"default_branch"
:
"master"
,
"tag_list"
:[],
"ssh_url_to_repo"
:
"git@gitlab.com:gitlab-org/gitlab-ce.git"
,
"http_url_to_repo"
:
"https://gitlab.com/gitlab-org/gitlab-ce.git"
,
"web_url"
:
"https://gitlab.com/gitlab-org/gitlab-ce"
,
"avatar_url"
:
"https://assets.gitlab-static.net/uploads/-/system/project/avatar/13083/logo-extra-whitespace.png"
,
"star_count"
:
3812
,
"forks_count"
:
3561
,
"last_activity_at"
:
"2018-01-02T11:40:26.570Z"
}
...
}
```
## Get project users
## Get project users
Get the users list of a project.
Get the users list of a project.
...
...
doc/ci/examples/container_scanning.md
View file @
ca3ea76c
...
@@ -57,9 +57,9 @@ so, the CI/CD job must be named `container_scanning` and the artifact path must
...
@@ -57,9 +57,9 @@ so, the CI/CD job must be named `container_scanning` and the artifact path must
[
Learn more on container scanning results shown in merge requests
](
https://docs.gitlab.com/ee/user/project/merge_requests/container_scanning.html
)
.
[
Learn more on container scanning results shown in merge requests
](
https://docs.gitlab.com/ee/user/project/merge_requests/container_scanning.html
)
.
CAUTION:
**Caution:**
CAUTION:
**Caution:**
Container Scanning was previously using
`sast:container`
for job name and
Before GitLab 11.0,
Container Scanning was previously using
`sast:container`
for job name and
`gl-sast-container-report.json`
for the artifact name. While these old names
`gl-sast-container-report.json`
for the artifact name. While these old names
are still maintained they have been deprecated with GitLab 11.0 and may be removed
are still maintained
,
they have been deprecated with GitLab 11.0 and may be removed
in next major release, GitLab 12.0. You are advised to update your current
`.gitlab-ci.yml`
in next major release, GitLab 12.0. You are advised to update your current
`.gitlab-ci.yml`
configuration to reflect that change.
configuration to reflect that change.
...
...
lib/api/entities.rb
View file @
ca3ea76c
...
@@ -1203,6 +1203,7 @@ module API
...
@@ -1203,6 +1203,7 @@ module API
class
RunnerInfo
<
Grape
::
Entity
class
RunnerInfo
<
Grape
::
Entity
expose
:metadata_timeout
,
as: :timeout
expose
:metadata_timeout
,
as: :timeout
expose
:runner_session_url
end
end
class
Step
<
Grape
::
Entity
class
Step
<
Grape
::
Entity
...
...
lib/api/runner.rb
View file @
ca3ea76c
...
@@ -81,6 +81,11 @@ module API
...
@@ -81,6 +81,11 @@ module API
requires
:token
,
type:
String
,
desc:
%q(Runner's authentication token)
requires
:token
,
type:
String
,
desc:
%q(Runner's authentication token)
optional
:last_update
,
type:
String
,
desc:
%q(Runner's queue last_update token)
optional
:last_update
,
type:
String
,
desc:
%q(Runner's queue last_update token)
optional
:info
,
type:
Hash
,
desc:
%q(Runner's metadata)
optional
:info
,
type:
Hash
,
desc:
%q(Runner's metadata)
optional
:session
,
type:
Hash
,
desc:
%q(Runner's session data)
do
optional
:url
,
type:
String
,
desc:
%q(Session's url)
optional
:certificate
,
type:
String
,
desc:
%q(Session's certificate)
optional
:authorization
,
type:
String
,
desc:
%q(Session's authorization)
end
end
end
post
'/request'
do
post
'/request'
do
authenticate_runner!
authenticate_runner!
...
@@ -90,14 +95,16 @@ module API
...
@@ -90,14 +95,16 @@ module API
break
no_content!
break
no_content!
end
end
if
current_runner
.
runner_queue_value_latest?
(
params
[
:last_update
])
runner_params
=
declared_params
(
include_missing:
false
)
header
'X-GitLab-Last-Update'
,
params
[
:last_update
]
if
current_runner
.
runner_queue_value_latest?
(
runner_params
[
:last_update
])
header
'X-GitLab-Last-Update'
,
runner_params
[
:last_update
]
Gitlab
::
Metrics
.
add_event
(
:build_not_found_cached
)
Gitlab
::
Metrics
.
add_event
(
:build_not_found_cached
)
break
no_content!
break
no_content!
end
end
new_update
=
current_runner
.
ensure_runner_queue_value
new_update
=
current_runner
.
ensure_runner_queue_value
result
=
::
Ci
::
RegisterJobService
.
new
(
current_runner
).
execute
result
=
::
Ci
::
RegisterJobService
.
new
(
current_runner
).
execute
(
runner_params
)
if
result
.
valid?
if
result
.
valid?
if
result
.
build
if
result
.
build
...
...
lib/gitlab/ci/trace.rb
View file @
ca3ea76c
...
@@ -6,6 +6,7 @@ module Gitlab
...
@@ -6,6 +6,7 @@ module Gitlab
LEASE_TIMEOUT
=
1
.
hour
LEASE_TIMEOUT
=
1
.
hour
ArchiveError
=
Class
.
new
(
StandardError
)
ArchiveError
=
Class
.
new
(
StandardError
)
AlreadyArchivedError
=
Class
.
new
(
StandardError
)
attr_reader
:job
attr_reader
:job
...
@@ -81,7 +82,9 @@ module Gitlab
...
@@ -81,7 +82,9 @@ module Gitlab
def
write
(
mode
)
def
write
(
mode
)
stream
=
Gitlab
::
Ci
::
Trace
::
Stream
.
new
do
stream
=
Gitlab
::
Ci
::
Trace
::
Stream
.
new
do
if
current_path
if
trace_artifact
raise
AlreadyArchivedError
,
'Could not write to the archived trace'
elsif
current_path
File
.
open
(
current_path
,
mode
)
File
.
open
(
current_path
,
mode
)
elsif
Feature
.
enabled?
(
'ci_enable_live_trace'
)
elsif
Feature
.
enabled?
(
'ci_enable_live_trace'
)
Gitlab
::
Ci
::
Trace
::
ChunkedIO
.
new
(
job
)
Gitlab
::
Ci
::
Trace
::
ChunkedIO
.
new
(
job
)
...
@@ -98,14 +101,17 @@ module Gitlab
...
@@ -98,14 +101,17 @@ module Gitlab
end
end
def
erase!
def
erase!
trace_artifact
&
.
destroy
##
# Erase the archived trace
paths
.
each
do
|
trace_path
|
trace_artifact
&
.
destroy!
FileUtils
.
rm
(
trace_path
,
force:
true
)
end
##
# Erase the live trace
job
.
trace_chunks
.
fast_destroy_all
job
.
trace_chunks
.
fast_destroy_all
# Destroy chunks of a live trace
job
.
erase_old_trace!
FileUtils
.
rm_f
(
current_path
)
if
current_path
# Remove a trace file of a live trace
job
.
erase_old_trace!
if
job
.
has_old_trace?
# Remove a trace in database of a live trace
ensure
@current_path
=
nil
end
end
def
archive!
def
archive!
...
@@ -117,7 +123,7 @@ module Gitlab
...
@@ -117,7 +123,7 @@ module Gitlab
private
private
def
unsafe_archive!
def
unsafe_archive!
raise
A
rchiveError
,
'Already archived
'
if
trace_artifact
raise
A
lreadyArchivedError
,
'Could not archive again
'
if
trace_artifact
raise
ArchiveError
,
'Job is not finished yet'
unless
job
.
complete?
raise
ArchiveError
,
'Job is not finished yet'
unless
job
.
complete?
if
job
.
trace_chunks
.
any?
if
job
.
trace_chunks
.
any?
...
...
lib/gitlab/git/commit.rb
View file @
ca3ea76c
...
@@ -63,8 +63,12 @@ module Gitlab
...
@@ -63,8 +63,12 @@ module Gitlab
# This saves us an RPC round trip.
# This saves us an RPC round trip.
return
nil
if
commit_id
.
include?
(
':'
)
return
nil
if
commit_id
.
include?
(
':'
)
commit
=
repo
.
wrapped_gitaly_errors
do
commit
=
repo
.
gitaly_migrate
(
:find_commit
)
do
|
is_enabled
|
repo
.
gitaly_commit_client
.
find_commit
(
commit_id
)
if
is_enabled
repo
.
gitaly_commit_client
.
find_commit
(
commit_id
)
else
rugged_find
(
repo
,
commit_id
)
end
end
end
decorate
(
repo
,
commit
)
if
commit
decorate
(
repo
,
commit
)
if
commit
...
@@ -74,6 +78,12 @@ module Gitlab
...
@@ -74,6 +78,12 @@ module Gitlab
nil
nil
end
end
def
rugged_find
(
repo
,
commit_id
)
obj
=
repo
.
rev_parse_target
(
commit_id
)
obj
.
is_a?
(
Rugged
::
Commit
)
?
obj
:
nil
end
# Get last commit for HEAD
# Get last commit for HEAD
#
#
# Ex.
# Ex.
...
...
lib/gitlab/git/conflict/resolver.rb
View file @
ca3ea76c
...
@@ -12,8 +12,14 @@ module Gitlab
...
@@ -12,8 +12,14 @@ module Gitlab
end
end
def
conflicts
def
conflicts
@conflicts
||=
@target_repository
.
wrapped_gitaly_errors
do
@conflicts
||=
begin
gitaly_conflicts_client
(
@target_repository
).
list_conflict_files
.
to_a
@target_repository
.
gitaly_migrate
(
:conflicts_list_conflict_files
)
do
|
is_enabled
|
if
is_enabled
gitaly_conflicts_client
(
@target_repository
).
list_conflict_files
.
to_a
else
rugged_list_conflict_files
end
end
end
end
rescue
GRPC
::
FailedPrecondition
=>
e
rescue
GRPC
::
FailedPrecondition
=>
e
raise
Gitlab
::
Git
::
Conflict
::
Resolver
::
ConflictSideMissing
.
new
(
e
.
message
)
raise
Gitlab
::
Git
::
Conflict
::
Resolver
::
ConflictSideMissing
.
new
(
e
.
message
)
...
@@ -22,8 +28,12 @@ module Gitlab
...
@@ -22,8 +28,12 @@ module Gitlab
end
end
def
resolve_conflicts
(
source_repository
,
resolution
,
source_branch
:,
target_branch
:)
def
resolve_conflicts
(
source_repository
,
resolution
,
source_branch
:,
target_branch
:)
source_repository
.
wrapped_gitaly_errors
do
source_repository
.
gitaly_migrate
(
:conflicts_resolve_conflicts
)
do
|
is_enabled
|
gitaly_conflicts_client
(
source_repository
).
resolve_conflicts
(
@target_repository
,
resolution
,
source_branch
,
target_branch
)
if
is_enabled
gitaly_conflicts_client
(
source_repository
).
resolve_conflicts
(
@target_repository
,
resolution
,
source_branch
,
target_branch
)
else
rugged_resolve_conflicts
(
source_repository
,
resolution
,
source_branch
,
target_branch
)
end
end
end
end
end
...
@@ -51,6 +61,57 @@ module Gitlab
...
@@ -51,6 +61,57 @@ module Gitlab
def
gitaly_conflicts_client
(
repository
)
def
gitaly_conflicts_client
(
repository
)
repository
.
gitaly_conflicts_client
(
@our_commit_oid
,
@their_commit_oid
)
repository
.
gitaly_conflicts_client
(
@our_commit_oid
,
@their_commit_oid
)
end
end
def
write_resolved_file_to_index
(
repository
,
index
,
file
,
params
)
if
params
[
:sections
]
resolved_lines
=
file
.
resolve_lines
(
params
[
:sections
])
new_file
=
resolved_lines
.
map
{
|
line
|
line
[
:full_line
]
}.
join
(
"
\n
"
)
new_file
<<
"
\n
"
if
file
.
our_blob
.
data
.
end_with?
(
"
\n
"
)
elsif
params
[
:content
]
new_file
=
file
.
resolve_content
(
params
[
:content
])
end
our_path
=
file
.
our_path
oid
=
repository
.
rugged
.
write
(
new_file
,
:blob
)
index
.
add
(
path:
our_path
,
oid:
oid
,
mode:
file
.
our_mode
)
index
.
conflict_remove
(
our_path
)
end
def
rugged_list_conflict_files
target_index
=
@target_repository
.
rugged
.
merge_commits
(
@our_commit_oid
,
@their_commit_oid
)
# We don't need to do `with_repo_branch_commit` here, because the target
# project always fetches source refs when creating merge request diffs.
conflict_files
(
@target_repository
,
target_index
)
end
def
rugged_resolve_conflicts
(
source_repository
,
resolution
,
source_branch
,
target_branch
)
source_repository
.
with_repo_branch_commit
(
@target_repository
,
target_branch
)
do
index
=
source_repository
.
rugged
.
merge_commits
(
@our_commit_oid
,
@their_commit_oid
)
conflicts
=
conflict_files
(
source_repository
,
index
)
resolution
.
files
.
each
do
|
file_params
|
conflict_file
=
conflict_for_path
(
conflicts
,
file_params
[
:old_path
],
file_params
[
:new_path
])
write_resolved_file_to_index
(
source_repository
,
index
,
conflict_file
,
file_params
)
end
unless
index
.
conflicts
.
empty?
missing_files
=
index
.
conflicts
.
map
{
|
file
|
file
[
:ours
][
:path
]
}
raise
ResolutionError
,
"Missing resolutions for the following files:
#{
missing_files
.
join
(
', '
)
}
"
end
commit_params
=
{
message:
resolution
.
commit_message
,
parents:
[
@our_commit_oid
,
@their_commit_oid
]
}
source_repository
.
commit_index
(
resolution
.
user
,
source_branch
,
index
,
commit_params
)
end
end
end
end
end
end
end
end
...
...
lib/gitlab/git/repository.rb
View file @
ca3ea76c
...
@@ -555,8 +555,12 @@ module Gitlab
...
@@ -555,8 +555,12 @@ module Gitlab
# diff options. The +options+ hash can also include :break_rewrites to
# diff options. The +options+ hash can also include :break_rewrites to
# split larger rewrites into delete/add pairs.
# split larger rewrites into delete/add pairs.
def
diff
(
from
,
to
,
options
=
{},
*
paths
)
def
diff
(
from
,
to
,
options
=
{},
*
paths
)
iterator
=
wrapped_gitaly_errors
do
iterator
=
gitaly_migrate
(
:diff_between
)
do
|
is_enabled
|
gitaly_commit_client
.
diff
(
from
,
to
,
options
.
merge
(
paths:
paths
))
if
is_enabled
gitaly_commit_client
.
diff
(
from
,
to
,
options
.
merge
(
paths:
paths
))
else
diff_patches
(
from
,
to
,
options
,
*
paths
)
end
end
end
Gitlab
::
Git
::
DiffCollection
.
new
(
iterator
,
options
)
Gitlab
::
Git
::
DiffCollection
.
new
(
iterator
,
options
)
...
@@ -1587,6 +1591,17 @@ module Gitlab
...
@@ -1587,6 +1591,17 @@ module Gitlab
tmp_entry
tmp_entry
end
end
# Return the Rugged patches for the diff between +from+ and +to+.
def
diff_patches
(
from
,
to
,
options
=
{},
*
paths
)
options
||=
{}
break_rewrites
=
options
[
:break_rewrites
]
actual_options
=
Gitlab
::
Git
::
Diff
.
filter_diff_options
(
options
.
merge
(
paths:
paths
))
diff
=
rugged
.
diff
(
from
,
to
,
actual_options
)
diff
.
find_similar!
(
break_rewrites:
break_rewrites
)
diff
.
each_patch
end
def
sort_branches
(
branches
,
sort_by
)
def
sort_branches
(
branches
,
sort_by
)
case
sort_by
case
sort_by
when
'name'
when
'name'
...
...
lib/gitlab/gitaly_client/blob_service.rb
View file @
ca3ea76c
...
@@ -13,7 +13,7 @@ module Gitlab
...
@@ -13,7 +13,7 @@ module Gitlab
oid:
oid
,
oid:
oid
,
limit:
limit
limit:
limit
)
)
response
=
GitalyClient
.
call
(
@gitaly_repo
.
storage_name
,
:blob_service
,
:get_blob
,
request
)
response
=
GitalyClient
.
call
(
@gitaly_repo
.
storage_name
,
:blob_service
,
:get_blob
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
data
=
''
data
=
''
blob
=
nil
blob
=
nil
...
@@ -43,7 +43,7 @@ module Gitlab
...
@@ -43,7 +43,7 @@ module Gitlab
blob_ids:
blob_ids
blob_ids:
blob_ids
)
)
response
=
GitalyClient
.
call
(
@gitaly_repo
.
storage_name
,
:blob_service
,
:get_lfs_pointers
,
request
)
response
=
GitalyClient
.
call
(
@gitaly_repo
.
storage_name
,
:blob_service
,
:get_lfs_pointers
,
request
,
timeout:
GitalyClient
.
medium_timeout
)
map_lfs_pointers
(
response
)
map_lfs_pointers
(
response
)
end
end
...
@@ -66,7 +66,7 @@ module Gitlab
...
@@ -66,7 +66,7 @@ module Gitlab
:blob_service
,
:blob_service
,
:get_blobs
,
:get_blobs
,
request
,
request
,
timeout:
GitalyClient
.
defaul
t_timeout
timeout:
GitalyClient
.
fas
t_timeout
)
)
GitalyClient
::
BlobsStitcher
.
new
(
response
)
GitalyClient
::
BlobsStitcher
.
new
(
response
)
...
@@ -85,7 +85,7 @@ module Gitlab
...
@@ -85,7 +85,7 @@ module Gitlab
request
.
not_in_refs
+=
not_in
request
.
not_in_refs
+=
not_in
end
end
response
=
GitalyClient
.
call
(
@gitaly_repo
.
storage_name
,
:blob_service
,
:get_new_lfs_pointers
,
request
)
response
=
GitalyClient
.
call
(
@gitaly_repo
.
storage_name
,
:blob_service
,
:get_new_lfs_pointers
,
request
,
timeout:
GitalyClient
.
medium_timeout
)
map_lfs_pointers
(
response
)
map_lfs_pointers
(
response
)
end
end
...
@@ -96,7 +96,7 @@ module Gitlab
...
@@ -96,7 +96,7 @@ module Gitlab
revision:
encode_binary
(
revision
)
revision:
encode_binary
(
revision
)
)
)
response
=
GitalyClient
.
call
(
@gitaly_repo
.
storage_name
,
:blob_service
,
:get_all_lfs_pointers
,
request
)
response
=
GitalyClient
.
call
(
@gitaly_repo
.
storage_name
,
:blob_service
,
:get_all_lfs_pointers
,
request
,
timeout:
GitalyClient
.
medium_timeout
)
map_lfs_pointers
(
response
)
map_lfs_pointers
(
response
)
end
end
...
...
lib/gitlab/gitaly_client/commit_service.rb
View file @
ca3ea76c
...
@@ -70,7 +70,7 @@ module Gitlab
...
@@ -70,7 +70,7 @@ module Gitlab
def
commit_deltas
(
commit
)
def
commit_deltas
(
commit
)
request
=
Gitaly
::
CommitDeltaRequest
.
new
(
diff_from_parent_request_params
(
commit
))
request
=
Gitaly
::
CommitDeltaRequest
.
new
(
diff_from_parent_request_params
(
commit
))
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:diff_service
,
:commit_delta
,
request
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:diff_service
,
:commit_delta
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
response
.
flat_map
{
|
msg
|
msg
.
deltas
}
response
.
flat_map
{
|
msg
|
msg
.
deltas
}
end
end
...
@@ -302,7 +302,7 @@ module Gitlab
...
@@ -302,7 +302,7 @@ module Gitlab
end
end
end
end
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:commit_service
,
:filter_shas_with_signatures
,
enum
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:commit_service
,
:filter_shas_with_signatures
,
enum
,
timeout:
GitalyClient
.
fast_timeout
)
response
.
flat_map
do
|
msg
|
response
.
flat_map
do
|
msg
|
msg
.
shas
.
map
{
|
sha
|
EncodingHelper
.
encode!
(
sha
)
}
msg
.
shas
.
map
{
|
sha
|
EncodingHelper
.
encode!
(
sha
)
}
...
@@ -330,7 +330,7 @@ module Gitlab
...
@@ -330,7 +330,7 @@ module Gitlab
def
get_commit_signatures
(
commit_ids
)
def
get_commit_signatures
(
commit_ids
)
request
=
Gitaly
::
GetCommitSignaturesRequest
.
new
(
repository:
@gitaly_repo
,
commit_ids:
commit_ids
)
request
=
Gitaly
::
GetCommitSignaturesRequest
.
new
(
repository:
@gitaly_repo
,
commit_ids:
commit_ids
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:commit_service
,
:get_commit_signatures
,
request
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:commit_service
,
:get_commit_signatures
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
signatures
=
Hash
.
new
{
|
h
,
k
|
h
[
k
]
=
[
''
.
b
,
''
.
b
]
}
signatures
=
Hash
.
new
{
|
h
,
k
|
h
[
k
]
=
[
''
.
b
,
''
.
b
]
}
current_commit_id
=
nil
current_commit_id
=
nil
...
@@ -349,7 +349,7 @@ module Gitlab
...
@@ -349,7 +349,7 @@ module Gitlab
def
get_commit_messages
(
commit_ids
)
def
get_commit_messages
(
commit_ids
)
request
=
Gitaly
::
GetCommitMessagesRequest
.
new
(
repository:
@gitaly_repo
,
commit_ids:
commit_ids
)
request
=
Gitaly
::
GetCommitMessagesRequest
.
new
(
repository:
@gitaly_repo
,
commit_ids:
commit_ids
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:commit_service
,
:get_commit_messages
,
request
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:commit_service
,
:get_commit_messages
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
messages
=
Hash
.
new
{
|
h
,
k
|
h
[
k
]
=
''
.
b
}
messages
=
Hash
.
new
{
|
h
,
k
|
h
[
k
]
=
''
.
b
}
current_commit_id
=
nil
current_commit_id
=
nil
...
...
lib/gitlab/gitaly_client/conflicts_service.rb
View file @
ca3ea76c
...
@@ -46,7 +46,7 @@ module Gitlab
...
@@ -46,7 +46,7 @@ module Gitlab
end
end
end
end
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:conflicts_service
,
:resolve_conflicts
,
req_enum
,
remote_storage:
target_repository
.
storage
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:conflicts_service
,
:resolve_conflicts
,
req_enum
,
remote_storage:
target_repository
.
storage
,
timeout:
GitalyClient
.
medium_timeout
)
if
response
.
resolution_error
.
present?
if
response
.
resolution_error
.
present?
raise
Gitlab
::
Git
::
Conflict
::
Resolver
::
ResolutionError
,
response
.
resolution_error
raise
Gitlab
::
Git
::
Conflict
::
Resolver
::
ResolutionError
,
response
.
resolution_error
...
...
lib/gitlab/gitaly_client/namespace_service.rb
View file @
ca3ea76c
...
@@ -8,31 +8,31 @@ module Gitlab
...
@@ -8,31 +8,31 @@ module Gitlab
def
exists?
(
name
)
def
exists?
(
name
)
request
=
Gitaly
::
NamespaceExistsRequest
.
new
(
storage_name:
@storage
,
name:
name
)
request
=
Gitaly
::
NamespaceExistsRequest
.
new
(
storage_name:
@storage
,
name:
name
)
gitaly_client_call
(
:namespace_exists
,
request
).
exists
gitaly_client_call
(
:namespace_exists
,
request
,
timeout:
GitalyClient
.
fast_timeout
).
exists
end
end
def
add
(
name
)
def
add
(
name
)
request
=
Gitaly
::
AddNamespaceRequest
.
new
(
storage_name:
@storage
,
name:
name
)
request
=
Gitaly
::
AddNamespaceRequest
.
new
(
storage_name:
@storage
,
name:
name
)
gitaly_client_call
(
:add_namespace
,
request
)
gitaly_client_call
(
:add_namespace
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
end
end
def
remove
(
name
)
def
remove
(
name
)
request
=
Gitaly
::
RemoveNamespaceRequest
.
new
(
storage_name:
@storage
,
name:
name
)
request
=
Gitaly
::
RemoveNamespaceRequest
.
new
(
storage_name:
@storage
,
name:
name
)
gitaly_client_call
(
:remove_namespace
,
request
)
gitaly_client_call
(
:remove_namespace
,
request
,
timeout:
nil
)
end
end
def
rename
(
from
,
to
)
def
rename
(
from
,
to
)
request
=
Gitaly
::
RenameNamespaceRequest
.
new
(
storage_name:
@storage
,
from:
from
,
to:
to
)
request
=
Gitaly
::
RenameNamespaceRequest
.
new
(
storage_name:
@storage
,
from:
from
,
to:
to
)
gitaly_client_call
(
:rename_namespace
,
request
)
gitaly_client_call
(
:rename_namespace
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
end
end
private
private
def
gitaly_client_call
(
type
,
request
)
def
gitaly_client_call
(
type
,
request
,
timeout:
nil
)
GitalyClient
.
call
(
@storage
,
:namespace_service
,
type
,
request
)
GitalyClient
.
call
(
@storage
,
:namespace_service
,
type
,
request
,
timeout:
timeout
)
end
end
end
end
end
end
...
...
lib/gitlab/gitaly_client/operation_service.rb
View file @
ca3ea76c
...
@@ -17,7 +17,7 @@ module Gitlab
...
@@ -17,7 +17,7 @@ module Gitlab
user:
Gitlab
::
Git
::
User
.
from_gitlab
(
user
).
to_gitaly
user:
Gitlab
::
Git
::
User
.
from_gitlab
(
user
).
to_gitaly
)
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:operation_service
,
:user_delete_tag
,
request
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:operation_service
,
:user_delete_tag
,
request
,
timeout:
GitalyClient
.
medium_timeout
)
if
pre_receive_error
=
response
.
pre_receive_error
.
presence
if
pre_receive_error
=
response
.
pre_receive_error
.
presence
raise
Gitlab
::
Git
::
PreReceiveError
,
pre_receive_error
raise
Gitlab
::
Git
::
PreReceiveError
,
pre_receive_error
...
@@ -33,7 +33,7 @@ module Gitlab
...
@@ -33,7 +33,7 @@ module Gitlab
message:
encode_binary
(
message
.
to_s
)
message:
encode_binary
(
message
.
to_s
)
)
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:operation_service
,
:user_create_tag
,
request
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:operation_service
,
:user_create_tag
,
request
,
timeout:
GitalyClient
.
medium_timeout
)
if
pre_receive_error
=
response
.
pre_receive_error
.
presence
if
pre_receive_error
=
response
.
pre_receive_error
.
presence
raise
Gitlab
::
Git
::
PreReceiveError
,
pre_receive_error
raise
Gitlab
::
Git
::
PreReceiveError
,
pre_receive_error
elsif
response
.
exists
elsif
response
.
exists
...
@@ -276,7 +276,8 @@ module Gitlab
...
@@ -276,7 +276,8 @@ module Gitlab
:operation_service
,
:operation_service
,
:"user_
#{
rpc
}
"
,
:"user_
#{
rpc
}
"
,
request
,
request
,
remote_storage:
start_repository
.
storage
remote_storage:
start_repository
.
storage
,
timeout:
GitalyClient
.
medium_timeout
)
)
handle_cherry_pick_or_revert_response
(
response
)
handle_cherry_pick_or_revert_response
(
response
)
...
...
lib/gitlab/gitaly_client/ref_service.rb
View file @
ca3ea76c
...
@@ -12,7 +12,7 @@ module Gitlab
...
@@ -12,7 +12,7 @@ module Gitlab
def
branches
def
branches
request
=
Gitaly
::
FindAllBranchesRequest
.
new
(
repository:
@gitaly_repo
)
request
=
Gitaly
::
FindAllBranchesRequest
.
new
(
repository:
@gitaly_repo
)
response
=
GitalyClient
.
call
(
@storage
,
:ref_service
,
:find_all_branches
,
request
)
response
=
GitalyClient
.
call
(
@storage
,
:ref_service
,
:find_all_branches
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
consume_find_all_branches_response
(
response
)
consume_find_all_branches_response
(
response
)
end
end
...
@@ -23,26 +23,26 @@ module Gitlab
...
@@ -23,26 +23,26 @@ module Gitlab
merged_only:
true
,
merged_only:
true
,
merged_branches:
branch_names
.
map
{
|
s
|
encode_binary
(
s
)
}
merged_branches:
branch_names
.
map
{
|
s
|
encode_binary
(
s
)
}
)
)
response
=
GitalyClient
.
call
(
@storage
,
:ref_service
,
:find_all_branches
,
request
)
response
=
GitalyClient
.
call
(
@storage
,
:ref_service
,
:find_all_branches
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
consume_find_all_branches_response
(
response
)
consume_find_all_branches_response
(
response
)
end
end
def
default_branch_name
def
default_branch_name
request
=
Gitaly
::
FindDefaultBranchNameRequest
.
new
(
repository:
@gitaly_repo
)
request
=
Gitaly
::
FindDefaultBranchNameRequest
.
new
(
repository:
@gitaly_repo
)
response
=
GitalyClient
.
call
(
@storage
,
:ref_service
,
:find_default_branch_name
,
request
)
response
=
GitalyClient
.
call
(
@storage
,
:ref_service
,
:find_default_branch_name
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
Gitlab
::
Git
.
branch_name
(
response
.
name
)
Gitlab
::
Git
.
branch_name
(
response
.
name
)
end
end
def
branch_names
def
branch_names
request
=
Gitaly
::
FindAllBranchNamesRequest
.
new
(
repository:
@gitaly_repo
)
request
=
Gitaly
::
FindAllBranchNamesRequest
.
new
(
repository:
@gitaly_repo
)
response
=
GitalyClient
.
call
(
@storage
,
:ref_service
,
:find_all_branch_names
,
request
)
response
=
GitalyClient
.
call
(
@storage
,
:ref_service
,
:find_all_branch_names
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
consume_refs_response
(
response
)
{
|
name
|
Gitlab
::
Git
.
branch_name
(
name
)
}
consume_refs_response
(
response
)
{
|
name
|
Gitlab
::
Git
.
branch_name
(
name
)
}
end
end
def
tag_names
def
tag_names
request
=
Gitaly
::
FindAllTagNamesRequest
.
new
(
repository:
@gitaly_repo
)
request
=
Gitaly
::
FindAllTagNamesRequest
.
new
(
repository:
@gitaly_repo
)
response
=
GitalyClient
.
call
(
@storage
,
:ref_service
,
:find_all_tag_names
,
request
)
response
=
GitalyClient
.
call
(
@storage
,
:ref_service
,
:find_all_tag_names
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
consume_refs_response
(
response
)
{
|
name
|
Gitlab
::
Git
.
tag_name
(
name
)
}
consume_refs_response
(
response
)
{
|
name
|
Gitlab
::
Git
.
tag_name
(
name
)
}
end
end
...
@@ -67,19 +67,19 @@ module Gitlab
...
@@ -67,19 +67,19 @@ module Gitlab
def
local_branches
(
sort_by:
nil
)
def
local_branches
(
sort_by:
nil
)
request
=
Gitaly
::
FindLocalBranchesRequest
.
new
(
repository:
@gitaly_repo
)
request
=
Gitaly
::
FindLocalBranchesRequest
.
new
(
repository:
@gitaly_repo
)
request
.
sort_by
=
sort_by_param
(
sort_by
)
if
sort_by
request
.
sort_by
=
sort_by_param
(
sort_by
)
if
sort_by
response
=
GitalyClient
.
call
(
@storage
,
:ref_service
,
:find_local_branches
,
request
)
response
=
GitalyClient
.
call
(
@storage
,
:ref_service
,
:find_local_branches
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
consume_find_local_branches_response
(
response
)
consume_find_local_branches_response
(
response
)
end
end
def
tags
def
tags
request
=
Gitaly
::
FindAllTagsRequest
.
new
(
repository:
@gitaly_repo
)
request
=
Gitaly
::
FindAllTagsRequest
.
new
(
repository:
@gitaly_repo
)
response
=
GitalyClient
.
call
(
@storage
,
:ref_service
,
:find_all_tags
,
request
)
response
=
GitalyClient
.
call
(
@storage
,
:ref_service
,
:find_all_tags
,
request
,
timeout:
GitalyClient
.
medium_timeout
)
consume_tags_response
(
response
)
consume_tags_response
(
response
)
end
end
def
ref_exists?
(
ref_name
)
def
ref_exists?
(
ref_name
)
request
=
Gitaly
::
RefExistsRequest
.
new
(
repository:
@gitaly_repo
,
ref:
encode_binary
(
ref_name
))
request
=
Gitaly
::
RefExistsRequest
.
new
(
repository:
@gitaly_repo
,
ref:
encode_binary
(
ref_name
))
response
=
GitalyClient
.
call
(
@storage
,
:ref_service
,
:ref_exists
,
request
)
response
=
GitalyClient
.
call
(
@storage
,
:ref_service
,
:ref_exists
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
response
.
value
response
.
value
rescue
GRPC
::
InvalidArgument
=>
e
rescue
GRPC
::
InvalidArgument
=>
e
raise
ArgumentError
,
e
.
message
raise
ArgumentError
,
e
.
message
...
@@ -91,7 +91,7 @@ module Gitlab
...
@@ -91,7 +91,7 @@ module Gitlab
name:
encode_binary
(
branch_name
)
name:
encode_binary
(
branch_name
)
)
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:ref_service
,
:find_branch
,
request
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:ref_service
,
:find_branch
,
request
,
timeout:
GitalyClient
.
medium_timeout
)
branch
=
response
.
branch
branch
=
response
.
branch
return
unless
branch
return
unless
branch
...
@@ -140,7 +140,7 @@ module Gitlab
...
@@ -140,7 +140,7 @@ module Gitlab
except_with_prefix:
except_with_prefixes
.
map
{
|
r
|
encode_binary
(
r
)
}
except_with_prefix:
except_with_prefixes
.
map
{
|
r
|
encode_binary
(
r
)
}
)
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:ref_service
,
:delete_refs
,
request
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:ref_service
,
:delete_refs
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
raise
Gitlab
::
Git
::
Repository
::
GitError
,
response
.
git_error
if
response
.
git_error
.
present?
raise
Gitlab
::
Git
::
Repository
::
GitError
,
response
.
git_error
if
response
.
git_error
.
present?
end
end
...
@@ -153,7 +153,7 @@ module Gitlab
...
@@ -153,7 +153,7 @@ module Gitlab
limit:
limit
limit:
limit
)
)
stream
=
GitalyClient
.
call
(
@repository
.
storage
,
:ref_service
,
:list_tag_names_containing_commit
,
request
)
stream
=
GitalyClient
.
call
(
@repository
.
storage
,
:ref_service
,
:list_tag_names_containing_commit
,
request
,
timeout:
GitalyClient
.
medium_timeout
)
consume_ref_contains_sha_response
(
stream
,
:tag_names
)
consume_ref_contains_sha_response
(
stream
,
:tag_names
)
end
end
...
@@ -166,14 +166,14 @@ module Gitlab
...
@@ -166,14 +166,14 @@ module Gitlab
limit:
limit
limit:
limit
)
)
stream
=
GitalyClient
.
call
(
@repository
.
storage
,
:ref_service
,
:list_branch_names_containing_commit
,
request
)
stream
=
GitalyClient
.
call
(
@repository
.
storage
,
:ref_service
,
:list_branch_names_containing_commit
,
request
,
timeout:
GitalyClient
.
medium_timeout
)
consume_ref_contains_sha_response
(
stream
,
:branch_names
)
consume_ref_contains_sha_response
(
stream
,
:branch_names
)
end
end
def
get_tag_messages
(
tag_ids
)
def
get_tag_messages
(
tag_ids
)
request
=
Gitaly
::
GetTagMessagesRequest
.
new
(
repository:
@gitaly_repo
,
tag_ids:
tag_ids
)
request
=
Gitaly
::
GetTagMessagesRequest
.
new
(
repository:
@gitaly_repo
,
tag_ids:
tag_ids
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:ref_service
,
:get_tag_messages
,
request
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:ref_service
,
:get_tag_messages
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
messages
=
Hash
.
new
{
|
h
,
k
|
h
[
k
]
=
''
.
b
}
messages
=
Hash
.
new
{
|
h
,
k
|
h
[
k
]
=
''
.
b
}
current_tag_id
=
nil
current_tag_id
=
nil
...
...
lib/gitlab/gitaly_client/remote_service.rb
View file @
ca3ea76c
...
@@ -28,13 +28,13 @@ module Gitlab
...
@@ -28,13 +28,13 @@ module Gitlab
mirror_refmaps:
Array
.
wrap
(
mirror_refmaps
).
map
(
&
:to_s
)
mirror_refmaps:
Array
.
wrap
(
mirror_refmaps
).
map
(
&
:to_s
)
)
)
GitalyClient
.
call
(
@storage
,
:remote_service
,
:add_remote
,
request
)
GitalyClient
.
call
(
@storage
,
:remote_service
,
:add_remote
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
end
end
def
remove_remote
(
name
)
def
remove_remote
(
name
)
request
=
Gitaly
::
RemoveRemoteRequest
.
new
(
repository:
@gitaly_repo
,
name:
name
)
request
=
Gitaly
::
RemoveRemoteRequest
.
new
(
repository:
@gitaly_repo
,
name:
name
)
response
=
GitalyClient
.
call
(
@storage
,
:remote_service
,
:remove_remote
,
request
)
response
=
GitalyClient
.
call
(
@storage
,
:remote_service
,
:remove_remote
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
response
.
result
response
.
result
end
end
...
...
lib/gitlab/gitaly_client/repository_service.rb
View file @
ca3ea76c
...
@@ -21,7 +21,7 @@ module Gitlab
...
@@ -21,7 +21,7 @@ module Gitlab
def
cleanup
def
cleanup
request
=
Gitaly
::
CleanupRequest
.
new
(
repository:
@gitaly_repo
)
request
=
Gitaly
::
CleanupRequest
.
new
(
repository:
@gitaly_repo
)
GitalyClient
.
call
(
@storage
,
:repository_service
,
:cleanup
,
request
)
GitalyClient
.
call
(
@storage
,
:repository_service
,
:cleanup
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
end
end
def
garbage_collect
(
create_bitmap
)
def
garbage_collect
(
create_bitmap
)
...
@@ -41,13 +41,13 @@ module Gitlab
...
@@ -41,13 +41,13 @@ module Gitlab
def
repository_size
def
repository_size
request
=
Gitaly
::
RepositorySizeRequest
.
new
(
repository:
@gitaly_repo
)
request
=
Gitaly
::
RepositorySizeRequest
.
new
(
repository:
@gitaly_repo
)
response
=
GitalyClient
.
call
(
@storage
,
:repository_service
,
:repository_size
,
request
)
response
=
GitalyClient
.
call
(
@storage
,
:repository_service
,
:repository_size
,
request
,
timeout:
GitalyClient
.
medium_timeout
)
response
.
size
response
.
size
end
end
def
apply_gitattributes
(
revision
)
def
apply_gitattributes
(
revision
)
request
=
Gitaly
::
ApplyGitattributesRequest
.
new
(
repository:
@gitaly_repo
,
revision:
encode_binary
(
revision
))
request
=
Gitaly
::
ApplyGitattributesRequest
.
new
(
repository:
@gitaly_repo
,
revision:
encode_binary
(
revision
))
GitalyClient
.
call
(
@storage
,
:repository_service
,
:apply_gitattributes
,
request
)
GitalyClient
.
call
(
@storage
,
:repository_service
,
:apply_gitattributes
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
rescue
GRPC
::
InvalidArgument
=>
ex
rescue
GRPC
::
InvalidArgument
=>
ex
raise
Gitlab
::
Git
::
Repository
::
InvalidRef
,
ex
raise
Gitlab
::
Git
::
Repository
::
InvalidRef
,
ex
end
end
...
@@ -55,7 +55,7 @@ module Gitlab
...
@@ -55,7 +55,7 @@ module Gitlab
def
info_attributes
def
info_attributes
request
=
Gitaly
::
GetInfoAttributesRequest
.
new
(
repository:
@gitaly_repo
)
request
=
Gitaly
::
GetInfoAttributesRequest
.
new
(
repository:
@gitaly_repo
)
response
=
GitalyClient
.
call
(
@storage
,
:repository_service
,
:get_info_attributes
,
request
)
response
=
GitalyClient
.
call
(
@storage
,
:repository_service
,
:get_info_attributes
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
response
.
each_with_object
(
""
)
do
|
message
,
attributes
|
response
.
each_with_object
(
""
)
do
|
message
,
attributes
|
attributes
<<
message
.
attributes
attributes
<<
message
.
attributes
end
end
...
@@ -82,7 +82,7 @@ module Gitlab
...
@@ -82,7 +82,7 @@ module Gitlab
def
create_repository
def
create_repository
request
=
Gitaly
::
CreateRepositoryRequest
.
new
(
repository:
@gitaly_repo
)
request
=
Gitaly
::
CreateRepositoryRequest
.
new
(
repository:
@gitaly_repo
)
GitalyClient
.
call
(
@storage
,
:repository_service
,
:create_repository
,
request
)
GitalyClient
.
call
(
@storage
,
:repository_service
,
:create_repository
,
request
,
timeout:
GitalyClient
.
medium_timeout
)
end
end
def
has_local_branches?
def
has_local_branches?
...
@@ -98,7 +98,7 @@ module Gitlab
...
@@ -98,7 +98,7 @@ module Gitlab
revisions:
revisions
.
map
{
|
r
|
encode_binary
(
r
)
}
revisions:
revisions
.
map
{
|
r
|
encode_binary
(
r
)
}
)
)
response
=
GitalyClient
.
call
(
@storage
,
:repository_service
,
:find_merge_base
,
request
)
response
=
GitalyClient
.
call
(
@storage
,
:repository_service
,
:find_merge_base
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
response
.
base
.
presence
response
.
base
.
presence
end
end
...
@@ -258,7 +258,7 @@ module Gitlab
...
@@ -258,7 +258,7 @@ module Gitlab
)
)
request
.
old_revision
=
old_ref
.
b
unless
old_ref
.
nil?
request
.
old_revision
=
old_ref
.
b
unless
old_ref
.
nil?
response
=
GitalyClient
.
call
(
@storage
,
:repository_service
,
:write_ref
,
request
)
response
=
GitalyClient
.
call
(
@storage
,
:repository_service
,
:write_ref
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
raise
Gitlab
::
Git
::
CommandError
,
encode!
(
response
.
error
)
if
response
.
error
.
present?
raise
Gitlab
::
Git
::
CommandError
,
encode!
(
response
.
error
)
if
response
.
error
.
present?
...
@@ -288,7 +288,7 @@ module Gitlab
...
@@ -288,7 +288,7 @@ module Gitlab
def
calculate_checksum
def
calculate_checksum
request
=
Gitaly
::
CalculateChecksumRequest
.
new
(
repository:
@gitaly_repo
)
request
=
Gitaly
::
CalculateChecksumRequest
.
new
(
repository:
@gitaly_repo
)
response
=
GitalyClient
.
call
(
@storage
,
:repository_service
,
:calculate_checksum
,
request
)
response
=
GitalyClient
.
call
(
@storage
,
:repository_service
,
:calculate_checksum
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
response
.
checksum
.
presence
response
.
checksum
.
presence
rescue
GRPC
::
DataLoss
=>
e
rescue
GRPC
::
DataLoss
=>
e
raise
Gitlab
::
Git
::
Repository
::
InvalidRepository
.
new
(
e
)
raise
Gitlab
::
Git
::
Repository
::
InvalidRepository
.
new
(
e
)
...
@@ -297,12 +297,12 @@ module Gitlab
...
@@ -297,12 +297,12 @@ module Gitlab
def
raw_changes_between
(
from
,
to
)
def
raw_changes_between
(
from
,
to
)
request
=
Gitaly
::
GetRawChangesRequest
.
new
(
repository:
@gitaly_repo
,
from_revision:
from
,
to_revision:
to
)
request
=
Gitaly
::
GetRawChangesRequest
.
new
(
repository:
@gitaly_repo
,
from_revision:
from
,
to_revision:
to
)
GitalyClient
.
call
(
@storage
,
:repository_service
,
:get_raw_changes
,
request
)
GitalyClient
.
call
(
@storage
,
:repository_service
,
:get_raw_changes
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
end
end
def
search_files_by_name
(
ref
,
query
)
def
search_files_by_name
(
ref
,
query
)
request
=
Gitaly
::
SearchFilesByNameRequest
.
new
(
repository:
@gitaly_repo
,
ref:
ref
,
query:
query
)
request
=
Gitaly
::
SearchFilesByNameRequest
.
new
(
repository:
@gitaly_repo
,
ref:
ref
,
query:
query
)
GitalyClient
.
call
(
@storage
,
:repository_service
,
:search_files_by_name
,
request
).
flat_map
(
&
:files
)
GitalyClient
.
call
(
@storage
,
:repository_service
,
:search_files_by_name
,
request
,
timeout:
GitalyClient
.
fast_timeout
).
flat_map
(
&
:files
)
end
end
def
search_files_by_content
(
ref
,
query
)
def
search_files_by_content
(
ref
,
query
)
...
...
lib/gitlab/gitaly_client/wiki_service.rb
View file @
ca3ea76c
...
@@ -69,7 +69,7 @@ module Gitlab
...
@@ -69,7 +69,7 @@ module Gitlab
commit_details:
gitaly_commit_details
(
commit_details
)
commit_details:
gitaly_commit_details
(
commit_details
)
)
)
GitalyClient
.
call
(
@repository
.
storage
,
:wiki_service
,
:wiki_delete_page
,
request
)
GitalyClient
.
call
(
@repository
.
storage
,
:wiki_service
,
:wiki_delete_page
,
request
,
timeout:
GitalyClient
.
medium_timeout
)
end
end
def
find_page
(
title
:,
version:
nil
,
dir:
nil
)
def
find_page
(
title
:,
version:
nil
,
dir:
nil
)
...
@@ -80,14 +80,14 @@ module Gitlab
...
@@ -80,14 +80,14 @@ module Gitlab
directory:
encode_binary
(
dir
)
directory:
encode_binary
(
dir
)
)
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:wiki_service
,
:wiki_find_page
,
request
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:wiki_service
,
:wiki_find_page
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
wiki_page_from_iterator
(
response
)
wiki_page_from_iterator
(
response
)
end
end
def
get_all_pages
def
get_all_pages
request
=
Gitaly
::
WikiGetAllPagesRequest
.
new
(
repository:
@gitaly_repo
)
request
=
Gitaly
::
WikiGetAllPagesRequest
.
new
(
repository:
@gitaly_repo
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:wiki_service
,
:wiki_get_all_pages
,
request
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:wiki_service
,
:wiki_get_all_pages
,
request
,
timeout:
GitalyClient
.
medium_timeout
)
pages
=
[]
pages
=
[]
loop
do
loop
do
...
@@ -113,7 +113,7 @@ module Gitlab
...
@@ -113,7 +113,7 @@ module Gitlab
per_page:
options
[
:per_page
]
||
Gollum
::
Page
.
per_page
per_page:
options
[
:per_page
]
||
Gollum
::
Page
.
per_page
)
)
stream
=
GitalyClient
.
call
(
@repository
.
storage
,
:wiki_service
,
:wiki_get_page_versions
,
request
)
stream
=
GitalyClient
.
call
(
@repository
.
storage
,
:wiki_service
,
:wiki_get_page_versions
,
request
,
timeout:
GitalyClient
.
medium_timeout
)
versions
=
[]
versions
=
[]
stream
.
each
do
|
message
|
stream
.
each
do
|
message
|
...
@@ -132,7 +132,7 @@ module Gitlab
...
@@ -132,7 +132,7 @@ module Gitlab
revision:
encode_binary
(
revision
)
revision:
encode_binary
(
revision
)
)
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:wiki_service
,
:wiki_find_file
,
request
)
response
=
GitalyClient
.
call
(
@repository
.
storage
,
:wiki_service
,
:wiki_find_file
,
request
,
timeout:
GitalyClient
.
fast_timeout
)
wiki_file
=
nil
wiki_file
=
nil
response
.
each
do
|
message
|
response
.
each
do
|
message
|
...
...
qa/qa/runtime/browser.rb
View file @
ca3ea76c
...
@@ -32,6 +32,12 @@ module QA
...
@@ -32,6 +32,12 @@ module QA
end
end
def
self
.
configure!
def
self
.
configure!
RSpec
.
configure
do
|
config
|
config
.
define_derived_metadata
(
file_path:
%r{/qa/specs/features/}
)
do
|
metadata
|
metadata
[
:type
]
=
:feature
end
end
return
if
Capybara
.
drivers
.
include?
(
:chrome
)
return
if
Capybara
.
drivers
.
include?
(
:chrome
)
Capybara
.
register_driver
:chrome
do
|
app
|
Capybara
.
register_driver
:chrome
do
|
app
|
...
...
spec/controllers/projects/jobs_controller_spec.rb
View file @
ca3ea76c
...
@@ -562,4 +562,105 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
...
@@ -562,4 +562,105 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
end
end
end
end
end
describe
'GET #terminal'
do
before
do
project
.
add_developer
(
user
)
sign_in
(
user
)
end
context
'when job exists'
do
context
'and it has a terminal'
do
let!
(
:job
)
{
create
(
:ci_build
,
:running
,
:with_runner_session
,
pipeline:
pipeline
)
}
it
'has a job'
do
get_terminal
(
id:
job
.
id
)
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
expect
(
assigns
(
:build
).
id
).
to
eq
(
job
.
id
)
end
end
context
'and does not have a terminal'
do
let!
(
:job
)
{
create
(
:ci_build
,
:running
,
pipeline:
pipeline
)
}
it
'returns not_found'
do
get_terminal
(
id:
job
.
id
)
expect
(
response
).
to
have_gitlab_http_status
(
:not_found
)
end
end
end
context
'when job does not exist'
do
it
'renders not_found'
do
get_terminal
(
id:
1234
)
expect
(
response
).
to
have_gitlab_http_status
(
:not_found
)
end
end
def
get_terminal
(
**
extra_params
)
params
=
{
namespace_id:
project
.
namespace
.
to_param
,
project_id:
project
}
get
:terminal
,
params
.
merge
(
extra_params
)
end
end
describe
'GET #terminal_websocket_authorize'
do
let!
(
:job
)
{
create
(
:ci_build
,
:running
,
:with_runner_session
,
pipeline:
pipeline
)
}
before
do
project
.
add_developer
(
user
)
sign_in
(
user
)
end
context
'with valid workhorse signature'
do
before
do
allow
(
Gitlab
::
Workhorse
).
to
receive
(
:verify_api_request!
).
and_return
(
nil
)
end
context
'and valid id'
do
it
'returns the terminal for the job'
do
expect
(
Gitlab
::
Workhorse
)
.
to
receive
(
:terminal_websocket
)
.
and_return
(
workhorse: :response
)
get_terminal_websocket
(
id:
job
.
id
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
response
.
headers
[
"Content-Type"
]).
to
eq
(
Gitlab
::
Workhorse
::
INTERNAL_API_CONTENT_TYPE
)
expect
(
response
.
body
).
to
eq
(
'{"workhorse":"response"}'
)
end
end
context
'and invalid id'
do
it
'returns 404'
do
get_terminal_websocket
(
id:
1234
)
expect
(
response
).
to
have_gitlab_http_status
(
404
)
end
end
end
context
'with invalid workhorse signature'
do
it
'aborts with an exception'
do
allow
(
Gitlab
::
Workhorse
).
to
receive
(
:verify_api_request!
).
and_raise
(
JWT
::
DecodeError
)
expect
{
get_terminal_websocket
(
id:
job
.
id
)
}.
to
raise_error
(
JWT
::
DecodeError
)
end
end
def
get_terminal_websocket
(
**
extra_params
)
params
=
{
namespace_id:
project
.
namespace
.
to_param
,
project_id:
project
}
get
:terminal_websocket_authorize
,
params
.
merge
(
extra_params
)
end
end
end
end
spec/controllers/projects/pipelines_controller_spec.rb
View file @
ca3ea76c
...
@@ -74,7 +74,7 @@ describe Projects::PipelinesController do
...
@@ -74,7 +74,7 @@ describe Projects::PipelinesController do
expect
(
stages
.
count
).
to
eq
3
expect
(
stages
.
count
).
to
eq
3
end
end
expect
(
queries
.
count
).
to
be_within
(
3
).
of
(
30
)
expect
(
queries
.
count
).
to
be_within
(
5
).
of
(
30
)
end
end
end
end
...
...
spec/controllers/projects_controller_spec.rb
View file @
ca3ea76c
...
@@ -616,13 +616,40 @@ describe ProjectsController do
...
@@ -616,13 +616,40 @@ describe ProjectsController do
end
end
describe
'POST #preview_markdown'
do
describe
'POST #preview_markdown'
do
it
'renders json in a correct format'
do
before
do
sign_in
(
user
)
sign_in
(
user
)
end
it
'renders json in a correct format'
do
post
:preview_markdown
,
namespace_id:
public_project
.
namespace
,
id:
public_project
,
text:
'*Markdown* text'
post
:preview_markdown
,
namespace_id:
public_project
.
namespace
,
id:
public_project
,
text:
'*Markdown* text'
expect
(
JSON
.
parse
(
response
.
body
).
keys
).
to
match_array
(
%w(body references)
)
expect
(
JSON
.
parse
(
response
.
body
).
keys
).
to
match_array
(
%w(body references)
)
end
end
context
'state filter on references'
do
let
(
:issue
)
{
create
(
:issue
,
:closed
,
project:
public_project
)
}
let
(
:merge_request
)
{
create
(
:merge_request
,
:closed
,
target_project:
public_project
)
}
it
'renders JSON body with state filter for issues'
do
post
:preview_markdown
,
namespace_id:
public_project
.
namespace
,
id:
public_project
,
text:
issue
.
to_reference
json_response
=
JSON
.
parse
(
response
.
body
)
expect
(
json_response
[
'body'
]).
to
match
(
/\#
#{
issue
.
iid
}
\(closed\)/
)
end
it
'renders JSON body with state filter for MRs'
do
post
:preview_markdown
,
namespace_id:
public_project
.
namespace
,
id:
public_project
,
text:
merge_request
.
to_reference
json_response
=
JSON
.
parse
(
response
.
body
)
expect
(
json_response
[
'body'
]).
to
match
(
/\!
#{
merge_request
.
iid
}
\(closed\)/
)
end
end
end
end
describe
'#ensure_canonical_path'
do
describe
'#ensure_canonical_path'
do
...
...
spec/factories/ci/builds.rb
View file @
ca3ea76c
...
@@ -248,5 +248,11 @@ FactoryBot.define do
...
@@ -248,5 +248,11 @@ FactoryBot.define do
failed
failed
failure_reason
2
failure_reason
2
end
end
trait
:with_runner_session
do
after
(
:build
)
do
|
build
|
build
.
build_runner_session
(
url:
'ws://localhost'
)
end
end
end
end
end
end
spec/features/dashboard/projects_spec.rb
View file @
ca3ea76c
...
@@ -29,6 +29,34 @@ describe 'Dashboard Projects' do
...
@@ -29,6 +29,34 @@ describe 'Dashboard Projects' do
end
end
end
end
context
'when user has access to the project'
do
it
'shows role badge'
do
visit
dashboard_projects_path
page
.
within
'.user-access-role'
do
expect
(
page
).
to
have_content
(
'Developer'
)
end
end
context
'when role changes'
,
:use_clean_rails_memory_store_fragment_caching
do
it
'displays the right role'
do
visit
dashboard_projects_path
page
.
within
'.user-access-role'
do
expect
(
page
).
to
have_content
(
'Developer'
)
end
project
.
members
.
last
.
update
(
access_level:
40
)
visit
dashboard_projects_path
page
.
within
'.user-access-role'
do
expect
(
page
).
to
have_content
(
'Maintainer'
)
end
end
end
end
context
'when last_repository_updated_at, last_activity_at and update_at are present'
do
context
'when last_repository_updated_at, last_activity_at and update_at are present'
do
it
'shows the last_repository_updated_at attribute as the update date'
do
it
'shows the last_repository_updated_at attribute as the update date'
do
project
.
update_attributes!
(
last_repository_updated_at:
Time
.
now
,
last_activity_at:
1
.
hour
.
ago
)
project
.
update_attributes!
(
last_repository_updated_at:
Time
.
now
,
last_activity_at:
1
.
hour
.
ago
)
...
...
spec/features/projects/issues/user_comments_on_issue_spec.rb
View file @
ca3ea76c
...
@@ -63,6 +63,14 @@ describe "User comments on issue", :js do
...
@@ -63,6 +63,14 @@ describe "User comments on issue", :js do
page
.
within
(
".current-note-edit-form"
)
do
page
.
within
(
".current-note-edit-form"
)
do
fill_in
(
"note[note]"
,
with:
comment
)
fill_in
(
"note[note]"
,
with:
comment
)
find
(
'textarea'
).
send_keys
[
:control
,
:shift
,
'p'
]
expect
(
page
).
to
have_selector
(
'.current-note-edit-form .md-preview-holder'
)
expect
(
page
.
find
(
'.current-note-edit-form .md-preview-holder p'
)).
to
have_content
(
comment
)
end
expect
(
page
).
to
have_selector
(
'.new-note .note-textarea'
)
page
.
within
(
".current-note-edit-form"
)
do
click_button
(
"Save comment"
)
click_button
(
"Save comment"
)
end
end
...
...
spec/helpers/projects_helper_spec.rb
View file @
ca3ea76c
...
@@ -80,6 +80,7 @@ describe ProjectsHelper do
...
@@ -80,6 +80,7 @@ describe ProjectsHelper do
before
do
before
do
allow
(
helper
).
to
receive
(
:current_user
).
and_return
(
user
)
allow
(
helper
).
to
receive
(
:current_user
).
and_return
(
user
)
allow
(
helper
).
to
receive
(
:can?
).
with
(
user
,
:read_cross_project
)
{
true
}
allow
(
helper
).
to
receive
(
:can?
).
with
(
user
,
:read_cross_project
)
{
true
}
allow
(
user
).
to
receive
(
:max_member_access_for_project
).
and_return
(
40
)
end
end
it
"includes the route"
do
it
"includes the route"
do
...
@@ -125,6 +126,10 @@ describe ProjectsHelper do
...
@@ -125,6 +126,10 @@ describe ProjectsHelper do
expect
(
helper
.
project_list_cache_key
(
project
)).
to
include
(
"pipeline-status/
#{
project
.
commit
.
sha
}
-success"
)
expect
(
helper
.
project_list_cache_key
(
project
)).
to
include
(
"pipeline-status/
#{
project
.
commit
.
sha
}
-success"
)
end
end
it
"includes the user max member access"
do
expect
(
helper
.
project_list_cache_key
(
project
)).
to
include
(
'access:40'
)
end
end
end
describe
'#load_pipeline_status'
do
describe
'#load_pipeline_status'
do
...
...
spec/javascripts/diffs/components/diff_file_header_spec.js
View file @
ca3ea76c
...
@@ -280,11 +280,11 @@ describe('diff_file_header', () => {
...
@@ -280,11 +280,11 @@ describe('diff_file_header', () => {
});
});
});
});
it
(
'
displays an icon in the title
'
,
()
=>
{
it
(
'
displays an
file
icon in the title
'
,
()
=>
{
vm
=
mountComponent
(
Component
,
props
);
vm
=
mountComponent
(
Component
,
props
);
expect
(
vm
.
$el
.
querySelector
(
'
svg.js-file-icon use
'
).
getAttribute
(
'
xlink:href
'
)).
toContain
(
const
icon
=
vm
.
$el
.
querySelector
(
`i[class="fa fa-fw fa-
${
vm
.
icon
}
"]`
);
'
ruby
'
,
expect
(
icon
).
not
.
toBe
(
null
);
);
});
});
describe
(
'
file paths
'
,
()
=>
{
describe
(
'
file paths
'
,
()
=>
{
...
...
spec/javascripts/diffs/store/utils_spec.js
View file @
ca3ea76c
...
@@ -176,4 +176,35 @@ describe('DiffsStoreUtils', () => {
...
@@ -176,4 +176,35 @@ describe('DiffsStoreUtils', () => {
expect
(
linesWithReferences
[
1
].
metaData
.
newPos
).
toEqual
(
3
);
expect
(
linesWithReferences
[
1
].
metaData
.
newPos
).
toEqual
(
3
);
});
});
});
});
describe
(
'
trimFirstCharOfLineContent
'
,
()
=>
{
it
(
'
trims the line when it starts with a space
'
,
()
=>
{
expect
(
utils
.
trimFirstCharOfLineContent
({
richText
:
'
diff
'
})).
toEqual
({
richText
:
'
diff
'
});
});
it
(
'
trims the line when it starts with a +
'
,
()
=>
{
expect
(
utils
.
trimFirstCharOfLineContent
({
richText
:
'
+diff
'
})).
toEqual
({
richText
:
'
diff
'
});
});
it
(
'
trims the line when it starts with a -
'
,
()
=>
{
expect
(
utils
.
trimFirstCharOfLineContent
({
richText
:
'
-diff
'
})).
toEqual
({
richText
:
'
diff
'
});
});
it
(
'
does not trims the line when it starts with a letter
'
,
()
=>
{
expect
(
utils
.
trimFirstCharOfLineContent
({
richText
:
'
diff
'
})).
toEqual
({
richText
:
'
diff
'
});
});
it
(
'
does not modify the provided object
'
,
()
=>
{
const
lineObj
=
{
richText
:
'
diff
'
,
};
utils
.
trimFirstCharOfLineContent
(
lineObj
);
expect
(
lineObj
).
toEqual
({
richText
:
'
diff
'
});
});
it
(
'
handles a undefined or null parameter
'
,
()
=>
{
expect
(
utils
.
trimFirstCharOfLineContent
()).
toEqual
({});
});
});
});
});
spec/javascripts/fixtures/merge_requests.rb
View file @
ca3ea76c
...
@@ -80,6 +80,13 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont
...
@@ -80,6 +80,13 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont
render_discussions_json
(
merge_request
,
example
.
description
)
render_discussions_json
(
merge_request
,
example
.
description
)
end
end
it
'merge_requests/resolved_diff_discussion.json'
do
|
example
|
note
=
create
(
:discussion_note_on_merge_request
,
:resolved
,
project:
project
,
author:
admin
,
position:
position
,
noteable:
merge_request
)
create
(
:system_note
,
project:
project
,
author:
admin
,
noteable:
merge_request
,
discussion_id:
note
.
discussion
.
id
)
render_discussions_json
(
merge_request
,
example
.
description
)
end
context
'with image diff'
do
context
'with image diff'
do
let
(
:merge_request2
)
{
create
(
:merge_request_with_diffs
,
:with_image_diffs
,
source_project:
project
,
title:
"Added images"
)
}
let
(
:merge_request2
)
{
create
(
:merge_request_with_diffs
,
:with_image_diffs
,
source_project:
project
,
title:
"Added images"
)
}
let
(
:image_path
)
{
"files/images/ee_repo_logo.png"
}
let
(
:image_path
)
{
"files/images/ee_repo_logo.png"
}
...
...
spec/javascripts/notes/components/discussion_counter_spec.js
View file @
ca3ea76c
...
@@ -32,12 +32,12 @@ describe('DiscussionCounter component', () => {
...
@@ -32,12 +32,12 @@ describe('DiscussionCounter component', () => {
{
{
...
discussionMock
,
...
discussionMock
,
id
:
discussionMock
.
id
,
id
:
discussionMock
.
id
,
notes
:
[{
...
discussionMock
.
notes
[
0
],
resolved
:
true
}],
notes
:
[{
...
discussionMock
.
notes
[
0
],
resolv
able
:
true
,
resolv
ed
:
true
}],
},
},
{
{
...
discussionMock
,
...
discussionMock
,
id
:
discussionMock
.
id
+
1
,
id
:
discussionMock
.
id
+
1
,
notes
:
[{
...
discussionMock
.
notes
[
0
],
resolved
:
false
}],
notes
:
[{
...
discussionMock
.
notes
[
0
],
resolv
able
:
true
,
resolv
ed
:
false
}],
},
},
];
];
const
firstDiscussionId
=
discussionMock
.
id
+
1
;
const
firstDiscussionId
=
discussionMock
.
id
+
1
;
...
...
spec/javascripts/notes/components/noteable_discussion_spec.js
View file @
ca3ea76c
...
@@ -4,22 +4,23 @@ import noteableDiscussion from '~/notes/components/noteable_discussion.vue';
...
@@ -4,22 +4,23 @@ import noteableDiscussion from '~/notes/components/noteable_discussion.vue';
import
'
~/behaviors/markdown/render_gfm
'
;
import
'
~/behaviors/markdown/render_gfm
'
;
import
{
noteableDataMock
,
discussionMock
,
notesDataMock
}
from
'
../mock_data
'
;
import
{
noteableDataMock
,
discussionMock
,
notesDataMock
}
from
'
../mock_data
'
;
const
discussionWithTwoUnresolvedNotes
=
'
merge_requests/resolved_diff_discussion.json
'
;
describe
(
'
noteable_discussion component
'
,
()
=>
{
describe
(
'
noteable_discussion component
'
,
()
=>
{
const
Component
=
Vue
.
extend
(
noteableDiscussion
);
let
store
;
let
store
;
let
vm
;
let
vm
;
beforeEach
(()
=>
{
preloadFixtures
(
discussionWithTwoUnresolvedNotes
);
const
Component
=
Vue
.
extend
(
noteableDiscussion
);
beforeEach
(()
=>
{
store
=
createStore
();
store
=
createStore
();
store
.
dispatch
(
'
setNoteableData
'
,
noteableDataMock
);
store
.
dispatch
(
'
setNoteableData
'
,
noteableDataMock
);
store
.
dispatch
(
'
setNotesData
'
,
notesDataMock
);
store
.
dispatch
(
'
setNotesData
'
,
notesDataMock
);
vm
=
new
Component
({
vm
=
new
Component
({
store
,
store
,
propsData
:
{
propsData
:
{
discussion
:
discussionMock
},
discussion
:
discussionMock
,
},
}).
$mount
();
}).
$mount
();
});
});
...
@@ -84,7 +85,9 @@ describe('noteable_discussion component', () => {
...
@@ -84,7 +85,9 @@ describe('noteable_discussion component', () => {
});
});
it
(
'
is true if there are two unresolved discussions
'
,
done
=>
{
it
(
'
is true if there are two unresolved discussions
'
,
done
=>
{
spyOnProperty
(
vm
,
'
unresolvedDiscussions
'
).
and
.
returnValue
([{},
{}]);
const
discussion
=
getJSONFixture
(
discussionWithTwoUnresolvedNotes
)[
0
];
discussion
.
notes
[
0
].
resolved
=
false
;
vm
.
$store
.
dispatch
(
'
setInitialNotes
'
,
[
discussion
,
discussion
]);
Vue
.
nextTick
()
Vue
.
nextTick
()
.
then
(()
=>
{
.
then
(()
=>
{
...
@@ -105,12 +108,12 @@ describe('noteable_discussion component', () => {
...
@@ -105,12 +108,12 @@ describe('noteable_discussion component', () => {
{
{
...
discussionMock
,
...
discussionMock
,
id
:
discussionMock
.
id
+
1
,
id
:
discussionMock
.
id
+
1
,
notes
:
[{
...
discussionMock
.
notes
[
0
],
resolved
:
true
}],
notes
:
[{
...
discussionMock
.
notes
[
0
],
resolv
able
:
true
,
resolv
ed
:
true
}],
},
},
{
{
...
discussionMock
,
...
discussionMock
,
id
:
discussionMock
.
id
+
2
,
id
:
discussionMock
.
id
+
2
,
notes
:
[{
...
discussionMock
.
notes
[
0
],
resolved
:
false
}],
notes
:
[{
...
discussionMock
.
notes
[
0
],
resolv
able
:
true
,
resolv
ed
:
false
}],
},
},
];
];
const
nextDiscussionId
=
discussionMock
.
id
+
2
;
const
nextDiscussionId
=
discussionMock
.
id
+
2
;
...
...
spec/javascripts/notes/mock_data.js
View file @
ca3ea76c
...
@@ -303,6 +303,7 @@ export const discussionMock = {
...
@@ -303,6 +303,7 @@ export const discussionMock = {
},
},
],
],
individual_note
:
false
,
individual_note
:
false
,
resolvable
:
true
,
};
};
export
const
loggedOutnoteableData
=
{
export
const
loggedOutnoteableData
=
{
...
...
spec/javascripts/notes/stores/getters_spec.js
View file @
ca3ea76c
...
@@ -7,9 +7,13 @@ import {
...
@@ -7,9 +7,13 @@ import {
collapseNotesMock
,
collapseNotesMock
,
}
from
'
../mock_data
'
;
}
from
'
../mock_data
'
;
const
discussionWithTwoUnresolvedNotes
=
'
merge_requests/resolved_diff_discussion.json
'
;
describe
(
'
Getters Notes Store
'
,
()
=>
{
describe
(
'
Getters Notes Store
'
,
()
=>
{
let
state
;
let
state
;
preloadFixtures
(
discussionWithTwoUnresolvedNotes
);
beforeEach
(()
=>
{
beforeEach
(()
=>
{
state
=
{
state
=
{
discussions
:
[
individualNote
],
discussions
:
[
individualNote
],
...
@@ -22,12 +26,26 @@ describe('Getters Notes Store', () => {
...
@@ -22,12 +26,26 @@ describe('Getters Notes Store', () => {
noteableData
:
noteableDataMock
,
noteableData
:
noteableDataMock
,
};
};
});
});
describe
(
'
discussions
'
,
()
=>
{
describe
(
'
discussions
'
,
()
=>
{
it
(
'
should return all discussions in the store
'
,
()
=>
{
it
(
'
should return all discussions in the store
'
,
()
=>
{
expect
(
getters
.
discussions
(
state
)).
toEqual
([
individualNote
]);
expect
(
getters
.
discussions
(
state
)).
toEqual
([
individualNote
]);
});
});
});
});
describe
(
'
resolvedDiscussionsById
'
,
()
=>
{
it
(
'
ignores unresolved system notes
'
,
()
=>
{
const
[
discussion
]
=
getJSONFixture
(
discussionWithTwoUnresolvedNotes
);
discussion
.
notes
[
0
].
resolved
=
true
;
discussion
.
notes
[
1
].
resolved
=
false
;
state
.
discussions
.
push
(
discussion
);
expect
(
getters
.
resolvedDiscussionsById
(
state
)).
toEqual
({
[
discussion
.
id
]:
discussion
,
});
});
});
describe
(
'
Collapsed notes
'
,
()
=>
{
describe
(
'
Collapsed notes
'
,
()
=>
{
const
stateCollapsedNotes
=
{
const
stateCollapsedNotes
=
{
discussions
:
collapseNotesMock
,
discussions
:
collapseNotesMock
,
...
...
spec/javascripts/vue_shared/components/markdown/header_spec.js
View file @
ca3ea76c
...
@@ -51,7 +51,7 @@ describe('Markdown field header component', () => {
...
@@ -51,7 +51,7 @@ describe('Markdown field header component', () => {
spyOn
(
vm
,
'
$emit
'
);
spyOn
(
vm
,
'
$emit
'
);
$
(
document
).
triggerHandler
(
'
markdown-preview:show
'
,
[
$
(
document
).
triggerHandler
(
'
markdown-preview:show
'
,
[
$
(
'
<form><
textarea class="markdown-area"></textarea></textarea
></form>
'
),
$
(
'
<form><
div class="js-vue-markdown-field"><textarea class="markdown-area"></textarea></div
></form>
'
),
]);
]);
expect
(
vm
.
$emit
).
not
.
toHaveBeenCalled
();
expect
(
vm
.
$emit
).
not
.
toHaveBeenCalled
();
...
...
spec/models/ci/build_runner_session_spec.rb
0 → 100644
View file @
ca3ea76c
require
'spec_helper'
describe
Ci
::
BuildRunnerSession
,
model:
true
do
let!
(
:build
)
{
create
(
:ci_build
,
:with_runner_session
)
}
subject
{
build
.
runner_session
}
it
{
is_expected
.
to
belong_to
(
:build
)
}
it
{
is_expected
.
to
validate_presence_of
(
:build
)
}
it
{
is_expected
.
to
validate_presence_of
(
:url
).
with_message
(
'must be a valid URL'
)
}
describe
'#terminal_specification'
do
let
(
:terminal_specification
)
{
subject
.
terminal_specification
}
it
'returns empty hash if no url'
do
subject
.
url
=
''
expect
(
terminal_specification
).
to
be_empty
end
context
'when url is present'
do
it
'returns ca_pem nil if empty certificate'
do
subject
.
certificate
=
''
expect
(
terminal_specification
[
:ca_pem
]).
to
be_nil
end
it
'adds Authorization header if authorization is present'
do
subject
.
authorization
=
'whatever'
expect
(
terminal_specification
[
:headers
]).
to
include
(
Authorization
:
'whatever'
)
end
end
end
end
spec/models/ci/build_spec.rb
View file @
ca3ea76c
...
@@ -19,6 +19,7 @@ describe Ci::Build do
...
@@ -19,6 +19,7 @@ describe Ci::Build do
it
{
is_expected
.
to
belong_to
(
:erased_by
)
}
it
{
is_expected
.
to
belong_to
(
:erased_by
)
}
it
{
is_expected
.
to
have_many
(
:deployments
)
}
it
{
is_expected
.
to
have_many
(
:deployments
)
}
it
{
is_expected
.
to
have_many
(
:trace_sections
)}
it
{
is_expected
.
to
have_many
(
:trace_sections
)}
it
{
is_expected
.
to
have_one
(
:runner_session
)}
it
{
is_expected
.
to
validate_presence_of
(
:ref
)
}
it
{
is_expected
.
to
validate_presence_of
(
:ref
)
}
it
{
is_expected
.
to
respond_to
(
:has_trace?
)
}
it
{
is_expected
.
to
respond_to
(
:has_trace?
)
}
it
{
is_expected
.
to
respond_to
(
:trace
)
}
it
{
is_expected
.
to
respond_to
(
:trace
)
}
...
@@ -42,6 +43,20 @@ describe Ci::Build do
...
@@ -42,6 +43,20 @@ describe Ci::Build do
end
end
end
end
describe
'status'
do
context
'when transitioning to any state from running'
do
it
'removes runner_session'
do
%w(success drop cancel)
.
each
do
|
event
|
build
=
FactoryBot
.
create
(
:ci_build
,
:running
,
:with_runner_session
,
pipeline:
pipeline
)
build
.
fire_events!
(
event
)
expect
(
build
.
reload
.
runner_session
).
to
be_nil
end
end
end
end
describe
'.manual_actions'
do
describe
'.manual_actions'
do
let!
(
:manual_but_created
)
{
create
(
:ci_build
,
:manual
,
status: :created
,
pipeline:
pipeline
)
}
let!
(
:manual_but_created
)
{
create
(
:ci_build
,
:manual
,
status: :created
,
pipeline:
pipeline
)
}
let!
(
:manual_but_succeeded
)
{
create
(
:ci_build
,
:manual
,
status: :success
,
pipeline:
pipeline
)
}
let!
(
:manual_but_succeeded
)
{
create
(
:ci_build
,
:manual
,
status: :success
,
pipeline:
pipeline
)
}
...
@@ -499,6 +514,22 @@ describe Ci::Build do
...
@@ -499,6 +514,22 @@ describe Ci::Build do
end
end
end
end
describe
'#has_old_trace?'
do
subject
{
build
.
has_old_trace?
}
context
'when old trace exists'
do
before
do
build
.
update_column
(
:trace
,
'old trace'
)
end
it
{
is_expected
.
to
be_truthy
}
end
context
'when old trace does not exist'
do
it
{
is_expected
.
to
be_falsy
}
end
end
describe
'#trace='
do
describe
'#trace='
do
it
"expect to fail trace="
do
it
"expect to fail trace="
do
expect
{
build
.
trace
=
"new"
}.
to
raise_error
(
NotImplementedError
)
expect
{
build
.
trace
=
"new"
}.
to
raise_error
(
NotImplementedError
)
...
@@ -518,16 +549,32 @@ describe Ci::Build do
...
@@ -518,16 +549,32 @@ describe Ci::Build do
end
end
describe
'#erase_old_trace!'
do
describe
'#erase_old_trace!'
do
subject
{
build
.
send
(
:read_attribute
,
:trace
)
}
subject
{
build
.
erase_old_trace!
}
before
do
context
'when old trace exists'
do
build
.
send
(
:write_attribute
,
:trace
,
'old trace'
)
before
do
build
.
update_column
(
:trace
,
'old trace'
)
end
it
"erases old trace"
do
subject
expect
(
build
.
old_trace
).
to
be_nil
end
it
"executes UPDATE query"
do
recorded
=
ActiveRecord
::
QueryRecorder
.
new
{
subject
}
expect
(
recorded
.
log
.
select
{
|
l
|
l
.
match?
(
/UPDATE.*ci_builds/
)
}.
count
).
to
eq
(
1
)
end
end
end
it
"expect to receive data from database"
do
context
'when old trace does not exist'
do
build
.
erase_old_trace!
it
'does not execute UPDATE query'
do
recorded
=
ActiveRecord
::
QueryRecorder
.
new
{
subject
}
is_expected
.
to
be_nil
expect
(
recorded
.
log
.
select
{
|
l
|
l
.
match?
(
/UPDATE.*ci_builds/
)
}.
count
).
to
eq
(
0
)
end
end
end
end
end
...
@@ -2605,4 +2652,39 @@ describe Ci::Build do
...
@@ -2605,4 +2652,39 @@ describe Ci::Build do
end
end
end
end
end
end
describe
'#has_terminal?'
do
let
(
:states
)
{
described_class
.
state_machines
[
:status
].
states
.
keys
-
[
:running
]
}
subject
{
build
.
has_terminal?
}
it
'returns true if the build is running and it has a runner_session_url'
do
build
.
build_runner_session
(
url:
'whatever'
)
build
.
status
=
:running
expect
(
subject
).
to
be_truthy
end
context
'returns false'
do
it
'when runner_session_url is empty'
do
build
.
status
=
:running
expect
(
subject
).
to
be_falsey
end
context
'unless the build is running'
do
before
do
build
.
build_runner_session
(
url:
'whatever'
)
end
it
do
states
.
each
do
|
state
|
build
.
status
=
state
is_expected
.
to
be_falsey
end
end
end
end
end
end
end
spec/models/service_spec.rb
View file @
ca3ea76c
...
@@ -78,7 +78,7 @@ describe Service do
...
@@ -78,7 +78,7 @@ describe Service do
context
'when template is invalid'
do
context
'when template is invalid'
do
it
'sets service template to inactive when template is invalid'
do
it
'sets service template to inactive when template is invalid'
do
project
=
create
(
:project
)
project
=
create
(
:project
)
template
=
Jira
Service
.
new
(
template:
true
,
active:
true
)
template
=
Kubernetes
Service
.
new
(
template:
true
,
active:
true
)
template
.
save
(
validate:
false
)
template
.
save
(
validate:
false
)
service
=
described_class
.
build_from_template
(
project
.
id
,
template
)
service
=
described_class
.
build_from_template
(
project
.
id
,
template
)
...
...
spec/requests/api/runner_spec.rb
View file @
ca3ea76c
...
@@ -851,6 +851,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
...
@@ -851,6 +851,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
it
'does not update job status and job trace'
do
it
'does not update job status and job trace'
do
update_job
(
state:
'success'
,
trace:
'BUILD TRACE UPDATED'
)
update_job
(
state:
'success'
,
trace:
'BUILD TRACE UPDATED'
)
job
.
reload
expect
(
response
).
to
have_gitlab_http_status
(
403
)
expect
(
response
).
to
have_gitlab_http_status
(
403
)
expect
(
response
.
header
[
'Job-Status'
]).
to
eq
'failed'
expect
(
response
.
header
[
'Job-Status'
]).
to
eq
'failed'
expect
(
job
.
trace
.
raw
).
to
eq
'Job failed'
expect
(
job
.
trace
.
raw
).
to
eq
'Job failed'
...
...
spec/services/ci/register_job_service_spec.rb
View file @
ca3ea76c
...
@@ -548,8 +548,21 @@ module Ci
...
@@ -548,8 +548,21 @@ module Ci
end
end
end
end
def
execute
(
runner
)
context
'when runner_session params are'
do
described_class
.
new
(
runner
).
execute
.
build
it
'present sets runner session configuration in the build'
do
runner_session_params
=
{
session:
{
'url'
=>
'https://example.com'
}
}
expect
(
execute
(
specific_runner
,
runner_session_params
).
runner_session
.
attributes
)
.
to
include
(
runner_session_params
[
:session
])
end
it
'not present it does not configure the runner session'
do
expect
(
execute
(
specific_runner
).
runner_session
).
to
be_nil
end
end
def
execute
(
runner
,
params
=
{})
described_class
.
new
(
runner
).
execute
(
params
).
build
end
end
end
end
end
end
spec/services/ci/retry_build_service_spec.rb
View file @
ca3ea76c
...
@@ -32,7 +32,7 @@ describe Ci::RetryBuildService do
...
@@ -32,7 +32,7 @@ describe Ci::RetryBuildService do
runner_id tag_taggings taggings tags trigger_request_id
runner_id tag_taggings taggings tags trigger_request_id
user_id auto_canceled_by_id retried failure_reason
user_id auto_canceled_by_id retried failure_reason
artifacts_file_store artifacts_metadata_store
artifacts_file_store artifacts_metadata_store
metadata trace_chunks]
.
freeze
metadata
runner_session
trace_chunks]
.
freeze
shared_examples
'build duplication'
do
shared_examples
'build duplication'
do
let
(
:another_pipeline
)
{
create
(
:ci_empty_pipeline
,
project:
project
)
}
let
(
:another_pipeline
)
{
create
(
:ci_empty_pipeline
,
project:
project
)
}
...
...
spec/services/merge_requests/conflicts/list_service_spec.rb
View file @
ca3ea76c
...
@@ -84,5 +84,23 @@ describe MergeRequests::Conflicts::ListService do
...
@@ -84,5 +84,23 @@ describe MergeRequests::Conflicts::ListService do
expect
(
service
.
can_be_resolved_in_ui?
).
to
be_falsey
expect
(
service
.
can_be_resolved_in_ui?
).
to
be_falsey
end
end
context
'with gitaly disabled'
,
:skip_gitaly_mock
do
it
'returns a falsey value when the MR has a missing ref after a force push'
do
merge_request
=
create_merge_request
(
'conflict-resolvable'
)
service
=
conflicts_service
(
merge_request
)
allow_any_instance_of
(
Rugged
::
Repository
).
to
receive
(
:merge_commits
).
and_raise
(
Rugged
::
OdbError
)
expect
(
service
.
can_be_resolved_in_ui?
).
to
be_falsey
end
it
'returns a falsey value when the MR has a missing revision after a force push'
do
merge_request
=
create_merge_request
(
'conflict-resolvable'
)
service
=
conflicts_service
(
merge_request
)
allow
(
merge_request
).
to
receive_message_chain
(
:target_branch_head
,
:raw
,
:id
).
and_return
(
Gitlab
::
Git
::
BLANK_SHA
)
expect
(
service
.
can_be_resolved_in_ui?
).
to
be_falsey
end
end
end
end
end
end
spec/services/merge_requests/conflicts/resolve_service_spec.rb
View file @
ca3ea76c
...
@@ -123,6 +123,17 @@ describe MergeRequests::Conflicts::ResolveService do
...
@@ -123,6 +123,17 @@ describe MergeRequests::Conflicts::ResolveService do
expect
(
merge_request_from_fork
.
source_branch_head
.
parents
.
map
(
&
:id
))
expect
(
merge_request_from_fork
.
source_branch_head
.
parents
.
map
(
&
:id
))
.
to
eq
([
'404fa3fc7c2c9b5dacff102f353bdf55b1be2813'
,
target_head
])
.
to
eq
([
'404fa3fc7c2c9b5dacff102f353bdf55b1be2813'
,
target_head
])
end
end
context
'when gitaly is disabled'
,
:skip_gitaly_mock
do
it
'gets conflicts from the source project'
do
# REFACTOR NOTE: We used to test that `project.repository.rugged` wasn't
# used in this case, but since the refactor, for simplification,
# we always use that repository for read only operations.
expect
(
forked_project
.
repository
.
rugged
).
to
receive
(
:merge_commits
).
and_call_original
subject
end
end
end
end
end
end
...
...
spec/spec_helper.rb
View file @
ca3ea76c
...
@@ -170,6 +170,17 @@ RSpec.configure do |config|
...
@@ -170,6 +170,17 @@ RSpec.configure do |config|
redis_queues_cleanup!
redis_queues_cleanup!
end
end
config
.
around
(
:each
,
:use_clean_rails_memory_store_fragment_caching
)
do
|
example
|
caching_store
=
ActionController
::
Base
.
cache_store
ActionController
::
Base
.
cache_store
=
ActiveSupport
::
Cache
::
MemoryStore
.
new
ActionController
::
Base
.
perform_caching
=
true
example
.
run
ActionController
::
Base
.
perform_caching
=
false
ActionController
::
Base
.
cache_store
=
caching_store
end
# The :each scope runs "inside" the example, so this hook ensures the DB is in the
# The :each scope runs "inside" the example, so this hook ensures the DB is in the
# correct state before any examples' before hooks are called. This prevents a
# correct state before any examples' before hooks are called. This prevents a
# problem where `ScheduleIssuesClosedAtTypeChange` (or any migration that depends
# problem where `ScheduleIssuesClosedAtTypeChange` (or any migration that depends
...
...
spec/support/helpers/wait_for_requests.rb
View file @
ca3ea76c
...
@@ -24,7 +24,9 @@ module WaitForRequests
...
@@ -24,7 +24,9 @@ module WaitForRequests
# Wait for client-side AJAX requests
# Wait for client-side AJAX requests
def
wait_for_requests
def
wait_for_requests
wait_for
(
'JS requests complete'
)
{
finished_all_js_requests?
}
wait_for
(
'JS requests complete'
,
max_wait_time:
2
*
Capybara
.
default_max_wait_time
)
do
finished_all_js_requests?
end
end
end
# Wait for active Rack requests and client-side AJAX requests
# Wait for active Rack requests and client-side AJAX requests
...
...
spec/support/shared_examples/ci_trace_shared_examples.rb
View file @
ca3ea76c
...
@@ -138,6 +138,28 @@ shared_examples_for 'common trace features' do
...
@@ -138,6 +138,28 @@ shared_examples_for 'common trace features' do
end
end
end
end
describe
'#write'
do
subject
{
trace
.
send
(
:write
,
mode
)
{
}
}
let
(
:mode
)
{
'wb'
}
context
'when arhicved trace does not exist yet'
do
it
'does not raise an error'
do
expect
{
subject
}.
not_to
raise_error
end
end
context
'when arhicved trace already exists'
do
before
do
create
(
:ci_job_artifact
,
:trace
,
job:
build
)
end
it
'raises an error'
do
expect
{
subject
}.
to
raise_error
(
Gitlab
::
Ci
::
Trace
::
AlreadyArchivedError
)
end
end
end
describe
'#set'
do
describe
'#set'
do
before
do
before
do
trace
.
set
(
"12"
)
trace
.
set
(
"12"
)
...
@@ -574,7 +596,7 @@ shared_examples_for 'trace with disabled live trace feature' do
...
@@ -574,7 +596,7 @@ shared_examples_for 'trace with disabled live trace feature' do
it
'does not archive'
do
it
'does not archive'
do
expect_any_instance_of
(
described_class
).
not_to
receive
(
:archive_stream!
)
expect_any_instance_of
(
described_class
).
not_to
receive
(
:archive_stream!
)
expect
{
subject
}.
to
raise_error
(
'Already archived'
)
expect
{
subject
}.
to
raise_error
(
Gitlab
::
Ci
::
Trace
::
AlreadyArchivedError
)
expect
(
build
.
job_artifacts_trace
.
file
.
exists?
).
to
be_truthy
expect
(
build
.
job_artifacts_trace
.
file
.
exists?
).
to
be_truthy
end
end
end
end
...
@@ -589,6 +611,55 @@ shared_examples_for 'trace with disabled live trace feature' do
...
@@ -589,6 +611,55 @@ shared_examples_for 'trace with disabled live trace feature' do
end
end
end
end
end
end
describe
'#erase!'
do
subject
{
trace
.
erase!
}
context
'when it is a live trace'
do
context
'when trace is stored in database'
do
let
(
:build
)
{
create
(
:ci_build
)
}
before
do
build
.
update_column
(
:trace
,
'sample trace'
)
end
it
{
expect
(
trace
.
raw
).
not_to
be_nil
}
it
"removes trace"
do
subject
expect
(
trace
.
raw
).
to
be_nil
end
end
context
'when trace is stored in file storage'
do
let
(
:build
)
{
create
(
:ci_build
,
:trace_live
)
}
it
{
expect
(
trace
.
raw
).
not_to
be_nil
}
it
"removes trace"
do
subject
expect
(
trace
.
raw
).
to
be_nil
end
end
end
context
'when it is an archived trace'
do
let
(
:build
)
{
create
(
:ci_build
,
:trace_artifact
)
}
it
"has trace at first"
do
expect
(
trace
.
raw
).
not_to
be_nil
end
it
"removes trace"
do
subject
build
.
reload
expect
(
trace
.
raw
).
to
be_nil
end
end
end
end
end
shared_examples_for
'trace with enabled live trace feature'
do
shared_examples_for
'trace with enabled live trace feature'
do
...
@@ -761,7 +832,7 @@ shared_examples_for 'trace with enabled live trace feature' do
...
@@ -761,7 +832,7 @@ shared_examples_for 'trace with enabled live trace feature' do
it
'does not archive'
do
it
'does not archive'
do
expect_any_instance_of
(
described_class
).
not_to
receive
(
:archive_stream!
)
expect_any_instance_of
(
described_class
).
not_to
receive
(
:archive_stream!
)
expect
{
subject
}.
to
raise_error
(
'Already archived'
)
expect
{
subject
}.
to
raise_error
(
Gitlab
::
Ci
::
Trace
::
AlreadyArchivedError
)
expect
(
build
.
job_artifacts_trace
.
file
.
exists?
).
to
be_truthy
expect
(
build
.
job_artifacts_trace
.
file
.
exists?
).
to
be_truthy
end
end
end
end
...
@@ -776,4 +847,35 @@ shared_examples_for 'trace with enabled live trace feature' do
...
@@ -776,4 +847,35 @@ shared_examples_for 'trace with enabled live trace feature' do
end
end
end
end
end
end
describe
'#erase!'
do
subject
{
trace
.
erase!
}
context
'when it is a live trace'
do
let
(
:build
)
{
create
(
:ci_build
,
:trace_live
)
}
it
{
expect
(
trace
.
raw
).
not_to
be_nil
}
it
"removes trace"
do
subject
expect
(
trace
.
raw
).
to
be_nil
end
end
context
'when it is an archived trace'
do
let
(
:build
)
{
create
(
:ci_build
,
:trace_artifact
)
}
it
"has trace at first"
do
expect
(
trace
.
raw
).
not_to
be_nil
end
it
"removes trace"
do
subject
build
.
reload
expect
(
trace
.
raw
).
to
be_nil
end
end
end
end
end
spec/workers/ci/archive_traces_cron_worker_spec.rb
View file @
ca3ea76c
...
@@ -25,24 +25,36 @@ describe Ci::ArchiveTracesCronWorker do
...
@@ -25,24 +25,36 @@ describe Ci::ArchiveTracesCronWorker do
end
end
end
end
context
'when a job
was
succeeded'
do
context
'when a job succeeded'
do
let!
(
:build
)
{
create
(
:ci_build
,
:success
,
:trace_live
)
}
let!
(
:build
)
{
create
(
:ci_build
,
:success
,
:trace_live
)
}
it_behaves_like
'archives trace'
it_behaves_like
'archives trace'
context
'when a
rchive raised an exception
'
do
context
'when a
trace had already been archived
'
do
let!
(
:build
)
{
create
(
:ci_build
,
:success
,
:trace_
artifact
,
:trace_live
)
}
let!
(
:build
)
{
create
(
:ci_build
,
:success
,
:trace_
live
,
:trace_artifact
)
}
let!
(
:build2
)
{
create
(
:ci_build
,
:success
,
:trace_live
)
}
let!
(
:build2
)
{
create
(
:ci_build
,
:success
,
:trace_live
)
}
it
'archives valid targets'
do
it
'continues to archive live traces'
do
expect
(
Rails
.
logger
).
to
receive
(
:error
).
with
(
"Failed to archive stale live trace. id:
#{
build
.
id
}
message: Already archived"
)
subject
subject
build2
.
reload
build2
.
reload
expect
(
build2
.
job_artifacts_trace
).
to
be_exist
expect
(
build2
.
job_artifacts_trace
).
to
be_exist
end
end
end
end
context
'when an unexpected exception happened during archiving'
do
let!
(
:build
)
{
create
(
:ci_build
,
:success
,
:trace_live
)
}
before
do
allow_any_instance_of
(
Gitlab
::
Ci
::
Trace
).
to
receive
(
:archive!
).
and_raise
(
'Unexpected error'
)
end
it
'puts a log'
do
expect
(
Rails
.
logger
).
to
receive
(
:error
).
with
(
"Failed to archive stale live trace. id:
#{
build
.
id
}
message: Unexpected error"
)
subject
end
end
end
end
context
'when a job was cancelled'
do
context
'when a job was cancelled'
do
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment