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
1
Merge Requests
1
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
nexedi
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/
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?
[
Yes
](
https://news.ycombinator.com/item?id=3067434
)
...
...
app/assets/javascripts/diffs/components/diff_file_header.vue
View file @
ca3ea76c
...
...
@@ -2,6 +2,7 @@
import
_
from
'
underscore
'
;
import
ClipboardButton
from
'
~/vue_shared/components/clipboard_button.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
{
truncateSha
}
from
'
~/lib/utils/text_utility
'
;
import
{
__
,
s__
,
sprintf
}
from
'
~/locale
'
;
...
...
@@ -12,6 +13,7 @@ export default {
ClipboardButton
,
EditButton
,
Icon
,
FileIcon
,
},
directives
:
{
Tooltip
,
...
...
@@ -139,18 +141,20 @@ export default {
:name=
"collapseIcon"
:size=
"16"
aria-hidden=
"true"
class=
"diff-toggle-caret"
class=
"diff-toggle-caret
append-right-5
"
@
click.stop=
"handleToggle"
/>
<a
ref=
"titleWrapper"
:href=
"titleLink"
class=
"append-right-4"
>
<
i
:
class=
"`fa-$
{icon}`
"
class="fa fa-fw
"
<
file-icon
:
file-name=
"filePath
"
:size=
"18
"
aria-hidden=
"true"
>
</i>
css-classes=
"js-file-icon append-right-5"
/>
<span
v-if=
"diffFile.renamedFile"
>
<strong
v-tooltip
...
...
app/assets/javascripts/diffs/components/parallel_diff_view.vue
View file @
ca3ea76c
...
...
@@ -24,19 +24,21 @@ export default {
...
mapGetters
([
'
commit
'
]),
parallelDiffLines
()
{
return
this
.
diffLines
.
map
(
line
=>
{
const
parallelLine
=
Object
.
assign
({},
line
);
if
(
line
.
left
)
{
Object
.
assign
(
line
,
{
left
:
trimFirstCharOfLineContent
(
line
.
left
)
}
);
parallelLine
.
left
=
trimFirstCharOfLineContent
(
line
.
left
);
}
else
{
Object
.
assign
(
line
,
{
left
:
{
type
:
EMPTY_CELL_TYPE
}
})
;
parallelLine
.
left
=
{
type
:
EMPTY_CELL_TYPE
}
;
}
if
(
line
.
right
)
{
Object
.
assign
(
line
,
{
right
:
trimFirstCharOfLineContent
(
line
.
right
)
}
);
parallelLine
.
right
=
trimFirstCharOfLineContent
(
line
.
right
);
}
else
{
Object
.
assign
(
line
,
{
right
:
{
type
:
EMPTY_CELL_TYPE
}
})
;
parallelLine
.
right
=
{
type
:
EMPTY_CELL_TYPE
}
;
}
return
l
ine
;
return
parallelL
ine
;
});
},
diffLinesLength
()
{
...
...
app/assets/javascripts/diffs/store/utils.js
View file @
ca3ea76c
...
...
@@ -155,18 +155,21 @@ export function addContextLines(options) {
}
}
export
function
trimFirstCharOfLineContent
(
line
)
{
if
(
!
line
.
richText
)
{
return
line
;
}
const
firstChar
=
line
.
richText
.
charAt
(
0
);
if
(
firstChar
===
'
'
||
firstChar
===
'
+
'
||
firstChar
===
'
-
'
)
{
Object
.
assign
(
line
,
{
richText
:
line
.
richText
.
substring
(
1
),
});
/**
* Trims the first char of the `richText` property when it's either a space or a diff symbol.
* @param {Object} line
* @returns {Object}
*/
export
function
trimFirstCharOfLineContent
(
line
=
{})
{
const
parsedLine
=
Object
.
assign
({},
line
);
if
(
line
.
richText
)
{
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
>
import
{
mapState
,
mapActions
}
from
'
vuex
'
;
import
imageDiffHelper
from
'
~/image_diff/helpers/index
'
;
import
{
convertObjectPropsToCamelCase
}
from
'
~/lib/utils/common_utils
'
;
import
DiffFileHeader
from
'
~/diffs/components/diff_file_header.vue
'
;
import
SkeletonLoadingContainer
from
'
~/vue_shared/components/skeleton_loading_container.vue
'
;
import
{
trimFirstCharOfLineContent
}
from
'
~/diffs/store/utils
'
;
import
{
mapState
,
mapActions
}
from
'
vuex
'
;
import
imageDiffHelper
from
'
~/image_diff/helpers/index
'
;
import
{
convertObjectPropsToCamelCase
}
from
'
~/lib/utils/common_utils
'
;
import
DiffFileHeader
from
'
~/diffs/components/diff_file_header.vue
'
;
import
SkeletonLoadingContainer
from
'
~/vue_shared/components/skeleton_loading_container.vue
'
;
import
{
trimFirstCharOfLineContent
}
from
'
~/diffs/store/utils
'
;
export
default
{
components
:
{
DiffFileHeader
,
SkeletonLoadingContainer
,
},
props
:
{
discussion
:
{
type
:
Object
,
required
:
true
,
export
default
{
components
:
{
DiffFileHeader
,
SkeletonLoadingContainer
,
},
},
data
()
{
return
{
error
:
false
,
};
},
computed
:
{
...
mapState
({
noteableData
:
state
=>
state
.
notes
.
noteableData
,
}),
hasTruncatedDiffLines
()
{
return
this
.
discussion
.
truncatedDiffLines
&&
this
.
discussion
.
truncatedDiffLines
.
length
!==
0
;
props
:
{
discussion
:
{
type
:
Object
,
required
:
true
,
},
},
isDiscussionsExpanded
()
{
return
true
;
// TODO: @fatihacet - Fix this.
data
()
{
return
{
error
:
false
,
};
},
isCollapsed
()
{
return
this
.
diffFile
.
collapsed
||
false
;
},
isImageDiff
()
{
return
!
this
.
diffFile
.
text
;
},
diffFileClass
()
{
const
{
text
}
=
this
.
diffFile
;
return
text
?
'
text-file
'
:
'
js-image-file
'
;
},
diffFile
()
{
return
convertObjectPropsToCamelCase
(
this
.
discussion
.
diffFile
,
{
deep
:
true
});
},
imageDiffHtml
()
{
return
this
.
discussion
.
imageDiffHtml
;
},
currentUser
()
{
return
this
.
noteableData
.
current_user
;
},
userColorScheme
()
{
return
window
.
gon
.
user_color_scheme
;
},
normalizedDiffLines
()
{
const
lines
=
this
.
discussion
.
truncatedDiffLines
||
[];
computed
:
{
...
mapState
({
noteableData
:
state
=>
state
.
notes
.
noteableData
,
}),
hasTruncatedDiffLines
()
{
return
this
.
discussion
.
truncatedDiffLines
&&
this
.
discussion
.
truncatedDiffLines
.
length
!==
0
;
},
isDiscussionsExpanded
()
{
return
true
;
// TODO: @fatihacet - Fix this.
},
isCollapsed
()
{
return
this
.
diffFile
.
collapsed
||
false
;
},
isImageDiff
()
{
return
!
this
.
diffFile
.
text
;
},
diffFileClass
()
{
const
{
text
}
=
this
.
diffFile
;
return
text
?
'
text-file
'
:
'
js-image-file
'
;
},
diffFile
()
{
return
convertObjectPropsToCamelCase
(
this
.
discussion
.
diffFile
,
{
deep
:
true
});
},
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
()
{
if
(
this
.
isImageDiff
)
{
const
canCreateNote
=
false
;
const
renderCommentBadge
=
true
;
imageDiffHelper
.
initImageDiff
(
this
.
$refs
.
fileHolder
,
canCreateNote
,
renderCommentBadge
);
}
else
if
(
!
this
.
hasTruncatedDiffLines
)
{
this
.
fetchDiff
();
}
},
methods
:
{
...
mapActions
([
'
fetchDiscussionDiffLines
'
]),
rowTag
(
html
)
{
return
html
.
outerHTML
?
'
tr
'
:
'
template
'
;
mounted
()
{
if
(
this
.
isImageDiff
)
{
const
canCreateNote
=
false
;
const
renderCommentBadge
=
true
;
imageDiffHelper
.
initImageDiff
(
this
.
$refs
.
fileHolder
,
canCreateNote
,
renderCommentBadge
);
}
else
if
(
!
this
.
hasTruncatedDiffLines
)
{
this
.
fetchDiff
();
}
},
fetchDiff
()
{
this
.
error
=
false
;
this
.
fetchDiscussionDiffLines
(
this
.
discussion
)
.
then
(
this
.
highlight
)
.
catch
(()
=>
{
this
.
error
=
true
;
});
methods
:
{
...
mapActions
([
'
fetchDiscussionDiffLines
'
]),
rowTag
(
html
)
{
return
html
.
outerHTML
?
'
tr
'
:
'
template
'
;
},
fetchDiff
()
{
this
.
error
=
false
;
this
.
fetchDiscussionDiffLines
(
this
.
discussion
)
.
then
(
this
.
highlight
)
.
catch
(()
=>
{
this
.
error
=
true
;
});
},
},
},
};
};
</
script
>
<
template
>
...
...
app/assets/javascripts/notes/stores/getters.js
View file @
ca3ea76c
...
...
@@ -85,9 +85,9 @@ export const allDiscussions = (state, getters) => {
export
const
resolvedDiscussionsById
=
state
=>
{
const
map
=
{};
state
.
discussions
.
forEach
(
n
=>
{
state
.
discussions
.
f
ilter
(
d
=>
d
.
resolvable
).
f
orEach
(
n
=>
{
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
)
{
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 @@
methods
:
{
isValid
(
form
)
{
return
!
form
||
form
.
find
(
'
.js-vue-markdown-field
'
).
length
||
$
(
this
.
$el
).
closest
(
'
form
'
)
===
form
[
0
];
form
.
find
(
'
.js-vue-markdown-field
'
).
length
&&
$
(
this
.
$el
).
closest
(
'
form
'
)
[
0
]
===
form
[
0
];
},
previewMarkdownTab
(
event
,
form
)
{
...
...
app/assets/stylesheets/pages/diff.scss
View file @
ca3ea76c
...
...
@@ -15,7 +15,7 @@
}
svg
{
vertical-align
:
text-bottom
;
vertical-align
:
middle
;
}
}
...
...
app/controllers/concerns/preview_markdown.rb
View file @
ca3ea76c
...
...
@@ -10,6 +10,7 @@ module PreviewMarkdown
when
'wikis'
then
{
pipeline: :wiki
,
project_wiki:
@project_wiki
,
page_slug:
params
[
:id
]
}
when
'snippets'
then
{
skip_project_check:
true
}
when
'groups'
then
{
group:
group
}
when
'projects'
then
{
issuable_state_filter_enabled:
true
}
else
{}
end
...
...
app/controllers/dashboard/projects_controller.rb
View file @
ca3ea76c
...
...
@@ -7,7 +7,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
skip_cross_project_access_check
:index
,
:starred
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
|
format
.
html
...
...
@@ -25,7 +25,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
def
starred
@projects
=
load_projects
(
params
.
merge
(
starred:
true
))
.
includes
(
:forked_from_project
,
:tags
)
.
page
(
params
[
:page
])
.
includes
(
:forked_from_project
,
:tags
)
@groups
=
[]
...
...
@@ -51,6 +51,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
.
new
(
params:
finder_params
,
current_user:
current_user
)
.
execute
.
includes
(
:route
,
:creator
,
namespace:
[
:route
,
:owner
])
.
page
(
finder_params
[
:page
])
prepare_projects_for_rendering
(
projects
)
end
...
...
app/controllers/projects/jobs_controller.rb
View file @
ca3ea76c
...
...
@@ -2,11 +2,12 @@ class Projects::JobsController < Projects::ApplicationController
include
SendFileUpload
before_action
:build
,
except:
[
:index
,
:cancel_all
]
before_action
:authorize_read_build!
,
only:
[
:index
,
:show
,
:status
,
:raw
,
:trace
]
before_action
:authorize_read_build!
before_action
:authorize_update_build!
,
except:
[
:index
,
:show
,
:status
,
:raw
,
:trace
,
:cancel_all
,
: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'
...
...
@@ -134,6 +135,15 @@ class Projects::JobsController < Projects::ApplicationController
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
def
authorize_update_build!
...
...
@@ -144,6 +154,14 @@ class Projects::JobsController < Projects::ApplicationController
return
access_denied!
unless
can?
(
current_user
,
:erase_build
,
build
)
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
{
type:
'text/plain; charset=utf-8'
,
disposition:
'inline'
}
end
...
...
app/helpers/projects_helper.rb
View file @
ca3ea76c
...
...
@@ -177,6 +177,7 @@ module ProjectsHelper
controller
.
action_name
,
Gitlab
::
CurrentSettings
.
cache_key
,
"cross-project:
#{
can?
(
current_user
,
:read_cross_project
)
}
"
,
max_project_member_access_cache_key
(
project
),
'v2.6'
]
...
...
app/helpers/users_helper.rb
View file @
ca3ea76c
...
...
@@ -31,6 +31,14 @@ module UsersHelper
current_user_menu_items
.
include?
(
item
)
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
def
get_profile_tabs
...
...
app/models/board.rb
View file @
ca3ea76c
...
...
@@ -26,4 +26,8 @@ class Board < ActiveRecord::Base
def
closed_list
lists
.
merge
(
List
.
closed
).
take
end
def
scoped?
false
end
end
app/models/ci/build.rb
View file @
ca3ea76c
...
...
@@ -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
: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
:url
,
to: :runner_session
,
prefix:
true
,
allow_nil:
true
delegate
:terminal_specification
,
to: :runner_session
,
allow_nil:
true
delegate
:gitlab_deploy_token
,
to: :project
##
...
...
@@ -174,6 +180,10 @@ module Ci
after_transition
pending: :running
do
|
build
|
build
.
ensure_metadata
.
update_timeout_state
end
after_transition
running:
any
do
|
build
|
Ci
::
BuildRunnerSession
.
where
(
build:
build
).
delete_all
end
end
def
ensure_metadata
...
...
@@ -376,6 +386,10 @@ module Ci
trace
.
exist?
end
def
has_old_trace?
old_trace
.
present?
end
def
trace
=
(
data
)
raise
NotImplementedError
end
...
...
@@ -385,6 +399,8 @@ module Ci
end
def
erase_old_trace!
return
unless
has_old_trace?
update_column
(
:trace
,
nil
)
end
...
...
@@ -584,6 +600,10 @@ module Ci
super
(
options
).
merge
(
when:
read_attribute
(
:when
))
end
def
has_terminal?
running?
&&
runner_session_url
.
present?
end
private
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
end
def
deprecation_validation
return
if
active_changed?
(
from:
true
,
to:
false
)
return
if
active_changed?
(
from:
true
,
to:
false
)
||
(
new_record?
&&
!
active?
)
if
deprecated?
errors
[
:base
]
<<
deprecation_message
...
...
app/models/service.rb
View file @
ca3ea76c
...
...
@@ -281,9 +281,9 @@ class Service < ActiveRecord::Base
def
self
.
build_from_template
(
project_id
,
template
)
service
=
template
.
dup
service
.
active
=
false
unless
service
.
valid?
service
.
template
=
false
service
.
project_id
=
project_id
service
.
active
=
false
if
service
.
active?
&&
!
service
.
valid?
service
end
...
...
app/policies/ci/build_policy.rb
View file @
ca3ea76c
...
...
@@ -18,6 +18,10 @@ module Ci
@subject
.
project
.
branch_allows_collaboration?
(
@user
,
@subject
.
ref
)
end
condition
(
:terminal
,
scope: :subject
)
do
@subject
.
has_terminal?
end
rule
{
protected_ref
}.
policy
do
prevent
:update_build
prevent
:erase_build
...
...
@@ -29,5 +33,7 @@ module Ci
enable
:update_build
enable
:update_commit_status
end
rule
{
can?
(
:update_build
)
&
terminal
}.
enable
:create_build_terminal
end
end
app/services/ci/register_job_service.rb
View file @
ca3ea76c
...
...
@@ -13,7 +13,7 @@ module Ci
@runner
=
runner
end
def
execute
def
execute
(
params
=
{})
builds
=
if
runner
.
instance_type?
builds_for_shared_runner
...
...
@@ -41,6 +41,8 @@ module Ci
# with StateMachines::InvalidTransition or StaleObjectError when doing run! or save method.
begin
build
.
runner_id
=
runner
.
id
build
.
runner_session_attributes
=
params
[
:session
]
if
params
[
:session
].
present?
build
.
run!
register_success
(
build
)
...
...
app/services/issues/base_service.rb
View file @
ca3ea76c
...
...
@@ -32,8 +32,9 @@ module Issues
def
filter_assignee
(
issuable
)
return
if
params
[
:assignee_ids
].
blank?
# The number of assignees is limited by one for GitLab CE
params
[
:assignee_ids
]
=
params
[
:assignee_ids
][
0
,
1
]
unless
issuable
.
allows_multiple_assignees?
params
[
:assignee_ids
]
=
params
[
:assignee_ids
].
take
(
1
)
end
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 @@
=
link_to
_
(
"Help"
),
help_path
-
if
current_user_menu?
(
:help
)
||
current_user_menu?
(
:settings
)
||
current_user_menu?
(
:profile
)
%li
.divider
%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
=
render
'shared/user_dropdown_contributing_link'
-
if
current_user_menu?
(
:sign_out
)
%li
=
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"
}
}
.sidebar-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?
}
}
...
...
@@ -14,8 +18,8 @@
#{
time_ago_with_tooltip
(
@build
.
artifacts_expire_at
)
}
-
elsif
@build
.
has_expiring_artifacts?
%p
.build-detail-row
The artifacts will be removed
in
%span
=
time_ago_with_tooltip
@build
.
artifacts_expire_at
The artifacts will be removed
#{
time_ago_with_tooltip
(
@build
.
artifacts_expire_at
)
}
-
if
@build
.
artifacts?
.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 @@
%li
JaCoCo (Java/Kotlin)
%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"
...
...
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 @@
-
group
=
local_assigns
.
fetch
(
:group
,
false
)
-
@no_breadcrumb_container
=
true
-
@no_container
=
true
-
@content_class
=
"issue-boards-content"
-
breadcrumb_title
_
(
"Issue Board"
)
-
@content_class
=
"issue-boards-content
js-focus-mode-board
"
-
breadcrumb_title
_
(
"Issue Board
s
"
)
-
page_title
_
(
"Boards"
)
-
content_for
:page_specific_javascripts
do
...
...
@@ -11,10 +11,11 @@
-# haml-lint:disable InlineJavaScript
%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-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 }"
}
.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-app-loading.text-center
{
"v-if"
=>
"loading"
}
...
...
app/views/shared/issuable/_search_bar.html.haml
View file @
ca3ea76c
-
type
=
local_assigns
.
fetch
(
:type
)
-
board
=
local_assigns
.
fetch
(
:board
,
nil
)
-
block_css_class
=
type
!=
:boards_modal
?
'row-content-block second-block'
:
''
-
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-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
-
if
params
[
:search
].
present?
=
hidden_field_tag
:search
,
params
[
:search
]
...
...
@@ -99,13 +104,18 @@
%gl-emoji
%span
.js-data-value.prepend-left-10
{{name}}
=
render_if_exists
'shared/issuable/filter_weight'
,
type:
type
%button
.clear-search.hidden
{
type:
'button'
}
=
icon
(
'times'
)
.filter-dropdown-container
-
if
type
==
:boards
-
if
can?
(
current_user
,
:admin_list
,
board
.
parent
)
=
render_if_exists
'shared/issuable/board_create_list_dropdown'
,
board:
board
.js-board-config
{
data:
{
can_admin_list:
user_can_admin_list
,
has_scope:
board
.
scoped?
}
}
-
if
user_can_admin_list
=
render
'shared/issuable/board_create_list_dropdown'
,
board:
board
-
if
@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
=
render
'shared/sort_dropdown'
app/views/shared/projects/_project.html.haml
View file @
ca3ea76c
...
...
@@ -4,7 +4,7 @@
-
ci
=
false
unless
local_assigns
[
:ci
]
==
true
-
skip_namespace
=
false
unless
local_assigns
[
:skip_namespace
]
==
true
-
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
]
-
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
...
...
app/workers/archive_trace_worker.rb
View file @
ca3ea76c
...
...
@@ -5,7 +5,7 @@ class ArchiveTraceWorker
include
PipelineBackgroundQueue
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!
end
end
...
...
app/workers/ci/archive_traces_cron_worker.rb
View file @
ca3ea76c
...
...
@@ -12,6 +12,7 @@ module Ci
Ci
::
Build
.
finished
.
with_live_trace
.
find_each
(
batch_size:
100
)
do
|
build
|
begin
build
.
trace
.
archive!
rescue
::
Gitlab
::
Ci
::
Trace
::
AlreadyArchivedError
rescue
=>
e
failed_archive_counter
.
increment
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
post
:erase
get
:trace
,
defaults:
{
format:
'json'
}
get
:raw
get
:terminal
get
'/terminal.ws/authorize'
,
to:
'jobs#terminal_websocket_authorize'
,
constraints:
{
format:
nil
}
end
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
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
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
|
t
.
string
"key"
,
null:
false
t
.
text
"value"
...
...
@@ -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_metadata"
,
"ci_builds"
,
column:
"build_id"
,
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_job_artifacts"
,
"ci_builds"
,
column:
"job_id"
,
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
}
```
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 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
[
Learn more on container scanning results shown in merge requests
](
https://docs.gitlab.com/ee/user/project/merge_requests/container_scanning.html
)
.
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
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`
configuration to reflect that change.
...
...
lib/api/entities.rb
View file @
ca3ea76c
...
...
@@ -1203,6 +1203,7 @@ module API
class
RunnerInfo
<
Grape
::
Entity
expose
:metadata_timeout
,
as: :timeout
expose
:runner_session_url
end
class
Step
<
Grape
::
Entity
...
...
lib/api/runner.rb
View file @
ca3ea76c
...
...
@@ -81,6 +81,11 @@ module API
requires
:token
,
type:
String
,
desc:
%q(Runner's authentication token)
optional
:last_update
,
type:
String
,
desc:
%q(Runner's queue last_update token)
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
post
'/request'
do
authenticate_runner!
...
...
@@ -90,14 +95,16 @@ module API
break
no_content!
end
if
current_runner
.
runner_queue_value_latest?
(
params
[
:last_update
])
header
'X-GitLab-Last-Update'
,
params
[
:last_update
]
runner_params
=
declared_params
(
include_missing:
false
)
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
)
break
no_content!
end
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
.
build
...
...
lib/gitlab/ci/trace.rb
View file @
ca3ea76c
...
...
@@ -6,6 +6,7 @@ module Gitlab
LEASE_TIMEOUT
=
1
.
hour
ArchiveError
=
Class
.
new
(
StandardError
)
AlreadyArchivedError
=
Class
.
new
(
StandardError
)
attr_reader
:job
...
...
@@ -81,7 +82,9 @@ module Gitlab
def
write
(
mode
)
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
)
elsif
Feature
.
enabled?
(
'ci_enable_live_trace'
)
Gitlab
::
Ci
::
Trace
::
ChunkedIO
.
new
(
job
)
...
...
@@ -98,14 +101,17 @@ module Gitlab
end
def
erase!
trace_artifact
&
.
destroy
paths
.
each
do
|
trace_path
|
FileUtils
.
rm
(
trace_path
,
force:
true
)
end
job
.
trace_chunks
.
fast_destroy_all
job
.
erase_old_trace!
##
# Erase the archived trace
trace_artifact
&
.
destroy!
##
# Erase the live trace
job
.
trace_chunks
.
fast_destroy_all
# Destroy chunks of a live 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
def
archive!
...
...
@@ -117,7 +123,7 @@ module Gitlab
private
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?
if
job
.
trace_chunks
.
any?
...
...
lib/gitlab/git/commit.rb
View file @
ca3ea76c
...
...
@@ -63,8 +63,12 @@ module Gitlab
# This saves us an RPC round trip.
return
nil
if
commit_id
.
include?
(
':'
)
commit
=
repo
.
wrapped_gitaly_errors
do
repo
.
gitaly_commit_client
.
find_commit
(
commit_id
)
commit
=
repo
.
gitaly_migrate
(
:find_commit
)
do
|
is_enabled
|
if
is_enabled
repo
.
gitaly_commit_client
.
find_commit
(
commit_id
)
else
rugged_find
(
repo
,
commit_id
)
end
end
decorate
(
repo
,
commit
)
if
commit
...
...
@@ -74,6 +78,12 @@ module Gitlab
nil
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
#
# Ex.
...
...
lib/gitlab/git/conflict/resolver.rb
View file @
ca3ea76c
...
...
@@ -12,8 +12,14 @@ module Gitlab
end
def
conflicts
@conflicts
||=
@target_repository
.
wrapped_gitaly_errors
do
gitaly_conflicts_client
(
@target_repository
).
list_conflict_files
.
to_a
@conflicts
||=
begin
@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
rescue
GRPC
::
FailedPrecondition
=>
e
raise
Gitlab
::
Git
::
Conflict
::
Resolver
::
ConflictSideMissing
.
new
(
e
.
message
)
...
...
@@ -22,8 +28,12 @@ module Gitlab
end
def
resolve_conflicts
(
source_repository
,
resolution
,
source_branch
:,
target_branch
:)
source_repository
.
wrapped_gitaly_errors
do
gitaly_conflicts_client
(
source_repository
).
resolve_conflicts
(
@target_repository
,
resolution
,
source_branch
,
target_branch
)
source_repository
.
gitaly_migrate
(
:conflicts_resolve_conflicts
)
do
|
is_enabled
|
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
...
...
@@ -51,6 +61,57 @@ module Gitlab
def
gitaly_conflicts_client
(
repository
)
repository
.
gitaly_conflicts_client
(
@our_commit_oid
,
@their_commit_oid
)
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
...
...
lib/gitlab/git/repository.rb
View file @
ca3ea76c
...
...
@@ -555,8 +555,12 @@ module Gitlab
# diff options. The +options+ hash can also include :break_rewrites to
# split larger rewrites into delete/add pairs.
def
diff
(
from
,
to
,
options
=
{},
*
paths
)
iterator
=
wrapped_gitaly_errors
do
gitaly_commit_client
.
diff
(
from
,
to
,
options
.
merge
(
paths:
paths
))
iterator
=
gitaly_migrate
(
:diff_between
)
do
|
is_enabled
|
if
is_enabled
gitaly_commit_client
.
diff
(
from
,
to
,
options
.
merge
(
paths:
paths
))
else
diff_patches
(
from
,
to
,
options
,
*
paths
)
end
end
Gitlab
::
Git
::
DiffCollection
.
new
(
iterator
,
options
)
...
...
@@ -1587,6 +1591,17 @@ module Gitlab
tmp_entry
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
)
case
sort_by
when
'name'
...
...
lib/gitlab/gitaly_client/blob_service.rb
View file @
ca3ea76c
...
...
@@ -13,7 +13,7 @@ module Gitlab
oid:
oid
,
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
=
''
blob
=
nil
...
...
@@ -43,7 +43,7 @@ module Gitlab
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
)
end
...
...
@@ -66,7 +66,7 @@ module Gitlab
:blob_service
,
:get_blobs
,
request
,
timeout:
GitalyClient
.
defaul
t_timeout
timeout:
GitalyClient
.
fas
t_timeout
)
GitalyClient
::
BlobsStitcher
.
new
(
response
)
...
...
@@ -85,7 +85,7 @@ module Gitlab
request
.
not_in_refs
+=
not_in
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
)
end
...
...
@@ -96,7 +96,7 @@ module Gitlab
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
)
end
...
...
lib/gitlab/gitaly_client/commit_service.rb
View file @
ca3ea76c
...
...
@@ -70,7 +70,7 @@ module Gitlab
def
commit_deltas
(
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
}
end
...
...
@@ -302,7 +302,7 @@ module Gitlab
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
|
msg
.
shas
.
map
{
|
sha
|
EncodingHelper
.
encode!
(
sha
)
}
...
...
@@ -330,7 +330,7 @@ module Gitlab
def
get_commit_signatures
(
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
]
}
current_commit_id
=
nil
...
...
@@ -349,7 +349,7 @@ module Gitlab
def
get_commit_messages
(
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
}
current_commit_id
=
nil
...
...
lib/gitlab/gitaly_client/conflicts_service.rb
View file @
ca3ea76c
...
...
@@ -46,7 +46,7 @@ module Gitlab
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?
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
def
exists?
(
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
def
add
(
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
def
remove
(
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
def
rename
(
from
,
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
private
def
gitaly_client_call
(
type
,
request
)
GitalyClient
.
call
(
@storage
,
:namespace_service
,
type
,
request
)
def
gitaly_client_call
(
type
,
request
,
timeout:
nil
)
GitalyClient
.
call
(
@storage
,
:namespace_service
,
type
,
request
,
timeout:
timeout
)
end
end
end
...
...
lib/gitlab/gitaly_client/operation_service.rb
View file @
ca3ea76c
...
...
@@ -17,7 +17,7 @@ module Gitlab
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
raise
Gitlab
::
Git
::
PreReceiveError
,
pre_receive_error
...
...
@@ -33,7 +33,7 @@ module Gitlab
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
raise
Gitlab
::
Git
::
PreReceiveError
,
pre_receive_error
elsif
response
.
exists
...
...
@@ -276,7 +276,8 @@ module Gitlab
:operation_service
,
:"user_
#{
rpc
}
"
,
request
,
remote_storage:
start_repository
.
storage
remote_storage:
start_repository
.
storage
,
timeout:
GitalyClient
.
medium_timeout
)
handle_cherry_pick_or_revert_response
(
response
)
...
...
lib/gitlab/gitaly_client/ref_service.rb
View file @
ca3ea76c
...
...
@@ -12,7 +12,7 @@ module Gitlab
def
branches
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
)
end
...
...
@@ -23,26 +23,26 @@ module Gitlab
merged_only:
true
,
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
)
end
def
default_branch_name
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
)
end
def
branch_names
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
)
}
end
def
tag_names
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
)
}
end
...
...
@@ -67,19 +67,19 @@ module Gitlab
def
local_branches
(
sort_by:
nil
)
request
=
Gitaly
::
FindLocalBranchesRequest
.
new
(
repository:
@gitaly_repo
)
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
)
end
def
tags
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
)
end
def
ref_exists?
(
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
rescue
GRPC
::
InvalidArgument
=>
e
raise
ArgumentError
,
e
.
message
...
...
@@ -91,7 +91,7 @@ module Gitlab
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
return
unless
branch
...
...
@@ -140,7 +140,7 @@ module Gitlab
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?
end
...
...
@@ -153,7 +153,7 @@ module Gitlab
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
)
end
...
...
@@ -166,14 +166,14 @@ module Gitlab
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
)
end
def
get_tag_messages
(
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
}
current_tag_id
=
nil
...
...
lib/gitlab/gitaly_client/remote_service.rb
View file @
ca3ea76c
...
...
@@ -28,13 +28,13 @@ module Gitlab
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
def
remove_remote
(
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
end
...
...
lib/gitlab/gitaly_client/repository_service.rb
View file @
ca3ea76c
...
...
@@ -21,7 +21,7 @@ module Gitlab
def
cleanup
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
def
garbage_collect
(
create_bitmap
)
...
...
@@ -41,13 +41,13 @@ module Gitlab
def
repository_size
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
end
def
apply_gitattributes
(
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
raise
Gitlab
::
Git
::
Repository
::
InvalidRef
,
ex
end
...
...
@@ -55,7 +55,7 @@ module Gitlab
def
info_attributes
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
|
attributes
<<
message
.
attributes
end
...
...
@@ -82,7 +82,7 @@ module Gitlab
def
create_repository
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
def
has_local_branches?
...
...
@@ -98,7 +98,7 @@ module Gitlab
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
end
...
...
@@ -258,7 +258,7 @@ module Gitlab
)
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?
...
...
@@ -288,7 +288,7 @@ module Gitlab
def
calculate_checksum
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
rescue
GRPC
::
DataLoss
=>
e
raise
Gitlab
::
Git
::
Repository
::
InvalidRepository
.
new
(
e
)
...
...
@@ -297,12 +297,12 @@ module Gitlab
def
raw_changes_between
(
from
,
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
def
search_files_by_name
(
ref
,
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
def
search_files_by_content
(
ref
,
query
)
...
...
lib/gitlab/gitaly_client/wiki_service.rb
View file @
ca3ea76c
...
...
@@ -69,7 +69,7 @@ module Gitlab
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
def
find_page
(
title
:,
version:
nil
,
dir:
nil
)
...
...
@@ -80,14 +80,14 @@ module Gitlab
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
)
end
def
get_all_pages
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
=
[]
loop
do
...
...
@@ -113,7 +113,7 @@ module Gitlab
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
=
[]
stream
.
each
do
|
message
|
...
...
@@ -132,7 +132,7 @@ module Gitlab
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
response
.
each
do
|
message
|
...
...
qa/qa/runtime/browser.rb
View file @
ca3ea76c
...
...
@@ -32,6 +32,12 @@ module QA
end
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
)
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
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
spec/controllers/projects/pipelines_controller_spec.rb
View file @
ca3ea76c
...
...
@@ -74,7 +74,7 @@ describe Projects::PipelinesController do
expect
(
stages
.
count
).
to
eq
3
end
expect
(
queries
.
count
).
to
be_within
(
3
).
of
(
30
)
expect
(
queries
.
count
).
to
be_within
(
5
).
of
(
30
)
end
end
...
...
spec/controllers/projects_controller_spec.rb
View file @
ca3ea76c
...
...
@@ -616,13 +616,40 @@ describe ProjectsController do
end
describe
'POST #preview_markdown'
do
it
'renders json in a correct format'
do
before
do
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'
expect
(
JSON
.
parse
(
response
.
body
).
keys
).
to
match_array
(
%w(body references)
)
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
describe
'#ensure_canonical_path'
do
...
...
spec/factories/ci/builds.rb
View file @
ca3ea76c
...
...
@@ -248,5 +248,11 @@ FactoryBot.define do
failed
failure_reason
2
end
trait
:with_runner_session
do
after
(
:build
)
do
|
build
|
build
.
build_runner_session
(
url:
'ws://localhost'
)
end
end
end
end
spec/features/dashboard/projects_spec.rb
View file @
ca3ea76c
...
...
@@ -29,6 +29,34 @@ describe 'Dashboard Projects' do
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
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
)
...
...
spec/features/projects/issues/user_comments_on_issue_spec.rb
View file @
ca3ea76c
...
...
@@ -63,6 +63,14 @@ describe "User comments on issue", :js do
page
.
within
(
".current-note-edit-form"
)
do
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"
)
end
...
...
spec/helpers/projects_helper_spec.rb
View file @
ca3ea76c
...
...
@@ -80,6 +80,7 @@ describe ProjectsHelper do
before
do
allow
(
helper
).
to
receive
(
:current_user
).
and_return
(
user
)
allow
(
helper
).
to
receive
(
:can?
).
with
(
user
,
:read_cross_project
)
{
true
}
allow
(
user
).
to
receive
(
:max_member_access_for_project
).
and_return
(
40
)
end
it
"includes the route"
do
...
...
@@ -125,6 +126,10 @@ describe ProjectsHelper do
expect
(
helper
.
project_list_cache_key
(
project
)).
to
include
(
"pipeline-status/
#{
project
.
commit
.
sha
}
-success"
)
end
it
"includes the user max member access"
do
expect
(
helper
.
project_list_cache_key
(
project
)).
to
include
(
'access:40'
)
end
end
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', () => {
});
});
it
(
'
displays an icon in the title
'
,
()
=>
{
it
(
'
displays an
file
icon in the title
'
,
()
=>
{
vm
=
mountComponent
(
Component
,
props
);
const
icon
=
vm
.
$el
.
querySelector
(
`i[class="fa fa-fw fa-
${
vm
.
icon
}
"]`
);
expect
(
icon
).
not
.
toBe
(
null
);
expect
(
vm
.
$el
.
querySelector
(
'
svg.js-file-icon use
'
).
getAttribute
(
'
xlink:href
'
)).
toContain
(
'
ruby
'
,
);
});
describe
(
'
file paths
'
,
()
=>
{
...
...
spec/javascripts/diffs/store/utils_spec.js
View file @
ca3ea76c
...
...
@@ -176,4 +176,35 @@ describe('DiffsStoreUtils', () => {
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
render_discussions_json
(
merge_request
,
example
.
description
)
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
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"
}
...
...
spec/javascripts/notes/components/discussion_counter_spec.js
View file @
ca3ea76c
...
...
@@ -32,12 +32,12 @@ describe('DiscussionCounter component', () => {
{
...
discussionMock
,
id
:
discussionMock
.
id
,
notes
:
[{
...
discussionMock
.
notes
[
0
],
resolved
:
true
}],
notes
:
[{
...
discussionMock
.
notes
[
0
],
resolv
able
:
true
,
resolv
ed
:
true
}],
},
{
...
discussionMock
,
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
;
...
...
spec/javascripts/notes/components/noteable_discussion_spec.js
View file @
ca3ea76c
...
...
@@ -4,22 +4,23 @@ import noteableDiscussion from '~/notes/components/noteable_discussion.vue';
import
'
~/behaviors/markdown/render_gfm
'
;
import
{
noteableDataMock
,
discussionMock
,
notesDataMock
}
from
'
../mock_data
'
;
const
discussionWithTwoUnresolvedNotes
=
'
merge_requests/resolved_diff_discussion.json
'
;
describe
(
'
noteable_discussion component
'
,
()
=>
{
const
Component
=
Vue
.
extend
(
noteableDiscussion
);
let
store
;
let
vm
;
beforeEach
(()
=>
{
const
Component
=
Vue
.
extend
(
noteableDiscussion
);
preloadFixtures
(
discussionWithTwoUnresolvedNotes
);
beforeEach
(()
=>
{
store
=
createStore
();
store
.
dispatch
(
'
setNoteableData
'
,
noteableDataMock
);
store
.
dispatch
(
'
setNotesData
'
,
notesDataMock
);
vm
=
new
Component
({
store
,
propsData
:
{
discussion
:
discussionMock
,
},
propsData
:
{
discussion
:
discussionMock
},
}).
$mount
();
});
...
...
@@ -84,7 +85,9 @@ describe('noteable_discussion component', () => {
});
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
()
.
then
(()
=>
{
...
...
@@ -105,12 +108,12 @@ describe('noteable_discussion component', () => {
{
...
discussionMock
,
id
:
discussionMock
.
id
+
1
,
notes
:
[{
...
discussionMock
.
notes
[
0
],
resolved
:
true
}],
notes
:
[{
...
discussionMock
.
notes
[
0
],
resolv
able
:
true
,
resolv
ed
:
true
}],
},
{
...
discussionMock
,
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
;
...
...
spec/javascripts/notes/mock_data.js
View file @
ca3ea76c
...
...
@@ -303,6 +303,7 @@ export const discussionMock = {
},
],
individual_note
:
false
,
resolvable
:
true
,
};
export
const
loggedOutnoteableData
=
{
...
...
spec/javascripts/notes/stores/getters_spec.js
View file @
ca3ea76c
...
...
@@ -7,9 +7,13 @@ import {
collapseNotesMock
,
}
from
'
../mock_data
'
;
const
discussionWithTwoUnresolvedNotes
=
'
merge_requests/resolved_diff_discussion.json
'
;
describe
(
'
Getters Notes Store
'
,
()
=>
{
let
state
;
preloadFixtures
(
discussionWithTwoUnresolvedNotes
);
beforeEach
(()
=>
{
state
=
{
discussions
:
[
individualNote
],
...
...
@@ -22,12 +26,26 @@ describe('Getters Notes Store', () => {
noteableData
:
noteableDataMock
,
};
});
describe
(
'
discussions
'
,
()
=>
{
it
(
'
should return all discussions in the store
'
,
()
=>
{
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
'
,
()
=>
{
const
stateCollapsedNotes
=
{
discussions
:
collapseNotesMock
,
...
...
spec/javascripts/vue_shared/components/markdown/header_spec.js
View file @
ca3ea76c
...
...
@@ -51,7 +51,7 @@ describe('Markdown field header component', () => {
spyOn
(
vm
,
'
$emit
'
);
$
(
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
();
...
...
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
it
{
is_expected
.
to
belong_to
(
:erased_by
)
}
it
{
is_expected
.
to
have_many
(
:deployments
)
}
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
respond_to
(
:has_trace?
)
}
it
{
is_expected
.
to
respond_to
(
:trace
)
}
...
...
@@ -42,6 +43,20 @@ describe Ci::Build do
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
let!
(
:manual_but_created
)
{
create
(
:ci_build
,
:manual
,
status: :created
,
pipeline:
pipeline
)
}
let!
(
:manual_but_succeeded
)
{
create
(
:ci_build
,
:manual
,
status: :success
,
pipeline:
pipeline
)
}
...
...
@@ -499,6 +514,22 @@ describe Ci::Build do
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
it
"expect to fail trace="
do
expect
{
build
.
trace
=
"new"
}.
to
raise_error
(
NotImplementedError
)
...
...
@@ -518,16 +549,32 @@ describe Ci::Build do
end
describe
'#erase_old_trace!'
do
subject
{
build
.
send
(
:read_attribute
,
:trace
)
}
subject
{
build
.
erase_old_trace!
}
before
do
build
.
send
(
:write_attribute
,
:trace
,
'old trace'
)
context
'when old trace exists'
do
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
it
"expect to receive data from database"
do
build
.
erase_old_trace!
context
'when old trace does not exist'
do
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
...
...
@@ -2605,4 +2652,39 @@ describe Ci::Build do
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
spec/models/service_spec.rb
View file @
ca3ea76c
...
...
@@ -78,7 +78,7 @@ describe Service do
context
'when template is invalid'
do
it
'sets service template to inactive when template is invalid'
do
project
=
create
(
:project
)
template
=
Jira
Service
.
new
(
template:
true
,
active:
true
)
template
=
Kubernetes
Service
.
new
(
template:
true
,
active:
true
)
template
.
save
(
validate:
false
)
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
it
'does not update job status and job trace'
do
update_job
(
state:
'success'
,
trace:
'BUILD TRACE UPDATED'
)
job
.
reload
expect
(
response
).
to
have_gitlab_http_status
(
403
)
expect
(
response
.
header
[
'Job-Status'
]).
to
eq
'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
end
end
def
execute
(
runner
)
described_class
.
new
(
runner
).
execute
.
build
context
'when runner_session params are'
do
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
spec/services/ci/retry_build_service_spec.rb
View file @
ca3ea76c
...
...
@@ -32,7 +32,7 @@ describe Ci::RetryBuildService do
runner_id tag_taggings taggings tags trigger_request_id
user_id auto_canceled_by_id retried failure_reason
artifacts_file_store artifacts_metadata_store
metadata trace_chunks]
.
freeze
metadata
runner_session
trace_chunks]
.
freeze
shared_examples
'build duplication'
do
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
expect
(
service
.
can_be_resolved_in_ui?
).
to
be_falsey
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
spec/services/merge_requests/conflicts/resolve_service_spec.rb
View file @
ca3ea76c
...
...
@@ -123,6 +123,17 @@ describe MergeRequests::Conflicts::ResolveService do
expect
(
merge_request_from_fork
.
source_branch_head
.
parents
.
map
(
&
:id
))
.
to
eq
([
'404fa3fc7c2c9b5dacff102f353bdf55b1be2813'
,
target_head
])
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
...
...
spec/spec_helper.rb
View file @
ca3ea76c
...
...
@@ -170,6 +170,17 @@ RSpec.configure do |config|
redis_queues_cleanup!
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
# correct state before any examples' before hooks are called. This prevents a
# problem where `ScheduleIssuesClosedAtTypeChange` (or any migration that depends
...
...
spec/support/helpers/wait_for_requests.rb
View file @
ca3ea76c
...
...
@@ -24,7 +24,9 @@ module WaitForRequests
# Wait for client-side AJAX 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
# 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
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
before
do
trace
.
set
(
"12"
)
...
...
@@ -574,7 +596,7 @@ shared_examples_for 'trace with disabled live trace feature' do
it
'does not archive'
do
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
end
end
...
...
@@ -589,6 +611,55 @@ shared_examples_for 'trace with disabled live trace feature' do
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
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
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
end
end
...
...
@@ -776,4 +847,35 @@ shared_examples_for 'trace with enabled live trace feature' do
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
spec/workers/ci/archive_traces_cron_worker_spec.rb
View file @
ca3ea76c
...
...
@@ -25,24 +25,36 @@ describe Ci::ArchiveTracesCronWorker do
end
end
context
'when a job
was
succeeded'
do
context
'when a job succeeded'
do
let!
(
:build
)
{
create
(
:ci_build
,
:success
,
:trace_live
)
}
it_behaves_like
'archives trace'
context
'when a
rchive raised an exception
'
do
let!
(
:build
)
{
create
(
:ci_build
,
:success
,
:trace_
artifact
,
:trace_live
)
}
context
'when a
trace had already been archived
'
do
let!
(
:build
)
{
create
(
:ci_build
,
:success
,
:trace_
live
,
:trace_artifact
)
}
let!
(
:build2
)
{
create
(
:ci_build
,
:success
,
:trace_live
)
}
it
'archives valid targets'
do
expect
(
Rails
.
logger
).
to
receive
(
:error
).
with
(
"Failed to archive stale live trace. id:
#{
build
.
id
}
message: Already archived"
)
it
'continues to archive live traces'
do
subject
build2
.
reload
expect
(
build2
.
job_artifacts_trace
).
to
be_exist
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
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