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
aa621050
Commit
aa621050
authored
Mar 03, 2021
by
GitLab Bot
Browse files
Options
Browse Files
Download
Plain Diff
Automatic merge of gitlab-org/gitlab master
parents
058e5f4b
ef48555e
Changes
32
Hide whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
440 additions
and
55 deletions
+440
-55
app/assets/javascripts/ref/components/ref_results_section.vue
...assets/javascripts/ref/components/ref_results_section.vue
+7
-1
app/assets/javascripts/ref/components/ref_selector.vue
app/assets/javascripts/ref/components/ref_selector.vue
+51
-7
app/assets/javascripts/ref/constants.js
app/assets/javascripts/ref/constants.js
+5
-0
app/assets/javascripts/ref/stores/actions.js
app/assets/javascripts/ref/stores/actions.js
+13
-4
app/assets/javascripts/ref/stores/mutation_types.js
app/assets/javascripts/ref/stores/mutation_types.js
+2
-0
app/assets/javascripts/ref/stores/mutations.js
app/assets/javascripts/ref/stores/mutations.js
+3
-0
app/assets/javascripts/ref/stores/state.js
app/assets/javascripts/ref/stores/state.js
+10
-15
app/controllers/root_controller.rb
app/controllers/root_controller.rb
+2
-0
app/helpers/preferences_helper.rb
app/helpers/preferences_helper.rb
+1
-0
app/models/user.rb
app/models/user.rb
+1
-1
app/views/shared/milestones/_milestone.html.haml
app/views/shared/milestones/_milestone.html.haml
+5
-1
changelogs/unreleased/add-ollowed-user-activity-as-dashboard-user-choices.yml
...d/add-ollowed-user-activity-as-dashboard-user-choices.yml
+5
-0
changelogs/unreleased/runners-api-context-metadata.yml
changelogs/unreleased/runners-api-context-metadata.yml
+5
-0
doc/api/graphql/index.md
doc/api/graphql/index.md
+1
-2
doc/user/profile/preferences.md
doc/user/profile/preferences.md
+2
-1
ee/app/models/ci/minutes/namespace_monthly_usage.rb
ee/app/models/ci/minutes/namespace_monthly_usage.rb
+5
-1
ee/app/models/ci/minutes/project_monthly_usage.rb
ee/app/models/ci/minutes/project_monthly_usage.rb
+5
-1
ee/changelogs/unreleased/nfriend-fix-301002-group-milestone-bug.yml
...ogs/unreleased/nfriend-fix-301002-group-milestone-bug.yml
+6
-0
ee/spec/models/ci/minutes/namespace_monthly_usage_spec.rb
ee/spec/models/ci/minutes/namespace_monthly_usage_spec.rb
+3
-3
ee/spec/models/ci/minutes/project_monthly_usage_spec.rb
ee/spec/models/ci/minutes/project_monthly_usage_spec.rb
+3
-3
ee/spec/views/shared/milestones/_milestone.html.haml_spec.rb
ee/spec/views/shared/milestones/_milestone.html.haml_spec.rb
+54
-0
lib/api/ci/runner.rb
lib/api/ci/runner.rb
+5
-10
lib/api/helpers/runner.rb
lib/api/helpers/runner.rb
+20
-0
locale/gitlab.pot
locale/gitlab.pot
+3
-0
spec/controllers/root_controller_spec.rb
spec/controllers/root_controller_spec.rb
+12
-0
spec/frontend/ref/components/ref_selector_spec.js
spec/frontend/ref/components/ref_selector_spec.js
+91
-1
spec/frontend/ref/stores/actions_spec.js
spec/frontend/ref/stores/actions_spec.js
+21
-1
spec/frontend/ref/stores/mutations_spec.js
spec/frontend/ref/stores/mutations_spec.js
+10
-1
spec/helpers/preferences_helper_spec.rb
spec/helpers/preferences_helper_spec.rb
+1
-0
spec/requests/api/ci/runner/jobs_request_post_spec.rb
spec/requests/api/ci/runner/jobs_request_post_spec.rb
+44
-0
spec/requests/api/ci/runner/runners_post_spec.rb
spec/requests/api/ci/runner/runners_post_spec.rb
+28
-2
spec/support/shared_examples/requests/api/logging_application_context_shared_examples.rb
...quests/api/logging_application_context_shared_examples.rb
+16
-0
No files found.
app/assets/javascripts/ref/components/ref_results_section.vue
View file @
aa621050
...
...
@@ -11,6 +11,12 @@ export default {
GlIcon
,
},
props
:
{
showHeader
:
{
type
:
Boolean
,
required
:
false
,
default
:
true
,
},
sectionTitle
:
{
type
:
String
,
required
:
true
,
...
...
@@ -84,7 +90,7 @@ export default {
<
template
>
<div>
<gl-dropdown-section-header>
<gl-dropdown-section-header
v-if=
"showHeader"
>
<div
class=
"gl-display-flex align-items-center"
data-testid=
"section-header"
>
<span
class=
"gl-mr-2 gl-mb-1"
>
{{
sectionTitle
}}
</span>
<gl-badge
variant=
"neutral"
>
{{
totalCountText
}}
</gl-badge>
...
...
app/assets/javascripts/ref/components/ref_selector.vue
View file @
aa621050
...
...
@@ -8,9 +8,16 @@ import {
GlIcon
,
GlLoadingIcon
,
}
from
'
@gitlab/ui
'
;
import
{
debounce
}
from
'
lodash
'
;
import
{
debounce
,
isArray
}
from
'
lodash
'
;
import
{
mapActions
,
mapGetters
,
mapState
}
from
'
vuex
'
;
import
{
SEARCH_DEBOUNCE_MS
,
DEFAULT_I18N
}
from
'
../constants
'
;
import
{
ALL_REF_TYPES
,
SEARCH_DEBOUNCE_MS
,
DEFAULT_I18N
,
REF_TYPE_BRANCHES
,
REF_TYPE_TAGS
,
REF_TYPE_COMMITS
,
}
from
'
../constants
'
;
import
createStore
from
'
../stores
'
;
import
RefResultsSection
from
'
./ref_results_section.vue
'
;
...
...
@@ -28,6 +35,20 @@ export default {
RefResultsSection
,
},
props
:
{
enabledRefTypes
:
{
type
:
Array
,
required
:
false
,
default
:
()
=>
ALL_REF_TYPES
,
validator
:
(
val
)
=>
// It has to be an arrray
isArray
(
val
)
&&
// with at least one item
val
.
length
>
0
&&
// and only "REF_TYPE_BRANCHES", "REF_TYPE_TAGS", and "REF_TYPE_COMMITS" are allowed
val
.
every
((
item
)
=>
ALL_REF_TYPES
.
includes
(
item
))
&&
// and no duplicates are allowed
val
.
length
===
new
Set
(
val
).
size
,
},
value
:
{
type
:
String
,
required
:
false
,
...
...
@@ -62,17 +83,29 @@ export default {
};
},
showBranchesSection
()
{
return
Boolean
(
this
.
matches
.
branches
.
totalCount
>
0
||
this
.
matches
.
branches
.
error
);
return
(
this
.
enabledRefTypes
.
includes
(
REF_TYPE_BRANCHES
)
&&
Boolean
(
this
.
matches
.
branches
.
totalCount
>
0
||
this
.
matches
.
branches
.
error
)
);
},
showTagsSection
()
{
return
Boolean
(
this
.
matches
.
tags
.
totalCount
>
0
||
this
.
matches
.
tags
.
error
);
return
(
this
.
enabledRefTypes
.
includes
(
REF_TYPE_TAGS
)
&&
Boolean
(
this
.
matches
.
tags
.
totalCount
>
0
||
this
.
matches
.
tags
.
error
)
);
},
showCommitsSection
()
{
return
Boolean
(
this
.
matches
.
commits
.
totalCount
>
0
||
this
.
matches
.
commits
.
error
);
return
(
this
.
enabledRefTypes
.
includes
(
REF_TYPE_COMMITS
)
&&
Boolean
(
this
.
matches
.
commits
.
totalCount
>
0
||
this
.
matches
.
commits
.
error
)
);
},
showNoResults
()
{
return
!
this
.
showBranchesSection
&&
!
this
.
showTagsSection
&&
!
this
.
showCommitsSection
;
},
showSectionHeaders
()
{
return
this
.
enabledRefTypes
.
length
>
1
;
},
},
watch
:
{
// Keep the Vuex store synchronized if the parent
...
...
@@ -97,10 +130,18 @@ export default {
},
SEARCH_DEBOUNCE_MS
);
this
.
setProjectId
(
this
.
projectId
);
this
.
search
(
this
.
query
);
this
.
$watch
(
'
enabledRefTypes
'
,
()
=>
{
this
.
setEnabledRefTypes
(
this
.
enabledRefTypes
);
this
.
search
(
this
.
query
);
},
{
immediate
:
true
},
);
},
methods
:
{
...
mapActions
([
'
setProjectId
'
,
'
setSelectedRef
'
,
'
search
'
]),
...
mapActions
([
'
set
EnabledRefTypes
'
,
'
set
ProjectId
'
,
'
setSelectedRef
'
,
'
search
'
]),
focusSearchBox
()
{
this
.
$refs
.
searchBox
.
$el
.
querySelector
(
'
input
'
).
focus
();
},
...
...
@@ -170,6 +211,7 @@ export default {
:selected-ref=
"selectedRef"
:error=
"matches.branches.error"
:error-message=
"i18n.branchesErrorMessage"
:show-header=
"showSectionHeaders"
data-testid=
"branches-section"
@
selected=
"selectRef($event)"
/>
...
...
@@ -185,6 +227,7 @@ export default {
:selected-ref=
"selectedRef"
:error=
"matches.tags.error"
:error-message=
"i18n.tagsErrorMessage"
:show-header=
"showSectionHeaders"
data-testid=
"tags-section"
@
selected=
"selectRef($event)"
/>
...
...
@@ -200,6 +243,7 @@ export default {
:selected-ref=
"selectedRef"
:error=
"matches.commits.error"
:error-message=
"i18n.commitsErrorMessage"
:show-header=
"showSectionHeaders"
data-testid=
"commits-section"
@
selected=
"selectRef($event)"
/>
...
...
app/assets/javascripts/ref/constants.js
View file @
aa621050
import
{
__
}
from
'
~/locale
'
;
export
const
REF_TYPE_BRANCHES
=
'
REF_TYPE_BRANCHES
'
;
export
const
REF_TYPE_TAGS
=
'
REF_TYPE_TAGS
'
;
export
const
REF_TYPE_COMMITS
=
'
REF_TYPE_COMMITS
'
;
export
const
ALL_REF_TYPES
=
Object
.
freeze
([
REF_TYPE_BRANCHES
,
REF_TYPE_TAGS
,
REF_TYPE_COMMITS
]);
export
const
X_TOTAL_HEADER
=
'
x-total
'
;
export
const
SEARCH_DEBOUNCE_MS
=
250
;
...
...
app/assets/javascripts/ref/stores/actions.js
View file @
aa621050
import
Api
from
'
~/api
'
;
import
{
REF_TYPE_BRANCHES
,
REF_TYPE_TAGS
,
REF_TYPE_COMMITS
}
from
'
../constants
'
;
import
*
as
types
from
'
./mutation_types
'
;
export
const
setEnabledRefTypes
=
({
commit
},
refTypes
)
=>
commit
(
types
.
SET_ENABLED_REF_TYPES
,
refTypes
);
export
const
setProjectId
=
({
commit
},
projectId
)
=>
commit
(
types
.
SET_PROJECT_ID
,
projectId
);
export
const
setSelectedRef
=
({
commit
},
selectedRef
)
=>
commit
(
types
.
SET_SELECTED_REF
,
selectedRef
);
export
const
search
=
({
dispatch
,
commit
},
query
)
=>
{
export
const
search
=
({
state
,
dispatch
,
commit
},
query
)
=>
{
commit
(
types
.
SET_QUERY
,
query
);
dispatch
(
'
searchBranches
'
);
dispatch
(
'
searchTags
'
);
dispatch
(
'
searchCommits
'
);
const
dispatchIfRefTypeEnabled
=
(
refType
,
action
)
=>
{
if
(
state
.
enabledRefTypes
.
includes
(
refType
))
{
dispatch
(
action
);
}
};
dispatchIfRefTypeEnabled
(
REF_TYPE_BRANCHES
,
'
searchBranches
'
);
dispatchIfRefTypeEnabled
(
REF_TYPE_TAGS
,
'
searchTags
'
);
dispatchIfRefTypeEnabled
(
REF_TYPE_COMMITS
,
'
searchCommits
'
);
};
export
const
searchBranches
=
({
commit
,
state
})
=>
{
...
...
app/assets/javascripts/ref/stores/mutation_types.js
View file @
aa621050
export
const
SET_ENABLED_REF_TYPES
=
'
SET_ENABLED_REF_TYPES
'
;
export
const
SET_PROJECT_ID
=
'
SET_PROJECT_ID
'
;
export
const
SET_SELECTED_REF
=
'
SET_SELECTED_REF
'
;
export
const
SET_QUERY
=
'
SET_QUERY
'
;
...
...
app/assets/javascripts/ref/stores/mutations.js
View file @
aa621050
...
...
@@ -4,6 +4,9 @@ import { X_TOTAL_HEADER } from '../constants';
import
*
as
types
from
'
./mutation_types
'
;
export
default
{
[
types
.
SET_ENABLED_REF_TYPES
](
state
,
refTypes
)
{
state
.
enabledRefTypes
=
refTypes
;
},
[
types
.
SET_PROJECT_ID
](
state
,
projectId
)
{
state
.
projectId
=
projectId
;
},
...
...
app/assets/javascripts/ref/stores/state.js
View file @
aa621050
const
createRefTypeState
=
()
=>
({
list
:
[],
totalCount
:
0
,
error
:
null
,
});
export
default
()
=>
({
enabledRefTypes
:
[],
projectId
:
null
,
query
:
''
,
matches
:
{
branches
:
{
list
:
[],
totalCount
:
0
,
error
:
null
,
},
tags
:
{
list
:
[],
totalCount
:
0
,
error
:
null
,
},
commits
:
{
list
:
[],
totalCount
:
0
,
error
:
null
,
},
branches
:
createRefTypeState
(),
tags
:
createRefTypeState
(),
commits
:
createRefTypeState
(),
},
selectedRef
:
null
,
requestCount
:
0
,
...
...
app/controllers/root_controller.rb
View file @
aa621050
...
...
@@ -46,6 +46,8 @@ class RootController < Dashboard::ProjectsController
redirect_to
(
activity_dashboard_path
)
when
'starred_project_activity'
redirect_to
(
activity_dashboard_path
(
filter:
'starred'
))
when
'followed_user_activity'
redirect_to
(
activity_dashboard_path
(
filter:
'followed'
))
when
'groups'
redirect_to
(
dashboard_groups_path
)
when
'todos'
...
...
app/helpers/preferences_helper.rb
View file @
aa621050
...
...
@@ -29,6 +29,7 @@ module PreferencesHelper
stars:
_
(
"Starred Projects"
),
project_activity:
_
(
"Your Projects' Activity"
),
starred_project_activity:
_
(
"Starred Projects' Activity"
),
followed_user_activity:
_
(
"Followed Users' Activity"
),
groups:
_
(
"Your Groups"
),
todos:
_
(
"Your To-Do List"
),
issues:
_
(
"Assigned Issues"
),
...
...
app/models/user.rb
View file @
aa621050
...
...
@@ -272,7 +272,7 @@ class User < ApplicationRecord
enum
layout:
{
fixed:
0
,
fluid:
1
}
# User's Dashboard preference
enum
dashboard:
{
projects:
0
,
stars:
1
,
project_activity:
2
,
starred_project_activity:
3
,
groups:
4
,
todos:
5
,
issues:
6
,
merge_requests:
7
,
operations:
8
}
enum
dashboard:
{
projects:
0
,
stars:
1
,
project_activity:
2
,
starred_project_activity:
3
,
groups:
4
,
todos:
5
,
issues:
6
,
merge_requests:
7
,
operations:
8
,
followed_user_activity:
9
}
# User's Project preference
enum
project_view:
{
readme:
0
,
activity:
1
,
files:
2
}
...
...
app/views/shared/milestones/_milestone.html.haml
View file @
aa621050
...
...
@@ -25,7 +25,11 @@
•
-
if
total_count
>
recent_releases
.
count
•
=
link_to
n_
(
'%{count} more release'
,
'%{count} more releases'
,
more_count
)
%
{
count:
more_count
},
project_releases_path
(
milestone
.
project
)
-
more_text
=
n_
(
'%{count} more release'
,
'%{count} more releases'
,
more_count
)
%
{
count:
more_count
}
-
if
milestone
.
project_milestone?
=
link_to
more_text
,
project_releases_path
(
milestone
.
project
)
-
else
=
more_text
%div
=
render
(
'shared/milestone_expired'
,
milestone:
milestone
)
-
if
milestone
.
group_milestone?
...
...
changelogs/unreleased/add-ollowed-user-activity-as-dashboard-user-choices.yml
0 → 100644
View file @
aa621050
---
title
:
"
Add
'Followed
User
Activity'
as
dashboard
user
choices"
merge_request
:
55165
author
:
Benj Fassbind @randombenj
type
:
added
changelogs/unreleased/runners-api-context-metadata.yml
0 → 100644
View file @
aa621050
---
title
:
Add runners api context metadata
merge_request
:
55089
author
:
type
:
changed
doc/api/graphql/index.md
View file @
aa621050
...
...
@@ -171,8 +171,7 @@ certain arguments may also increase the complexity of a query.
NOTE:
The complexity limits may be revised in future, and additionally, the complexity
of a query may be altered. Changes to complexity can happen on
`X.0`
or
`X.6`
releases without a deprecation period.
of a query may be altered.
### Request timeout
...
...
doc/user/profile/preferences.md
View file @
aa621050
...
...
@@ -108,12 +108,13 @@ select few, the amount of activity on the default Dashboard page can be
overwhelming. Changing this setting allows you to redefine your default
dashboard.
You
have 8 options here that you can use
for your default dashboard view:
You
can include the following options
for your default dashboard view:
-
Your projects (default)
-
Starred projects
-
Your projects' activity
-
Starred projects' activity
-
Followed Users' Activity
-
Your groups
-
Your
[
To-Do List
](
../todos.md
)
-
Assigned Issues
...
...
ee/app/models/ci/minutes/namespace_monthly_usage.rb
View file @
aa621050
...
...
@@ -9,7 +9,11 @@ module Ci
belongs_to
:namespace
scope
:current_month
,
->
{
where
(
date:
Time
.
current
.
utc
.
beginning_of_month
)
}
scope
:current_month
,
->
{
where
(
date:
beginning_of_month
)
}
def
self
.
beginning_of_month
(
time
=
Time
.
current
)
time
.
utc
.
beginning_of_month
end
# We should pretty much always use this method to access data for the current month
# since this will lazily create an entry if it doesn't exist.
...
...
ee/app/models/ci/minutes/project_monthly_usage.rb
View file @
aa621050
...
...
@@ -9,7 +9,11 @@ module Ci
belongs_to
:project
scope
:current_month
,
->
{
where
(
date:
Time
.
current
.
beginning_of_month
)
}
scope
:current_month
,
->
{
where
(
date:
beginning_of_month
)
}
def
self
.
beginning_of_month
(
time
=
Time
.
current
)
time
.
utc
.
beginning_of_month
end
# We should pretty much always use this method to access data for the current month
# since this will lazily create an entry if it doesn't exist.
...
...
ee/changelogs/unreleased/nfriend-fix-301002-group-milestone-bug.yml
0 → 100644
View file @
aa621050
---
title
:
Fix 500 error on group milestones page when milestones are associated to more
than 3 releases
merge_request
:
55540
author
:
type
:
fixed
ee/spec/models/ci/minutes/namespace_monthly_usage_spec.rb
View file @
aa621050
...
...
@@ -16,7 +16,7 @@ RSpec.describe Ci::Minutes::NamespaceMonthlyUsage do
end
it
'does not raise exception if unique index is not violated'
do
expect
{
create
(
:ci_namespace_monthly_usage
,
namespace:
namespace
,
date:
1
.
month
.
ago
.
utc
.
beginning_of_month
)
}
expect
{
create
(
:ci_namespace_monthly_usage
,
namespace:
namespace
,
date:
described_class
.
beginning_of_month
(
1
.
month
.
ago
)
)
}
.
to
change
{
described_class
.
count
}.
by
(
1
)
end
end
...
...
@@ -31,7 +31,7 @@ RSpec.describe Ci::Minutes::NamespaceMonthlyUsage do
expect
(
subject
.
amount_used
).
to
eq
(
0
)
expect
(
subject
.
namespace
).
to
eq
(
namespace
)
expect
(
subject
.
date
).
to
eq
(
Time
.
current
.
beginning_of_month
)
expect
(
subject
.
date
).
to
eq
(
described_class
.
beginning_of_month
)
end
end
end
...
...
@@ -42,7 +42,7 @@ RSpec.describe Ci::Minutes::NamespaceMonthlyUsage do
context
'when namespace usage exists for previous months'
do
before
do
create
(
:ci_namespace_monthly_usage
,
namespace:
namespace
,
date:
2
.
months
.
ago
.
utc
.
beginning_of_month
)
create
(
:ci_namespace_monthly_usage
,
namespace:
namespace
,
date:
described_class
.
beginning_of_month
(
2
.
months
.
ago
)
)
end
it_behaves_like
'creates usage record'
...
...
ee/spec/models/ci/minutes/project_monthly_usage_spec.rb
View file @
aa621050
...
...
@@ -16,7 +16,7 @@ RSpec.describe Ci::Minutes::ProjectMonthlyUsage do
end
it
'does not raise exception if unique index is not violated'
do
expect
{
create
(
:ci_project_monthly_usage
,
project:
project
,
date:
1
.
month
.
ago
.
utc
.
beginning_of_month
)
}
expect
{
create
(
:ci_project_monthly_usage
,
project:
project
,
date:
described_class
.
beginning_of_month
(
1
.
month
.
ago
)
)
}
.
to
change
{
described_class
.
count
}.
by
(
1
)
end
end
...
...
@@ -31,7 +31,7 @@ RSpec.describe Ci::Minutes::ProjectMonthlyUsage do
expect
(
subject
.
amount_used
).
to
eq
(
0
)
expect
(
subject
.
project
).
to
eq
(
project
)
expect
(
subject
.
date
).
to
eq
(
Time
.
current
.
beginning_of_month
)
expect
(
subject
.
date
).
to
eq
(
described_class
.
beginning_of_month
)
end
end
end
...
...
@@ -42,7 +42,7 @@ RSpec.describe Ci::Minutes::ProjectMonthlyUsage do
context
'when project usage exists for previous months'
do
before
do
create
(
:ci_project_monthly_usage
,
project:
project
,
date:
2
.
months
.
ago
.
utc
.
beginning_of_month
)
create
(
:ci_project_monthly_usage
,
project:
project
,
date:
described_class
.
beginning_of_month
(
2
.
months
.
ago
)
)
end
it_behaves_like
'creates usage record'
...
...
ee/spec/views/shared/milestones/_milestone.html.haml_spec.rb
0 → 100644
View file @
aa621050
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
'shared/milestones/_milestone.html.haml'
do
let_it_be
(
:group
)
{
create
(
:group
)
}
let_it_be
(
:project
)
{
create
(
:project
,
group:
group
)
}
let_it_be
(
:user
)
{
create
(
:user
).
tap
{
|
user
|
project
.
add_maintainer
(
user
)
}
}
let_it_be
(
:releases
)
{
create_list
(
:release
,
4
,
project:
project
)
}
let_it_be
(
:milestone
)
{
nil
}
let
(
:more_text
)
{
'1 more release'
}
let
(
:link_href
)
{
project_releases_path
(
project
)
}
before
do
stub_licensed_features
(
group_milestone_project_releases:
true
)
allow
(
view
).
to
receive
(
:current_user
).
and_return
(
user
)
allow
(
view
).
to
receive
(
:milestone
).
and_return
(
milestone
)
allow
(
view
).
to
receive
(
:issues_path
).
and_return
(
'path/to/issues'
)
allow
(
view
).
to
receive
(
:merge_requests_path
).
and_return
(
'path/to/merge_requests'
)
end
context
'when a milestone is associated to a lot of releases'
do
context
'when viewing a project milestone'
do
let
(
:milestone
)
{
create
(
:milestone
,
project:
project
,
releases:
releases
)
}
before
do
assign
(
:project
,
project
)
end
it
'renders "1 more release" as a link to the project\'s Releases page'
do
render
expect
(
rendered
).
to
have_link
(
more_text
,
href:
link_href
)
end
end
context
'when viewing a group milestone'
do
let
(
:milestone
)
{
create
(
:milestone
,
group:
group
,
releases:
releases
)
}
before
do
assign
(
:group
,
group
)
end
it
'renders "1 more release" as plain text instead of as a link'
,
:aggregate_failures
do
render
expect
(
rendered
).
not_to
have_link
(
more_text
,
href:
link_href
)
expect
(
rendered
).
to
have_content
(
more_text
)
end
end
end
end
lib/api/ci/runner.rb
View file @
aa621050
...
...
@@ -34,12 +34,12 @@ module API
if
runner_registration_token_valid?
# Create shared runner. Requires admin access
attributes
.
merge
(
runner_type: :instance_type
)
elsif
project
=
Project
.
find_by_runners_token
(
params
[
:token
])
elsif
@
project
=
Project
.
find_by_runners_token
(
params
[
:token
])
# Create a specific runner for the project
attributes
.
merge
(
runner_type: :project_type
,
projects:
[
project
])
elsif
group
=
Group
.
find_by_runners_token
(
params
[
:token
])
attributes
.
merge
(
runner_type: :project_type
,
projects:
[
@
project
])
elsif
@
group
=
Group
.
find_by_runners_token
(
params
[
:token
])
# Create a specific runner for the group
attributes
.
merge
(
runner_type: :group_type
,
groups:
[
group
])
attributes
.
merge
(
runner_type: :group_type
,
groups:
[
@
group
])
else
forbidden!
end
...
...
@@ -81,12 +81,7 @@ module API
end
resource
:jobs
do
before
do
Gitlab
::
ApplicationContext
.
push
(
user:
->
{
current_job
&
.
user
},
project:
->
{
current_job
&
.
project
}
)
end
before
{
set_application_context
}
desc
'Request a job'
do
success
Entities
::
JobRequest
::
Response
...
...
lib/api/helpers/runner.rb
View file @
aa621050
...
...
@@ -71,6 +71,26 @@ module API
header
'Job-Status'
,
job
.
status
forbidden!
(
reason
)
end
def
set_application_context
if
current_job
Gitlab
::
ApplicationContext
.
push
(
user:
->
{
current_job
.
user
},
project:
->
{
current_job
.
project
}
)
elsif
current_runner
&
.
project_type?
Gitlab
::
ApplicationContext
.
push
(
project:
->
do
projects
=
current_runner
.
projects
.
limit
(
2
)
# rubocop: disable CodeReuse/ActiveRecord
projects
.
first
if
projects
.
length
==
1
end
)
elsif
current_runner
&
.
group_type?
Gitlab
::
ApplicationContext
.
push
(
namespace:
->
{
current_runner
.
groups
.
first
}
)
end
end
end
end
end
locale/gitlab.pot
View file @
aa621050
...
...
@@ -13201,6 +13201,9 @@ msgstr ""
msgid "Follow"
msgstr ""
msgid "Followed Users' Activity"
msgstr ""
msgid "Followed users"
msgstr ""
...
...
spec/controllers/root_controller_spec.rb
View file @
aa621050
...
...
@@ -68,6 +68,18 @@ RSpec.describe RootController do
end
end
context
'who has customized their dashboard setting for followed user activities'
do
before
do
user
.
dashboard
=
'followed_user_activity'
end
it
'redirects to the activity list'
do
get
:index
expect
(
response
).
to
redirect_to
activity_dashboard_path
(
filter:
'followed'
)
end
end
context
'who has customized their dashboard setting for groups'
do
before
do
user
.
dashboard
=
'groups'
...
...
spec/frontend/ref/components/ref_selector_spec.js
View file @
aa621050
...
...
@@ -7,7 +7,13 @@ import { trimText } from 'helpers/text_helper';
import
{
ENTER_KEY
}
from
'
~/lib/utils/keys
'
;
import
{
sprintf
}
from
'
~/locale
'
;
import
RefSelector
from
'
~/ref/components/ref_selector.vue
'
;
import
{
X_TOTAL_HEADER
,
DEFAULT_I18N
}
from
'
~/ref/constants
'
;
import
{
X_TOTAL_HEADER
,
DEFAULT_I18N
,
REF_TYPE_BRANCHES
,
REF_TYPE_TAGS
,
REF_TYPE_COMMITS
,
}
from
'
~/ref/constants
'
;
import
createStore
from
'
~/ref/stores/
'
;
const
localVue
=
createLocalVue
();
...
...
@@ -26,6 +32,7 @@ describe('Ref selector component', () => {
let
branchesApiCallSpy
;
let
tagsApiCallSpy
;
let
commitApiCallSpy
;
let
requestSpies
;
const
createComponent
=
(
props
=
{},
attrs
=
{})
=>
{
wrapper
=
mount
(
RefSelector
,
{
...
...
@@ -58,6 +65,7 @@ describe('Ref selector component', () => {
.
mockReturnValue
([
200
,
fixtures
.
branches
,
{
[
X_TOTAL_HEADER
]:
'
123
'
}]);
tagsApiCallSpy
=
jest
.
fn
().
mockReturnValue
([
200
,
fixtures
.
tags
,
{
[
X_TOTAL_HEADER
]:
'
456
'
}]);
commitApiCallSpy
=
jest
.
fn
().
mockReturnValue
([
200
,
fixtures
.
commit
]);
requestSpies
=
{
branchesApiCallSpy
,
tagsApiCallSpy
,
commitApiCallSpy
};
mock
.
onGet
(
`/api/v4/projects/
${
projectId
}
/repository/branches`
)
...
...
@@ -592,4 +600,86 @@ describe('Ref selector component', () => {
});
});
});
describe
(
'
with non-default ref types
'
,
()
=>
{
it
.
each
`
enabledRefTypes | reqsCalled | reqsNotCalled
${[
REF_TYPE_BRANCHES
]}
|
${[
'
branchesApiCallSpy
'
]}
|
${[
'
tagsApiCallSpy
'
,
'
commitApiCallSpy
'
]}
${[
REF_TYPE_TAGS
]}
|
${[
'
tagsApiCallSpy
'
]}
|
${[
'
branchesApiCallSpy
'
,
'
commitApiCallSpy
'
]}
${[
REF_TYPE_COMMITS
]}
|
${[]}
|
${[
'
branchesApiCallSpy
'
,
'
tagsApiCallSpy
'
,
'
commitApiCallSpy
'
]}
${[
REF_TYPE_TAGS
,
REF_TYPE_COMMITS
]}
|
${[
'
tagsApiCallSpy
'
]}
|
${[
'
branchesApiCallSpy
'
,
'
commitApiCallSpy
'
]}
`
(
'
only calls $reqsCalled requests when $enabledRefTypes are enabled
'
,
async
({
enabledRefTypes
,
reqsCalled
,
reqsNotCalled
})
=>
{
createComponent
({
enabledRefTypes
});
await
waitForRequests
();
reqsCalled
.
forEach
((
req
)
=>
expect
(
requestSpies
[
req
]).
toHaveBeenCalledTimes
(
1
));
reqsNotCalled
.
forEach
((
req
)
=>
expect
(
requestSpies
[
req
]).
not
.
toHaveBeenCalled
());
},
);
it
(
'
only calls commitApiCallSpy when REF_TYPE_COMMITS is enabled
'
,
async
()
=>
{
createComponent
({
enabledRefTypes
:
[
REF_TYPE_COMMITS
]
});
updateQuery
(
'
abcd1234
'
);
await
waitForRequests
();
expect
(
commitApiCallSpy
).
toHaveBeenCalledTimes
(
1
);
expect
(
branchesApiCallSpy
).
not
.
toHaveBeenCalled
();
expect
(
tagsApiCallSpy
).
not
.
toHaveBeenCalled
();
});
it
(
'
triggers another search if enabled ref types change
'
,
async
()
=>
{
createComponent
({
enabledRefTypes
:
[
REF_TYPE_BRANCHES
]
});
await
waitForRequests
();
expect
(
branchesApiCallSpy
).
toHaveBeenCalledTimes
(
1
);
expect
(
tagsApiCallSpy
).
not
.
toHaveBeenCalled
();
wrapper
.
setProps
({
enabledRefTypes
:
[
REF_TYPE_BRANCHES
,
REF_TYPE_TAGS
],
});
await
waitForRequests
();
expect
(
branchesApiCallSpy
).
toHaveBeenCalledTimes
(
2
);
expect
(
tagsApiCallSpy
).
toHaveBeenCalledTimes
(
1
);
});
it
(
'
if a ref type becomes disabled, its section is hidden, even if it had some results in store
'
,
async
()
=>
{
createComponent
({
enabledRefTypes
:
[
REF_TYPE_BRANCHES
,
REF_TYPE_COMMITS
]
});
updateQuery
(
'
abcd1234
'
);
await
waitForRequests
();
expect
(
findBranchesSection
().
exists
()).
toBe
(
true
);
expect
(
findCommitsSection
().
exists
()).
toBe
(
true
);
wrapper
.
setProps
({
enabledRefTypes
:
[
REF_TYPE_COMMITS
]
});
await
waitForRequests
();
expect
(
findBranchesSection
().
exists
()).
toBe
(
false
);
expect
(
findCommitsSection
().
exists
()).
toBe
(
true
);
});
it
.
each
`
enabledRefType | findVisibleSection | findHiddenSections
${
REF_TYPE_BRANCHES
}
|
${
findBranchesSection
}
|
${[
findTagsSection
,
findCommitsSection
]}
${
REF_TYPE_TAGS
}
|
${
findTagsSection
}
|
${[
findBranchesSection
,
findCommitsSection
]}
${
REF_TYPE_COMMITS
}
|
${
findCommitsSection
}
|
${[
findBranchesSection
,
findTagsSection
]}
`
(
'
hides section headers if a single ref type is enabled
'
,
async
({
enabledRefType
,
findVisibleSection
,
findHiddenSections
})
=>
{
createComponent
({
enabledRefTypes
:
[
enabledRefType
]
});
updateQuery
(
'
abcd1234
'
);
await
waitForRequests
();
expect
(
findVisibleSection
().
exists
()).
toBe
(
true
);
expect
(
findVisibleSection
().
find
(
'
[data-testid="section-header"]
'
).
exists
()).
toBe
(
false
);
findHiddenSections
.
forEach
((
findHiddenSection
)
=>
expect
(
findHiddenSection
().
exists
()).
toBe
(
false
),
);
},
);
});
});
spec/frontend/ref/stores/actions_spec.js
View file @
aa621050
import
testAction
from
'
helpers/vuex_action_helper
'
;
import
{
ALL_REF_TYPES
,
REF_TYPE_BRANCHES
,
REF_TYPE_TAGS
,
REF_TYPE_COMMITS
}
from
'
~/ref/constants
'
;
import
*
as
actions
from
'
~/ref/stores/actions
'
;
import
*
as
types
from
'
~/ref/stores/mutation_types
'
;
import
createState
from
'
~/ref/stores/state
'
;
...
...
@@ -25,6 +26,14 @@ describe('Ref selector Vuex store actions', () => {
state
=
createState
();
});
describe
(
'
setEnabledRefTypes
'
,
()
=>
{
it
(
`commits
${
types
.
SET_ENABLED_REF_TYPES
}
with the enabled ref types`
,
()
=>
{
testAction
(
actions
.
setProjectId
,
ALL_REF_TYPES
,
state
,
[
{
type
:
types
.
SET_PROJECT_ID
,
payload
:
ALL_REF_TYPES
},
]);
});
});
describe
(
'
setProjectId
'
,
()
=>
{
it
(
`commits
${
types
.
SET_PROJECT_ID
}
with the new project ID`
,
()
=>
{
const
projectId
=
'
4
'
;
...
...
@@ -46,12 +55,23 @@ describe('Ref selector Vuex store actions', () => {
describe
(
'
search
'
,
()
=>
{
it
(
`commits
${
types
.
SET_QUERY
}
with the new search query`
,
()
=>
{
const
query
=
'
hello
'
;
testAction
(
actions
.
search
,
query
,
state
,
[{
type
:
types
.
SET_QUERY
,
payload
:
query
}]);
});
it
.
each
`
enabledRefTypes | expectedActions
${[
REF_TYPE_BRANCHES
]}
|
${[
'
searchBranches
'
]}
${[
REF_TYPE_COMMITS
]}
|
${[
'
searchCommits
'
]}
${[
REF_TYPE_BRANCHES
,
REF_TYPE_TAGS
,
REF_TYPE_COMMITS
]}
|
${[
'
searchBranches
'
,
'
searchTags
'
,
'
searchCommits
'
]}
`
(
`dispatches fetch actions for enabled ref types`
,
({
enabledRefTypes
,
expectedActions
})
=>
{
const
query
=
'
hello
'
;
state
.
enabledRefTypes
=
enabledRefTypes
;
testAction
(
actions
.
search
,
query
,
state
,
[{
type
:
types
.
SET_QUERY
,
payload
:
query
}],
[{
type
:
'
searchBranches
'
},
{
type
:
'
searchTags
'
},
{
type
:
'
searchCommits
'
}]
,
expectedActions
.
map
((
type
)
=>
({
type
}))
,
);
});
});
...
...
spec/frontend/ref/stores/mutations_spec.js
View file @
aa621050
import
{
X_TOTAL_HEADER
}
from
'
~/ref/constants
'
;
import
{
X_TOTAL_HEADER
,
ALL_REF_TYPES
}
from
'
~/ref/constants
'
;
import
*
as
types
from
'
~/ref/stores/mutation_types
'
;
import
mutations
from
'
~/ref/stores/mutations
'
;
import
createState
from
'
~/ref/stores/state
'
;
...
...
@@ -13,6 +13,7 @@ describe('Ref selector Vuex store mutations', () => {
describe
(
'
initial state
'
,
()
=>
{
it
(
'
is created with the correct structure and initial values
'
,
()
=>
{
expect
(
state
).
toEqual
({
enabledRefTypes
:
[],
projectId
:
null
,
query
:
''
,
...
...
@@ -39,6 +40,14 @@ describe('Ref selector Vuex store mutations', () => {
});
});
describe
(
`
${
types
.
SET_ENABLED_REF_TYPES
}
`
,
()
=>
{
it
(
'
sets the enabled ref types
'
,
()
=>
{
mutations
[
types
.
SET_ENABLED_REF_TYPES
](
state
,
ALL_REF_TYPES
);
expect
(
state
.
enabledRefTypes
).
toBe
(
ALL_REF_TYPES
);
});
});
describe
(
`
${
types
.
SET_PROJECT_ID
}
`
,
()
=>
{
it
(
'
updates the project ID
'
,
()
=>
{
const
newProjectId
=
'
4
'
;
...
...
spec/helpers/preferences_helper_spec.rb
View file @
aa621050
...
...
@@ -29,6 +29,7 @@ RSpec.describe PreferencesHelper do
[
'Starred Projects'
,
'stars'
],
[
"Your Projects' Activity"
,
'project_activity'
],
[
"Starred Projects' Activity"
,
'starred_project_activity'
],
[
"Followed Users' Activity"
,
'followed_user_activity'
],
[
"Your Groups"
,
'groups'
],
[
"Your To-Do List"
,
'todos'
],
[
"Assigned Issues"
,
'issues'
],
...
...
spec/requests/api/ci/runner/jobs_request_post_spec.rb
View file @
aa621050
...
...
@@ -797,6 +797,50 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
end
describe
'setting the application context'
do
subject
{
request_job
}
context
'when triggered by a user'
do
let
(
:job
)
{
create
(
:ci_build
,
user:
user
,
project:
project
)
}
subject
{
request_job
(
id:
job
.
id
)
}
it_behaves_like
'storing arguments in the application context'
do
let
(
:expected_params
)
{
{
user:
user
.
username
,
project:
project
.
full_path
}
}
end
it_behaves_like
'not executing any extra queries for the application context'
,
3
do
# Extra queries: User, Project, Route
let
(
:subject_proc
)
{
proc
{
request_job
(
id:
job
.
id
)
}
}
end
end
context
'when the runner is of project type'
do
it_behaves_like
'storing arguments in the application context'
do
let
(
:expected_params
)
{
{
project:
project
.
full_path
}
}
end
it_behaves_like
'not executing any extra queries for the application context'
,
2
do
# Extra queries: Project, Route
let
(
:subject_proc
)
{
proc
{
request_job
}
}
end
end
context
'when the runner is of group type'
do
let
(
:group
)
{
create
(
:group
)
}
let
(
:runner
)
{
create
(
:ci_runner
,
:group
,
groups:
[
group
])
}
it_behaves_like
'storing arguments in the application context'
do
let
(
:expected_params
)
{
{
root_namespace:
group
.
full_path_components
.
first
}
}
end
it_behaves_like
'not executing any extra queries for the application context'
,
2
do
# Extra queries: Group, Route
let
(
:subject_proc
)
{
proc
{
request_job
}
}
end
end
end
def
request_job
(
token
=
runner
.
token
,
**
params
)
new_params
=
params
.
merge
(
token:
token
,
last_update:
last_update
)
post
api
(
'/jobs/request'
),
params:
new_params
.
to_json
,
headers:
{
'User-Agent'
=>
user_agent
,
'Content-Type'
:
'application/json'
}
...
...
spec/requests/api/ci/runner/runners_post_spec.rb
View file @
aa621050
...
...
@@ -35,6 +35,10 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
context
'when valid token is provided'
do
def
request
post
api
(
'/runners'
),
params:
{
token:
token
}
end
it
'creates runner with default values'
do
post
api
(
'/runners'
),
params:
{
token:
registration_token
}
...
...
@@ -51,9 +55,10 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
context
'when project token is used'
do
let
(
:project
)
{
create
(
:project
)
}
let
(
:token
)
{
project
.
runners_token
}
it
'creates project runner'
do
post
api
(
'/runners'
),
params:
{
token:
project
.
runners_token
}
request
expect
(
response
).
to
have_gitlab_http_status
(
:created
)
expect
(
project
.
runners
.
size
).
to
eq
(
1
)
...
...
@@ -62,13 +67,24 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
expect
(
runner
.
token
).
not_to
eq
(
project
.
runners_token
)
expect
(
runner
).
to
be_project_type
end
it_behaves_like
'storing arguments in the application context'
do
subject
{
request
}
let
(
:expected_params
)
{
{
project:
project
.
full_path
}
}
end
it_behaves_like
'not executing any extra queries for the application context'
do
let
(
:subject_proc
)
{
proc
{
request
}
}
end
end
context
'when group token is used'
do
let
(
:group
)
{
create
(
:group
)
}
let
(
:token
)
{
group
.
runners_token
}
it
'creates a group runner'
do
post
api
(
'/runners'
),
params:
{
token:
group
.
runners_token
}
request
expect
(
response
).
to
have_gitlab_http_status
(
:created
)
expect
(
group
.
runners
.
reload
.
size
).
to
eq
(
1
)
...
...
@@ -77,6 +93,16 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
expect
(
runner
.
token
).
not_to
eq
(
group
.
runners_token
)
expect
(
runner
).
to
be_group_type
end
it_behaves_like
'storing arguments in the application context'
do
subject
{
request
}
let
(
:expected_params
)
{
{
root_namespace:
group
.
full_path_components
.
first
}
}
end
it_behaves_like
'not executing any extra queries for the application context'
do
let
(
:subject_proc
)
{
proc
{
request
}
}
end
end
end
...
...
spec/support/shared_examples/requests/api/logging_application_context_shared_examples.rb
View file @
aa621050
...
...
@@ -22,3 +22,19 @@ RSpec.shared_examples 'storing arguments in the application context' do
hash
.
transform_keys!
{
|
key
|
"meta.
#{
key
}
"
}
end
end
RSpec
.
shared_examples
'not executing any extra queries for the application context'
do
|
expected_extra_queries
=
0
|
it
'does not execute more queries than without adding anything to the application context'
do
# Call the subject once to memoize all factories being used for the spec, so they won't
# add any queries to the expectation.
subject_proc
.
call
expect
do
allow
(
Gitlab
::
ApplicationContext
).
to
receive
(
:push
).
and_call_original
subject_proc
.
call
end
.
to
issue_same_number_of_queries_as
{
allow
(
Gitlab
::
ApplicationContext
).
to
receive
(
:push
)
subject_proc
.
call
}.
with_threshold
(
expected_extra_queries
).
ignoring_cached_queries
end
end
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