summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/build.js52
-rw-r--r--app/assets/javascripts/commons/polyfills.js1
-rw-r--r--app/assets/stylesheets/pages/builds.scss28
-rw-r--r--app/controllers/concerns/milestone_actions.rb4
-rw-r--r--app/controllers/dashboard/milestones_controller.rb4
-rw-r--r--app/controllers/jwt_controller.rb2
-rw-r--r--app/controllers/projects/git_http_client_controller.rb2
-rw-r--r--app/helpers/milestones_helper.rb6
-rw-r--r--app/presenters/merge_request_presenter.rb16
-rw-r--r--app/views/help/index.html.haml2
-rw-r--r--app/views/projects/jobs/show.html.haml27
-rw-r--r--changelogs/unreleased/33381-display-issue-state-in-mr-widget-issue-links.yml4
-rw-r--r--changelogs/unreleased/dashboard-milestone-tabs-loading-async.yml4
-rw-r--r--changelogs/unreleased/pat-msg-on-auth-failure.yml4
-rw-r--r--changelogs/unreleased/tc-link-to-commit-on-help-page.yml4
-rw-r--r--config/locales/de.yml37
-rw-r--r--config/locales/es.yml2
-rw-r--r--config/routes/dashboard.rb8
-rw-r--r--doc/api/projects.md8
-rw-r--r--doc/integration/google.md15
-rw-r--r--doc/university/glossary/README.md3
-rw-r--r--doc/user/project/container_registry.md8
-rw-r--r--doc/workflow/groups.md5
-rw-r--r--features/steps/project/source/markdown_render.rb2
-rw-r--r--lib/gitlab.rb4
-rw-r--r--lib/gitlab/auth.rb6
-rwxr-xr-xscripts/trigger-build9
-rw-r--r--spec/controllers/dashboard/milestones_controller_spec.rb38
-rw-r--r--spec/features/dashboard/milestone_tabs_spec.rb40
-rw-r--r--spec/lib/gitlab/auth_spec.rb6
-rw-r--r--spec/presenters/merge_request_presenter_spec.rb10
-rw-r--r--spec/requests/git_http_spec.rb43
-rw-r--r--spec/requests/jwt_controller_spec.rb21
-rw-r--r--spec/support/milestone_tabs_examples.rb14
-rw-r--r--spec/views/help/index.html.haml_spec.rb2
35 files changed, 360 insertions, 81 deletions
diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js
index 3b2bb6f082f..d80b7f5bd42 100644
--- a/app/assets/javascripts/build.js
+++ b/app/assets/javascripts/build.js
@@ -20,6 +20,7 @@ window.Build = (function () {
this.$document = $(document);
this.logBytes = 0;
this.scrollOffsetPadding = 30;
+ this.hasBeenScrolled = false;
this.updateDropdown = this.updateDropdown.bind(this);
this.getBuildTrace = this.getBuildTrace.bind(this);
@@ -62,6 +63,15 @@ window.Build = (function () {
.off('click')
.on('click', this.scrollToBottom.bind(this));
+ const scrollThrottled = _.throttle(this.toggleScroll.bind(this), 100);
+
+ this.$scrollContainer
+ .off('scroll')
+ .on('scroll', () => {
+ this.hasBeenScrolled = true;
+ scrollThrottled();
+ });
+
$(window)
.off('resize.build')
.on('resize.build', _.throttle(this.sidebarOnResize.bind(this), 100));
@@ -70,25 +80,16 @@ window.Build = (function () {
// eslint-disable-next-line
this.getBuildTrace()
- .then(() => this.makeTraceScrollable())
- .then(() => this.scrollToBottom());
+ .then(() => this.toggleScroll())
+ .then(() => {
+ if (!this.hasBeenScrolled) {
+ this.scrollToBottom();
+ }
+ });
this.verifyTopPosition();
}
- Build.prototype.makeTraceScrollable = function () {
- this.$scrollContainer.niceScroll({
- cursorcolor: '#fff',
- cursoropacitymin: 1,
- cursorwidth: '7px',
- railpadding: { top: 5, bottom: 5, right: 5 },
- });
-
- this.$scrollContainer.on('scroll', _.throttle(this.toggleScroll.bind(this), 100));
-
- this.toggleScroll();
- };
-
Build.prototype.canScroll = function () {
return (this.$scrollContainer.prop('scrollHeight') - this.scrollOffsetPadding) > this.$scrollContainer.height();
};
@@ -104,12 +105,11 @@ window.Build = (function () {
*
*/
Build.prototype.toggleScroll = function () {
- const bottomScroll = this.$scrollContainer.scrollTop() +
- this.scrollOffsetPadding +
- this.$scrollContainer.height();
+ const currentPosition = this.$scrollContainer.scrollTop();
+ const bottomScroll = currentPosition + this.$scrollContainer.innerHeight();
if (this.canScroll()) {
- if (this.$scrollContainer.scrollTop() === 0) {
+ if (currentPosition === 0) {
this.toggleDisableButton(this.$scrollTopBtn, true);
this.toggleDisableButton(this.$scrollBottomBtn, false);
} else if (bottomScroll === this.$scrollContainer.prop('scrollHeight')) {
@@ -123,12 +123,14 @@ window.Build = (function () {
};
Build.prototype.scrollToTop = function () {
- this.$scrollContainer.getNiceScroll(0).doScrollTop(0);
+ this.hasBeenScrolled = true;
+ this.$scrollContainer.scrollTop(0);
this.toggleScroll();
};
Build.prototype.scrollToBottom = function () {
- this.$scrollContainer.getNiceScroll(0).doScrollTo(this.$scrollContainer.prop('scrollHeight'));
+ this.hasBeenScrolled = true;
+ this.$scrollContainer.scrollTop(this.$scrollContainer.prop('scrollHeight'));
this.toggleScroll();
};
@@ -216,7 +218,11 @@ window.Build = (function () {
Build.timeout = setTimeout(() => {
//eslint-disable-next-line
this.getBuildTrace()
- .then(() => this.scrollToBottom());
+ .then(() => {
+ if (!this.hasBeenScrolled) {
+ this.scrollToBottom();
+ }
+ });
}, 4000);
} else {
this.$buildRefreshAnimation.remove();
@@ -253,7 +259,7 @@ window.Build = (function () {
this.verifyTopPosition();
- if (this.$scrollContainer.getNiceScroll(0)) {
+ if (this.canScroll()) {
this.toggleScroll();
}
};
diff --git a/app/assets/javascripts/commons/polyfills.js b/app/assets/javascripts/commons/polyfills.js
index cb054a2a197..bc3e741f524 100644
--- a/app/assets/javascripts/commons/polyfills.js
+++ b/app/assets/javascripts/commons/polyfills.js
@@ -1,5 +1,6 @@
// ECMAScript polyfills
import 'core-js/fn/array/find';
+import 'core-js/fn/array/find-index';
import 'core-js/fn/array/from';
import 'core-js/fn/array/includes';
import 'core-js/fn/object/assign';
diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss
index e35558ad8e8..d931a78e112 100644
--- a/app/assets/stylesheets/pages/builds.scss
+++ b/app/assets/stylesheets/pages/builds.scss
@@ -71,7 +71,9 @@
height: 35px;
display: flex;
justify-content: flex-end;
- border-bottom: 1px outset $white-light;
+ background: $gray-light;
+ border: 1px solid $gray-normal;
+ color: $gl-text-color;
.truncated-info {
margin: 0 auto;
@@ -82,7 +84,7 @@
}
.raw-link {
- color: inherit;
+ color: $gl-text-color;
margin-left: 5px;
text-decoration: underline;
}
@@ -93,17 +95,25 @@
display: flex;
align-self: center;
font-size: 15px;
+ margin-bottom: 4px;
svg {
height: 15px;
display: block;
- fill: $white-light;
+ fill: $gl-text-color;
}
- a,
+ .controllers-buttons,
.btn-scroll {
- margin: 0 8px;
- color: $white-light;
+ color: $gl-text-color;
+ height: 15px;
+ vertical-align: middle;
+ padding: 0;
+ width: 12px;
+ }
+
+ .controllers-buttons {
+ margin: 1px 10px;
}
.btn-scroll.animate {
@@ -137,9 +147,9 @@
top: 35px;
left: 10px;
bottom: 0;
- overflow-y: hidden;
- padding-bottom: 20px;
- padding-right: 20px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ padding: 10px 20px 20px 5px;
}
.environment-information {
diff --git a/app/controllers/concerns/milestone_actions.rb b/app/controllers/concerns/milestone_actions.rb
index 3e2a0fe4f8b..b2536a1c949 100644
--- a/app/controllers/concerns/milestone_actions.rb
+++ b/app/controllers/concerns/milestone_actions.rb
@@ -46,8 +46,10 @@ module MilestoneActions
def milestone_redirect_path
if @project
namespace_project_milestone_path(@project.namespace, @project, @milestone)
- else
+ elsif @group
group_milestone_path(@group, @milestone.safe_title, title: @milestone.title)
+ else
+ dashboard_milestone_path(@milestone.safe_title, title: @milestone.title)
end
end
end
diff --git a/app/controllers/dashboard/milestones_controller.rb b/app/controllers/dashboard/milestones_controller.rb
index df528d10f6e..751dbbd8e96 100644
--- a/app/controllers/dashboard/milestones_controller.rb
+++ b/app/controllers/dashboard/milestones_controller.rb
@@ -1,6 +1,8 @@
class Dashboard::MilestonesController < Dashboard::ApplicationController
+ include MilestoneActions
+
before_action :projects
- before_action :milestone, only: [:show]
+ before_action :milestone, only: [:show, :merge_requests, :participants, :labels]
def index
respond_to do |format|
diff --git a/app/controllers/jwt_controller.rb b/app/controllers/jwt_controller.rb
index c585d26df77..11db164b3fa 100644
--- a/app/controllers/jwt_controller.rb
+++ b/app/controllers/jwt_controller.rb
@@ -39,7 +39,7 @@ class JwtController < ApplicationController
errors: [
{ code: 'UNAUTHORIZED',
message: "HTTP Basic: Access denied\n" \
- "You have 2FA enabled, please use a personal access token for Git over HTTP.\n" \
+ "You must use a personal access token with 'api' scope for Git over HTTP.\n" \
"You can generate one at #{profile_personal_access_tokens_url}" }
]
}, status: 401
diff --git a/app/controllers/projects/git_http_client_controller.rb b/app/controllers/projects/git_http_client_controller.rb
index 7f3205a8001..928f17e6a8e 100644
--- a/app/controllers/projects/git_http_client_controller.rb
+++ b/app/controllers/projects/git_http_client_controller.rb
@@ -104,7 +104,7 @@ class Projects::GitHttpClientController < Projects::ApplicationController
def render_missing_personal_token
render plain: "HTTP Basic: Access denied\n" \
- "You have 2FA enabled, please use a personal access token for Git over HTTP.\n" \
+ "You must use a personal access token with 'api' scope for Git over HTTP.\n" \
"You can generate one at #{profile_personal_access_tokens_url}",
status: 401
end
diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb
index c515774140c..a230db22fa2 100644
--- a/app/helpers/milestones_helper.rb
+++ b/app/helpers/milestones_helper.rb
@@ -121,6 +121,8 @@ module MilestonesHelper
merge_requests_namespace_project_milestone_path(@project.namespace, @project, milestone, format: :json)
elsif @group
merge_requests_group_milestone_path(@group, milestone.safe_title, title: milestone.title, format: :json)
+ else
+ merge_requests_dashboard_milestone_path(milestone, title: milestone.title, format: :json)
end
end
@@ -129,6 +131,8 @@ module MilestonesHelper
participants_namespace_project_milestone_path(@project.namespace, @project, milestone, format: :json)
elsif @group
participants_group_milestone_path(@group, milestone.safe_title, title: milestone.title, format: :json)
+ else
+ participants_dashboard_milestone_path(milestone, title: milestone.title, format: :json)
end
end
@@ -137,6 +141,8 @@ module MilestonesHelper
labels_namespace_project_milestone_path(@project.namespace, @project, milestone, format: :json)
elsif @group
labels_group_milestone_path(@group, milestone.safe_title, title: milestone.title, format: :json)
+ else
+ labels_dashboard_milestone_path(milestone, title: milestone.title, format: :json)
end
end
end
diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb
index 0db9e31031c..8bf35953d29 100644
--- a/app/presenters/merge_request_presenter.rb
+++ b/app/presenters/merge_request_presenter.rb
@@ -110,12 +110,24 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
end
def closing_issues_links
- markdown issues_sentence(project, closing_issues), pipeline: :gfm, author: author, project: project
+ markdown(
+ issues_sentence(project, closing_issues),
+ pipeline: :gfm,
+ author: author,
+ project: project,
+ issuable_state_filter_enabled: true
+ )
end
def mentioned_issues_links
mentioned_issues = issues_mentioned_but_not_closing(current_user)
- markdown issues_sentence(project, mentioned_issues), pipeline: :gfm, author: author, project: project
+ markdown(
+ issues_sentence(project, mentioned_issues),
+ pipeline: :gfm,
+ author: author,
+ project: project,
+ issuable_state_filter_enabled: true
+ )
end
def assign_to_closing_issues_link
diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml
index b20e3a22133..31d0e589c26 100644
--- a/app/views/help/index.html.haml
+++ b/app/views/help/index.html.haml
@@ -4,7 +4,7 @@
Community Edition
- if user_signed_in?
%span= Gitlab::VERSION
- %small= Gitlab::REVISION
+ %small= link_to Gitlab::REVISION, Gitlab::COM_URL + namespace_project_commits_path('gitlab-org', 'gitlab-ce', Gitlab::REVISION)
= version_status_badge
%p.slead
GitLab is open source software to collaborate on code.
diff --git a/app/views/projects/jobs/show.html.haml b/app/views/projects/jobs/show.html.haml
index 0d10dfcef70..987068dc18e 100644
--- a/app/views/projects/jobs/show.html.haml
+++ b/app/views/projects/jobs/show.html.haml
@@ -66,29 +66,24 @@
.controllers
- if @build.has_trace?
= link_to raw_namespace_project_job_path(@project.namespace, @project, @build),
- title: 'Open raw trace',
+ title: 'Show complete raw',
data: { placement: 'top', container: 'body' },
- class: 'js-raw-link-controller has-tooltip' do
- = icon('download')
+ class: 'js-raw-link-controller has-tooltip controllers-buttons' do
+ = icon('file-text-o')
- if can?(current_user, :update_build, @project) && @build.erasable?
= link_to erase_namespace_project_job_path(@project.namespace, @project, @build),
method: :post,
data: { confirm: 'Are you sure you want to erase this build?', placement: 'top', container: 'body' },
- title: 'Erase Build',
- class: 'has-tooltip js-erase-link' do
+ title: 'Erase job log',
+ class: 'has-tooltip js-erase-link controllers-buttons' do
= icon('trash')
-
- %button.js-scroll-up.btn-scroll.btn-transparent.btn-blank.has-tooltip{ type: 'button',
- disabled: true,
- title: 'Scroll Up',
- data: { placement: 'top', container: 'body'} }
- = custom_icon('scroll_up')
- %button.js-scroll-down.btn-scroll.btn-transparent.btn-blank.has-tooltip{ type: 'button',
- disabled: true,
- title: 'Scroll Down',
- data: { placement: 'top', container: 'body'} }
- = custom_icon('scroll_down')
+ .has-tooltip.controllers-buttons{ title: 'Scroll to top', data: { placement: 'top', container: 'body'} }
+ %button.js-scroll-up.btn-scroll.btn-transparent.btn-blank{ type: 'button', disabled: true }
+ = custom_icon('scroll_up')
+ .has-tooltip.controllers-buttons{ title: 'Scroll to bottom', data: { placement: 'top', container: 'body'} }
+ %button.js-scroll-down.btn-scroll.btn-transparent.btn-blank{ type: 'button', disabled: true }
+ = custom_icon('scroll_down')
.bash.sticky.js-scroll-container
%code.js-build-output
.build-loader-animation.js-build-refresh
diff --git a/changelogs/unreleased/33381-display-issue-state-in-mr-widget-issue-links.yml b/changelogs/unreleased/33381-display-issue-state-in-mr-widget-issue-links.yml
new file mode 100644
index 00000000000..4a7b02fec94
--- /dev/null
+++ b/changelogs/unreleased/33381-display-issue-state-in-mr-widget-issue-links.yml
@@ -0,0 +1,4 @@
+---
+title: Display issue state in issue links section of merge request widget
+merge_request: 12021
+author:
diff --git a/changelogs/unreleased/dashboard-milestone-tabs-loading-async.yml b/changelogs/unreleased/dashboard-milestone-tabs-loading-async.yml
new file mode 100644
index 00000000000..357a623e0e8
--- /dev/null
+++ b/changelogs/unreleased/dashboard-milestone-tabs-loading-async.yml
@@ -0,0 +1,4 @@
+---
+title: Fixed dashboard milestone tabs not loading
+merge_request:
+author:
diff --git a/changelogs/unreleased/pat-msg-on-auth-failure.yml b/changelogs/unreleased/pat-msg-on-auth-failure.yml
new file mode 100644
index 00000000000..c1b1528bb7a
--- /dev/null
+++ b/changelogs/unreleased/pat-msg-on-auth-failure.yml
@@ -0,0 +1,4 @@
+---
+title: Instruct user to use personal access token for Git over HTTP
+merge_request: 11986
+author: Robin Bobbitt
diff --git a/changelogs/unreleased/tc-link-to-commit-on-help-page.yml b/changelogs/unreleased/tc-link-to-commit-on-help-page.yml
new file mode 100644
index 00000000000..3d11ba43d1f
--- /dev/null
+++ b/changelogs/unreleased/tc-link-to-commit-on-help-page.yml
@@ -0,0 +1,4 @@
+---
+title: Make the revision on the `/help` page clickable
+merge_request: 12016
+author:
diff --git a/config/locales/de.yml b/config/locales/de.yml
index 533663a2704..38c3711c6c7 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -62,6 +62,43 @@ de:
- :month
- :year
datetime:
+ # used in a custom scope that has been created to fix https://gitlab.com/gitlab-org/gitlab-ce/issues/32747
+ time_ago_in_words:
+ half_a_minute: vor einer halben Minute
+ less_than_x_seconds:
+ one: vor weniger als einer Sekunde
+ other: "vor weniger als %{count} Sekunden"
+ x_seconds:
+ one: vor einer Sekunde
+ other: "vor %{count} Sekunden"
+ less_than_x_minutes:
+ one: vor weniger als einer Minute
+ other: vor weniger als %{count} Minuten
+ x_minutes:
+ one: vor einer Minute
+ other: "vor %{count} Minuten"
+ about_x_hours:
+ one: vor etwa einer Stunde
+ other: "vor etwa %{count} Stunden"
+ x_days:
+ one: vor einem Tag
+ other: "vor %{count} Tagen"
+ about_x_months:
+ one: vor etwa einem Monat
+ other: "vor etwa %{count} Monaten"
+ x_months:
+ one: vor einem Monat
+ other: "vor %{count} Monaten"
+ about_x_years:
+ one: vor etwa einem Jahr
+ other: "vor etwa %{count} Jahren"
+ over_x_years:
+ one: vor mehr als einem Jahr
+ other: "vor mehr als %{count} Jahren"
+ almost_x_years:
+ one: vor fast einem Jahr
+ other: "vor fast %{count} Jahren"
+ # Used in distance_of_time_in_words(), distance_of_time_in_words_to_now(), time_ago_in_words()
distance_in_words:
about_x_hours:
one: etwa eine Stunde
diff --git a/config/locales/es.yml b/config/locales/es.yml
index 0f9dc39535d..d71c6eb5047 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -61,6 +61,7 @@ es:
- :month
- :year
datetime:
+ # used in a custom scope that has been created to fix https://gitlab.com/gitlab-org/gitlab-ce/issues/32747
time_ago_in_words:
half_a_minute: "hace medio minuto"
less_than_x_seconds:
@@ -96,6 +97,7 @@ es:
almost_x_years:
one: "hace casi 1 año"
other: "hace casi %{count} años"
+ # Used in distance_of_time_in_words(), distance_of_time_in_words_to_now(), time_ago_in_words()
distance_in_words:
about_x_hours:
one: alrededor de 1 hora
diff --git a/config/routes/dashboard.rb b/config/routes/dashboard.rb
index 8e380a0b0ac..d2437285cdf 100644
--- a/config/routes/dashboard.rb
+++ b/config/routes/dashboard.rb
@@ -4,7 +4,13 @@ resource :dashboard, controller: 'dashboard', only: [] do
get :activity
scope module: :dashboard do
- resources :milestones, only: [:index, :show]
+ resources :milestones, only: [:index, :show] do
+ member do
+ get :merge_requests
+ get :participants
+ get :labels
+ end
+ end
resources :labels, only: [:index]
resources :groups, only: [:index]
diff --git a/doc/api/projects.md b/doc/api/projects.md
index bf21aa0e179..716486022b0 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -2,10 +2,10 @@
### Project visibility level
-Project in GitLab has be either private, internal or public.
-You can determine it by `visibility` field in project.
+Project in GitLab can be either private, internal or public.
+This is determined by the `visibility` field in the project.
-Constants for project visibility levels are next:
+Values for the project visibility level are:
* `private`:
Project access must be granted explicitly for each user.
@@ -18,7 +18,7 @@ Constants for project visibility levels are next:
## List projects
-Get a list of visible projects for authenticated user. When being accessed without authentication, all public projects are returned.
+Get a list of visible projects for authenticated user. When accessed without authentication, only public projects are returned.
```
GET /projects
diff --git a/doc/integration/google.md b/doc/integration/google.md
index 1e7ad90c5a8..d5b523e6dc0 100644
--- a/doc/integration/google.md
+++ b/doc/integration/google.md
@@ -72,6 +72,21 @@ To enable the Google OAuth2 OmniAuth provider you must register your application
1. Change 'YOUR_APP_SECRET' to the client secret from the Google Developer page from step 10.
+1. Make sure that you configure GitLab to use an FQDN as Google will not accept raw IP addresses.
+
+ For Omnibus packages:
+
+ ```ruby
+ external_url 'https://gitlab.example.com'
+ ```
+
+ For installations from source:
+
+ ```yaml
+ gitlab:
+ host: https://gitlab.example.com
+ ```
+
1. Save the configuration file.
1. [Reconfigure][] or [restart GitLab][] for the changes to take effect if you
diff --git a/doc/university/glossary/README.md b/doc/university/glossary/README.md
index 591d1524061..9544de41b9a 100644
--- a/doc/university/glossary/README.md
+++ b/doc/university/glossary/README.md
@@ -1,4 +1,3 @@
-
## What is the Glossary
This contains a simplified list and definitions of some of the terms that you will encounter in your day to day activities when working with GitLab.
@@ -10,7 +9,7 @@ User authentication by combination of 2 different steps during login. This allow
### Access Levels
-Process of selective restriction to create, view, modify or delete a resource based on a set of assigned permissions. See [GitLab's Permission Guidelines](../../permissions/permissions.md
+Process of selective restriction to create, view, modify or delete a resource based on a set of assigned permissions. See [GitLab's Permission Guidelines](../../user/permissions.md)
### Active Directory (AD)
diff --git a/doc/user/project/container_registry.md b/doc/user/project/container_registry.md
index 10c281448a3..75ea911b9bc 100644
--- a/doc/user/project/container_registry.md
+++ b/doc/user/project/container_registry.md
@@ -39,6 +39,14 @@ You can read more about Docker Registry at https://docs.docker.com/registry/intr
## Build and push images
+>**Notes:**
+- Moving or renaming existing container registry repositories is not supported
+once you have pushed images because the images are signed, and the
+signature includes the repository name.
+- To move or rename a repository with a container registry you will have to
+delete all existing images.
+
+
If you visit the **Registry** link under your project's menu, you can see the
explicit instructions to login to the Container Registry using your GitLab
credentials.
diff --git a/doc/workflow/groups.md b/doc/workflow/groups.md
index 1cb3c940f00..1645e7e8d65 100644
--- a/doc/workflow/groups.md
+++ b/doc/workflow/groups.md
@@ -23,9 +23,10 @@ You can use the 'New project' button to add a project to the new group.
## Transferring an existing project into a group
-You can transfer an existing project into a group you own from the project settings page. The option to transfer a project is only available if you are the Owner of the project.
+You can transfer an existing project into a group you have at least Master access in from the project settings page.
+The option to transfer a project is only available if you are the Owner of the project.
First scroll down to the 'Dangerous settings' and click 'Show them to me'.
-Now you can pick any of the groups you manage as the new namespace for the group.
+Now you can pick any of the groups you have at least Master access in as the new namespace for the group.
![Transfer a project to a new namespace](groups/transfer_project.png)
diff --git a/features/steps/project/source/markdown_render.rb b/features/steps/project/source/markdown_render.rb
index 0fee158d590..cf31e61437e 100644
--- a/features/steps/project/source/markdown_render.rb
+++ b/features/steps/project/source/markdown_render.rb
@@ -90,6 +90,8 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps
click_link "api"
end
+ wait_for_requests
+
page.within '.tree-table' do
click_link "README.md"
end
diff --git a/lib/gitlab.rb b/lib/gitlab.rb
index c3064163e07..11f7c8b9510 100644
--- a/lib/gitlab.rb
+++ b/lib/gitlab.rb
@@ -1,9 +1,11 @@
require_dependency 'gitlab/git'
module Gitlab
+ COM_URL = 'https://gitlab.com'.freeze
+
def self.com?
# Check `staging?` as well to keep parity with gitlab.com
- Gitlab.config.gitlab.url == 'https://gitlab.com' || staging?
+ Gitlab.config.gitlab.url == COM_URL || staging?
end
def self.staging?
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index da07ba2f2a3..3933c3b04dd 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -37,7 +37,11 @@ module Gitlab
rate_limit!(ip, success: result.success?, login: login)
Gitlab::Auth::UniqueIpsLimiter.limit_user!(result.actor)
- result
+ return result if result.success? || current_application_settings.signin_enabled? || Gitlab::LDAP::Config.enabled?
+
+ # If sign-in is disabled and LDAP is not configured, recommend a
+ # personal access token on failed auth attempts
+ raise Gitlab::Auth::MissingPersonalTokenError
end
def find_with_user_password(login, password)
diff --git a/scripts/trigger-build b/scripts/trigger-build
index e4603533872..dcda70d7ed8 100755
--- a/scripts/trigger-build
+++ b/scripts/trigger-build
@@ -9,7 +9,7 @@ params = {
"token" => ENV["BUILD_TRIGGER_TOKEN"],
"variables[GITLAB_VERSION]" => ENV["CI_COMMIT_SHA"],
"variables[ALTERNATIVE_SOURCES]" => true,
- "variables[ee]" => ENV["EE_PACKAGE"]
+ "variables[ee]" => ENV["EE_PACKAGE"] || "false"
}
Dir.glob("*_VERSION").each do |version_file|
@@ -19,4 +19,9 @@ end
res = Net::HTTP.post_form(uri, params)
pipeline_id = JSON.parse(res.body)['id']
-puts "Triggered pipeline can be found at https://gitlab.com/gitlab-org/omnibus-gitlab/pipelines/#{pipeline_id}"
+unless pipeline_id.nil?
+ puts "Triggered pipeline can be found at https://gitlab.com/gitlab-org/omnibus-gitlab/pipelines/#{pipeline_id}"
+else
+ puts "Trigger failed. The response from trigger is: "
+ puts res.body
+end
diff --git a/spec/controllers/dashboard/milestones_controller_spec.rb b/spec/controllers/dashboard/milestones_controller_spec.rb
new file mode 100644
index 00000000000..424f39fd3b8
--- /dev/null
+++ b/spec/controllers/dashboard/milestones_controller_spec.rb
@@ -0,0 +1,38 @@
+require 'spec_helper'
+
+describe Dashboard::MilestonesController do
+ let(:project) { create(:empty_project) }
+ let(:user) { create(:user) }
+ let(:project_milestone) { create(:milestone, project: project) }
+ let(:milestone) do
+ DashboardMilestone.build(
+ [project],
+ project_milestone.title
+ )
+ end
+ let(:issue) { create(:issue, project: project, milestone: project_milestone) }
+ let!(:label) { create(:label, project: project, title: 'Issue Label', issues: [issue]) }
+ let!(:merge_request) { create(:merge_request, source_project: project, target_project: project, milestone: project_milestone) }
+ let(:milestone_path) { dashboard_milestone_path(milestone.safe_title, title: milestone.title) }
+
+ before do
+ sign_in(user)
+ project.team << [user, :master]
+ end
+
+ it_behaves_like 'milestone tabs'
+
+ describe "#show" do
+ render_views
+
+ def view_milestone
+ get :show, id: milestone.safe_title, title: milestone.title
+ end
+
+ it 'shows milestone page' do
+ view_milestone
+
+ expect(response).to have_http_status(200)
+ end
+ end
+end
diff --git a/spec/features/dashboard/milestone_tabs_spec.rb b/spec/features/dashboard/milestone_tabs_spec.rb
new file mode 100644
index 00000000000..0c7b992c500
--- /dev/null
+++ b/spec/features/dashboard/milestone_tabs_spec.rb
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+describe 'Dashboard milestone tabs', :js, :feature do
+ let(:user) { create(:user) }
+ let(:project) { create(:empty_project) }
+ let!(:label) { create(:label, project: project) }
+ let(:project_milestone) { create(:milestone, project: project) }
+ let(:milestone) do
+ DashboardMilestone.build(
+ [project],
+ project_milestone.title
+ )
+ end
+ let!(:merge_request) { create(:labeled_merge_request, source_project: project, target_project: project, milestone: project_milestone, labels: [label]) }
+
+ before do
+ project.add_master(user)
+ login_as(user)
+
+ visit dashboard_milestone_path(milestone.safe_title, title: milestone.title)
+ end
+
+ it 'loads merge requests async' do
+ click_link 'Merge Requests'
+
+ expect(page).to have_selector('.merge_requests-sortable-list')
+ end
+
+ it 'loads participants async' do
+ click_link 'Participants'
+
+ expect(page).to have_selector('#tab-participants .bordered-list')
+ end
+
+ it 'loads labels async' do
+ click_link 'Labels'
+
+ expect(page).to have_selector('#tab-labels .bordered-list')
+ end
+end
diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb
index d6006eab0c9..d09da951869 100644
--- a/spec/lib/gitlab/auth_spec.rb
+++ b/spec/lib/gitlab/auth_spec.rb
@@ -204,6 +204,12 @@ describe Gitlab::Auth, lib: true do
expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: login)
expect(gl_auth.find_for_git_client(login, 'bar', project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new)
end
+
+ it 'throws an error suggesting user create a PAT when internal auth is disabled' do
+ allow_any_instance_of(ApplicationSetting).to receive(:signin_enabled?) { false }
+
+ expect { gl_auth.find_for_git_client('foo', 'bar', project: nil, ip: 'ip') }.to raise_error(Gitlab::Auth::MissingPersonalTokenError)
+ end
end
describe 'find_with_user_password' do
diff --git a/spec/presenters/merge_request_presenter_spec.rb b/spec/presenters/merge_request_presenter_spec.rb
index 44720fc4448..f5a14b1d04d 100644
--- a/spec/presenters/merge_request_presenter_spec.rb
+++ b/spec/presenters/merge_request_presenter_spec.rb
@@ -132,6 +132,11 @@ describe MergeRequestPresenter do
it 'does not present related issues links' do
is_expected.not_to match("#{project.full_path}/issues/#{issue_b.iid}")
end
+
+ it 'appends status when closing issue is already closed' do
+ issue_a.close
+ is_expected.to match('(closed)')
+ end
end
describe '#mentioned_issues_links' do
@@ -147,6 +152,11 @@ describe MergeRequestPresenter do
it 'does not present closing issues links' do
is_expected.not_to match("#{project.full_path}/issues/#{issue_a.iid}")
end
+
+ it 'appends status when mentioned issue is already closed' do
+ issue_b.close
+ is_expected.to match('(closed)')
+ end
end
describe '#assign_to_closing_issues_link' do
diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb
index c09be0ce1b9..6a83024d0d5 100644
--- a/spec/requests/git_http_spec.rb
+++ b/spec/requests/git_http_spec.rb
@@ -418,17 +418,17 @@ describe 'Git HTTP requests', lib: true do
end
context 'when username and password are provided' do
- it 'rejects pulls with 2FA error message' do
+ it 'rejects pulls with personal access token error message' do
download(path, user: user.username, password: user.password) do |response|
expect(response).to have_http_status(:unauthorized)
- expect(response.body).to include('You have 2FA enabled, please use a personal access token for Git over HTTP')
+ expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP')
end
end
- it 'rejects the push attempt' do
+ it 'rejects the push attempt with personal access token error message' do
upload(path, user: user.username, password: user.password) do |response|
expect(response).to have_http_status(:unauthorized)
- expect(response.body).to include('You have 2FA enabled, please use a personal access token for Git over HTTP')
+ expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP')
end
end
end
@@ -441,6 +441,41 @@ describe 'Git HTTP requests', lib: true do
end
end
+ context 'when internal auth is disabled' do
+ before do
+ allow_any_instance_of(ApplicationSetting).to receive(:signin_enabled?) { false }
+ end
+
+ it 'rejects pulls with personal access token error message' do
+ download(path, user: 'foo', password: 'bar') do |response|
+ expect(response).to have_http_status(:unauthorized)
+ expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP')
+ end
+ end
+
+ it 'rejects pushes with personal access token error message' do
+ upload(path, user: 'foo', password: 'bar') do |response|
+ expect(response).to have_http_status(:unauthorized)
+ expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP')
+ end
+ end
+
+ context 'when LDAP is configured' do
+ before do
+ allow(Gitlab::LDAP::Config).to receive(:enabled?).and_return(true)
+ allow_any_instance_of(Gitlab::LDAP::Authentication).
+ to receive(:login).and_return(nil)
+ end
+
+ it 'does not display the personal access token error message' do
+ upload(path, user: 'foo', password: 'bar') do |response|
+ expect(response).to have_http_status(:unauthorized)
+ expect(response.body).not_to include('You must use a personal access token with \'api\' scope for Git over HTTP')
+ end
+ end
+ end
+ end
+
context "when blank password attempts follow a valid login" do
def attempt_login(include_password)
password = include_password ? user.password : ""
diff --git a/spec/requests/jwt_controller_spec.rb b/spec/requests/jwt_controller_spec.rb
index e056353fa6f..54d7cf5f10d 100644
--- a/spec/requests/jwt_controller_spec.rb
+++ b/spec/requests/jwt_controller_spec.rb
@@ -70,7 +70,7 @@ describe JwtController do
context 'without personal token' do
it 'rejects the authorization attempt' do
expect(response).to have_http_status(401)
- expect(response.body).to include('You have 2FA enabled, please use a personal access token for Git over HTTP')
+ expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP')
end
end
@@ -88,9 +88,24 @@ describe JwtController do
context 'using invalid login' do
let(:headers) { { authorization: credentials('invalid', 'password') } }
- subject! { get '/jwt/auth', parameters, headers }
+ context 'when internal auth is enabled' do
+ it 'rejects the authorization attempt' do
+ get '/jwt/auth', parameters, headers
+
+ expect(response).to have_http_status(401)
+ expect(response.body).not_to include('You must use a personal access token with \'api\' scope for Git over HTTP')
+ end
+ end
- it { expect(response).to have_http_status(401) }
+ context 'when internal auth is disabled' do
+ it 'rejects the authorization attempt with personal access token message' do
+ allow_any_instance_of(ApplicationSetting).to receive(:signin_enabled?) { false }
+ get '/jwt/auth', parameters, headers
+
+ expect(response).to have_http_status(401)
+ expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP')
+ end
+ end
end
end
diff --git a/spec/support/milestone_tabs_examples.rb b/spec/support/milestone_tabs_examples.rb
index 4ad8b0a16e1..7cfc1e06975 100644
--- a/spec/support/milestone_tabs_examples.rb
+++ b/spec/support/milestone_tabs_examples.rb
@@ -1,10 +1,14 @@
shared_examples 'milestone tabs' do
def go(path, extra_params = {})
- params = if milestone.is_a?(GlobalMilestone)
- { group_id: group.to_param, id: milestone.safe_title, title: milestone.title }
- else
- { namespace_id: project.namespace.to_param, project_id: project, id: milestone.iid }
- end
+ params =
+ case milestone
+ when DashboardMilestone
+ { id: milestone.safe_title, title: milestone.title }
+ when GroupMilestone
+ { group_id: group.to_param, id: milestone.safe_title, title: milestone.title }
+ else
+ { namespace_id: project.namespace.to_param, project_id: project, id: milestone.iid }
+ end
get path, params.merge(extra_params)
end
diff --git a/spec/views/help/index.html.haml_spec.rb b/spec/views/help/index.html.haml_spec.rb
index 6b07fcfc987..1f8261cc46b 100644
--- a/spec/views/help/index.html.haml_spec.rb
+++ b/spec/views/help/index.html.haml_spec.rb
@@ -21,7 +21,7 @@ describe 'help/index' do
render
expect(rendered).to match '8.0.2'
- expect(rendered).to match 'abcdefg'
+ expect(rendered).to have_link('abcdefg', 'https://gitlab.com/gitlab-org/gitlab-ce/commits/abcdefg')
end
end