summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore78
-rw-r--r--.rubocop.yml30
-rw-r--r--CHANGELOG23
-rw-r--r--GITLAB_WORKHORSE_VERSION2
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock4
-rw-r--r--app/assets/javascripts/calendar.js.coffee2
-rw-r--r--app/assets/javascripts/issuable_form.js.coffee17
-rw-r--r--app/assets/javascripts/merge_request_widget.js.coffee10
-rw-r--r--app/assets/javascripts/notes.js.coffee10
-rw-r--r--app/assets/javascripts/users_select.js.coffee12
-rw-r--r--app/assets/stylesheets/framework/buttons.scss18
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss2
-rw-r--r--app/assets/stylesheets/framework/nav.scss21
-rw-r--r--app/assets/stylesheets/framework/variables.scss2
-rw-r--r--app/assets/stylesheets/pages/commit.scss24
-rw-r--r--app/controllers/admin/application_settings_controller.rb1
-rw-r--r--app/controllers/application_controller.rb2
-rw-r--r--app/controllers/autocomplete_controller.rb18
-rw-r--r--app/controllers/jwt_controller.rb2
-rw-r--r--app/controllers/omniauth_callbacks_controller.rb2
-rw-r--r--app/controllers/projects/application_controller.rb2
-rw-r--r--app/controllers/projects/find_file_controller.rb52
-rw-r--r--app/controllers/projects/hooks_controller.rb3
-rw-r--r--app/controllers/projects/merge_requests_controller.rb2
-rw-r--r--app/controllers/sessions_controller.rb2
-rw-r--r--app/finders/issuable_finder.rb2
-rw-r--r--app/helpers/commits_helper.rb19
-rw-r--r--app/helpers/diff_helper.rb4
-rw-r--r--app/helpers/issuables_helper.rb10
-rw-r--r--app/helpers/issues_helper.rb4
-rw-r--r--app/models/ability.rb13
-rw-r--r--app/models/application_setting.rb11
-rw-r--r--app/models/ci/build.rb2
-rw-r--r--app/models/ci/commit.rb4
-rw-r--r--app/models/ci/runner.rb2
-rw-r--r--app/models/concerns/issuable.rb20
-rw-r--r--app/models/key.rb2
-rw-r--r--app/models/members/project_member.rb7
-rw-r--r--app/models/network/graph.rb25
-rw-r--r--app/models/note.rb33
-rw-r--r--app/models/project.rb4
-rw-r--r--app/models/project_services/irker_service.rb2
-rw-r--r--app/models/project_wiki.rb14
-rw-r--r--app/models/repository.rb6
-rw-r--r--app/services/auth/container_registry_authentication_service.rb12
-rw-r--r--app/services/git_push_service.rb17
-rw-r--r--app/services/git_tag_push_service.rb2
-rw-r--r--app/services/notes/create_service.rb11
-rw-r--r--app/services/projects/housekeeping_service.rb2
-rw-r--r--app/services/wiki_pages/base_service.rb5
-rw-r--r--app/views/admin/application_settings/_form.html.haml8
-rw-r--r--app/views/devise/sessions/two_factor.html.haml1
-rw-r--r--app/views/events/event/_common.html.haml2
-rw-r--r--app/views/kaminari/gitlab/_first_page.html.haml2
-rw-r--r--app/views/kaminari/gitlab/_gap.html.haml2
-rw-r--r--app/views/kaminari/gitlab/_last_page.html.haml2
-rw-r--r--app/views/kaminari/gitlab/_next_page.html.haml2
-rw-r--r--app/views/kaminari/gitlab/_page.html.haml2
-rw-r--r--app/views/kaminari/gitlab/_paginator.html.haml6
-rw-r--r--app/views/kaminari/gitlab/_prev_page.html.haml2
-rw-r--r--app/views/projects/activity.html.haml1
-rw-r--r--app/views/projects/artifacts/browse.html.haml1
-rw-r--r--app/views/projects/badges/index.html.haml1
-rw-r--r--app/views/projects/blame/show.html.haml1
-rw-r--r--app/views/projects/blob/_header_title.html.haml1
-rw-r--r--app/views/projects/blob/edit.html.haml1
-rw-r--r--app/views/projects/blob/new.html.haml1
-rw-r--r--app/views/projects/blob/show.html.haml1
-rw-r--r--app/views/projects/branches/index.html.haml1
-rw-r--r--app/views/projects/branches/new.html.haml1
-rw-r--r--app/views/projects/builds/_header_title.html.haml1
-rw-r--r--app/views/projects/builds/index.html.haml1
-rw-r--r--app/views/projects/builds/show.html.haml1
-rw-r--r--app/views/projects/ci/commits/_commit.html.haml4
-rw-r--r--app/views/projects/commit/_ci_commit.html.haml16
-rw-r--r--app/views/projects/commit/_commit_box.html.haml56
-rw-r--r--app/views/projects/commit/builds.html.haml4
-rw-r--r--app/views/projects/commit/show.html.haml2
-rw-r--r--app/views/projects/commits/_header_title.html.haml1
-rw-r--r--app/views/projects/commits/show.html.haml1
-rw-r--r--app/views/projects/compare/index.html.haml1
-rw-r--r--app/views/projects/compare/show.html.haml1
-rw-r--r--app/views/projects/container_registry/_header_title.html.haml1
-rw-r--r--app/views/projects/container_registry/index.html.haml3
-rw-r--r--app/views/projects/find_file/show.html.haml1
-rw-r--r--app/views/projects/graphs/_header_title.html.haml1
-rw-r--r--app/views/projects/graphs/ci.html.haml1
-rw-r--r--app/views/projects/graphs/commits.html.haml1
-rw-r--r--app/views/projects/graphs/languages.html.haml1
-rw-r--r--app/views/projects/graphs/show.html.haml1
-rw-r--r--app/views/projects/hooks/_project_hook.html.haml2
-rw-r--r--app/views/projects/hooks/index.html.haml7
-rw-r--r--app/views/projects/issues/_header_title.html.haml1
-rw-r--r--app/views/projects/issues/_issue.html.haml2
-rw-r--r--app/views/projects/issues/edit.html.haml1
-rw-r--r--app/views/projects/issues/index.html.haml1
-rw-r--r--app/views/projects/issues/new.html.haml1
-rw-r--r--app/views/projects/issues/show.html.haml1
-rw-r--r--app/views/projects/labels/_header_title.html.haml1
-rw-r--r--app/views/projects/labels/edit.html.haml1
-rw-r--r--app/views/projects/labels/index.html.haml1
-rw-r--r--app/views/projects/labels/new.html.haml1
-rw-r--r--app/views/projects/merge_requests/_header_title.html.haml1
-rw-r--r--app/views/projects/merge_requests/_merge_request.html.haml2
-rw-r--r--app/views/projects/merge_requests/_show.html.haml1
-rw-r--r--app/views/projects/merge_requests/edit.html.haml1
-rw-r--r--app/views/projects/merge_requests/index.html.haml1
-rw-r--r--app/views/projects/merge_requests/invalid.html.haml1
-rw-r--r--app/views/projects/merge_requests/new.html.haml1
-rw-r--r--app/views/projects/merge_requests/widget/_show.html.haml8
-rw-r--r--app/views/projects/milestones/_header_title.html.haml1
-rw-r--r--app/views/projects/milestones/edit.html.haml1
-rw-r--r--app/views/projects/milestones/index.html.haml2
-rw-r--r--app/views/projects/milestones/new.html.haml1
-rw-r--r--app/views/projects/milestones/show.html.haml2
-rw-r--r--app/views/projects/network/show.html.haml1
-rw-r--r--app/views/projects/new.html.haml2
-rw-r--r--app/views/projects/pipelines/_header_title.html.haml1
-rw-r--r--app/views/projects/pipelines/index.html.haml1
-rw-r--r--app/views/projects/pipelines/new.html.haml1
-rw-r--r--app/views/projects/pipelines/show.html.haml1
-rw-r--r--app/views/projects/project_members/_header_title.html.haml1
-rw-r--r--app/views/projects/project_members/import.html.haml1
-rw-r--r--app/views/projects/project_members/index.html.haml1
-rw-r--r--app/views/projects/releases/edit.html.haml1
-rw-r--r--app/views/projects/services/_form.html.haml32
-rw-r--r--app/views/projects/services/index.html.haml52
-rw-r--r--app/views/projects/snippets/_header_title.html.haml1
-rw-r--r--app/views/projects/snippets/edit.html.haml1
-rw-r--r--app/views/projects/snippets/index.html.haml1
-rw-r--r--app/views/projects/snippets/new.html.haml1
-rw-r--r--app/views/projects/snippets/show.html.haml1
-rw-r--r--app/views/projects/tags/index.html.haml1
-rw-r--r--app/views/projects/tags/new.html.haml1
-rw-r--r--app/views/projects/tags/show.html.haml1
-rw-r--r--app/views/projects/tree/show.html.haml1
-rw-r--r--app/views/projects/wikis/_header_title.html.haml1
-rw-r--r--app/views/projects/wikis/edit.html.haml1
-rw-r--r--app/views/projects/wikis/empty.html.haml1
-rw-r--r--app/views/projects/wikis/git_access.html.haml1
-rw-r--r--app/views/projects/wikis/history.html.haml1
-rw-r--r--app/views/projects/wikis/pages.html.haml1
-rw-r--r--app/views/projects/wikis/show.html.haml1
-rw-r--r--app/views/shared/issuable/_filter.html.haml2
-rw-r--r--app/views/shared/issuable/_form.html.haml4
-rw-r--r--app/views/shared/projects/_project.html.haml3
-rw-r--r--app/views/shared/snippets/_header.html.haml2
-rw-r--r--app/workers/emails_on_push_worker.rb1
-rw-r--r--config/initializers/1_settings.rb2
-rw-r--r--config/initializers/doorkeeper.rb4
-rw-r--r--config/initializers/metrics.rb1
-rw-r--r--config/initializers/omniauth.rb2
-rw-r--r--config/initializers/session_store.rb2
-rw-r--r--config/routes.rb9
-rw-r--r--db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb2
-rw-r--r--db/migrate/20160525205328_remove_main_language_from_projects.rb21
-rw-r--r--db/migrate/20160527020117_remove_notification_settings_for_deleted_projects.rb13
-rw-r--r--db/migrate/20160528043124_add_users_state_index.rb9
-rw-r--r--db/migrate/20160530150109_add_container_registry_token_expire_delay_to_application_settings.rb9
-rw-r--r--db/schema.rb51
-rw-r--r--doc/administration/repository_checks.md4
-rw-r--r--doc/api/labels.md2
-rw-r--r--doc/api/services.md6
-rw-r--r--doc/api/settings.md7
-rw-r--r--doc/ci/yaml/README.md2
-rw-r--r--doc/development/migration_style_guide.md2
-rw-r--r--doc/install/installation.md2
-rw-r--r--doc/install/requirements.md2
-rw-r--r--doc/logs/logs.md6
-rw-r--r--doc/migrate_ci_to_ce/README.md2
-rw-r--r--doc/operations/moving_repositories.md8
-rw-r--r--doc/update/8.6-to-8.7.md8
-rw-r--r--doc/update/8.7-to-8.8.md10
-rw-r--r--doc/web_hooks/web_hooks.md55
-rw-r--r--features/steps/dashboard/todos.rb2
-rw-r--r--features/steps/project/issues/issues.rb2
-rw-r--r--features/steps/project/merge_requests.rb4
-rw-r--r--lib/api/entities.rb1
-rw-r--r--lib/api/licenses.rb14
-rw-r--r--lib/api/users.rb2
-rw-r--r--lib/backup/manager.rb2
-rw-r--r--lib/banzai/filter/abstract_reference_filter.rb4
-rw-r--r--lib/ci/gitlab_ci_yaml_processor.rb2
-rw-r--r--lib/event_filter.rb2
-rw-r--r--lib/gitlab/ci/build/artifacts/metadata.rb2
-rw-r--r--lib/gitlab/current_settings.rb23
-rw-r--r--lib/gitlab/diff/parser.rb14
-rw-r--r--lib/gitlab/github_import/pull_request_formatter.rb5
-rw-r--r--lib/gitlab/gitlab_import/importer.rb8
-rw-r--r--lib/gitlab/middleware/rails_queue_duration.rb24
-rw-r--r--lib/gitlab/project_search_results.rb2
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb2
-rw-r--r--spec/controllers/projects_controller_spec.rb11
-rw-r--r--spec/controllers/registrations_controller_spec.rb4
-rw-r--r--spec/controllers/sessions_controller_spec.rb21
-rw-r--r--spec/factories/notes.rb20
-rw-r--r--spec/features/issues/filter_issues_spec.rb36
-rw-r--r--spec/features/issues/move_spec.rb16
-rw-r--r--spec/features/issues/note_polling_spec.rb5
-rw-r--r--spec/features/issues_spec.rb2
-rw-r--r--spec/features/login_spec.rb8
-rw-r--r--spec/features/merge_requests/created_from_fork_spec.rb58
-rw-r--r--spec/features/merge_requests/user_lists_merge_requests_spec.rb9
-rw-r--r--spec/features/notes_on_merge_requests_spec.rb10
-rw-r--r--spec/features/participants_autocomplete_spec.rb6
-rw-r--r--spec/features/pipelines_spec.rb30
-rw-r--r--spec/features/project/shortcuts_spec.rb4
-rw-r--r--spec/features/task_lists_spec.rb5
-rw-r--r--spec/features/todos/todos_spec.rb21
-rw-r--r--spec/lib/gitlab/akismet_helper_spec.rb4
-rw-r--r--spec/lib/gitlab/middleware/rails_queue_duration_spec.rb31
-rw-r--r--spec/lib/gitlab/note_data_builder_spec.rb71
-rw-r--r--spec/mailers/notify_spec.rb6
-rw-r--r--spec/models/build_spec.rb42
-rw-r--r--spec/models/ci/runner_project_spec.rb5
-rw-r--r--spec/models/concerns/issuable_spec.rb17
-rw-r--r--spec/models/legacy_diff_note_spec.rb4
-rw-r--r--spec/models/members/project_member_spec.rb42
-rw-r--r--spec/models/merge_request_spec.rb7
-rw-r--r--spec/models/note_spec.rb63
-rw-r--r--spec/models/project_services/hipchat_service_spec.rb149
-rw-r--r--spec/models/project_services/slack_service_spec.rb68
-rw-r--r--spec/models/project_wiki_spec.rb13
-rw-r--r--spec/models/repository_spec.rb12
-rw-r--r--spec/models/user_spec.rb8
-rw-r--r--spec/requests/api/notes_spec.rb4
-rw-r--r--spec/requests/api/users_spec.rb2
-rw-r--r--spec/services/auth/container_registry_authentication_service_spec.rb61
-rw-r--r--spec/services/git_push_service_spec.rb43
-rw-r--r--spec/services/groups/create_service_spec.rb2
-rw-r--r--spec/services/issues/bulk_update_service_spec.rb9
-rw-r--r--spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb10
-rw-r--r--spec/services/system_note_service_spec.rb12
-rw-r--r--spec/support/login_helpers.rb6
-rw-r--r--spec/teaspoon_env.rb50
236 files changed, 1460 insertions, 783 deletions
diff --git a/.gitignore b/.gitignore
index 8f861d76a37..ce6a363fe35 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,46 +4,46 @@
.bundle
.chef
.directory
-.envrc
-.gitlab_shell_secret
+/.envrc
+/.gitlab_shell_secret
.idea
-.rbenv-version
+/.rbenv-version
.rbx/
-.ruby-gemset
-.ruby-version
-.rvmrc
+/.ruby-gemset
+/.ruby-version
+/.rvmrc
.sass-cache/
-.secret
-.vagrant
-.byebug_history
-Vagrantfile
-backups/*
-config/aws.yml
-config/database.yml
-config/gitlab.yml
-config/gitlab_ci.yml
-config/initializers/rack_attack.rb
-config/initializers/smtp_settings.rb
-config/initializers/relative_url.rb
-config/resque.yml
-config/unicorn.rb
-config/secrets.yml
-config/sidekiq.yml
-coverage/*
-db/*.sqlite3
-db/*.sqlite3-journal
-db/data.yml
-doc/code/*
-dump.rdb
-log/*.log*
-nohup.out
-public/assets/
-public/uploads.*
-public/uploads/
-shared/artifacts/
-rails_best_practices_output.html
+/.secret
+/.vagrant
+/.byebug_history
+/Vagrantfile
+/backups/*
+/config/aws.yml
+/config/database.yml
+/config/gitlab.yml
+/config/gitlab_ci.yml
+/config/initializers/rack_attack.rb
+/config/initializers/smtp_settings.rb
+/config/initializers/relative_url.rb
+/config/resque.yml
+/config/unicorn.rb
+/config/secrets.yml
+/config/sidekiq.yml
+/coverage/*
+/db/*.sqlite3
+/db/*.sqlite3-journal
+/db/data.yml
+/doc/code/*
+/dump.rdb
+/log/*.log*
+/nohup.out
+/public/assets/
+/public/uploads.*
+/public/uploads/
+/shared/artifacts/
+/rails_best_practices_output.html
/tags
-tmp/
-vendor/bundle/*
-builds/*
-shared/*
+/tmp/*
+/vendor/bundle/*
+/builds/*
+/shared/*
diff --git a/.rubocop.yml b/.rubocop.yml
index 2d8eb4077f3..9275f9537d5 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -222,7 +222,7 @@ Style/EndBlock:
# Use Unix-style line endings.
Style/EndOfLine:
- Enabled: false
+ Enabled: true
# Favor the use of Fixnum#even? && Fixnum#odd?
Style/EvenOdd:
@@ -286,7 +286,7 @@ Style/IdenticalConditionalBranches:
# Checks the indentation of the first line of the right-hand-side of a
# multi-line assignment.
Style/IndentAssignment:
- Enabled: false
+ Enabled: true
# Keep indentation straight.
Style/IndentationConsistency:
@@ -318,7 +318,7 @@ Style/LambdaCall:
# Comments should start with a space.
Style/LeadingCommentSpace:
- Enabled: false
+ Enabled: true
# Use \ instead of + or << to concatenate two string literals at line end.
Style/LineEndConcatenation:
@@ -330,7 +330,7 @@ Style/MethodCallParentheses:
# Checks if the method definitions have or don't have parentheses.
Style/MethodDefParentheses:
- Enabled: false
+ Enabled: true
# Use the configured style when naming methods.
Style/MethodName:
@@ -362,7 +362,7 @@ Style/MultilineHashBraceLayout:
# Do not use then for multi-line if/unless.
Style/MultilineIfThen:
- Enabled: false
+ Enabled: true
# Checks that the closing brace in a method call is either on the same line as
# the last method argument, or a new line.
@@ -394,7 +394,7 @@ Style/MutableConstant:
# Favor unless over if for negative conditions (or control flow or).
Style/NegatedIf:
- Enabled: false
+ Enabled: true
# Favor until over while for negative conditions.
Style/NegatedWhile:
@@ -486,10 +486,9 @@ Style/RedundantException:
Style/RedundantFreeze:
Enabled: false
-# TODO: Enable RedundantParentheses Cop.
# Checks for parentheses that seem not to serve any purpose.
Style/RedundantParentheses:
- Enabled: false
+ Enabled: true
# Don't use return where it's not required.
Style/RedundantReturn:
@@ -541,7 +540,7 @@ Style/SpaceAfterComma:
# Do not put a space between a method name and the opening parenthesis in a
# method definition.
Style/SpaceAfterMethodName:
- Enabled: false
+ Enabled: true
# Tracks redundant space after the ! operator.
Style/SpaceAfterNot:
@@ -570,11 +569,11 @@ Style/SpaceBeforeBlockBraces:
# No spaces before commas.
Style/SpaceBeforeComma:
- Enabled: false
+ Enabled: true
# Checks for missing space between code and a comment on the same line.
Style/SpaceBeforeComment:
- Enabled: false
+ Enabled: true
# Checks that exactly one space is used between a method name and the first
# argument for method calls without parentheses.
@@ -705,7 +704,7 @@ Style/WhenThen:
# Checks for redundant do after while or until.
Style/WhileUntilDo:
- Enabled: false
+ Enabled: true
# Favor modifier while/until usage when you have a single-line body.
Style/WhileUntilModifier:
@@ -785,7 +784,7 @@ Lint/AssignmentInCondition:
# Align block ends correctly.
Lint/BlockAlignment:
- Enabled: false
+ Enabled: true
# Default values in optional keyword arguments and optional ordinal arguments
# should not refer back to the name of the argument.
@@ -878,7 +877,7 @@ Lint/InvalidCharacterLiteral:
# Checks of literals used in conditions.
Lint/LiteralInCondition:
- Enabled: false
+ Enabled: true
# Checks for literals used in interpolation.
Lint/LiteralInInterpolation:
@@ -1027,10 +1026,9 @@ Performance/StartWith:
Performance/StringReplacement:
Enabled: true
-# TODO: Enable TimesMap Cop.
# Checks for `.times.map` calls.
Performance/TimesMap:
- Enabled: false
+ Enabled: true
##################### Rails ##################################
diff --git a/CHANGELOG b/CHANGELOG
index 24c691b4718..848aaa8506e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,15 +1,37 @@
Please view this file on the master branch, on stable branches it's out of date.
v 8.9.0 (unreleased)
+ - Allow enabling wiki page events from Webhook management UI
+ - Make EmailsOnPushWorker use Sidekiq mailers queue
+ - Fix wiki page events' webhook to point to the wiki repository
+ - Fix issue todo not remove when leave project !4150 (Long Nguyen)
- Allow forking projects with restricted visibility level
+ - Improve note validation to prevent errors when creating invalid note via API
+ - Remove project notification settings associated with deleted projects
+ - Fix 404 page when viewing TODOs that contain milestones or labels in different projects
- Redesign navigation for project pages
- Fix groups API to list only user's accessible projects
- Redesign account and email confirmation emails
- Use gitlab-shell v3.0.0
+ - Add DB index on users.state
- Add rake task 'gitlab:db:configure' for conditionally seeding or migrating the database
- Changed the Slack build message to use the singular duration if necessary (Aran Koning)
- Fix issues filter when ordering by milestone
- Todos will display target state if issuable target is 'Closed' or 'Merged'
+ - Fix bug when sorting issues by milestone due date and filtering by two or more labels
+ - Remove 'main language' feature
+ - Pipelines can be canceled only when there are running builds
+ - Projects pending deletion will render a 404 page
+ - Measure queue duration between gitlab-workhorse and Rails
+ - Make authentication service for Container Registry to be compatible with < Docker 1.11
+ - Add Application Setting to configure Container Registry token expire delay (default 5min)
+
+v 8.8.3
+ - Fix incorrect links on pipeline page when merge request created from fork
+ - Fix gitlab importer failing to import new projects due to missing credentials
+ - Fix import URL migration not rescuing with the correct Error
+ - In search results, only show notes on confidential issues that the user has access to
+ - Fix health check access token changing due to old application settings being used
v 8.8.2
- Added remove due date button. !4209
@@ -110,6 +132,7 @@ v 8.7.6
- Fix links on wiki pages for relative url setups. !4131 (Artem Sidorenko)
- Fix import from GitLab.com to a private instance failure. !4181
- Fix external imports not finding the import data. !4106
+ - Fix notification delay when changing status of an issue
v 8.7.5
- Fix relative links in wiki pages. !4050
diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION
index f38fc5393ff..0a1ffad4b4d 100644
--- a/GITLAB_WORKHORSE_VERSION
+++ b/GITLAB_WORKHORSE_VERSION
@@ -1 +1 @@
-0.7.3
+0.7.4
diff --git a/Gemfile b/Gemfile
index b897dc0a741..540710712fc 100644
--- a/Gemfile
+++ b/Gemfile
@@ -73,7 +73,7 @@ gem 'grape-entity', '~> 0.4.2'
gem 'rack-cors', '~> 0.4.0', require: 'rack/cors'
# Pagination
-gem "kaminari", "~> 0.16.3"
+gem "kaminari", "~> 0.17.0"
# HAML
gem "haml-rails", '~> 0.9.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index fa2b72b2524..146e95167b2 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -442,7 +442,7 @@ GEM
railties (>= 3.2.16)
json (1.8.3)
jwt (1.5.2)
- kaminari (0.16.3)
+ kaminari (0.17.0)
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
kgio (2.10.0)
@@ -959,7 +959,7 @@ DEPENDENCIES
jquery-turbolinks (~> 2.1.0)
jquery-ui-rails (~> 5.0.0)
jwt
- kaminari (~> 0.16.3)
+ kaminari (~> 0.17.0)
letter_opener_web (~> 1.3.0)
licensee (~> 8.0.0)
loofah (~> 2.0.3)
diff --git a/app/assets/javascripts/calendar.js.coffee b/app/assets/javascripts/calendar.js.coffee
index f9c7bffdadb..26a26061539 100644
--- a/app/assets/javascripts/calendar.js.coffee
+++ b/app/assets/javascripts/calendar.js.coffee
@@ -175,7 +175,7 @@ class @Calendar
.range(['#acd5f2', '#254e77'])
.domain([0, 3])
- clickDay: (stamp) ->
+ clickDay: (stamp) =>
if @currentSelectedDate isnt stamp.date
@currentSelectedDate = stamp.date
formatted_date = @currentSelectedDate.getFullYear() + "-" + (@currentSelectedDate.getMonth()+1) + "-" + @currentSelectedDate.getDate()
diff --git a/app/assets/javascripts/issuable_form.js.coffee b/app/assets/javascripts/issuable_form.js.coffee
index 72ae3bde81e..898506fde32 100644
--- a/app/assets/javascripts/issuable_form.js.coffee
+++ b/app/assets/javascripts/issuable_form.js.coffee
@@ -19,6 +19,7 @@ class @IssuableForm
@form.on "click", ".btn-cancel", @resetAutosave
@initWip()
+ @initMoveDropdown()
$issuableDueDate = $('#issuable-due-date')
@@ -89,3 +90,19 @@ class @IssuableForm
addWip: ->
@titleField.val "WIP: #{@titleField.val()}"
+
+ initMoveDropdown: ->
+ $moveDropdown = $('.js-move-dropdown')
+
+ if $moveDropdown.length
+ $('.js-move-dropdown').select2
+ ajax:
+ url: $moveDropdown.data('projects-url')
+ results: (data) ->
+ return {
+ results: data
+ }
+ formatResult: (project) ->
+ project.name_with_namespace
+ formatSelection: (project) ->
+ project.name_with_namespace
diff --git a/app/assets/javascripts/merge_request_widget.js.coffee b/app/assets/javascripts/merge_request_widget.js.coffee
index d16f44d52f8..779f536d9f0 100644
--- a/app/assets/javascripts/merge_request_widget.js.coffee
+++ b/app/assets/javascripts/merge_request_widget.js.coffee
@@ -10,6 +10,7 @@ class @MergeRequestWidget
$('#modal_merge_info').modal(show: false)
@firstCICheck = true
@readyForCICheck = false
+ @cancel = false
clearInterval @fetchBuildStatusInterval
@clearEventListeners()
@@ -21,10 +22,16 @@ class @MergeRequestWidget
clearEventListeners: ->
$(document).off 'page:change.merge_request'
+ cancelPolling: ->
+ @cancel = true
+
addEventListeners: ->
+ allowedPages = ['show', 'commits', 'builds', 'changes']
$(document).on 'page:change.merge_request', =>
- if $('body').data('page') isnt 'projects:merge_requests:show'
+ page = $('body').data('page').split(':').last()
+ if allowedPages.indexOf(page) < 0
clearInterval @fetchBuildStatusInterval
+ @cancelPolling()
@clearEventListeners()
mergeInProgress: (deleteSourceBranch = false)->
@@ -67,6 +74,7 @@ class @MergeRequestWidget
$('.ci-widget-fetching').show()
$.getJSON @opts.ci_status_url, (data) =>
+ return if @cancel
@readyForCICheck = true
if data.status is ''
diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee
index 6d9d6528f45..f8151963fa7 100644
--- a/app/assets/javascripts/notes.js.coffee
+++ b/app/assets/javascripts/notes.js.coffee
@@ -114,9 +114,9 @@ class @Notes
@refresh()
, @pollingInterval
- refresh: ->
+ refresh: =>
return if @refreshing is true
- refreshing = true
+ @refreshing = true
if not document.hidden and document.URL.indexOf(@noteable_url) is 0
@getContent()
@@ -134,8 +134,8 @@ class @Notes
@renderDiscussionNote(note)
else
@renderNote(note)
- always: =>
- @refreshing = false
+ .always () =>
+ @refreshing = false
###
Increase @pollingInterval up to 120 seconds on every function call,
@@ -329,7 +329,7 @@ class @Notes
@renderDiscussionNote(note)
# cleanup after successfully creating a diff/discussion note
- @removeDiscussionNoteForm($("#new-discussion-note-form-#{note.discussion_id}"))
+ @removeDiscussionNoteForm($(xhr.target))
###
Called in response to the edit note form being submitted
diff --git a/app/assets/javascripts/users_select.js.coffee b/app/assets/javascripts/users_select.js.coffee
index b80b1b861cc..519618aa617 100644
--- a/app/assets/javascripts/users_select.js.coffee
+++ b/app/assets/javascripts/users_select.js.coffee
@@ -93,7 +93,9 @@ class @UsersSelect
$dropdown.glDropdown(
data: (term, callback) =>
- @users term, (users) =>
+ isAuthorFilter = $('.js-author-search')
+
+ @users term, term is '' and isAuthorFilter, (users) =>
if term.length is 0
showDivider = 0
@@ -138,7 +140,7 @@ class @UsersSelect
toggleLabel: (selected) ->
if selected && 'id' of selected
- selected.name
+ if selected.text then selected.text else selected.name
else
defaultLabel
@@ -219,7 +221,7 @@ class @UsersSelect
multiple: $(select).hasClass('multiselect')
minimumInputLength: 0
query: (query) =>
- @users query.term, (users) =>
+ @users query.term, @projectId?, (users) =>
data = { results: users }
if query.term.length == 0
@@ -302,7 +304,7 @@ class @UsersSelect
# Return users list. Filtered by query
# Only active users retrieved
- users: (query, callback) =>
+ users: (query, fromProject, callback) =>
url = @buildUrl(@usersPath)
$.ajax(
@@ -311,7 +313,7 @@ class @UsersSelect
search: query
per_page: 20
active: true
- project_id: @projectId
+ project_id: @projectId if fromProject
group_id: @groupId
current_user: @showCurrentUser
author_id: @authorId
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index eaf85bb17ca..467f3b35d74 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -16,6 +16,19 @@
@include btn-default;
}
+@mixin btn-outline($background, $text, $border, $hover-background, $hover-text, $hover-border) {
+ background-color: $background;
+ color: $text;
+ border-color: $border;
+
+ &:hover,
+ &:focus {
+ background-color: $hover-background;
+ color: $hover-text;
+ border-color: $hover-border;;
+ }
+}
+
@mixin btn-color($light, $border-light, $normal, $border-normal, $dark, $border-dark, $color) {
background-color: $light;
border-color: $border-light;
@@ -106,11 +119,14 @@
@include btn-blue;
}
- &.btn-close,
&.btn-warning {
@include btn-orange;
}
+ &.btn-close {
+ @include btn-outline($white-light, $orange-normal, $orange-normal, $orange-light, $white-light, $orange-light);
+ }
+
&.btn-danger,
&.btn-remove,
&.btn-red {
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 79a37d87e82..93c63c69843 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -154,7 +154,7 @@
color: $dropdown-header-color;
font-size: 13px;
line-height: 22px;
- padding: 0 10px 10px;
+ padding: 0 10px;
}
.separator + .dropdown-header {
diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss
index adfe5540704..7eb7a8e4544 100644
--- a/app/assets/stylesheets/framework/nav.scss
+++ b/app/assets/stylesheets/framework/nav.scss
@@ -336,6 +336,16 @@
@include fade(right, rgba(255, 255, 255, 0.4), $white-light);
left: 0;
}
+
+ &.event-filter {
+ .fade-right {
+ visibility: hidden;
+
+ @media (max-width: $screen-xs-max) {
+ visibility: visible;
+ }
+ }
+ }
}
}
@@ -346,3 +356,14 @@
top: ($header-height * 2) + 2;
}
}
+
+.activities {
+
+ .nav-block {
+ border-bottom: 1px solid $border-color;
+
+ .nav-links {
+ border-bottom: none;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index c7784e15844..8c54d935b6c 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -104,7 +104,7 @@ $blue-medium-light: #3498cb;
$blue-medium: #2f8ebf;
$blue-medium-dark: #2d86b4;
-$orange-light: rgba(252, 109, 38, 0.80);
+$orange-light: #fc8a51;
$orange-normal: #e75e40;
$orange-dark: #ce5237;
diff --git a/app/assets/stylesheets/pages/commit.scss b/app/assets/stylesheets/pages/commit.scss
index c2cd227571f..fc3f214aba5 100644
--- a/app/assets/stylesheets/pages/commit.scss
+++ b/app/assets/stylesheets/pages/commit.scss
@@ -26,8 +26,28 @@
.commit-info-row {
margin-bottom: 10px;
+
+ &.commit-info-row-header {
+ line-height: 34px;
+
+ @media (min-width: $screen-sm-min) {
+ margin-bottom: 0;
+ }
+
+ .commit-options-dropdown-caret {
+ @media (max-width: $screen-sm) {
+ margin-left: 0;
+ }
+ }
+ }
+
.avatar {
@extend .avatar-inline;
+ margin-left: 0;
+
+ @media (min-width: $screen-sm-min) {
+ margin-left: 4px;
+ }
}
.commit-committer-link,
.commit-author-link {
@@ -35,10 +55,6 @@
font-weight: bold;
}
- .time_ago {
- margin-left: 8px;
- }
-
.fa-clipboard {
color: $dropdown-title-btn-color;
}
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index ff7a5cad2fb..0a34a12e2a7 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -107,6 +107,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:repository_checks_enabled,
:metrics_packet_size,
:send_user_confirmation_email,
+ :container_registry_token_expire_delay,
restricted_visibility_levels: [],
import_sources: [],
disabled_oauth_sign_in_sources: []
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 1429ee40bb7..9b2a9d298b3 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -263,7 +263,7 @@ class ApplicationController < ActionController::Base
# internal repos where you are not a member. Enable this filter
# or improve current implementation to filter only issues you
# created or assigned or mentioned
- #@filter_params[:authorized_only] = true
+ # @filter_params[:authorized_only] = true
end
@filter_params
diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb
index eb0abc80ab4..3865b2d61fd 100644
--- a/app/controllers/autocomplete_controller.rb
+++ b/app/controllers/autocomplete_controller.rb
@@ -31,6 +31,24 @@ class AutocompleteController < ApplicationController
render json: @user, only: [:name, :username, :id], methods: [:avatar_url]
end
+ def projects
+ project = Project.find_by_id(params[:project_id])
+
+ projects = current_user.authorized_projects
+ projects = projects.select do |project|
+ current_user.can?(:admin_issue, project)
+ end
+
+ no_project = {
+ id: 0,
+ name_with_namespace: 'No project',
+ }
+ projects.unshift(no_project)
+ projects.delete(project)
+
+ render json: projects.to_json(only: [:id, :name_with_namespace], methods: :name_with_namespace)
+ end
+
private
def find_users
diff --git a/app/controllers/jwt_controller.rb b/app/controllers/jwt_controller.rb
index 156ab2811d6..cee3b6c43e7 100644
--- a/app/controllers/jwt_controller.rb
+++ b/app/controllers/jwt_controller.rb
@@ -32,7 +32,7 @@ class JwtController < ApplicationController
end
def auth_params
- params.permit(:service, :scope, :offline_token, :account, :client_id)
+ params.permit(:service, :scope, :account, :client_id)
end
def authenticate_project(login, password)
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index df98f56a1cd..f35d631df0c 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -97,7 +97,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
handle_signup_error
end
- def handle_service_ticket provider, ticket
+ def handle_service_ticket(provider, ticket)
Gitlab::OAuth::Session.create provider, ticket
session[:service_tickets] ||= {}
session[:service_tickets][provider] = ticket
diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb
index be872a93fee..776ba92c9ab 100644
--- a/app/controllers/projects/application_controller.rb
+++ b/app/controllers/projects/application_controller.rb
@@ -26,7 +26,7 @@ class Projects::ApplicationController < ApplicationController
project_path = "#{namespace}/#{id}"
@project = Project.find_with_namespace(project_path)
- if @project && can?(current_user, :read_project, @project)
+ if can?(current_user, :read_project, @project) && !@project.pending_delete?
if @project.path_with_namespace != project_path
redirect_to request.original_url.gsub(project_path, @project.path_with_namespace)
end
diff --git a/app/controllers/projects/find_file_controller.rb b/app/controllers/projects/find_file_controller.rb
index 54a0c447aee..cf53ad0a670 100644
--- a/app/controllers/projects/find_file_controller.rb
+++ b/app/controllers/projects/find_file_controller.rb
@@ -1,26 +1,26 @@
-# Controller for viewing a repository's file structure
-class Projects::FindFileController < Projects::ApplicationController
- include ExtractsPath
- include ActionView::Helpers::SanitizeHelper
- include TreeHelper
-
- before_action :require_non_empty_project
- before_action :assign_ref_vars
- before_action :authorize_download_code!
-
- def show
- return render_404 unless @repository.commit(@ref)
-
- respond_to do |format|
- format.html
- end
- end
-
- def list
- file_paths = @repo.ls_files(@ref)
-
- respond_to do |format|
- format.json { render json: file_paths }
- end
- end
-end
+# Controller for viewing a repository's file structure
+class Projects::FindFileController < Projects::ApplicationController
+ include ExtractsPath
+ include ActionView::Helpers::SanitizeHelper
+ include TreeHelper
+
+ before_action :require_non_empty_project
+ before_action :assign_ref_vars
+ before_action :authorize_download_code!
+
+ def show
+ return render_404 unless @repository.commit(@ref)
+
+ respond_to do |format|
+ format.html
+ end
+ end
+
+ def list
+ file_paths = @repo.ls_files(@ref)
+
+ respond_to do |format|
+ format.json { render json: file_paths }
+ end
+ end
+end
diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb
index 47524b1cf0b..a60027ff477 100644
--- a/app/controllers/projects/hooks_controller.rb
+++ b/app/controllers/projects/hooks_controller.rb
@@ -63,7 +63,8 @@ class Projects::HooksController < Projects::ApplicationController
:push_events,
:tag_push_events,
:token,
- :url
+ :url,
+ :wiki_page_events
)
end
end
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 17ce8e2ad20..d54284d7b20 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -205,7 +205,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
def branch_from
- #This is always source
+ # This is always source
@source_project = @merge_request.nil? ? @project : @merge_request.source_project
@commit = @repository.commit(params[:ref]) if params[:ref].present?
render layout: false
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index c29f4609e93..d68c2a708e3 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -1,5 +1,6 @@
class SessionsController < Devise::SessionsController
include AuthenticatesWithTwoFactor
+ include Devise::Controllers::Rememberable
include Recaptcha::ClientHelper
skip_before_action :check_2fa_requirement, only: [:destroy]
@@ -96,6 +97,7 @@ class SessionsController < Devise::SessionsController
# Remove any lingering user data from login
session.delete(:otp_user_id)
+ remember_me(user) if user_params[:remember_me] == '1'
sign_in(user) and return
else
flash.now[:alert] = 'Invalid two-factor code.'
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index 8ed3ccf1c02..7d8c56f4c22 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -271,7 +271,7 @@ class IssuableFinder
if filter_by_no_label?
items = items.without_label
else
- items = items.with_label(label_names)
+ items = items.with_label(label_names, params[:sort])
if projects
items = items.where(labels: { project_id: projects })
end
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index b59c3982edd..d328f56c80c 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -123,13 +123,14 @@ module CommitsHelper
)
end
- def revert_commit_link(commit, continue_to_path, btn_class: nil)
+ def revert_commit_link(commit, continue_to_path, btn_class: nil, has_tooltip: true)
return unless current_user
- tooltip = "Revert this #{commit.change_type_title} in a new merge request"
+ tooltip = "Revert this #{commit.change_type_title} in a new merge request" if has_tooltip
if can_collaborate_with_project?
- link_to 'Revert', '#modal-revert-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: tooltip, class: "btn btn-default btn-grouped btn-#{btn_class} has-tooltip"
+ btn_class = "btn btn-grouped btn-close btn-#{btn_class}" unless btn_class.nil?
+ link_to 'Revert', '#modal-revert-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}"
elsif can?(current_user, :fork_project, @project)
continue_params = {
to: continue_to_path,
@@ -140,17 +141,20 @@ module CommitsHelper
namespace_key: current_user.namespace.id,
continue: continue_params)
- link_to 'Revert', fork_path, class: 'btn btn-grouped btn-close', method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: tooltip
+ btn_class = "btn btn-grouped btn-close" unless btn_class.nil?
+
+ link_to 'Revert', fork_path, class: btn_class, method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: (tooltip if has_tooltip)
end
end
- def cherry_pick_commit_link(commit, continue_to_path, btn_class: nil)
+ def cherry_pick_commit_link(commit, continue_to_path, btn_class: nil, has_tooltip: true)
return unless current_user
tooltip = "Cherry-pick this #{commit.change_type_title} in a new merge request"
if can_collaborate_with_project?
- link_to 'Cherry-pick', '#modal-cherry-pick-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: tooltip, class: "btn btn-default btn-grouped btn-#{btn_class} has-tooltip"
+ btn_class = "btn btn-default btn-grouped btn-#{btn_class}" unless btn_class.nil?
+ link_to 'Cherry-pick', '#modal-cherry-pick-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}"
elsif can?(current_user, :fork_project, @project)
continue_params = {
to: continue_to_path,
@@ -161,7 +165,8 @@ module CommitsHelper
namespace_key: current_user.namespace.id,
continue: continue_params)
- link_to 'Cherry-pick', fork_path, class: 'btn btn-grouped btn-close', method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: tooltip
+ btn_class = "btn btn-grouped btn-close" unless btn_class.nil?
+ link_to 'Cherry-pick', fork_path, class: "#{btn_class}", method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: (tooltip if has_tooltip)
end
end
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index ea383f9b0f6..cbe47176831 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -39,11 +39,11 @@ module DiffHelper
end
def unfold_bottom_class(bottom)
- (bottom) ? 'js-unfold-bottom' : ''
+ bottom ? 'js-unfold-bottom' : ''
end
def unfold_class(unfold)
- (unfold) ? 'unfold js-unfold' : ''
+ unfold ? 'unfold js-unfold' : ''
end
def diff_line_content(line, line_type = nil)
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 39474217286..fe84ee3de44 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -50,14 +50,10 @@ module IssuablesHelper
end
def user_dropdown_label(user_id, default_label)
+ return default_label if user_id.nil?
return "Unassigned" if user_id == "0"
- if @project
- member = @project.team.find_member(user_id)
- user = member.user if member
- else
- user = User.find_by(id: user_id)
- end
+ user = User.find_by(id: user_id)
if user
user.name
@@ -76,7 +72,7 @@ module IssuablesHelper
def issuable_meta(issuable, project, text)
output = content_tag :strong, "#{text} #{issuable.to_reference}", class: "identifier"
- output << " opened #{time_ago_with_tooltip(issuable.created_at)} by".html_safe
+ output << " opened #{time_ago_with_tooltip(issuable.created_at)} by ".html_safe
output << content_tag(:strong) do
author_output = link_to_member(project, issuable.author, size: 24, mobile_classes: "hidden-xs")
author_output << link_to_member(project, issuable.author, size: 24, by_username: true, avatar: false, mobile_classes: "hidden-sm hidden-md hidden-lg")
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index 551409e8855..173bdbb8654 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -147,8 +147,8 @@ module IssuesHelper
def emoji_author_list(notes, current_user)
list = notes.map do |note|
- note.author == current_user ? "me" : note.author.name
- end
+ note.author == current_user ? "me" : note.author.name
+ end
list.join(", ")
end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 2a433afe3a6..44515550d9e 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -47,18 +47,17 @@ class Ability
# List of possible abilities for anonymous user
def anonymous_abilities(user, subject)
- case true
- when subject.is_a?(PersonalSnippet)
+ if subject.is_a?(PersonalSnippet)
anonymous_personal_snippet_abilities(subject)
- when subject.is_a?(ProjectSnippet)
+ elsif subject.is_a?(ProjectSnippet)
anonymous_project_snippet_abilities(subject)
- when subject.is_a?(CommitStatus)
+ elsif subject.is_a?(CommitStatus)
anonymous_commit_status_abilities(subject)
- when subject.is_a?(Project) || subject.respond_to?(:project)
+ elsif subject.is_a?(Project) || subject.respond_to?(:project)
anonymous_project_abilities(subject)
- when subject.is_a?(Group) || subject.respond_to?(:group)
+ elsif subject.is_a?(Group) || subject.respond_to?(:group)
anonymous_group_abilities(subject)
- when subject.is_a?(User)
+ elsif subject.is_a?(User)
anonymous_user_abilities
else
[]
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 9a14954b4a7..42f908aa344 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -51,6 +51,10 @@ class ApplicationSetting < ActiveRecord::Base
presence: true,
numericality: { only_integer: true, greater_than: 0 }
+ validates :container_registry_token_expire_delay,
+ presence: true,
+ numericality: { only_integer: true, greater_than: 0 }
+
validates_each :restricted_visibility_levels do |record, attr, value|
unless value.nil?
value.each do |level|
@@ -98,6 +102,10 @@ class ApplicationSetting < ActiveRecord::Base
Rails.cache.delete(CACHE_KEY)
end
+ def self.cached
+ Rails.cache.fetch(CACHE_KEY)
+ end
+
def self.create_from_defaults
create(
default_projects_limit: Settings.gitlab['default_projects_limit'],
@@ -121,7 +129,8 @@ class ApplicationSetting < ActiveRecord::Base
akismet_enabled: false,
repository_checks_enabled: true,
disabled_oauth_sign_in_sources: [],
- send_user_confirmation_email: false
+ send_user_confirmation_email: false,
+ container_registry_token_expire_delay: 5,
)
end
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index ff7dd44c526..5e77fda70b9 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -286,7 +286,7 @@ module Ci
project.runners_token
end
- def valid_token? token
+ def valid_token?(token)
project.valid_runners_token? token
end
diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb
index 6675a3f5d53..f22b573a94c 100644
--- a/app/models/ci/commit.rb
+++ b/app/models/ci/commit.rb
@@ -66,6 +66,10 @@ module Ci
end
end
+ def cancelable?
+ builds.running_or_pending.any?
+ end
+
def cancel_running
builds.running_or_pending.each(&:cancel)
end
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 6829dc91cb9..adb65292208 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -60,7 +60,7 @@ module Ci
end
def display_name
- return short_sha unless !description.blank?
+ return short_sha if description.blank?
description
end
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index 0a26fb2df04..2326a395cb8 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -130,13 +130,29 @@ module Issuable
joins(join_clause).group(issuable_table[:id]).reorder("COUNT(notes.id) DESC")
end
- def with_label(title)
+ def with_label(title, sort = nil)
if title.is_a?(Array) && title.size > 1
- joins(:labels).where(labels: { title: title }).group(arel_table[:id]).having("COUNT(DISTINCT labels.title) = #{title.size}")
+ joins(:labels).where(labels: { title: title }).group(*grouping_columns(sort)).having("COUNT(DISTINCT labels.title) = #{title.size}")
else
joins(:labels).where(labels: { title: title })
end
end
+
+ # Includes table keys in group by clause when sorting
+ # preventing errors in postgres
+ #
+ # Returns an array of arel columns
+ def grouping_columns(sort)
+ grouping_columns = [arel_table[:id]]
+
+ if ["milestone_due_desc", "milestone_due_asc"].include?(sort)
+ milestone_table = Milestone.arel_table
+ grouping_columns << milestone_table[:id]
+ grouping_columns << milestone_table[:due_date]
+ end
+
+ grouping_columns
+ end
end
def today?
diff --git a/app/models/key.rb b/app/models/key.rb
index d52afda67d1..0532e84f47d 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -26,7 +26,7 @@ class Key < ActiveRecord::Base
end
def publishable_key
- #Removes anything beyond the keytype and key itself
+ # Removes anything beyond the keytype and key itself
self.key.split[0..1].join(' ')
end
diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb
index 8dae3bb2ef2..46955b430f3 100644
--- a/app/models/members/project_member.rb
+++ b/app/models/members/project_member.rb
@@ -5,7 +5,6 @@ class ProjectMember < Member
belongs_to :project, class_name: 'Project', foreign_key: 'source_id'
-
# Make sure project member points only to project as it source
default_value_for :source_type, SOURCE_TYPE
validates_format_of :source_type, with: /\AProject\z/
@@ -15,6 +14,8 @@ class ProjectMember < Member
scope :in_projects, ->(projects) { where(source_id: projects.pluck(:id)) }
scope :with_user, ->(user) { where(user_id: user.id) }
+ before_destroy :delete_member_todos
+
class << self
# Add users to project teams with passed access option
@@ -102,6 +103,10 @@ class ProjectMember < Member
private
+ def delete_member_todos
+ user.todos.where(project_id: source_id).destroy_all if user
+ end
+
def send_invite
notification_service.invite_project_member(self, @raw_invite_token)
diff --git a/app/models/network/graph.rb b/app/models/network/graph.rb
index 9259cb1a0fa..1ac37e0307f 100644
--- a/app/models/network/graph.rb
+++ b/app/models/network/graph.rb
@@ -22,9 +22,16 @@ module Network
def collect_notes
h = Hash.new(0)
- @project.notes.where('noteable_type = ?' ,"Commit").group('notes.commit_id').select('notes.commit_id, count(notes.id) as note_count').each do |item|
- h[item.commit_id] = item.note_count.to_i
- end
+
+ @project
+ .notes
+ .where('noteable_type = ?', 'Commit')
+ .group('notes.commit_id')
+ .select('notes.commit_id, count(notes.id) as note_count')
+ .each do |item|
+ h[item.commit_id] = item.note_count.to_i
+ end
+
h
end
@@ -89,7 +96,7 @@ module Network
end
end
- if self.class.max_count / 2 < offset then
+ if self.class.max_count / 2 < offset
# get max index that commit is displayed in the center.
offset - self.class.max_count / 2
else
@@ -130,7 +137,7 @@ module Network
commit.parents(@map).each do |parent|
range = commit.time..parent.time
- space = if commit.space >= parent.space then
+ space = if commit.space >= parent.space
find_free_parent_space(range, parent.space, -1, commit.space)
else
find_free_parent_space(range, commit.space, -1, parent.space)
@@ -144,7 +151,7 @@ module Network
end
def find_free_parent_space(range, space_base, space_step, space_default)
- if is_overlap?(range, space_default) then
+ if is_overlap?(range, space_default)
find_free_space(range, space_step, space_base, space_default)
else
space_default
@@ -155,7 +162,7 @@ module Network
range.each do |i|
if i != range.first &&
i != range.last &&
- @commits[i].spaces.include?(overlap_space) then
+ @commits[i].spaces.include?(overlap_space)
return true;
end
@@ -231,9 +238,9 @@ module Network
reserved.uniq!
space = space_default
- while reserved.include?(space) do
+ while reserved.include?(space)
space += space_step
- if space < space_base then
+ if space < space_base
space_step *= -1
space = space_base + space_step
end
diff --git a/app/models/note.rb b/app/models/note.rb
index 35e5258fe3f..c21981ead84 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -29,10 +29,17 @@ class Note < ActiveRecord::Base
# Attachments are deprecated and are handled by Markdown uploader
validates :attachment, file_size: { maximum: :max_attachment_size }
- validates :noteable_id, presence: true, if: ->(n) { n.noteable_type.present? && n.noteable_type != 'Commit' }
- validates :commit_id, presence: true, if: ->(n) { n.noteable_type == 'Commit' }
+ validates :noteable_type, presence: true
+ validates :noteable_id, presence: true, unless: :for_commit?
+ validates :commit_id, presence: true, if: :for_commit?
validates :author, presence: true
+ validate unless: :for_commit? do |note|
+ unless note.noteable.try(:project) == note.project
+ errors.add(:invalid_project, 'Note and noteable project mismatch')
+ end
+ end
+
mount_uploader :attachment, AttachmentUploader
# Scopes
@@ -77,14 +84,30 @@ class Note < ActiveRecord::Base
#
# This method uses ILIKE on PostgreSQL and LIKE on MySQL.
#
- # query - The search query as a String.
+ # query - The search query as a String.
+ # as_user - Limit results to those viewable by a specific user
#
# Returns an ActiveRecord::Relation.
- def search(query)
+ def search(query, as_user: nil)
table = arel_table
pattern = "%#{query}%"
- where(table[:note].matches(pattern))
+ found_notes = joins('LEFT JOIN issues ON issues.id = noteable_id').
+ where(table[:note].matches(pattern))
+
+ if as_user
+ found_notes.where('
+ issues.confidential IS NULL
+ OR issues.confidential IS FALSE
+ OR (issues.confidential IS TRUE
+ AND (issues.author_id = :user_id
+ OR issues.assignee_id = :user_id
+ OR issues.project_id IN(:project_ids)))',
+ user_id: as_user.id,
+ project_ids: as_user.authorized_projects.select(:id))
+ else
+ found_notes.where('issues.confidential IS NULL OR issues.confidential IS FALSE')
+ end
end
def grouped_awards
diff --git a/app/models/project.rb b/app/models/project.rb
index f3a56b86d5a..c1d9bae44c9 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -946,13 +946,13 @@ class Project < ActiveRecord::Base
shared_runners_enabled? && Ci::Runner.shared.active.any?(&block)
end
- def valid_runners_token? token
+ def valid_runners_token?(token)
self.runners_token && ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.runners_token)
end
# TODO (ayufan): For now we use runners_token (backward compatibility)
# In 8.4 every build will have its own individual token valid for time of build
- def valid_build_token? token
+ def valid_build_token?(token)
self.builds_enabled? && self.runners_token && ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.runners_token)
end
diff --git a/app/models/project_services/irker_service.rb b/app/models/project_services/irker_service.rb
index 91015e6c9b1..2e5e854fc5e 100644
--- a/app/models/project_services/irker_service.rb
+++ b/app/models/project_services/irker_service.rb
@@ -70,7 +70,7 @@ class IrkerService < Service
private
def get_channels
- return true unless :activated?
+ return true unless activated?
return true if recipients.nil? || recipients.empty?
map_recipients
diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb
index 339fb0b9f9d..25d82929c0b 100644
--- a/app/models/project_wiki.rb
+++ b/app/models/project_wiki.rb
@@ -27,6 +27,10 @@ class ProjectWiki
@project.path_with_namespace + ".wiki"
end
+ def web_url
+ Gitlab::Routing.url_helpers.namespace_project_wiki_url(@project.namespace, @project, :home)
+ end
+
def url_to_repo
gitlab_shell.url_to_repo(path_with_namespace)
end
@@ -142,6 +146,16 @@ class ProjectWiki
wiki
end
+ def hook_attrs
+ {
+ web_url: web_url,
+ git_ssh_url: ssh_url_to_repo,
+ git_http_url: http_url_to_repo,
+ path_with_namespace: path_with_namespace,
+ default_branch: default_branch
+ }
+ end
+
private
def init_repo(path_with_namespace)
diff --git a/app/models/repository.rb b/app/models/repository.rb
index ecc8795c954..1ab163510bf 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -972,12 +972,6 @@ class Repository
end
end
- def main_language
- return unless head_exists?
-
- Linguist::Repository.new(rugged, rugged.head.target_id).language
- end
-
def avatar
return nil unless exists?
diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb
index 2bbab643e69..e57b95f21ec 100644
--- a/app/services/auth/container_registry_authentication_service.rb
+++ b/app/services/auth/container_registry_authentication_service.rb
@@ -1,13 +1,13 @@
module Auth
class ContainerRegistryAuthenticationService < BaseService
+ include Gitlab::CurrentSettings
+
AUDIENCE = 'container_registry'
def execute
return error('not found', 404) unless registry.enabled
- if params[:offline_token]
- return error('unauthorized', 401) unless current_user || project
- else
+ unless current_user || project
return error('forbidden', 403) unless scope
end
@@ -19,6 +19,7 @@ module Auth
token = JSONWebToken::RSAToken.new(registry.key)
token.issuer = registry.issuer
token.audience = AUDIENCE
+ token.expire_time = token_expire_at
token[:access] = names.map do |name|
{ type: 'repository', name: name, actions: %w(*) }
end
@@ -32,6 +33,7 @@ module Auth
token.issuer = registry.issuer
token.audience = params[:service]
token.subject = current_user.try(:username)
+ token.expire_time = ContainerRegistryAuthenticationService.token_expire_at
token[:access] = accesses.compact
token
end
@@ -77,5 +79,9 @@ module Auth
def registry
Gitlab.config.registry
end
+
+ def self.token_expire_at
+ Time.now + current_application_settings.container_registry_token_expire_delay.minutes
+ end
end
end
diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb
index 66136b62617..a886f35981f 100644
--- a/app/services/git_push_service.rb
+++ b/app/services/git_push_service.rb
@@ -53,10 +53,6 @@ class GitPushService < BaseService
# could cause the last commit of a merge request to change.
update_merge_requests
- # Checks if the main language has changed in the project and if so
- # it updates it accordingly
- update_main_language
-
perform_housekeeping
end
@@ -64,19 +60,6 @@ class GitPushService < BaseService
@project.repository.copy_gitattributes(params[:ref])
end
- def update_main_language
- # Performance can be bad so for now only check main_language once
- # See https://gitlab.com/gitlab-org/gitlab-ce/issues/14937
- return if @project.main_language.present?
-
- return unless is_default_branch?
- return unless push_to_new_branch? || push_to_existing_branch?
-
- current_language = @project.repository.main_language
- @project.update_attributes(main_language: current_language)
- true
- end
-
protected
def update_merge_requests
diff --git a/app/services/git_tag_push_service.rb b/app/services/git_tag_push_service.rb
index 7410442609d..299a0a967b0 100644
--- a/app/services/git_tag_push_service.rb
+++ b/app/services/git_tag_push_service.rb
@@ -23,7 +23,7 @@ class GitTagPushService < BaseService
commits = []
message = nil
- if !Gitlab::Git.blank_ref?(params[:newrev])
+ unless Gitlab::Git.blank_ref?(params[:newrev])
tag_name = Gitlab::Git.ref_name(params[:ref])
tag = project.repository.find_tag(tag_name)
if tag && tag.target == params[:newrev]
diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb
index 01586994813..2bb312bb252 100644
--- a/app/services/notes/create_service.rb
+++ b/app/services/notes/create_service.rb
@@ -5,8 +5,6 @@ module Notes
note.author = current_user
note.system = false
- return unless valid_project?(note)
-
if note.save
# Finish the harder work in the background
NewNoteWorker.perform_in(2.seconds, note.id, params)
@@ -15,14 +13,5 @@ module Notes
note
end
-
- private
-
- def valid_project?(note)
- return false unless project
- return true if note.for_commit?
-
- note.noteable.try(:project) == project
- end
end
end
diff --git a/app/services/projects/housekeeping_service.rb b/app/services/projects/housekeeping_service.rb
index 3b7c36f0908..43db29315a1 100644
--- a/app/services/projects/housekeeping_service.rb
+++ b/app/services/projects/housekeeping_service.rb
@@ -22,7 +22,7 @@ module Projects
end
def execute
- raise LeaseTaken if !try_obtain_lease
+ raise LeaseTaken unless try_obtain_lease
GitlabShellOneShotWorker.perform_async(:gc, @project.path_with_namespace)
ensure
diff --git a/app/services/wiki_pages/base_service.rb b/app/services/wiki_pages/base_service.rb
index 9162f128602..4c0a2c6b4d8 100644
--- a/app/services/wiki_pages/base_service.rb
+++ b/app/services/wiki_pages/base_service.rb
@@ -6,9 +6,8 @@ module WikiPages
object_kind: page.class.name.underscore,
user: current_user.hook_attrs,
project: @project.hook_attrs,
- object_attributes: page.hook_attrs,
- # DEPRECATED
- repository: @project.hook_attrs.slice(:name, :url, :description, :homepage)
+ wiki: @project.wiki.hook_attrs,
+ object_attributes: page.hook_attrs
}
page_url = Gitlab::UrlBuilder.build(page)
diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
index df286852b97..f149f9eb431 100644
--- a/app/views/admin/application_settings/_form.html.haml
+++ b/app/views/admin/application_settings/_form.html.haml
@@ -178,6 +178,14 @@
.col-sm-10
= f.number_field :max_artifacts_size, class: 'form-control'
+ - if Gitlab.config.registry.enabled
+ %fieldset
+ %legend Container Registry
+ .form-group
+ = f.label :container_registry_token_expire_delay, 'Authorization token duration (minutes)', class: 'control-label col-sm-2'
+ .col-sm-10
+ = f.number_field :container_registry_token_expire_delay, class: 'form-control'
+
%fieldset
%legend Metrics
%p
diff --git a/app/views/devise/sessions/two_factor.html.haml b/app/views/devise/sessions/two_factor.html.haml
index c9d1e454a5e..8c6a1552a53 100644
--- a/app/views/devise/sessions/two_factor.html.haml
+++ b/app/views/devise/sessions/two_factor.html.haml
@@ -4,6 +4,7 @@
%h3 Two-factor Authentication
.login-body
= form_for(resource, as: resource_name, url: session_path(resource_name), method: :post) do |f|
+ = f.hidden_field :remember_me, value: params[resource_name][:remember_me]
= f.text_field :otp_attempt, class: 'form-control', placeholder: 'Two-factor Authentication code', required: true, autofocus: true
%p.help-block.hint Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes.
.prepend-top-20
diff --git a/app/views/events/event/_common.html.haml b/app/views/events/event/_common.html.haml
index f9f623cc031..c7f29f2fc0e 100644
--- a/app/views/events/event/_common.html.haml
+++ b/app/views/events/event/_common.html.haml
@@ -4,7 +4,7 @@
= event_action_name(event)
- if event.target
- %strong= link_to event.target.reference_link_text, [event.project.namespace.becomes(Namespace), event.project, event.target], title: event.target_title
+ %strong= link_to event.target.reference_link_text, [event.project.namespace.becomes(Namespace), event.project, event.target], class: 'has-tooltip', title: event.target_title
= event_preposition(event)
diff --git a/app/views/kaminari/gitlab/_first_page.html.haml b/app/views/kaminari/gitlab/_first_page.html.haml
index ada7306d98d..e7a70e3bb28 100644
--- a/app/views/kaminari/gitlab/_first_page.html.haml
+++ b/app/views/kaminari/gitlab/_first_page.html.haml
@@ -2,7 +2,7 @@
-# available local variables
-# url: url to the first page
-# current_page: a page object for the currently displayed page
--# num_pages: total number of pages
+-# total_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
%li.first
diff --git a/app/views/kaminari/gitlab/_gap.html.haml b/app/views/kaminari/gitlab/_gap.html.haml
index 3ffd12f8587..80ca30f36e6 100644
--- a/app/views/kaminari/gitlab/_gap.html.haml
+++ b/app/views/kaminari/gitlab/_gap.html.haml
@@ -1,7 +1,7 @@
-# Non-link tag that stands for skipped pages...
-# available local variables
-# current_page: a page object for the currently displayed page
--# num_pages: total number of pages
+-# total_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
%li{class: "page"}
diff --git a/app/views/kaminari/gitlab/_last_page.html.haml b/app/views/kaminari/gitlab/_last_page.html.haml
index 3431d029bcc..53f780d1d1b 100644
--- a/app/views/kaminari/gitlab/_last_page.html.haml
+++ b/app/views/kaminari/gitlab/_last_page.html.haml
@@ -2,7 +2,7 @@
-# available local variables
-# url: url to the last page
-# current_page: a page object for the currently displayed page
--# num_pages: total number of pages
+-# total_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
%li.last
diff --git a/app/views/kaminari/gitlab/_next_page.html.haml b/app/views/kaminari/gitlab/_next_page.html.haml
index c805914fc3f..125f09777ba 100644
--- a/app/views/kaminari/gitlab/_next_page.html.haml
+++ b/app/views/kaminari/gitlab/_next_page.html.haml
@@ -2,7 +2,7 @@
-# available local variables
-# url: url to the next page
-# current_page: a page object for the currently displayed page
--# num_pages: total number of pages
+-# total_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
- if current_page.last?
diff --git a/app/views/kaminari/gitlab/_page.html.haml b/app/views/kaminari/gitlab/_page.html.haml
index a52d883b9a8..522e4d1d05f 100644
--- a/app/views/kaminari/gitlab/_page.html.haml
+++ b/app/views/kaminari/gitlab/_page.html.haml
@@ -3,7 +3,7 @@
-# page: a page object for "this" page
-# url: url to this page
-# current_page: a page object for the currently displayed page
--# num_pages: total number of pages
+-# total_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
%li{class: "page#{' active' if page.current?}"}
diff --git a/app/views/kaminari/gitlab/_paginator.html.haml b/app/views/kaminari/gitlab/_paginator.html.haml
index a12c53bcfe7..f5e0d2ed3f3 100644
--- a/app/views/kaminari/gitlab/_paginator.html.haml
+++ b/app/views/kaminari/gitlab/_paginator.html.haml
@@ -1,7 +1,7 @@
-# The container tag
-# available local variables
-# current_page: a page object for the currently displayed page
--# num_pages: total number of pages
+-# total_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
-# paginator: the paginator that renders the pagination tags inside
@@ -9,7 +9,7 @@
%div.gl-pagination
%ul.pagination.clearfix
- unless current_page.first?
- = first_page_tag unless num_pages < 5 # As kaminari will always show the first 5 pages
+ = first_page_tag unless total_pages < 5 # As kaminari will always show the first 5 pages
= prev_page_tag
- each_page do |page|
- if page.left_outer? || page.right_outer? || page.inside_window?
@@ -18,5 +18,5 @@
= gap_tag
= next_page_tag
- unless current_page.last?
- = last_page_tag unless num_pages < 5
+ = last_page_tag unless total_pages < 5
diff --git a/app/views/kaminari/gitlab/_prev_page.html.haml b/app/views/kaminari/gitlab/_prev_page.html.haml
index afb20455e0a..7edf10498a8 100644
--- a/app/views/kaminari/gitlab/_prev_page.html.haml
+++ b/app/views/kaminari/gitlab/_prev_page.html.haml
@@ -2,7 +2,7 @@
-# available local variables
-# url: url to the previous page
-# current_page: a page object for the currently displayed page
--# num_pages: total number of pages
+-# total_pages: total number of pages
-# per_page: number of items to fetch per page
-# remote: data-remote
- if current_page.first?
diff --git a/app/views/projects/activity.html.haml b/app/views/projects/activity.html.haml
index 69fa4ad37c4..3c0f01cbf6f 100644
--- a/app/views/projects/activity.html.haml
+++ b/app/views/projects/activity.html.haml
@@ -1,5 +1,4 @@
- page_title "Activity"
-- header_title project_title(@project, "Activity", activity_project_path(@project))
= render 'projects/last_push'
diff --git a/app/views/projects/artifacts/browse.html.haml b/app/views/projects/artifacts/browse.html.haml
index 49f95ff37db..ede01dcc1aa 100644
--- a/app/views/projects/artifacts/browse.html.haml
+++ b/app/views/projects/artifacts/browse.html.haml
@@ -1,5 +1,4 @@
- page_title 'Artifacts', "#{@build.name} (##{@build.id})", 'Builds'
-= render 'projects/builds/header_title'
.top-block.row-content-block.clearfix
.pull-right
diff --git a/app/views/projects/badges/index.html.haml b/app/views/projects/badges/index.html.haml
index c22384ddf46..ee63bc55a30 100644
--- a/app/views/projects/badges/index.html.haml
+++ b/app/views/projects/badges/index.html.haml
@@ -1,6 +1,5 @@
- page_title 'Badges'
- badges_path = namespace_project_badges_path(@project.namespace, @project)
-- header_title project_title(@project, 'Badges', badges_path)
.prepend-top-10
.panel.panel-default
diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml
index 5f9a92ff93f..377665b096f 100644
--- a/app/views/projects/blame/show.html.haml
+++ b/app/views/projects/blame/show.html.haml
@@ -1,5 +1,4 @@
- page_title "Blame", @blob.path, @ref
-- header_title project_title(@project, "Files", project_files_path(@project))
%h3.page-title Blame view
diff --git a/app/views/projects/blob/_header_title.html.haml b/app/views/projects/blob/_header_title.html.haml
deleted file mode 100644
index 78c5ef20a5f..00000000000
--- a/app/views/projects/blob/_header_title.html.haml
+++ /dev/null
@@ -1 +0,0 @@
-- header_title project_title(@project, "Files", project_files_path(@project))
diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml
index effcce5a1c4..e4f04ca7764 100644
--- a/app/views/projects/blob/edit.html.haml
+++ b/app/views/projects/blob/edit.html.haml
@@ -1,5 +1,4 @@
- page_title "Edit", @blob.path, @ref
-= render "header_title"
.file-editor
%ul.nav-links.no-bottom.js-edit-mode
diff --git a/app/views/projects/blob/new.html.haml b/app/views/projects/blob/new.html.haml
index 0459699432e..c952bc7e5db 100644
--- a/app/views/projects/blob/new.html.haml
+++ b/app/views/projects/blob/new.html.haml
@@ -1,5 +1,4 @@
- page_title "New File", @path.presence, @ref
-= render "header_title"
%h3.page-title
New File
diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml
index 6988039b6c7..ed670dae88d 100644
--- a/app/views/projects/blob/show.html.haml
+++ b/app/views/projects/blob/show.html.haml
@@ -1,5 +1,4 @@
- page_title @blob.path, @ref
-= render "header_title"
= render 'projects/last_push'
diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml
index ac7790421a4..08148b1a18b 100644
--- a/app/views/projects/branches/index.html.haml
+++ b/app/views/projects/branches/index.html.haml
@@ -1,5 +1,4 @@
- page_title "Branches"
-= render "projects/commits/header_title"
= render "projects/commits/head"
.row-content-block
.pull-right
diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml
index c659af6338c..5a6c8c243fa 100644
--- a/app/views/projects/branches/new.html.haml
+++ b/app/views/projects/branches/new.html.haml
@@ -1,5 +1,4 @@
- page_title "New Branch"
-= render "projects/commits/header_title"
- if @error
.alert.alert-danger
diff --git a/app/views/projects/builds/_header_title.html.haml b/app/views/projects/builds/_header_title.html.haml
deleted file mode 100644
index 082dab1f5b0..00000000000
--- a/app/views/projects/builds/_header_title.html.haml
+++ /dev/null
@@ -1 +0,0 @@
-- header_title project_title(@project, "Builds", project_builds_path(@project))
diff --git a/app/views/projects/builds/index.html.haml b/app/views/projects/builds/index.html.haml
index 7c0bec264ab..8fb9ebc1b8b 100644
--- a/app/views/projects/builds/index.html.haml
+++ b/app/views/projects/builds/index.html.haml
@@ -1,5 +1,4 @@
- page_title "Builds"
-= render "header_title"
.top-area
%ul.nav-links
diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml
index c7b9c36a3ab..16017c994ba 100644
--- a/app/views/projects/builds/show.html.haml
+++ b/app/views/projects/builds/show.html.haml
@@ -1,5 +1,4 @@
- page_title "#{@build.name} (##{@build.id})", "Builds"
-= render "header_title"
- trace_with_state = @build.trace_with_state
.build-page
diff --git a/app/views/projects/ci/commits/_commit.html.haml b/app/views/projects/ci/commits/_commit.html.haml
index 5b6b940a0c4..5e3a4123a8e 100644
--- a/app/views/projects/ci/commits/_commit.html.haml
+++ b/app/views/projects/ci/commits/_commit.html.haml
@@ -63,9 +63,9 @@
%span #{build.name}
- if can?(current_user, :update_pipeline, @project)
- - if commit.retryable? && commit.builds.failed.any?
+ - if commit.retryable?
= link_to retry_namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: 'btn has-tooltip', title: "Retry", method: :post do
= icon("repeat")
- - if commit.active?
+ - if commit.cancelable?
= link_to cancel_namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: 'btn btn-remove has-tooltip', title: "Cancel", method: :post do
= icon("remove")
diff --git a/app/views/projects/commit/_ci_commit.html.haml b/app/views/projects/commit/_ci_commit.html.haml
index ce5c550b441..32ff4d30977 100644
--- a/app/views/projects/commit/_ci_commit.html.haml
+++ b/app/views/projects/commit/_ci_commit.html.haml
@@ -1,24 +1,24 @@
.row-content-block.build-content.middle-block
.pull-right
- - if can?(current_user, :update_pipeline, @project)
+ - if can?(current_user, :update_pipeline, ci_commit.project)
- if ci_commit.builds.latest.failed.any?(&:retryable?)
- = link_to "Retry failed", retry_namespace_project_pipeline_path(@project.namespace, @project, ci_commit.id), class: 'btn btn-grouped btn-primary', method: :post
+ = link_to "Retry failed", retry_namespace_project_pipeline_path(ci_commit.project.namespace, ci_commit.project, ci_commit.id), class: 'btn btn-grouped btn-primary', method: :post
- if ci_commit.builds.running_or_pending.any?
- = link_to "Cancel running", cancel_namespace_project_pipeline_path(@project.namespace, @project, ci_commit.id), data: { confirm: 'Are you sure?' }, class: 'btn btn-grouped btn-danger', method: :post
+ = link_to "Cancel running", cancel_namespace_project_pipeline_path(ci_commit.project.namespace, ci_commit.project, ci_commit.id), data: { confirm: 'Are you sure?' }, class: 'btn btn-grouped btn-danger', method: :post
.oneline.clearfix
- if defined?(pipeline_details) && pipeline_details
Pipeline
- = link_to "##{ci_commit.id}", namespace_project_pipeline_path(@project.namespace, @project, ci_commit.id), class: "monospace"
+ = link_to "##{ci_commit.id}", namespace_project_pipeline_path(ci_commit.project.namespace, ci_commit.project, ci_commit.id), class: "monospace"
with
= pluralize ci_commit.statuses.count(:id), "build"
- if ci_commit.ref
for
- = link_to ci_commit.ref, namespace_project_commits_path(@project.namespace, @project, ci_commit.ref), class: "monospace"
+ = link_to ci_commit.ref, namespace_project_commits_path(ci_commit.project.namespace, ci_commit.project, ci_commit.ref), class: "monospace"
- if defined?(link_to_commit) && link_to_commit
for commit
- = link_to ci_commit.short_sha, namespace_project_commit_path(@project.namespace, @project, ci_commit.sha), class: "monospace"
+ = link_to ci_commit.short_sha, namespace_project_commit_path(ci_commit.project.namespace, ci_commit.project, ci_commit.sha), class: "monospace"
- if ci_commit.duration
in
= time_interval_in_words ci_commit.duration
@@ -31,7 +31,7 @@
%li= error
You can also test your .gitlab-ci.yml in the #{link_to "Lint", ci_lint_path}
-- if @project.builds_enabled? && !ci_commit.ci_yaml_file
+- if ci_commit.project.builds_enabled? && !ci_commit.ci_yaml_file
.bs-callout.bs-callout-warning
\.gitlab-ci.yml not found in this commit
@@ -45,7 +45,7 @@
%th Tags
%th Duration
%th Finished at
- - if @project.build_coverage_enabled?
+ - if ci_commit.project.build_coverage_enabled?
%th Coverage
%th
- ci_commit.statuses.stages.each do |stage|
diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml
index be00383a3d7..6674d58417b 100644
--- a/app/views/projects/commit/_commit_box.html.haml
+++ b/app/views/projects/commit/_commit_box.html.haml
@@ -1,32 +1,35 @@
-.pull-right.commit-action-buttons
- %div
+.commit-info-row.commit-info-row-header
+ %span.hidden-xs Authored by
+ %strong
+ = commit_author_link(@commit, avatar: true, size: 24)
+ #{time_ago_with_tooltip(@commit.authored_date)}
+
+ .pull-right.commit-action-buttons
- if defined?(@notes_count) && @notes_count > 0
- %span.btn.disabled.btn-grouped
- %i.fa.fa-comment
+ %span.btn.disabled.btn-grouped.hidden-xs
+ = icon('comment')
= @notes_count
- .pull-left.btn-group
- %a.btn.btn-grouped.dropdown-toggle{ data: {toggle: :dropdown} }
- %i.fa.fa-download
- Download as
- %span.caret
- %ul.dropdown-menu
+ = link_to namespace_project_tree_path(@project.namespace, @project, @commit), class: "btn btn-grouped hidden-xs hidden-sm" do
+ Browse Files
+ .dropdown.inline
+ %a.btn.btn-default.dropdown-toggle{ data: { toggle: "dropdown" } }
+ %span.hidden-xs Options
+ %span.caret.commit-options-dropdown-caret
+ %ul.dropdown-menu.dropdown-menu-align-right
+ %li.visible-xs-block.visible-sm-block
+ = link_to namespace_project_tree_path(@project.namespace, @project, @commit) do
+ Browse Files
+ - unless @commit.has_been_reverted?(current_user)
+ %li.clearfix
+ = revert_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id), has_tooltip: false)
+ %li.clearfix
+ = cherry_pick_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id), has_tooltip: false)
+ %li.divider
+ %li.dropdown-header
+ Download
- unless @commit.parents.length > 1
%li= link_to "Email Patches", namespace_project_commit_path(@project.namespace, @project, @commit, format: :patch)
%li= link_to "Plain Diff", namespace_project_commit_path(@project.namespace, @project, @commit, format: :diff)
- = link_to namespace_project_tree_path(@project.namespace, @project, @commit), class: "btn btn-grouped" do
- = icon('files-o')
- Browse Files
- - unless @commit.has_been_reverted?(current_user)
- = revert_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id))
- = cherry_pick_commit_link(@commit, namespace_project_commit_path(@project.namespace, @project, @commit.id))
- %div
-
-%p
-.commit-info-row
- %span.light Authored by
- %strong
- = commit_author_link(@commit, avatar: true, size: 24)
- #{time_ago_with_tooltip(@commit.authored_date)}
- if @commit.different_committer?
.commit-info-row
@@ -36,8 +39,9 @@
#{time_ago_with_tooltip(@commit.committed_date)}
.commit-info-row
- %span.light Commit
- = link_to @commit.id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace"
+ %span.hidden-xs.hidden-sm Commit
+ = link_to @commit.id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace hidden-xs hidden-sm"
+ = link_to @commit.short_id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace visible-xs-inline visible-sm-inline"
= clipboard_button(clipboard_text: @commit.id)
%span.cgray= pluralize(@commit.parents.count, "parent")
- @commit.parents.each do |parent|
diff --git a/app/views/projects/commit/builds.html.haml b/app/views/projects/commit/builds.html.haml
index 7118a4846c6..2f051fb90e0 100644
--- a/app/views/projects/commit/builds.html.haml
+++ b/app/views/projects/commit/builds.html.haml
@@ -1,7 +1,7 @@
- page_title "Builds", "#{@commit.title} (#{@commit.short_id})", "Commits"
-= render "projects/commits/header_title"
+
.prepend-top-default
= render "commit_box"
-= render "ci_menu"
+= render "ci_menu"
= render "builds"
diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml
index e5e3d696035..401cb4f7e30 100644
--- a/app/views/projects/commit/show.html.haml
+++ b/app/views/projects/commit/show.html.haml
@@ -1,8 +1,6 @@
- page_title "#{@commit.title} (#{@commit.short_id})", "Commits"
- page_description @commit.description
-= render "projects/commits/header_title"
-
.prepend-top-default
= render "commit_box"
- if @commit.status
diff --git a/app/views/projects/commits/_header_title.html.haml b/app/views/projects/commits/_header_title.html.haml
deleted file mode 100644
index e4385893dd9..00000000000
--- a/app/views/projects/commits/_header_title.html.haml
+++ /dev/null
@@ -1 +0,0 @@
-- header_title project_title(@project, "Commits", project_commits_path(@project))
diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml
index 088eaa28013..2c21923ed4f 100644
--- a/app/views/projects/commits/show.html.haml
+++ b/app/views/projects/commits/show.html.haml
@@ -1,5 +1,4 @@
- page_title "Commits", @ref
-= render "header_title"
= content_for :meta_tags do
- if current_user
= auto_discovery_link_tag(:atom, namespace_project_commits_url(@project.namespace, @project, @ref, format: :atom, private_token: current_user.private_token), title: "#{@project.name}:#{@ref} commits")
diff --git a/app/views/projects/compare/index.html.haml b/app/views/projects/compare/index.html.haml
index 5e188dd0f3c..0b8ed23b305 100644
--- a/app/views/projects/compare/index.html.haml
+++ b/app/views/projects/compare/index.html.haml
@@ -1,5 +1,4 @@
- page_title "Compare"
-= render "projects/commits/header_title"
= render "projects/commits/head"
.row-content-block
diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml
index 62525168239..cdc34f51d6d 100644
--- a/app/views/projects/compare/show.html.haml
+++ b/app/views/projects/compare/show.html.haml
@@ -1,5 +1,4 @@
- page_title "#{params[:from]}...#{params[:to]}"
-= render "projects/commits/header_title"
= render "projects/commits/head"
diff --git a/app/views/projects/container_registry/_header_title.html.haml b/app/views/projects/container_registry/_header_title.html.haml
deleted file mode 100644
index f1863c52a3e..00000000000
--- a/app/views/projects/container_registry/_header_title.html.haml
+++ /dev/null
@@ -1 +0,0 @@
-- header_title project_title(@project, "Container Registry", project_container_registry_path(@project))
diff --git a/app/views/projects/container_registry/index.html.haml b/app/views/projects/container_registry/index.html.haml
index e1e762410f2..993da27310f 100644
--- a/app/views/projects/container_registry/index.html.haml
+++ b/app/views/projects/container_registry/index.html.haml
@@ -1,5 +1,4 @@
- page_title "Container Registry"
-= render "header_title"
%hr
@@ -37,4 +36,4 @@
%th
- @tags.each do |tag|
- = render 'tag', tag: tag \ No newline at end of file
+ = render 'tag', tag: tag
diff --git a/app/views/projects/find_file/show.html.haml b/app/views/projects/find_file/show.html.haml
index 1fe1d98bf13..9322c82904f 100644
--- a/app/views/projects/find_file/show.html.haml
+++ b/app/views/projects/find_file/show.html.haml
@@ -1,5 +1,4 @@
- page_title "Find File", @ref
-- header_title project_title(@project, "Files", project_files_path(@project))
.file-finder-holder.tree-holder.clearfix
.nav-block
diff --git a/app/views/projects/graphs/_header_title.html.haml b/app/views/projects/graphs/_header_title.html.haml
deleted file mode 100644
index 1e2f61cd22b..00000000000
--- a/app/views/projects/graphs/_header_title.html.haml
+++ /dev/null
@@ -1 +0,0 @@
-- header_title project_title(@project, "Graphs", namespace_project_graph_path(@project.namespace, @project, current_ref))
diff --git a/app/views/projects/graphs/ci.html.haml b/app/views/projects/graphs/ci.html.haml
index 9f05be9982b..19ccc125ea8 100644
--- a/app/views/projects/graphs/ci.html.haml
+++ b/app/views/projects/graphs/ci.html.haml
@@ -1,5 +1,4 @@
- page_title "Continuous Integration", "Graphs"
-= render "header_title"
= render 'head'
.row-content-block.append-bottom-default
.oneline
diff --git a/app/views/projects/graphs/commits.html.haml b/app/views/projects/graphs/commits.html.haml
index da9f648cc9c..d9b2fb6c065 100644
--- a/app/views/projects/graphs/commits.html.haml
+++ b/app/views/projects/graphs/commits.html.haml
@@ -1,5 +1,4 @@
- page_title "Commits", "Graphs"
-= render "header_title"
= render 'head'
.row-content-block.append-bottom-default
diff --git a/app/views/projects/graphs/languages.html.haml b/app/views/projects/graphs/languages.html.haml
index ebecab1dbfc..249c16f4709 100644
--- a/app/views/projects/graphs/languages.html.haml
+++ b/app/views/projects/graphs/languages.html.haml
@@ -1,5 +1,4 @@
- page_title "Languages", "Graphs"
-= render "header_title"
= render 'head'
.row-content-block.append-bottom-default
diff --git a/app/views/projects/graphs/show.html.haml b/app/views/projects/graphs/show.html.haml
index f82c47301f4..33970e7b909 100644
--- a/app/views/projects/graphs/show.html.haml
+++ b/app/views/projects/graphs/show.html.haml
@@ -1,5 +1,4 @@
- page_title "Contributors", "Graphs"
-= render "header_title"
= render 'head'
.row-content-block.append-bottom-default
diff --git a/app/views/projects/hooks/_project_hook.html.haml b/app/views/projects/hooks/_project_hook.html.haml
index 62eba5888a4..8151187d499 100644
--- a/app/views/projects/hooks/_project_hook.html.haml
+++ b/app/views/projects/hooks/_project_hook.html.haml
@@ -3,7 +3,7 @@
.col-md-8.col-lg-7
%strong.light-header= hook.url
%div
- - %w(push_events tag_push_events issues_events note_events merge_requests_events build_events).each do |trigger|
+ - %w(push_events tag_push_events issues_events note_events merge_requests_events build_events wiki_page_events).each do |trigger|
- if hook.send(trigger)
%span.label.label-gray.deploy-project-label= trigger.titleize
.col-md-4.col-lg-5.text-right-lg.prepend-top-5
diff --git a/app/views/projects/hooks/index.html.haml b/app/views/projects/hooks/index.html.haml
index cffe9a01a96..917a0b805b1 100644
--- a/app/views/projects/hooks/index.html.haml
+++ b/app/views/projects/hooks/index.html.haml
@@ -64,6 +64,13 @@
Build events
%p.light
This url will be triggered when the build status changes
+ %div
+ = f.check_box :wiki_page_events, class: 'pull-left'
+ .prepend-left-20
+ = f.label :wiki_page_events, class: 'label-light append-bottom-0' do
+ Wiki Page events
+ %p.light
+ This url will be triggered when a wiki page is created/updated
.form-group
= f.label :enable_ssl_verification, "SSL verification", class: "label-light"
%div
diff --git a/app/views/projects/issues/_header_title.html.haml b/app/views/projects/issues/_header_title.html.haml
deleted file mode 100644
index 99f03549c44..00000000000
--- a/app/views/projects/issues/_header_title.html.haml
+++ /dev/null
@@ -1 +0,0 @@
-- header_title project_title(@project, "Issues", namespace_project_issues_path(@project.namespace, @project))
diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml
index 5cf70ea3bb7..78f64150601 100644
--- a/app/views/projects/issues/_issue.html.haml
+++ b/app/views/projects/issues/_issue.html.haml
@@ -6,7 +6,7 @@
.issue-title.title
%span.issue-title-text
= confidential_icon(issue)
- = link_to_gfm issue.title, issue_path(issue)
+ = link_to issue.title, issue_path(issue)
%ul.controls
- if issue.closed?
%li
diff --git a/app/views/projects/issues/edit.html.haml b/app/views/projects/issues/edit.html.haml
index 20216297d25..7cf1923456e 100644
--- a/app/views/projects/issues/edit.html.haml
+++ b/app/views/projects/issues/edit.html.haml
@@ -1,5 +1,4 @@
- page_title "Edit", "#{@issue.title} (##{@issue.iid})", "Issues"
-= render "header_title"
%h3.page-title
Edit Issue ##{@issue.iid}
diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml
index efa7642b2dc..19a6f4a91f6 100644
--- a/app/views/projects/issues/index.html.haml
+++ b/app/views/projects/issues/index.html.haml
@@ -1,5 +1,4 @@
- page_title "Issues"
-= render "header_title"
= content_for :meta_tags do
- if current_user
diff --git a/app/views/projects/issues/new.html.haml b/app/views/projects/issues/new.html.haml
index b317a0c1cf4..e8aae0f47e2 100644
--- a/app/views/projects/issues/new.html.haml
+++ b/app/views/projects/issues/new.html.haml
@@ -1,5 +1,4 @@
- page_title "New Issue"
-= render "header_title"
%h3.page-title
New Issue
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index 4634702dea8..f3b0469b7d4 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -1,7 +1,6 @@
- page_title "#{@issue.title} (##{@issue.iid})", "Issues"
- page_description @issue.description
- page_card_attributes @issue.card_attributes
-- header_title project_title(@project, "Issues", namespace_project_issues_path(@project.namespace, @project))
.clearfix.detail-page-header
.issuable-header
diff --git a/app/views/projects/labels/_header_title.html.haml b/app/views/projects/labels/_header_title.html.haml
deleted file mode 100644
index abe28da483b..00000000000
--- a/app/views/projects/labels/_header_title.html.haml
+++ /dev/null
@@ -1 +0,0 @@
-- header_title project_title(@project, "Labels", namespace_project_labels_path(@project.namespace, @project))
diff --git a/app/views/projects/labels/edit.html.haml b/app/views/projects/labels/edit.html.haml
index 675a805e12f..6901ba13ab7 100644
--- a/app/views/projects/labels/edit.html.haml
+++ b/app/views/projects/labels/edit.html.haml
@@ -1,5 +1,4 @@
- page_title "Edit", @label.name, "Labels"
-= render "header_title"
%h3.page-title
Edit Label
diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml
index 05382b9cee7..2557d1a4d5b 100644
--- a/app/views/projects/labels/index.html.haml
+++ b/app/views/projects/labels/index.html.haml
@@ -1,5 +1,4 @@
- page_title "Labels"
-= render "header_title"
.top-area
.nav-text
diff --git a/app/views/projects/labels/new.html.haml b/app/views/projects/labels/new.html.haml
index e20fd7d6891..49ddf901619 100644
--- a/app/views/projects/labels/new.html.haml
+++ b/app/views/projects/labels/new.html.haml
@@ -1,5 +1,4 @@
- page_title "New Label"
-= render "header_title"
%h3.page-title
New Label
diff --git a/app/views/projects/merge_requests/_header_title.html.haml b/app/views/projects/merge_requests/_header_title.html.haml
deleted file mode 100644
index 669a9b06bdf..00000000000
--- a/app/views/projects/merge_requests/_header_title.html.haml
+++ /dev/null
@@ -1 +0,0 @@
-- header_title project_title(@project, "Merge Requests", namespace_project_merge_requests_path(@project.namespace, @project))
diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml
index 2c54171c6bd..c02f94490a0 100644
--- a/app/views/projects/merge_requests/_merge_request.html.haml
+++ b/app/views/projects/merge_requests/_merge_request.html.haml
@@ -1,7 +1,7 @@
%li{ class: mr_css_classes(merge_request) }
.merge-request-title.title
%span.merge-request-title-text
- = link_to_gfm merge_request.title, merge_request_path(merge_request)
+ = link_to merge_request.title, merge_request_path(merge_request)
%ul.controls
- if merge_request.merged?
%li
diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml
index 290753d57c6..7af227129ec 100644
--- a/app/views/projects/merge_requests/_show.html.haml
+++ b/app/views/projects/merge_requests/_show.html.haml
@@ -1,7 +1,6 @@
- page_title "#{@merge_request.title} (#{@merge_request.to_reference})", "Merge Requests"
- page_description @merge_request.description
- page_card_attributes @merge_request.card_attributes
-- header_title project_title(@project, "Merge Requests", namespace_project_merge_requests_path(@project.namespace, @project))
- if diff_view == 'parallel'
- fluid_layout true
diff --git a/app/views/projects/merge_requests/edit.html.haml b/app/views/projects/merge_requests/edit.html.haml
index b31ea5e5321..03159f123f3 100644
--- a/app/views/projects/merge_requests/edit.html.haml
+++ b/app/views/projects/merge_requests/edit.html.haml
@@ -1,5 +1,4 @@
- page_title "Edit", "#{@merge_request.title} (#{@merge_request.to_reference}", "Merge Requests"
-= render "header_title"
%h3.page-title
Edit Merge Request #{@merge_request.to_reference}
diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml
index e56a44e0a79..b517e874b0f 100644
--- a/app/views/projects/merge_requests/index.html.haml
+++ b/app/views/projects/merge_requests/index.html.haml
@@ -1,5 +1,4 @@
- page_title "Merge Requests"
-= render "header_title"
= render 'projects/last_push'
diff --git a/app/views/projects/merge_requests/invalid.html.haml b/app/views/projects/merge_requests/invalid.html.haml
index f5bf16ef3ad..a00d3128ffe 100644
--- a/app/views/projects/merge_requests/invalid.html.haml
+++ b/app/views/projects/merge_requests/invalid.html.haml
@@ -1,5 +1,4 @@
- page_title "#{@merge_request.title} (#{@merge_request.to_reference}", "Merge Requests"
-= render "header_title"
.merge-request
= render "projects/merge_requests/show/mr_title"
diff --git a/app/views/projects/merge_requests/new.html.haml b/app/views/projects/merge_requests/new.html.haml
index d259968030e..2e798ce780a 100644
--- a/app/views/projects/merge_requests/new.html.haml
+++ b/app/views/projects/merge_requests/new.html.haml
@@ -1,5 +1,4 @@
- page_title "New Merge Request"
-= render "header_title"
- if @merge_request.can_be_created && !params[:change_branches]
= render 'new_submit'
diff --git a/app/views/projects/merge_requests/widget/_show.html.haml b/app/views/projects/merge_requests/widget/_show.html.haml
index 3c68d61c4b5..b79508bdc34 100644
--- a/app/views/projects/merge_requests/widget/_show.html.haml
+++ b/app/views/projects/merge_requests/widget/_show.html.haml
@@ -13,7 +13,7 @@
check_enable: #{@merge_request.unchecked? ? "true" : "false"},
ci_status_url: "#{ci_status_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}",
gitlab_icon: "#{asset_path 'gitlab_logo.png'}",
- ci_status: "",
+ ci_status: "#{@merge_request.ci_commit ? @merge_request.ci_commit.status : ''}",
ci_message: {
normal: "Build {{status}} for \"{{title}}\"",
preparing: "{{status}} build for \"{{title}}\""
@@ -26,4 +26,10 @@
builds_path: "#{builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}"
};
+ if (typeof merge_request_widget !== 'undefined') {
+ clearInterval(merge_request_widget.fetchBuildStatusInterval);
+ merge_request_widget.cancelPolling();
+ merge_request_widget.clearEventListeners();
+ }
+
merge_request_widget = new MergeRequestWidget(opts);
diff --git a/app/views/projects/milestones/_header_title.html.haml b/app/views/projects/milestones/_header_title.html.haml
deleted file mode 100644
index 5f4b6982a6d..00000000000
--- a/app/views/projects/milestones/_header_title.html.haml
+++ /dev/null
@@ -1 +0,0 @@
-- header_title project_title(@project, "Milestones", namespace_project_milestones_path(@project.namespace, @project))
diff --git a/app/views/projects/milestones/edit.html.haml b/app/views/projects/milestones/edit.html.haml
index 43f8863163d..be682226ab6 100644
--- a/app/views/projects/milestones/edit.html.haml
+++ b/app/views/projects/milestones/edit.html.haml
@@ -1,5 +1,4 @@
- page_title "Edit", @milestone.title, "Milestones"
-= render "header_title"
%h3.page-title
Edit Milestone ##{@milestone.iid}
diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml
index abe567af1dd..e6133b22f96 100644
--- a/app/views/projects/milestones/index.html.haml
+++ b/app/views/projects/milestones/index.html.haml
@@ -1,6 +1,4 @@
- page_title "Milestones"
-= render "header_title"
-
.top-area
= render 'shared/milestones_filter'
diff --git a/app/views/projects/milestones/new.html.haml b/app/views/projects/milestones/new.html.haml
index 0d016f78313..7f372b41698 100644
--- a/app/views/projects/milestones/new.html.haml
+++ b/app/views/projects/milestones/new.html.haml
@@ -1,5 +1,4 @@
- page_title "New Milestone"
-= render "header_title"
%h3.page-title
New Milestone
diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml
index 6ec84660157..19944e3e023 100644
--- a/app/views/projects/milestones/show.html.haml
+++ b/app/views/projects/milestones/show.html.haml
@@ -1,8 +1,6 @@
- page_title @milestone.title, "Milestones"
- page_description @milestone.description
-= render "header_title"
-
.detail-page-header
.status-box{ class: status_box_class(@milestone) }
- if @milestone.closed?
diff --git a/app/views/projects/network/show.html.haml b/app/views/projects/network/show.html.haml
index 8065663ca2a..326180ebe4e 100644
--- a/app/views/projects/network/show.html.haml
+++ b/app/views/projects/network/show.html.haml
@@ -1,5 +1,4 @@
- page_title "Network", @ref
-= render "projects/commits/header_title"
= render "projects/commits/head"
= render "head"
.project-network
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index a4c6094c69a..f9ac16b32f3 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -1,5 +1,5 @@
- page_title 'New Project'
-- header_title "Projects", root_path
+- header_title "Projects", dashboard_projects_path
%h3.page-title
New Project
diff --git a/app/views/projects/pipelines/_header_title.html.haml b/app/views/projects/pipelines/_header_title.html.haml
deleted file mode 100644
index faf63d64a79..00000000000
--- a/app/views/projects/pipelines/_header_title.html.haml
+++ /dev/null
@@ -1 +0,0 @@
-- header_title project_title(@project, "Pipelines", project_pipelines_path(@project))
diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml
index a6c12814adf..8788db09dbe 100644
--- a/app/views/projects/pipelines/index.html.haml
+++ b/app/views/projects/pipelines/index.html.haml
@@ -1,5 +1,4 @@
- page_title "Pipelines"
-= render "header_title"
.top-area
%ul.nav-links
diff --git a/app/views/projects/pipelines/new.html.haml b/app/views/projects/pipelines/new.html.haml
index b97c9f5f3b6..5f4ec2e40c8 100644
--- a/app/views/projects/pipelines/new.html.haml
+++ b/app/views/projects/pipelines/new.html.haml
@@ -1,5 +1,4 @@
- page_title "New Pipeline"
-= render "header_title"
%h3.page-title
New Pipeline
diff --git a/app/views/projects/pipelines/show.html.haml b/app/views/projects/pipelines/show.html.haml
index b082d4d5da8..2aad5602414 100644
--- a/app/views/projects/pipelines/show.html.haml
+++ b/app/views/projects/pipelines/show.html.haml
@@ -1,6 +1,5 @@
- page_title "Pipeline"
-= render "header_title"
.prepend-top-default
- if @commit
= render "projects/pipelines/info"
diff --git a/app/views/projects/project_members/_header_title.html.haml b/app/views/projects/project_members/_header_title.html.haml
deleted file mode 100644
index a31f0a37fa2..00000000000
--- a/app/views/projects/project_members/_header_title.html.haml
+++ /dev/null
@@ -1 +0,0 @@
-- header_title project_title(@project, "Members", namespace_project_project_members_path(@project.namespace, @project))
diff --git a/app/views/projects/project_members/import.html.haml b/app/views/projects/project_members/import.html.haml
index 189906498cb..eef97107d77 100644
--- a/app/views/projects/project_members/import.html.haml
+++ b/app/views/projects/project_members/import.html.haml
@@ -1,5 +1,4 @@
- page_title "Import members"
-= render "header_title"
%h3.page-title
Import members from another project
diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml
index ebcfc907ebb..15dc064e7ea 100644
--- a/app/views/projects/project_members/index.html.haml
+++ b/app/views/projects/project_members/index.html.haml
@@ -1,5 +1,4 @@
- page_title "Members"
-= render "header_title"
.project-members-page.prepend-top-default
- if can?(current_user, :admin_project_member, @project)
diff --git a/app/views/projects/releases/edit.html.haml b/app/views/projects/releases/edit.html.haml
index 0d59cec322c..835398b6f98 100644
--- a/app/views/projects/releases/edit.html.haml
+++ b/app/views/projects/releases/edit.html.haml
@@ -1,5 +1,4 @@
- page_title "Edit", @tag.name, "Tags"
-= render "projects/commits/header_title"
= render "projects/commits/head"
.row-content-block
diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml
index 1b70880043a..1f13ea28b4e 100644
--- a/app/views/projects/services/_form.html.haml
+++ b/app/views/projects/services/_form.html.haml
@@ -1,18 +1,16 @@
-%h3.page-title
- = @service.title
- = boolean_to_icon @service.activated?
+.row.prepend-top-default.append-bottom-default
+ .col-lg-3
+ %h4.prepend-top-0
+ = @service.title
+ = boolean_to_icon @service.activated?
-%p= @service.description
-
-%hr
-
-= form_for(@service, as: :service, url: namespace_project_service_path(@project.namespace, @project, @service.to_param), method: :put, html: { class: 'form-horizontal' }) do |form|
- = render 'shared/service_settings', form: form
-
- .form-actions
- = form.submit 'Save changes', class: 'btn btn-save'
- &nbsp;
- - if @service.valid? && @service.activated?
- - disabled = @service.can_test? ? '':'disabled'
- = link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service.to_param), class: "btn #{disabled}"
- = link_to "Cancel", namespace_project_services_path(@project.namespace, @project), class: "btn btn-cancel"
+ %p= @service.description
+ .col-lg-9
+ = form_for(@service, as: :service, url: namespace_project_service_path(@project.namespace, @project, @service.to_param), method: :put, html: { class: 'form-horizontal' }) do |form|
+ = render 'shared/service_settings', form: form
+ = form.submit 'Save changes', class: 'btn btn-save'
+ &nbsp;
+ - if @service.valid? && @service.activated?
+ - disabled = @service.can_test? ? '':'disabled'
+ = link_to 'Test settings', test_namespace_project_service_path(@project.namespace, @project, @service.to_param), class: "btn #{disabled}"
+ = link_to "Cancel", namespace_project_services_path(@project.namespace, @project), class: "btn btn-cancel"
diff --git a/app/views/projects/services/index.html.haml b/app/views/projects/services/index.html.haml
index c1356f6db02..4a33a5bc6f6 100644
--- a/app/views/projects/services/index.html.haml
+++ b/app/views/projects/services/index.html.haml
@@ -1,24 +1,32 @@
- page_title "Services"
-%h3.page-title Project services
-%p.light Project services allow you to integrate GitLab with other applications
-.table-holder
- %table.table
- %thead
- %tr
- %th
- %th Service
- %th Description
- %th Last edit
- - @services.sort_by(&:title).each do |service|
- %tr
- %td
- = boolean_to_icon service.activated?
- %td
- = link_to edit_namespace_project_service_path(@project.namespace, @project, service.to_param) do
- %strong= service.title
- %td
- = service.description
- %td.light
- = time_ago_in_words service.updated_at
- ago
+.row.prepend-top-default.append-bottom-default
+ .col-lg-3
+ %h4.prepend-top-0
+ Project services
+ %p Project services allow you to integrate GitLab with other applications
+ .col-lg-9
+ %table.table
+ %colgroup
+ %col
+ %col
+ %col.hidden-xs
+ %col{ width: "120" }
+ %thead
+ %tr
+ %th
+ %th Service
+ %th.hidden-xs Description
+ %th Last edit
+ - @services.sort_by(&:title).each do |service|
+ %tr
+ %td
+ = boolean_to_icon service.activated?
+ %td
+ = link_to edit_namespace_project_service_path(@project.namespace, @project, service.to_param) do
+ %strong= service.title
+ %td.hidden-xs
+ = service.description
+ %td.light
+ = time_ago_in_words service.updated_at
+ ago
diff --git a/app/views/projects/snippets/_header_title.html.haml b/app/views/projects/snippets/_header_title.html.haml
deleted file mode 100644
index 04f0bbe9853..00000000000
--- a/app/views/projects/snippets/_header_title.html.haml
+++ /dev/null
@@ -1 +0,0 @@
-- header_title project_title(@project, "Snippets", namespace_project_snippets_path(@project.namespace, @project))
diff --git a/app/views/projects/snippets/edit.html.haml b/app/views/projects/snippets/edit.html.haml
index dc3ea1fcf12..216f70f5605 100644
--- a/app/views/projects/snippets/edit.html.haml
+++ b/app/views/projects/snippets/edit.html.haml
@@ -1,5 +1,4 @@
- page_title "Edit", @snippet.title, "Snippets"
-= render "header_title"
%h3.page-title
Edit Snippet
diff --git a/app/views/projects/snippets/index.html.haml b/app/views/projects/snippets/index.html.haml
index 103ff447464..96fee3b17b2 100644
--- a/app/views/projects/snippets/index.html.haml
+++ b/app/views/projects/snippets/index.html.haml
@@ -1,5 +1,4 @@
- page_title "Snippets"
-= render "header_title"
.row-content-block.top-block
.pull-right
diff --git a/app/views/projects/snippets/new.html.haml b/app/views/projects/snippets/new.html.haml
index e57237991b4..772a594269c 100644
--- a/app/views/projects/snippets/new.html.haml
+++ b/app/views/projects/snippets/new.html.haml
@@ -1,5 +1,4 @@
- page_title "New Snippets"
-= render "header_title"
%h3.page-title
New Snippet
diff --git a/app/views/projects/snippets/show.html.haml b/app/views/projects/snippets/show.html.haml
index 6f7bdcb29e8..bae4d8f349f 100644
--- a/app/views/projects/snippets/show.html.haml
+++ b/app/views/projects/snippets/show.html.haml
@@ -1,5 +1,4 @@
- page_title @snippet.title, "Snippets"
-= render "header_title"
.snippet-holder
= render 'shared/snippets/header'
diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml
index dc6ece30dd2..8f381663e6e 100644
--- a/app/views/projects/tags/index.html.haml
+++ b/app/views/projects/tags/index.html.haml
@@ -1,5 +1,4 @@
- page_title "Tags"
-= render "projects/commits/header_title"
= render "projects/commits/head"
.row-content-block
diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml
index f9306453297..3a097750d6e 100644
--- a/app/views/projects/tags/new.html.haml
+++ b/app/views/projects/tags/new.html.haml
@@ -1,5 +1,4 @@
- page_title "New Tag"
-= render "projects/commits/header_title"
- if @error
.alert.alert-danger
diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml
index 9f1424aecc7..b7d7d5c5382 100644
--- a/app/views/projects/tags/show.html.haml
+++ b/app/views/projects/tags/show.html.haml
@@ -1,5 +1,4 @@
- page_title @tag.name, "Tags"
-= render "projects/commits/header_title"
= render "projects/commits/head"
.row-content-block
diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml
index 91fb2a44594..7e9ba09c720 100644
--- a/app/views/projects/tree/show.html.haml
+++ b/app/views/projects/tree/show.html.haml
@@ -1,5 +1,4 @@
- page_title @path.presence || "Files", @ref
-- header_title project_title(@project, "Files", project_files_path(@project))
= content_for :meta_tags do
- if current_user
= auto_discovery_link_tag(:atom, namespace_project_commits_url(@project.namespace, @project, @ref, format: :atom, private_token: current_user.private_token), title: "#{@project.name}:#{@ref} commits")
diff --git a/app/views/projects/wikis/_header_title.html.haml b/app/views/projects/wikis/_header_title.html.haml
deleted file mode 100644
index 408adc36ca6..00000000000
--- a/app/views/projects/wikis/_header_title.html.haml
+++ /dev/null
@@ -1 +0,0 @@
-- header_title project_title(@project, 'Wiki', get_project_wiki_path(@project))
diff --git a/app/views/projects/wikis/edit.html.haml b/app/views/projects/wikis/edit.html.haml
index 4dd818c7f67..aaa15dd3bbe 100644
--- a/app/views/projects/wikis/edit.html.haml
+++ b/app/views/projects/wikis/edit.html.haml
@@ -1,5 +1,4 @@
- page_title "Edit", @page.title.capitalize, "Wiki"
-= render "header_title"
= render 'nav'
.top-area
diff --git a/app/views/projects/wikis/empty.html.haml b/app/views/projects/wikis/empty.html.haml
index c7e490c3cd1..7dfa405d063 100644
--- a/app/views/projects/wikis/empty.html.haml
+++ b/app/views/projects/wikis/empty.html.haml
@@ -1,5 +1,4 @@
- page_title "Wiki"
-= render "header_title"
%h3.page-title Empty page
%hr
diff --git a/app/views/projects/wikis/git_access.html.haml b/app/views/projects/wikis/git_access.html.haml
index ba3f2cadc48..ccceab6155e 100644
--- a/app/views/projects/wikis/git_access.html.haml
+++ b/app/views/projects/wikis/git_access.html.haml
@@ -1,5 +1,4 @@
- page_title "Git Access", "Wiki"
-= render "header_title"
= render 'nav'
.row-content-block
diff --git a/app/views/projects/wikis/history.html.haml b/app/views/projects/wikis/history.html.haml
index dcaddae2b04..45460ed9f41 100644
--- a/app/views/projects/wikis/history.html.haml
+++ b/app/views/projects/wikis/history.html.haml
@@ -1,5 +1,4 @@
- page_title "History", @page.title.capitalize, "Wiki"
-= render "header_title"
= render 'nav'
.top-area
diff --git a/app/views/projects/wikis/pages.html.haml b/app/views/projects/wikis/pages.html.haml
index 92b494a513c..2f6162fa3c5 100644
--- a/app/views/projects/wikis/pages.html.haml
+++ b/app/views/projects/wikis/pages.html.haml
@@ -1,5 +1,4 @@
- page_title "Pages", "Wiki"
-= render "header_title"
= render 'nav'
diff --git a/app/views/projects/wikis/show.html.haml b/app/views/projects/wikis/show.html.haml
index 067fb7f8f54..1cb48a1e85d 100644
--- a/app/views/projects/wikis/show.html.haml
+++ b/app/views/projects/wikis/show.html.haml
@@ -1,5 +1,4 @@
- page_title @page.title.capitalize, "Wiki"
-= render "header_title"
= render 'nav'
.top-area
diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml
index 323d563cd4a..cedff4af2e0 100644
--- a/app/views/shared/issuable/_filter.html.haml
+++ b/app/views/shared/issuable/_filter.html.haml
@@ -12,7 +12,7 @@
- if params[:author_id].present?
= hidden_field_tag(:author_id, params[:author_id])
= dropdown_tag(user_dropdown_label(params[:author_id], "Author"), options: { toggle_class: "js-user-search js-filter-submit js-author-search", title: "Filter by author", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-author js-filter-submit",
- placeholder: "Search authors", data: { any_user: "Any Author", first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), selected: params[:author_id], field_name: "author_id", default_label: "Author" } })
+ placeholder: "Search authors", data: { any_user: "Any Author", first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), selected: params[:author], field_name: "author_id", default_label: "Author" } })
.filter-item.inline
- if params[:assignee_id].present?
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index fc3410f425d..b430251dbf6 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -98,9 +98,7 @@
= label_tag :move_to_project_id, 'Move', class: 'control-label'
.col-sm-10
.issuable-form-select-holder
- - projects = project_options(issuable, current_user, ability: :admin_issue)
- = select_tag(:move_to_project_id, projects, include_blank: true,
- class: 'select2', data: { placeholder: 'Select project' })
+ = hidden_field_tag :move_to_project_id, nil, class: 'js-move-dropdown', data: { placeholder: 'Select project', projects_url: autocomplete_projects_path(project_id: @project.id) }
&nbsp;
%span{ data: { toggle: 'tooltip', placement: 'auto top' }, style: 'cursor: default',
title: 'Moving an issue will copy the discussion to a different project and close it here. All participants will be notified of the new location.' }
diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml
index 9ef021747a5..b8b66d08db8 100644
--- a/app/views/shared/projects/_project.html.haml
+++ b/app/views/shared/projects/_project.html.haml
@@ -12,9 +12,6 @@
%li.project-row{ class: css_class }
= cache(cache_key) do
.controls
- - if project.main_language
- %span
- = project.main_language
- if project.commit.try(:status)
%span
= render_commit_status(project.commit)
diff --git a/app/views/shared/snippets/_header.html.haml b/app/views/shared/snippets/_header.html.haml
index eef8340b216..af753496260 100644
--- a/app/views/shared/snippets/_header.html.haml
+++ b/app/views/shared/snippets/_header.html.haml
@@ -4,7 +4,7 @@
= visibility_level_label(@snippet.visibility_level)
= visibility_level_icon(@snippet.visibility_level, fw: false)
%strong.item-title
- Snippet ##{@snippet.id}
+ Snippet #{@snippet.to_reference}
%span.creator
created by #{link_to_member(@project, @snippet.author, size: 24, author_class: "author item-title")}
= time_ago_with_tooltip(@snippet.created_at, placement: 'bottom', html_class: 'snippet_updated_ago')
diff --git a/app/workers/emails_on_push_worker.rb b/app/workers/emails_on_push_worker.rb
index fa959fc56e3..971f969e25e 100644
--- a/app/workers/emails_on_push_worker.rb
+++ b/app/workers/emails_on_push_worker.rb
@@ -1,6 +1,7 @@
class EmailsOnPushWorker
include Sidekiq::Worker
+ sidekiq_options queue: :mailers
attr_reader :email, :skip_premailer
def perform(project_id, recipients, push_data, options = {})
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 124d63ce3ac..436751b9d16 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -52,7 +52,7 @@ class Settings < Settingslogic
# check that values in `current` (string or integer) is a contant in `modul`.
def verify_constant_array(modul, current, default)
values = default || []
- if !current.nil?
+ unless current.nil?
values = []
current.each do |constant|
values.push(verify_constant(modul, constant, nil))
diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb
index 66ac88e9f4a..7bd13105045 100644
--- a/config/initializers/doorkeeper.rb
+++ b/config/initializers/doorkeeper.rb
@@ -52,7 +52,7 @@ Doorkeeper.configure do
# For more information go to
# https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes
default_scopes :api
- #optional_scopes :write, :update
+ # optional_scopes :write, :update
# Change the way client credentials are retrieved from the request object.
# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
@@ -71,7 +71,7 @@ Doorkeeper.configure do
# The value can be any string. Use nil to disable this feature. When disabled, clients must provide a valid URL
# (Similar behaviour: https://developers.google.com/accounts/docs/OAuth2InstalledApp#choosingredirecturi)
#
- native_redirect_uri nil#'urn:ietf:wg:oauth:2.0:oob'
+ native_redirect_uri nil # 'urn:ietf:wg:oauth:2.0:oob'
# Specify what grant flows are enabled in array of Strings. The valid
# strings and the flows they enable are:
diff --git a/config/initializers/metrics.rb b/config/initializers/metrics.rb
index 2338916e9da..0c788714714 100644
--- a/config/initializers/metrics.rb
+++ b/config/initializers/metrics.rb
@@ -12,6 +12,7 @@ if Gitlab::Metrics.enabled?
Gitlab::Application.configure do |config|
config.middleware.use(Gitlab::Metrics::RackMiddleware)
+ config.middleware.use(Gitlab::Middleware::RailsQueueDuration)
end
Sidekiq.configure_server do |config|
diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb
index 4c164119fff..26c30e523a7 100644
--- a/config/initializers/omniauth.rb
+++ b/config/initializers/omniauth.rb
@@ -13,7 +13,7 @@ end
OmniAuth.config.full_host = Settings.gitlab['base_url']
OmniAuth.config.allowed_request_methods = [:post]
-#In case of auto sign-in, the GET method is used (users don't get to click on a button)
+# In case of auto sign-in, the GET method is used (users don't get to click on a button)
OmniAuth.config.allowed_request_methods << :get if Gitlab.config.omniauth.auto_sign_in_with_provider.present?
OmniAuth.config.before_request_phase do |env|
OmniAuth::RequestForgeryProtection.call(env)
diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb
index 599dabb9e50..0d9d87bac00 100644
--- a/config/initializers/session_store.rb
+++ b/config/initializers/session_store.rb
@@ -23,6 +23,6 @@ else
secure: Gitlab.config.gitlab.https,
httponly: true,
expires_in: Settings.gitlab['session_expire_delay'] * 60,
- path: (Rails.application.config.relative_url_root.nil?) ? '/' : Gitlab::Application.config.relative_url_root
+ path: Rails.application.config.relative_url_root.nil? ? '/' : Gitlab::Application.config.relative_url_root
)
end
diff --git a/config/routes.rb b/config/routes.rb
index d8a2435b078..428302d0fd7 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -56,6 +56,7 @@ Rails.application.routes.draw do
# Autocomplete
get '/autocomplete/users' => 'autocomplete#users'
get '/autocomplete/users/:id' => 'autocomplete#user'
+ get '/autocomplete/projects' => 'autocomplete#projects'
# Emojis
resources :emojis, only: :index
@@ -420,7 +421,11 @@ Rails.application.routes.draw do
resources :projects, constraints: { id: /[^\/]+/ }, only: [:index, :new, :create]
- devise_for :users, controllers: { omniauth_callbacks: :omniauth_callbacks, registrations: :registrations , passwords: :passwords, sessions: :sessions, confirmations: :confirmations }
+ devise_for :users, controllers: { omniauth_callbacks: :omniauth_callbacks,
+ registrations: :registrations,
+ passwords: :passwords,
+ sessions: :sessions,
+ confirmations: :confirmations }
devise_scope :user do
get '/users/auth/:provider/omniauth_error' => 'omniauth_callbacks#omniauth_error', as: :omniauth_error
@@ -788,7 +793,7 @@ Rails.application.routes.draw do
end
# Get all keys of user
- get ':username.keys' => 'profiles/keys#get_keys' , constraints: { username: /.*/ }
+ get ':username.keys' => 'profiles/keys#get_keys', constraints: { username: /.*/ }
get ':id' => 'namespaces#show', constraints: { id: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }
end
diff --git a/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb b/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb
index 561c18a5776..6aed0fe03d2 100644
--- a/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb
+++ b/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb
@@ -28,7 +28,7 @@ class RemoveWrongImportUrlFromProjects < ActiveRecord::Migration
update_import_url(import_url, project)
update_import_data(import_url, project)
- rescue URI::InvalidURIError
+ rescue Addressable::URI::InvalidURIError
nullify_import_url(project)
end
end
diff --git a/db/migrate/20160525205328_remove_main_language_from_projects.rb b/db/migrate/20160525205328_remove_main_language_from_projects.rb
new file mode 100644
index 00000000000..0f9d60c385f
--- /dev/null
+++ b/db/migrate/20160525205328_remove_main_language_from_projects.rb
@@ -0,0 +1,21 @@
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class RemoveMainLanguageFromProjects < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ # When using the methods "add_concurrent_index" or "add_column_with_default"
+ # you must disable the use of transactions as these methods can not run in an
+ # existing transaction. When using "add_concurrent_index" make sure that this
+ # method is the _only_ method called in the migration, any other changes
+ # should go in a separate migration. This ensures that upon failure _only_ the
+ # index creation fails and can be retried or reverted easily.
+ #
+ # To disable transactions uncomment the following line and remove these
+ # comments:
+ # disable_ddl_transaction!
+
+ def change
+ remove_column :projects, :main_language
+ end
+end
diff --git a/db/migrate/20160527020117_remove_notification_settings_for_deleted_projects.rb b/db/migrate/20160527020117_remove_notification_settings_for_deleted_projects.rb
new file mode 100644
index 00000000000..7910120b4e0
--- /dev/null
+++ b/db/migrate/20160527020117_remove_notification_settings_for_deleted_projects.rb
@@ -0,0 +1,13 @@
+class RemoveNotificationSettingsForDeletedProjects < ActiveRecord::Migration
+ def up
+ execute <<-SQL
+ DELETE FROM notification_settings
+ WHERE notification_settings.source_type = 'Project'
+ AND NOT EXISTS (
+ SELECT *
+ FROM projects
+ WHERE projects.id = notification_settings.source_id
+ )
+ SQL
+ end
+end
diff --git a/db/migrate/20160528043124_add_users_state_index.rb b/db/migrate/20160528043124_add_users_state_index.rb
new file mode 100644
index 00000000000..e77a5460737
--- /dev/null
+++ b/db/migrate/20160528043124_add_users_state_index.rb
@@ -0,0 +1,9 @@
+class AddUsersStateIndex < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def change
+ add_concurrent_index :users, :state
+ end
+end
diff --git a/db/migrate/20160530150109_add_container_registry_token_expire_delay_to_application_settings.rb b/db/migrate/20160530150109_add_container_registry_token_expire_delay_to_application_settings.rb
new file mode 100644
index 00000000000..e21376bd571
--- /dev/null
+++ b/db/migrate/20160530150109_add_container_registry_token_expire_delay_to_application_settings.rb
@@ -0,0 +1,9 @@
+# This is ONLINE migration
+
+class AddContainerRegistryTokenExpireDelayToApplicationSettings < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ def change
+ add_column :application_settings, :container_registry_token_expire_delay, :integer, default: 5
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index aee5fb90937..b2af810f600 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20160516174813) do
+ActiveRecord::Schema.define(version: 20160530150109) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -43,46 +43,47 @@ ActiveRecord::Schema.define(version: 20160516174813) do
t.datetime "created_at"
t.datetime "updated_at"
t.string "home_page_url"
- t.integer "default_branch_protection", default: 2
+ t.integer "default_branch_protection", default: 2
t.text "restricted_visibility_levels"
- t.boolean "version_check_enabled", default: true
- t.integer "max_attachment_size", default: 10, null: false
+ t.boolean "version_check_enabled", default: true
+ t.integer "max_attachment_size", default: 10, null: false
t.integer "default_project_visibility"
t.integer "default_snippet_visibility"
t.text "restricted_signup_domains"
- t.boolean "user_oauth_applications", default: true
+ t.boolean "user_oauth_applications", default: true
t.string "after_sign_out_path"
- t.integer "session_expire_delay", default: 10080, null: false
+ t.integer "session_expire_delay", default: 10080, null: false
t.text "import_sources"
t.text "help_page_text"
t.string "admin_notification_email"
- t.boolean "shared_runners_enabled", default: true, null: false
- t.integer "max_artifacts_size", default: 100, null: false
+ t.boolean "shared_runners_enabled", default: true, null: false
+ t.integer "max_artifacts_size", default: 100, null: false
t.string "runners_registration_token"
- t.boolean "require_two_factor_authentication", default: false
- t.integer "two_factor_grace_period", default: 48
- t.boolean "metrics_enabled", default: false
- t.string "metrics_host", default: "localhost"
- t.integer "metrics_pool_size", default: 16
- t.integer "metrics_timeout", default: 10
- t.integer "metrics_method_call_threshold", default: 10
- t.boolean "recaptcha_enabled", default: false
+ t.boolean "require_two_factor_authentication", default: false
+ t.integer "two_factor_grace_period", default: 48
+ t.boolean "metrics_enabled", default: false
+ t.string "metrics_host", default: "localhost"
+ t.integer "metrics_pool_size", default: 16
+ t.integer "metrics_timeout", default: 10
+ t.integer "metrics_method_call_threshold", default: 10
+ t.boolean "recaptcha_enabled", default: false
t.string "recaptcha_site_key"
t.string "recaptcha_private_key"
- t.integer "metrics_port", default: 8089
- t.boolean "akismet_enabled", default: false
+ t.integer "metrics_port", default: 8089
+ t.boolean "akismet_enabled", default: false
t.string "akismet_api_key"
- t.integer "metrics_sample_interval", default: 15
- t.boolean "sentry_enabled", default: false
+ t.integer "metrics_sample_interval", default: 15
+ t.boolean "sentry_enabled", default: false
t.string "sentry_dsn"
- t.boolean "email_author_in_body", default: false
+ t.boolean "email_author_in_body", default: false
t.integer "default_group_visibility"
- t.boolean "repository_checks_enabled", default: false
+ t.boolean "repository_checks_enabled", default: false
t.text "shared_runners_text"
- t.integer "metrics_packet_size", default: 1
+ t.integer "metrics_packet_size", default: 1
t.text "disabled_oauth_sign_in_sources"
t.string "health_check_access_token"
- t.boolean "send_user_confirmation_email", default: false
+ t.boolean "send_user_confirmation_email", default: false
+ t.integer "container_registry_token_expire_delay", default: 5
end
create_table "audit_events", force: :cascade do |t|
@@ -760,7 +761,6 @@ ActiveRecord::Schema.define(version: 20160516174813) do
t.integer "build_timeout", default: 3600, null: false
t.boolean "pending_delete", default: false
t.boolean "public_builds", default: true, null: false
- t.string "main_language"
t.integer "pushes_since_gc", default: 0
t.boolean "last_repository_check_failed"
t.datetime "last_repository_check_at"
@@ -1001,6 +1001,7 @@ ActiveRecord::Schema.define(version: 20160516174813) do
add_index "users", ["name"], name: "index_users_on_name", using: :btree
add_index "users", ["name"], name: "index_users_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"}
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
+ add_index "users", ["state"], name: "index_users_on_state", using: :btree
add_index "users", ["username"], name: "index_users_on_username", using: :btree
add_index "users", ["username"], name: "index_users_on_username_trigram", using: :gin, opclasses: {"username"=>"gin_trgm_ops"}
diff --git a/doc/administration/repository_checks.md b/doc/administration/repository_checks.md
index 3411e4af6a7..4172b604cec 100644
--- a/doc/administration/repository_checks.md
+++ b/doc/administration/repository_checks.md
@@ -5,7 +5,7 @@ This feature was [introduced][ce-3232] in GitLab 8.7. It is OFF by
default because it still causes too many false alarms.
Git has a built-in mechanism, [git fsck][git-fsck], to verify the
-integrity of all data commited to a repository. GitLab administrators
+integrity of all data committed to a repository. GitLab administrators
can trigger such a check for a project via the project page under the
admin panel. The checks run asynchronously so it may take a few minutes
before the check result is visible on the project admin page. If the
@@ -41,4 +41,4 @@ alarms you can choose to clear ALL repository check states from the
---
[ce-3232]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3232 "Auto git fsck"
-[git-fsck]: https://www.kernel.org/pub/software/scm/git/docs/git-fsck.html "git fsck documentation" \ No newline at end of file
+[git-fsck]: https://www.kernel.org/pub/software/scm/git/docs/git-fsck.html "git fsck documentation"
diff --git a/doc/api/labels.md b/doc/api/labels.md
index b857d81768e..a181c0f57a2 100644
--- a/doc/api/labels.md
+++ b/doc/api/labels.md
@@ -39,7 +39,7 @@ Example response:
{
"name" : "critical",
"color" : "#d9534f",
- "description": "Criticalissue. Need fix ASAP",
+ "description": "Critical issue. Need fix ASAP",
"open_issues_count": 1,
"closed_issues_count": 3,
"open_merge_requests_count": 1
diff --git a/doc/api/services.md b/doc/api/services.md
index 83ac7845156..ccfc0fccb7f 100644
--- a/doc/api/services.md
+++ b/doc/api/services.md
@@ -16,8 +16,8 @@ PUT /projects/:id/services/asana
Parameters:
-- `api_key` (**required**) - User API token. User must have access to task,all comments will be attributed to this user.
-- `restrict_to_branch` (optional) - Comma-separated list of branches which will beautomatically inspected. Leave blank to include all branches.
+- `api_key` (**required**) - User API token. User must have access to task, all comments will be attributed to this user.
+- `restrict_to_branch` (optional) - Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches.
### Delete Asana service
@@ -503,6 +503,8 @@ Parameters:
- `project_url` (**required**) - Project url
- `issues_url` (**required**) - Issue url
- `description` (optional) - Jira issue tracker
+- `username` (optional) - Jira username
+- `password` (optional) - Jira password
### Delete JIRA service
diff --git a/doc/api/settings.md b/doc/api/settings.md
index 1e745115dc8..43a0fe35e42 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -37,7 +37,8 @@ Example response:
"created_at" : "2016-01-04T15:44:55.176Z",
"default_project_visibility" : 0,
"gravatar_enabled" : true,
- "sign_in_text" : null
+ "sign_in_text" : null,
+ "container_registry_token_expire_delay": 5
}
```
@@ -64,6 +65,7 @@ PUT /application/settings
| `restricted_signup_domains` | array of strings | no | Force people to use only corporate emails for sign-up. Default is null, meaning there is no restriction. |
| `user_oauth_applications` | boolean | no | Allow users to register any application to use GitLab as an OAuth provider |
| `after_sign_out_path` | string | no | Where to redirect users after logout |
+| `container_registry_token_expire_delay` | integer | no | Container Registry token duration in minutes |
```bash
curl -X PUT -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/application/settings?signup_enabled=false&default_project_visibility=1
@@ -90,6 +92,7 @@ Example response:
"default_snippet_visibility": 0,
"restricted_signup_domains": [],
"user_oauth_applications": true,
- "after_sign_out_path": ""
+ "after_sign_out_path": "",
+ "container_registry_token_expire_delay": 5
}
```
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 63866d8c71c..a3481f58c6c 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -348,7 +348,7 @@ job_name:
| allow_failure | no | Allow build to fail. Failed build doesn't contribute to commit status |
| when | no | Define when to run build. Can be `on_success`, `on_failure` or `always` |
| dependencies | no | Define other builds that a build depends on so that you can pass artifacts between them|
-| artifacts | no | Define list build artifacts |
+| artifacts | no | Define list of build artifacts |
| cache | no | Define list of files that should be cached between subsequent runs |
| before_script | no | Override a set of commands that are executed before build |
| after_script | no | Override a set of commands that are executed after build |
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index 1c13b094582..02e024ca15a 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -116,7 +116,7 @@ Example with Arel:
users = Arel::Table.new(:users)
users.group(users[:user_id]).having(users[:id].count.gt(5))
-#updtae other tables with this results
+#update other tables with these results
```
Example with plain SQL and `quote_string` helper:
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 108ceb593d0..1318b3d1fa5 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -394,7 +394,7 @@ GitLab Shell is an SSH access and repository management software developed speci
cd /home/git
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git
cd gitlab-workhorse
- sudo -u git -H git checkout v0.7.3
+ sudo -u git -H git checkout v0.7.4
sudo -u git -H make
### Initialize Database and Activate Advanced Features
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index df8e8bdc476..8cbd53cc27a 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -81,7 +81,7 @@ errors during usage.
- More users? Run it on [multiple application servers](https://about.gitlab.com/high-availability/)
We recommend having at least 1GB of swap on your server, even if you currently have
-enough available RAM. Having swap will help reduce the chance of errors occuring
+enough available RAM. Having swap will help reduce the chance of errors occurring
if your available memory changes.
Notice: The 25 workers of Sidekiq will show up as separate processes in your process overview (such as top or htop) but they share the same RAM allocation since Sidekiq is a multithreaded application. Please see the section below about Unicorn workers for information about many you need of those.
diff --git a/doc/logs/logs.md b/doc/logs/logs.md
index ef5affa2ebd..f84060b8d07 100644
--- a/doc/logs/logs.md
+++ b/doc/logs/logs.md
@@ -1,5 +1,5 @@
## Log system
-GitLab has advanced log system so everything is logging and you can analize your instance using various system log files.
+GitLab has an advanced log system where everything is logged so that you can analyze your instance using various system log files.
In addition to system log files, GitLab Enterprise Edition comes with Audit Events. Find more about them [in Audit Events documentation](http://docs.gitlab.com/ee/administration/audit_events.html)
System log files are typically plain text in a standard log file format. This guide talks about how to read and use these system log files.
@@ -67,13 +67,13 @@ gitlab-shell is using by Gitlab for executing git commands and provide ssh acces
```
I, [2015-02-13T06:17:00.671315 #9291] INFO -- : Adding project root/example.git at </var/opt/gitlab/git-data/repositories/root/dcdcdcdcd.git>.
-I, [2015-02-13T06:17:00.679433 #9291] INFO -- : Moving existing hooks directory and simlinking global hooks directory for /var/opt/gitlab/git-data/repositories/root/example.git.
+I, [2015-02-13T06:17:00.679433 #9291] INFO -- : Moving existing hooks directory and symlinking global hooks directory for /var/opt/gitlab/git-data/repositories/root/example.git.
```
#### unicorn_stderr.log
This file lives in `/var/log/gitlab/unicorn/unicorn_stderr.log` for omnibus package or in `/home/git/gitlab/log/unicorn_stderr.log` for installations from the source.
-Unicorn is a high-performance forking Web server which is used for serving GitLab application. You can look at this log, for example, if your application does not respond. This log cantains all information about state of unicorn processes at any given time.
+Unicorn is a high-performance forking Web server which is used for serving the GitLab application. You can look at this log if, for example, your application does not respond. This log contains all information about the state of unicorn processes at any given time.
```
I, [2015-02-13T06:14:46.680381 #9047] INFO -- : Refreshing Gem list
diff --git a/doc/migrate_ci_to_ce/README.md b/doc/migrate_ci_to_ce/README.md
index 5ec0a2069b5..8f9ef054949 100644
--- a/doc/migrate_ci_to_ce/README.md
+++ b/doc/migrate_ci_to_ce/README.md
@@ -355,7 +355,7 @@ sudo chown git:git /var/opt/gitlab/gitlab-ci/builds
```
#### Problems when importing CI database to GitLab
-If you were migrating CI database from MySQL to PostgreSQL manually you can see errros during import about missing sequences:
+If you were migrating CI database from MySQL to PostgreSQL manually you can see errors during import about missing sequences:
```
ALTER SEQUENCE
ERROR: relation "ci_builds_id_seq" does not exist
diff --git a/doc/operations/moving_repositories.md b/doc/operations/moving_repositories.md
index 39086b7a251..54adb99386a 100644
--- a/doc/operations/moving_repositories.md
+++ b/doc/operations/moving_repositories.md
@@ -134,7 +134,7 @@ sudo -u git sh -c '
cat /var/opt/gitlab/transfer-logs/* | sort | uniq -u |\
/usr/bin/env JOBS=10 \
/opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \
- /var/opt/gitlab/transfer-logs/succes-$(date +%s).log \
+ /var/opt/gitlab/transfer-logs/success-$(date +%s).log \
/var/opt/gitlab/git-data/repositories \
/mnt/gitlab/repositories
'
@@ -145,7 +145,7 @@ sudo -u git -H sh -c '
cat /home/git/transfer-logs/* | sort | uniq -u |\
/usr/bin/env JOBS=10 \
bin/parallel-rsync-repos \
- /home/git/transfer-logs/succes-$(date +%s).log \
+ /home/git/transfer-logs/success-$(date +%s).log \
/home/git/repositories \
/mnt/gitlab/repositories
`
@@ -164,7 +164,7 @@ sudo gitlab-rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\
sudo -u git \
/usr/bin/env JOBS=10 \
/opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \
- succes-$(date +%s).log \
+ success-$(date +%s).log \
/var/opt/gitlab/git-data/repositories \
/mnt/gitlab/repositories
@@ -174,7 +174,7 @@ sudo -u git -H bundle exec rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\
sudo -u git -H \
/usr/bin/env JOBS=10 \
bin/parallel-rsync-repos \
- succes-$(date +%s).log \
+ success-$(date +%s).log \
/home/git/repositories \
/mnt/gitlab/repositories
```
diff --git a/doc/update/8.6-to-8.7.md b/doc/update/8.6-to-8.7.md
index 4a2c6ea91d2..bb463d43a7c 100644
--- a/doc/update/8.6-to-8.7.md
+++ b/doc/update/8.6-to-8.7.md
@@ -86,6 +86,14 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS
### 7. Update configuration files
+#### New configuration options for `gitlab.yml`
+
+There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`:
+
+```sh
+git diff origin/8-6-stable:config/gitlab.yml.example origin/8-7-stable:config/gitlab.yml.example
+```
+
#### Git configuration
Disable `git gc --auto` because GitLab runs `git gc` for us already.
diff --git a/doc/update/8.7-to-8.8.md b/doc/update/8.7-to-8.8.md
index b4d9212289c..32906650f6f 100644
--- a/doc/update/8.7-to-8.8.md
+++ b/doc/update/8.7-to-8.8.md
@@ -86,6 +86,14 @@ sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS
### 7. Update configuration files
+#### New configuration options for `gitlab.yml`
+
+There are new configuration options available for [`gitlab.yml`](config/gitlab.yml.example). View them with the command below and apply them manually to your current `gitlab.yml`:
+
+```sh
+git diff origin/8-7-stable:config/gitlab.yml.example origin/8-8-stable:config/gitlab.yml.example
+```
+
#### Git configuration
Disable `git gc --auto` because GitLab runs `git gc` for us already.
@@ -137,7 +145,7 @@ To make sure you didn't miss anything run a more thorough check:
If all items are green, then congratulations, the upgrade is complete!
-## Things went south? Revert to previous version (8.6)
+## Things went south? Revert to previous version (8.7)
### 1. Revert the code to the previous version
diff --git a/doc/web_hooks/web_hooks.md b/doc/web_hooks/web_hooks.md
index 45506ac1d7c..8559b67af04 100644
--- a/doc/web_hooks/web_hooks.md
+++ b/doc/web_hooks/web_hooks.md
@@ -695,6 +695,61 @@ X-Gitlab-Event: Merge Request Hook
}
```
+## Wiki Page events
+
+Triggered when a wiki page is created or edited.
+
+**Request Header**:
+
+```
+X-Gitlab-Event: Wiki Page Hook
+```
+
+**Request Body**:
+
+```json
+{
+ "object_kind": "wiki_page",
+ "user": {
+ "name": "Administrator",
+ "username": "root",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon"
+ },
+ "project": {
+ "name": "awesome-project",
+ "description": "This is awesome",
+ "web_url": "http://example.com/root/awesome-project",
+ "avatar_url": null,
+ "git_ssh_url": "git@example.com:root/awesome-project.git",
+ "git_http_url": "http://example.com/root/awesome-project.git",
+ "namespace": "root",
+ "visibility_level": 0,
+ "path_with_namespace": "root/awesome-project",
+ "default_branch": "master",
+ "homepage": "http://example.com/root/awesome-project",
+ "url": "git@example.com:root/awesome-project.git",
+ "ssh_url": "git@example.com:root/awesome-project.git",
+ "http_url": "http://example.com/root/awesome-project.git"
+ },
+ "wiki": {
+ "web_url": "http://example.com/root/awesome-project/wikis/home",
+ "git_ssh_url": "git@example.com:root/awesome-project.wiki.git",
+ "git_http_url": "http://example.com/root/awesome-project.wiki.git",
+ "path_with_namespace": "root/awesome-project.wiki",
+ "default_branch": "master"
+ },
+ "object_attributes": {
+ "title": "Awesome",
+ "content": "awesome content goes here",
+ "format": "markdown",
+ "message": "adding an awesome page to the wiki",
+ "slug": "awesome",
+ "url": "http://example.com/root/awesome-project/wikis/awesome",
+ "action": "create"
+ }
+}
+```
+
#### Example webhook receiver
If you want to see GitLab's webhooks in action for testing purposes you can use
diff --git a/features/steps/dashboard/todos.rb b/features/steps/dashboard/todos.rb
index d3b6c7f6a15..bd8a270202e 100644
--- a/features/steps/dashboard/todos.rb
+++ b/features/steps/dashboard/todos.rb
@@ -20,7 +20,7 @@ class Spinach::Features::DashboardTodos < Spinach::FeatureSteps
step 'I have todos' do
create(:todo, user: current_user, project: project, author: mary_jane, target: issue, action: Todo::MENTIONED)
create(:todo, user: current_user, project: project, author: john_doe, target: issue, action: Todo::ASSIGNED)
- note = create(:note, author: john_doe, noteable: issue, note: "#{current_user.to_reference} Wdyt?")
+ note = create(:note, author: john_doe, noteable: issue, note: "#{current_user.to_reference} Wdyt?", project: project)
create(:todo, user: current_user, project: project, author: john_doe, target: issue, action: Todo::MENTIONED, note: note)
create(:todo, user: current_user, project: project, author: john_doe, target: merge_request, action: Todo::ASSIGNED)
end
diff --git a/features/steps/project/issues/issues.rb b/features/steps/project/issues/issues.rb
index f2c68f007ef..5cd431e05d5 100644
--- a/features/steps/project/issues/issues.rb
+++ b/features/steps/project/issues/issues.rb
@@ -348,7 +348,7 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps
step 'another user adds a comment with text "Yay!" to issue "Release 0.4"' do
issue = Issue.find_by!(title: 'Release 0.4')
- create(:note_on_issue, noteable: issue, note: 'Yay!')
+ create(:note_on_issue, noteable: issue, project: project, note: 'Yay!')
end
step 'I should see a new comment with text "Yay!"' do
diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb
index cfa586f859f..b30346790eb 100644
--- a/features/steps/project/merge_requests.rb
+++ b/features/steps/project/merge_requests.rb
@@ -273,7 +273,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
step 'user "John Doe" leaves a comment like "Line is wrong" on diff' do
mr = MergeRequest.find_by(title: "Bug NS-05")
create(:note_on_merge_request_diff, project: project,
- noteable_id: mr.id,
+ noteable: mr,
author: user_exists("John Doe"),
line_code: sample_commit.line_code,
note: 'Line is wrong')
@@ -567,7 +567,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
click_diff_line(sample_compare.changes[1][:line_code])
end
- def have_visible_content (text)
+ def have_visible_content(text)
have_css("*", text: text, visible: true)
end
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 31491cf31dd..790a1869f73 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -362,6 +362,7 @@ module API
expose :restricted_signup_domains
expose :user_oauth_applications
expose :after_sign_out_path
+ expose :container_registry_token_expire_delay
end
class Release < Grape::Entity
diff --git a/lib/api/licenses.rb b/lib/api/licenses.rb
index 187d2c04703..be0e113fbcb 100644
--- a/lib/api/licenses.rb
+++ b/lib/api/licenses.rb
@@ -2,15 +2,15 @@ module API
# Licenses API
class Licenses < Grape::API
PROJECT_TEMPLATE_REGEX =
- /[\<\{\[]
- (project|description|
- one\sline\s.+\swhat\sit\sdoes\.) # matching the start and end is enough here
- [\>\}\]]/xi.freeze
+ /[\<\{\[]
+ (project|description|
+ one\sline\s.+\swhat\sit\sdoes\.) # matching the start and end is enough here
+ [\>\}\]]/xi.freeze
YEAR_TEMPLATE_REGEX = /[<{\[](year|yyyy)[>}\]]/i.freeze
FULLNAME_TEMPLATE_REGEX =
- /[\<\{\[]
- (fullname|name\sof\s(author|copyright\sowner))
- [\>\}\]]/xi.freeze
+ /[\<\{\[]
+ (fullname|name\sof\s(author|copyright\sowner))
+ [\>\}\]]/xi.freeze
# Get the list of the available license templates
#
diff --git a/lib/api/users.rb b/lib/api/users.rb
index ea6fa2dc8a8..8a376d3c2a3 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -76,7 +76,7 @@ module API
required_attributes! [:email, :password, :name, :username]
attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :bio, :location, :can_create_group, :admin, :confirm, :external]
admin = attrs.delete(:admin)
- confirm = !(attrs.delete(:confirm) =~ (/(false|f|no|0)$/i))
+ confirm = !(attrs.delete(:confirm) =~ /(false|f|no|0)$/i)
user = User.build_user(attrs)
user.admin = admin unless admin.nil?
user.skip_confirmation! unless confirm
diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb
index 3e07096e6cc..660ca8c2923 100644
--- a/lib/backup/manager.rb
+++ b/lib/backup/manager.rb
@@ -48,7 +48,7 @@ module Backup
end
connection = ::Fog::Storage.new(connection_settings)
- directory = connection.directories.get(remote_directory)
+ directory = connection.directories.create(key: remote_directory)
if directory.files.create(key: tar_file, body: File.open(tar_file), public: false,
multipart_chunk_size: Gitlab.config.backup.upload.multipart_chunk_size,
diff --git a/lib/banzai/filter/abstract_reference_filter.rb b/lib/banzai/filter/abstract_reference_filter.rb
index 298a88ba08a..db95d7c908b 100644
--- a/lib/banzai/filter/abstract_reference_filter.rb
+++ b/lib/banzai/filter/abstract_reference_filter.rb
@@ -228,7 +228,9 @@ module Banzai
if cache.key?(key)
cache[key]
else
- cache[key] = yield
+ value = yield
+ cache[key] = value if key.present?
+ value
end
end
end
diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb
index e4b4760c53b..026a5ac97ca 100644
--- a/lib/ci/gitlab_ci_yaml_processor.rb
+++ b/lib/ci/gitlab_ci_yaml_processor.rb
@@ -265,7 +265,7 @@ module Ci
end
def validate_job_dependencies!(name, job)
- if !validate_array_of_strings(job[:dependencies])
+ unless validate_array_of_strings(job[:dependencies])
raise ValidationError, "#{name} job: dependencies parameter should be an array of strings"
end
diff --git a/lib/event_filter.rb b/lib/event_filter.rb
index f15b2cfd231..668d2fa41b3 100644
--- a/lib/event_filter.rb
+++ b/lib/event_filter.rb
@@ -27,7 +27,7 @@ class EventFilter
@params = if params
params.dup
else
- []#EventFilter.default_filter
+ [] # EventFilter.default_filter
end
end
diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb
index f2020c82d40..cd2e83b4c27 100644
--- a/lib/gitlab/ci/build/artifacts/metadata.rb
+++ b/lib/gitlab/ci/build/artifacts/metadata.rb
@@ -56,7 +56,7 @@ module Gitlab
child_pattern = '[^/]*/?$' unless @opts[:recursive]
match_pattern = /^#{Regexp.escape(@path)}#{child_pattern}/
- until gz.eof? do
+ until gz.eof?
begin
path = read_string(gz).force_encoding('UTF-8')
meta = read_string(gz).force_encoding('UTF-8')
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
index f44d1b3a44e..92c7e8b9d88 100644
--- a/lib/gitlab/current_settings.rb
+++ b/lib/gitlab/current_settings.rb
@@ -1,18 +1,22 @@
module Gitlab
module CurrentSettings
def current_application_settings
- key = :current_application_settings
-
- RequestStore.store[key] ||= begin
- settings = nil
+ if RequestStore.active?
+ RequestStore.fetch(:current_application_settings) { ensure_application_settings! }
+ else
+ ensure_application_settings!
+ end
+ end
- if connect_to_db?
- settings = ::ApplicationSetting.current
- settings ||= ::ApplicationSetting.create_from_defaults unless ActiveRecord::Migrator.needs_migration?
- end
+ def ensure_application_settings!
+ settings = ::ApplicationSetting.cached
- settings || fake_application_settings
+ if !settings && connect_to_db?
+ settings = ::ApplicationSetting.current
+ settings ||= ::ApplicationSetting.create_from_defaults unless ActiveRecord::Migrator.needs_migration?
end
+
+ settings || fake_application_settings
end
def fake_application_settings
@@ -36,6 +40,7 @@ module Gitlab
two_factor_grace_period: 48,
akismet_enabled: false,
repository_checks_enabled: true,
+ container_registry_token_expire_delay: 5,
)
end
diff --git a/lib/gitlab/diff/parser.rb b/lib/gitlab/diff/parser.rb
index 6fe7faa547a..522dd2b9428 100644
--- a/lib/gitlab/diff/parser.rb
+++ b/lib/gitlab/diff/parser.rb
@@ -17,16 +17,16 @@ module Gitlab
Enumerator.new do |yielder|
@lines.each do |line|
next if filename?(line)
-
+
full_line = line.delete("\n")
-
+
if line.match(/^@@ -/)
type = "match"
-
+
line_old = line.match(/\-[0-9]*/)[0].to_i.abs rescue 0
line_new = line.match(/\+[0-9]*/)[0].to_i.abs rescue 0
-
- next if line_old <= 1 && line_new <= 1 #top of file
+
+ next if line_old <= 1 && line_new <= 1 # top of file
yielder << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new)
line_obj_index += 1
next
@@ -39,8 +39,8 @@ module Gitlab
yielder << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new)
line_obj_index += 1
end
-
-
+
+
case line[0]
when "+"
line_new += 1
diff --git a/lib/gitlab/github_import/pull_request_formatter.rb b/lib/gitlab/github_import/pull_request_formatter.rb
index 574737b31c1..a2947b56ad9 100644
--- a/lib/gitlab/github_import/pull_request_formatter.rb
+++ b/lib/gitlab/github_import/pull_request_formatter.rb
@@ -79,10 +79,9 @@ module Gitlab
end
def state
- @state ||= case true
- when raw_data.state == 'closed' && raw_data.merged_at.present?
+ @state ||= if raw_data.state == 'closed' && raw_data.merged_at.present?
'merged'
- when raw_data.state == 'closed'
+ elsif raw_data.state == 'closed'
'closed'
else
'opened'
diff --git a/lib/gitlab/gitlab_import/importer.rb b/lib/gitlab/gitlab_import/importer.rb
index 3e51c06877e..3f76ec97977 100644
--- a/lib/gitlab/gitlab_import/importer.rb
+++ b/lib/gitlab/gitlab_import/importer.rb
@@ -5,9 +5,9 @@ module Gitlab
def initialize(project)
@project = project
- credentials = project.import_data
- if credentials && credentials[:password]
- @client = Client.new(credentials[:password])
+ import_data = project.import_data
+ if import_data && import_data.credentials && import_data.credentials[:password]
+ @client = Client.new(import_data.credentials[:password])
@formatter = Gitlab::ImportFormatter.new
else
raise Projects::ImportService::Error, "Unable to find project import data credentials for project ID: #{@project.id}"
@@ -17,7 +17,7 @@ module Gitlab
def execute
project_identifier = CGI.escape(project.import_source)
- #Issues && Comments
+ # Issues && Comments
issues = client.issues(project_identifier)
issues.each do |issue|
diff --git a/lib/gitlab/middleware/rails_queue_duration.rb b/lib/gitlab/middleware/rails_queue_duration.rb
new file mode 100644
index 00000000000..56608b1b276
--- /dev/null
+++ b/lib/gitlab/middleware/rails_queue_duration.rb
@@ -0,0 +1,24 @@
+# This Rack middleware is intended to measure the latency between
+# gitlab-workhorse forwarding a request to the Rails application and the
+# time this middleware is reached.
+
+module Gitlab
+ module Middleware
+ class RailsQueueDuration
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ trans = Gitlab::Metrics.current_transaction
+ proxy_start = env['HTTP_GITLAB_WORHORSE_PROXY_START'].presence
+ if trans && proxy_start
+ # Time in milliseconds since gitlab-workhorse started the request
+ trans.set(:rails_queue_duration, Time.now.to_f * 1_000 - proxy_start.to_f / 1_000_000)
+ end
+
+ @app.call(env)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/project_search_results.rb b/lib/gitlab/project_search_results.rb
index 71c5b6801fb..183bd10d6a3 100644
--- a/lib/gitlab/project_search_results.rb
+++ b/lib/gitlab/project_search_results.rb
@@ -74,7 +74,7 @@ module Gitlab
end
def notes
- project.notes.user.search(query).order('updated_at DESC')
+ project.notes.user.search(query, as_user: @current_user).order('updated_at DESC')
end
def commits
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index c0a1f45195f..4f621a43d7e 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -63,7 +63,7 @@ describe Projects::MergeRequestsController do
id: merge_request.iid,
format: format)
- expect(response.body).to eq((merge_request.send(:"to_#{format}")).to_s)
+ expect(response.body).to eq(merge_request.send(:"to_#{format}").to_s)
end
it "should not escape Html" do
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index 91b46c4d65c..fba545560c7 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -115,6 +115,17 @@ describe ProjectsController do
expect(public_project_with_dot_atom).not_to be_valid
end
end
+
+ context 'when the project is pending deletions' do
+ it 'renders a 404 error' do
+ project = create(:project, pending_delete: true)
+ sign_in(user)
+
+ get :show, namespace_id: project.namespace.path, id: project.path
+
+ expect(response.status).to eq 404
+ end
+ end
end
describe "#update" do
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index fbe50d10ec5..209fa37d97d 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -11,7 +11,7 @@ describe RegistrationsController do
let(:user_params) { { user: { name: "new_user", username: "new_username", email: "new@user.com", password: "Any_password" } } }
context 'when sending email confirmation' do
- before { allow(current_application_settings).to receive(:send_user_confirmation_email).and_return(false) }
+ before { allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(false) }
it 'logs user in directly' do
post(:create, user_params)
@@ -21,7 +21,7 @@ describe RegistrationsController do
end
context 'when not sending email confirmation' do
- before { allow(current_application_settings).to receive(:send_user_confirmation_email).and_return(true) }
+ before { allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(true) }
it 'does not authenticate user and sends confirmation email' do
post(:create, user_params)
diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb
index ab57c52c7cd..b39d8c8cd5b 100644
--- a/spec/controllers/sessions_controller_spec.rb
+++ b/spec/controllers/sessions_controller_spec.rb
@@ -35,6 +35,27 @@ describe SessionsController do
post(:create, { user: user_params }, { otp_user_id: user.id })
end
+ context 'remember_me field' do
+ it 'sets a remember_user_token cookie when enabled' do
+ allow(controller).to receive(:find_user).and_return(user)
+ expect(controller).
+ to receive(:remember_me).with(user).and_call_original
+
+ authenticate_2fa(remember_me: '1', otp_attempt: user.current_otp)
+
+ expect(response.cookies['remember_user_token']).to be_present
+ end
+
+ it 'does nothing when disabled' do
+ allow(controller).to receive(:find_user).and_return(user)
+ expect(controller).not_to receive(:remember_me)
+
+ authenticate_2fa(remember_me: '0', otp_attempt: user.current_otp)
+
+ expect(response.cookies['remember_user_token']).to be_nil
+ end
+ end
+
##
# See #14900 issue
#
diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb
index 26719f2652c..c32e205ee69 100644
--- a/spec/factories/notes.rb
+++ b/spec/factories/notes.rb
@@ -7,6 +7,7 @@ FactoryGirl.define do
project
note "Note"
author
+ on_issue
factory :note_on_commit, traits: [:on_commit]
factory :note_on_commit_diff, traits: [:on_commit, :on_diff], class: LegacyDiffNote
@@ -19,29 +20,26 @@ FactoryGirl.define do
factory :upvote_note, traits: [:award, :upvote]
trait :on_commit do
- project
+ noteable nil
+ noteable_id nil
+ noteable_type 'Commit'
commit_id RepoHelpers.sample_commit.id
- noteable_type "Commit"
end
trait :on_diff do
line_code "0_184_184"
end
- trait :on_merge_request do
- project
- noteable_id 1
- noteable_type "MergeRequest"
+ trait :on_issue do
+ noteable { create(:issue, project: project) }
end
- trait :on_issue do
- noteable_id 1
- noteable_type "Issue"
+ trait :on_merge_request do
+ noteable { create(:merge_request, source_project: project) }
end
trait :on_project_snippet do
- noteable_id 1
- noteable_type "Snippet"
+ noteable { create(:snippet, project: project) }
end
trait :system do
diff --git a/spec/features/issues/filter_issues_spec.rb b/spec/features/issues/filter_issues_spec.rb
index 1f0594e6b02..7efbaaa048c 100644
--- a/spec/features/issues/filter_issues_spec.rb
+++ b/spec/features/issues/filter_issues_spec.rb
@@ -294,4 +294,40 @@ describe 'Filter issues', feature: true do
end
end
end
+
+ describe 'filter by any author', js: true do
+ before do
+ user2 = create(:user, name: "tester")
+ create(:issue, project: project, author: user)
+ create(:issue, project: project, author: user2)
+
+ visit namespace_project_issues_path(project.namespace, project)
+ end
+
+ it 'should show filter by any author link' do
+ click_button "Author"
+ fill_in "Search authors", with: "tester"
+
+ page.within ".dropdown-menu-author" do
+ expect(page).to have_content "tester"
+ end
+ end
+
+ it 'should show filter issues by any author' do
+ page.within '.issues-list' do
+ expect(page).to have_selector ".issue", count: 2
+ end
+
+ click_button "Author"
+ fill_in "Search authors", with: "tester"
+
+ page.within ".dropdown-menu-author" do
+ click_link "tester"
+ end
+
+ page.within '.issues-list' do
+ expect(page).to have_selector ".issue", count: 1
+ end
+ end
+ end
end
diff --git a/spec/features/issues/move_spec.rb b/spec/features/issues/move_spec.rb
index 84c8e20ebaa..c7019c5aea1 100644
--- a/spec/features/issues/move_spec.rb
+++ b/spec/features/issues/move_spec.rb
@@ -19,7 +19,7 @@ feature 'issue move to another project' do
end
scenario 'moving issue to another project not allowed' do
- expect(page).to have_no_select('move_to_project_id')
+ expect(page).to have_no_selector('#move_to_project_id')
end
end
@@ -37,7 +37,7 @@ feature 'issue move to another project' do
end
scenario 'moving issue to another project' do
- select(new_project.name_with_namespace, from: 'move_to_project_id')
+ first('#move_to_project_id', visible: false).set(new_project.id)
click_button('Save changes')
expect(current_url).to include project_path(new_project)
@@ -47,14 +47,18 @@ feature 'issue move to another project' do
expect(page).to have_content(issue.title)
end
- context 'projects user does not have permission to move issue to exist' do
+ context 'user does not have permission to move the issue to a project', js: true do
let!(:private_project) { create(:project, :private) }
let(:another_project) { create(:project) }
background { another_project.team << [user, :guest] }
scenario 'browsing projects in projects select' do
- options = [ '', 'No project', new_project.name_with_namespace ]
- expect(page).to have_select('move_to_project_id', options: options)
+ click_link 'Select project'
+
+ page.within '.select2-results' do
+ expect(page).to have_content 'No project'
+ expect(page).to have_content new_project.name_with_namespace
+ end
end
end
@@ -65,7 +69,7 @@ feature 'issue move to another project' do
end
scenario 'user wants to move issue that has already been moved' do
- expect(page).to have_no_select('move_to_project_id')
+ expect(page).to have_no_selector('#move_to_project_id')
end
end
end
diff --git a/spec/features/issues/note_polling_spec.rb b/spec/features/issues/note_polling_spec.rb
index e4efdbe2421..f5cfe2d666e 100644
--- a/spec/features/issues/note_polling_spec.rb
+++ b/spec/features/issues/note_polling_spec.rb
@@ -9,8 +9,11 @@ feature 'Issue notes polling' do
end
scenario 'Another user adds a comment to an issue', js: true do
- note = create(:note_on_issue, noteable: issue, note: 'Looks good!')
+ note = create(:note, noteable: issue, project: project,
+ note: 'Looks good!')
+
page.execute_script('notes.refresh();')
+
expect(page).to have_selector("#note_#{note.id}", text: 'Looks good!')
end
end
diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb
index 749ee01890c..9271964166a 100644
--- a/spec/features/issues_spec.rb
+++ b/spec/features/issues_spec.rb
@@ -125,7 +125,7 @@ describe 'Issues', feature: true do
describe 'Issue info' do
it 'excludes award_emoji from comment count' do
issue = create(:issue, author: @user, assignee: @user, project: project, title: 'foobar')
- create(:upvote_note, noteable: issue)
+ create(:upvote_note, noteable: issue, project: project)
visit namespace_project_issues_path(project.namespace, project, assignee_id: @user.id)
diff --git a/spec/features/login_spec.rb b/spec/features/login_spec.rb
index 8c38dd5b122..a7dc3b2701b 100644
--- a/spec/features/login_spec.rb
+++ b/spec/features/login_spec.rb
@@ -32,7 +32,7 @@ feature 'Login', feature: true do
let(:user) { create(:user, :two_factor) }
before do
- login_with(user)
+ login_with(user, remember: true)
expect(page).to have_content('Two-factor Authentication')
end
@@ -52,6 +52,12 @@ feature 'Login', feature: true do
expect(current_path).to eq root_path
end
+ it 'persists remember_me value via hidden field' do
+ field = first('input#user_remember_me', visible: false)
+
+ expect(field.value).to eq '1'
+ end
+
it 'blocks login with invalid code' do
enter_code('foo')
expect(page).to have_content('Invalid two-factor code')
diff --git a/spec/features/merge_requests/created_from_fork_spec.rb b/spec/features/merge_requests/created_from_fork_spec.rb
new file mode 100644
index 00000000000..edc0bdec3db
--- /dev/null
+++ b/spec/features/merge_requests/created_from_fork_spec.rb
@@ -0,0 +1,58 @@
+require 'spec_helper'
+
+feature 'Merge request created from fork' do
+ given(:user) { create(:user) }
+ given(:project) { create(:project, :public) }
+ given(:fork_project) { create(:project, :public) }
+
+ given!(:merge_request) do
+ create(:forked_project_link, forked_to_project: fork_project,
+ forked_from_project: project)
+
+ create(:merge_request_with_diffs, source_project: fork_project,
+ target_project: project,
+ description: 'Test merge request')
+ end
+
+ background do
+ fork_project.team << [user, :master]
+ login_as user
+ end
+
+ scenario 'user can access merge request' do
+ visit_merge_request(merge_request)
+
+ expect(page).to have_content 'Test merge request'
+ end
+
+ context 'pipeline present in source project' do
+ include WaitForAjax
+
+ given(:pipeline) do
+ create(:ci_commit_with_two_jobs, project: fork_project,
+ sha: merge_request.last_commit.id,
+ ref: merge_request.source_branch)
+ end
+
+ background { pipeline.create_builds(user) }
+
+ scenario 'user visits a pipelines page', js: true do
+ visit_merge_request(merge_request)
+ page.within('.merge-request-tabs') { click_link 'Builds' }
+ wait_for_ajax
+
+ page.within('table.builds') do
+ expect(page).to have_content 'rspec'
+ expect(page).to have_content 'spinach'
+ end
+
+ expect(find_link('Cancel running')[:href])
+ .to include fork_project.path_with_namespace
+ end
+ end
+
+ def visit_merge_request(mr)
+ visit namespace_project_merge_request_path(project.namespace,
+ project, mr)
+ end
+end
diff --git a/spec/features/merge_requests/user_lists_merge_requests_spec.rb b/spec/features/merge_requests/user_lists_merge_requests_spec.rb
index 2c7e1c748ad..1c130057c56 100644
--- a/spec/features/merge_requests/user_lists_merge_requests_spec.rb
+++ b/spec/features/merge_requests/user_lists_merge_requests_spec.rb
@@ -131,6 +131,15 @@ describe 'Projects > Merge requests > User lists merge requests', feature: true
expect(first_merge_request).to include('fix')
expect(count_merge_requests).to eq(1)
end
+
+ it 'sorts by recently due milestone' do
+ visit namespace_project_merge_requests_path(project.namespace, project,
+ label_name: [label.name, label2.name],
+ assignee_id: user.id,
+ sort: sort_value_milestone_soon)
+
+ expect(first_merge_request).to include('fix')
+ end
end
end
diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb
index 9e9fec01943..2835cf44494 100644
--- a/spec/features/notes_on_merge_requests_spec.rb
+++ b/spec/features/notes_on_merge_requests_spec.rb
@@ -19,10 +19,14 @@ describe 'Comments', feature: true do
end
describe 'On a merge request', js: true, feature: true do
- let!(:merge_request) { create(:merge_request) }
- let!(:project) { merge_request.source_project }
+ let!(:project) { create(:project) }
+ let!(:merge_request) do
+ create(:merge_request, source_project: project, target_project: project)
+ end
+
let!(:note) do
- create(:note_on_merge_request, :with_attachment, project: project)
+ create(:note_on_merge_request, :with_attachment, noteable: merge_request,
+ project: project)
end
before do
diff --git a/spec/features/participants_autocomplete_spec.rb b/spec/features/participants_autocomplete_spec.rb
index 1adab7e9c6c..c7c00a3266a 100644
--- a/spec/features/participants_autocomplete_spec.rb
+++ b/spec/features/participants_autocomplete_spec.rb
@@ -32,7 +32,8 @@ feature 'Member autocomplete', feature: true do
context 'adding a new note on a Issue', js: true do
before do
issue = create(:issue, author: author, project: project)
- create(:note, note: 'Ultralight Beam', noteable: issue, author: participant)
+ create(:note, note: 'Ultralight Beam', noteable: issue,
+ project: project, author: participant)
visit_issue(project, issue)
end
@@ -47,7 +48,8 @@ feature 'Member autocomplete', feature: true do
context 'adding a new note on a Merge Request ', js: true do
before do
merge = create(:merge_request, source_project: project, target_project: project, author: author)
- create(:note, note: 'Ultralight Beam', noteable: merge, author: participant)
+ create(:note, note: 'Ultralight Beam', noteable: merge,
+ project: project, author: participant)
visit_merge_request(project, merge)
end
diff --git a/spec/features/pipelines_spec.rb b/spec/features/pipelines_spec.rb
index bef0578a9bb..acd6fb3538c 100644
--- a/spec/features/pipelines_spec.rb
+++ b/spec/features/pipelines_spec.rb
@@ -62,6 +62,36 @@ describe "Pipelines" do
end
end
+ context 'for generic statuses' do
+ context 'when running' do
+ let!(:running) { create(:generic_commit_status, status: 'running', commit: pipeline, stage: 'test') }
+
+ before { visit namespace_project_pipelines_path(project.namespace, project) }
+
+ it 'not be cancelable' do
+ expect(page).not_to have_link('Cancel')
+ end
+
+ it 'pipeline is running' do
+ expect(page).to have_selector('.ci-running')
+ end
+ end
+
+ context 'when failed' do
+ let!(:running) { create(:generic_commit_status, status: 'failed', commit: pipeline, stage: 'test') }
+
+ before { visit namespace_project_pipelines_path(project.namespace, project) }
+
+ it 'not be retryable' do
+ expect(page).not_to have_link('Retry')
+ end
+
+ it 'pipeline is failed' do
+ expect(page).to have_selector('.ci-failed')
+ end
+ end
+ end
+
context 'downloadable pipelines' do
context 'with artifacts' do
let!(:with_artifacts) { create(:ci_build, :artifacts, :success, commit: pipeline, name: 'rspec tests', stage: 'test') }
diff --git a/spec/features/project/shortcuts_spec.rb b/spec/features/project/shortcuts_spec.rb
index 2595c4181e5..54aa9c66a08 100644
--- a/spec/features/project/shortcuts_spec.rb
+++ b/spec/features/project/shortcuts_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
feature 'Project shortcuts', feature: true do
- let(:project) { create(:project) }
+ let(:project) { create(:project, name: 'Victorialand') }
let(:user) { create(:user) }
describe 'On a project', js: true do
@@ -14,7 +14,7 @@ feature 'Project shortcuts', feature: true do
describe 'pressing "i"' do
it 'redirects to new issue page' do
find('body').native.send_key('i')
- expect(page).to have_content('New Issue')
+ expect(page).to have_content('Victorialand')
end
end
end
diff --git a/spec/features/task_lists_spec.rb b/spec/features/task_lists_spec.rb
index b7368cca29d..6ed279ef9be 100644
--- a/spec/features/task_lists_spec.rb
+++ b/spec/features/task_lists_spec.rb
@@ -75,7 +75,10 @@ feature 'Task Lists', feature: true do
describe 'for Notes' do
let!(:issue) { create(:issue, author: user, project: project) }
- let!(:note) { create(:note, note: markdown, noteable: issue, author: user) }
+ let!(:note) do
+ create(:note, note: markdown, noteable: issue,
+ project: project, author: user)
+ end
it 'renders for note body' do
visit_issue(project, issue)
diff --git a/spec/features/todos/todos_spec.rb b/spec/features/todos/todos_spec.rb
index 3354f529295..4e627753cc7 100644
--- a/spec/features/todos/todos_spec.rb
+++ b/spec/features/todos/todos_spec.rb
@@ -43,6 +43,27 @@ describe 'Dashboard Todos', feature: true do
end
end
+ context 'User has Todos with labels spanning multiple projects' do
+ before do
+ label1 = create(:label, project: project)
+ note1 = create(:note_on_issue, note: "Hello #{label1.to_reference(format: :name)}", noteable_id: issue.id, noteable_type: 'Issue', project: issue.project)
+ create(:todo, :mentioned, project: project, target: issue, user: user, note_id: note1.id)
+
+ project2 = create(:project)
+ label2 = create(:label, project: project2)
+ issue2 = create(:issue, project: project2)
+ note2 = create(:note_on_issue, note: "Test #{label2.to_reference(format: :name)}", noteable_id: issue2.id, noteable_type: 'Issue', project: project2)
+ create(:todo, :mentioned, project: project2, target: issue2, user: user, note_id: note2.id)
+
+ login_as(user)
+ visit dashboard_todos_path
+ end
+
+ it 'shows page with two Todos' do
+ expect(page).to have_selector('.todos-list .todo', count: 2)
+ end
+ end
+
context 'User has multiple pages of Todos' do
before do
allow(Todo).to receive(:default_per_page).and_return(1)
diff --git a/spec/lib/gitlab/akismet_helper_spec.rb b/spec/lib/gitlab/akismet_helper_spec.rb
index 53f5d6c5c80..88a71528867 100644
--- a/spec/lib/gitlab/akismet_helper_spec.rb
+++ b/spec/lib/gitlab/akismet_helper_spec.rb
@@ -6,8 +6,8 @@ describe Gitlab::AkismetHelper, type: :helper do
before do
allow(Gitlab.config.gitlab).to receive(:url).and_return(Settings.send(:build_gitlab_url))
- current_application_settings.akismet_enabled = true
- current_application_settings.akismet_api_key = '12345'
+ allow_any_instance_of(ApplicationSetting).to receive(:akismet_enabled).and_return(true)
+ allow_any_instance_of(ApplicationSetting).to receive(:akismet_api_key).and_return('12345')
end
describe '#check_for_spam?' do
diff --git a/spec/lib/gitlab/middleware/rails_queue_duration_spec.rb b/spec/lib/gitlab/middleware/rails_queue_duration_spec.rb
new file mode 100644
index 00000000000..fd6f684db0c
--- /dev/null
+++ b/spec/lib/gitlab/middleware/rails_queue_duration_spec.rb
@@ -0,0 +1,31 @@
+require 'spec_helper'
+
+describe Gitlab::Middleware::RailsQueueDuration do
+ let(:app) { double(:app) }
+ let(:middleware) { described_class.new(app) }
+ let(:env) { {} }
+ let(:transaction) { double(:transaction) }
+
+ before { expect(app).to receive(:call).with(env).and_return('yay') }
+
+ describe '#call' do
+ it 'calls the app when metrics are disabled' do
+ expect(Gitlab::Metrics).to receive(:current_transaction).and_return(nil)
+ expect(middleware.call(env)).to eq('yay')
+ end
+
+ context 'when metrics are enabled' do
+ before { allow(Gitlab::Metrics).to receive(:current_transaction).and_return(transaction) }
+
+ it 'calls the app when metrics are enabled but no timing header is found' do
+ expect(middleware.call(env)).to eq('yay')
+ end
+
+ it 'sets proxy_flight_time and calls the app when the header is present' do
+ env['HTTP_GITLAB_WORHORSE_PROXY_START'] = '123'
+ expect(transaction).to receive(:set).with(:rails_queue_duration, an_instance_of(Float))
+ expect(middleware.call(env)).to eq('yay')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/note_data_builder_spec.rb b/spec/lib/gitlab/note_data_builder_spec.rb
index f093d0a0d8b..e848d88182f 100644
--- a/spec/lib/gitlab/note_data_builder_spec.rb
+++ b/spec/lib/gitlab/note_data_builder_spec.rb
@@ -9,7 +9,8 @@ describe 'Gitlab::NoteDataBuilder', lib: true do
before(:each) do
expect(data).to have_key(:object_attributes)
expect(data[:object_attributes]).to have_key(:url)
- expect(data[:object_attributes][:url]).to eq(Gitlab::UrlBuilder.build(note))
+ expect(data[:object_attributes][:url])
+ .to eq(Gitlab::UrlBuilder.build(note))
expect(data[:object_kind]).to eq('note')
expect(data[:user]).to eq(user.hook_attrs)
end
@@ -37,13 +38,21 @@ describe 'Gitlab::NoteDataBuilder', lib: true do
end
describe 'When asking for a note on issue' do
- let(:issue) { create(:issue, created_at: fixed_time, updated_at: fixed_time) }
- let(:note) { create(:note_on_issue, noteable_id: issue.id, project: project) }
+ let(:issue) do
+ create(:issue, created_at: fixed_time, updated_at: fixed_time,
+ project: project)
+ end
+
+ let(:note) do
+ create(:note_on_issue, noteable: issue, project: project)
+ end
it 'returns the note and issue-specific data' do
expect(data).to have_key(:issue)
- expect(data[:issue].except('updated_at')).to eq(issue.hook_attrs.except('updated_at'))
- expect(data[:issue]['updated_at']).to be > issue.hook_attrs['updated_at']
+ expect(data[:issue].except('updated_at'))
+ .to eq(issue.reload.hook_attrs.except('updated_at'))
+ expect(data[:issue]['updated_at'])
+ .to be > issue.hook_attrs['updated_at']
end
include_examples 'project hook data'
@@ -51,13 +60,23 @@ describe 'Gitlab::NoteDataBuilder', lib: true do
end
describe 'When asking for a note on merge request' do
- let(:merge_request) { create(:merge_request, created_at: fixed_time, updated_at: fixed_time) }
- let(:note) { create(:note_on_merge_request, noteable_id: merge_request.id, project: project) }
+ let(:merge_request) do
+ create(:merge_request, created_at: fixed_time,
+ updated_at: fixed_time,
+ source_project: project)
+ end
+
+ let(:note) do
+ create(:note_on_merge_request, noteable: merge_request,
+ project: project)
+ end
it 'returns the note and merge request data' do
expect(data).to have_key(:merge_request)
- expect(data[:merge_request].except('updated_at')).to eq(merge_request.hook_attrs.except('updated_at'))
- expect(data[:merge_request]['updated_at']).to be > merge_request.hook_attrs['updated_at']
+ expect(data[:merge_request].except('updated_at'))
+ .to eq(merge_request.reload.hook_attrs.except('updated_at'))
+ expect(data[:merge_request]['updated_at'])
+ .to be > merge_request.hook_attrs['updated_at']
end
include_examples 'project hook data'
@@ -65,13 +84,22 @@ describe 'Gitlab::NoteDataBuilder', lib: true do
end
describe 'When asking for a note on merge request diff' do
- let(:merge_request) { create(:merge_request, created_at: fixed_time, updated_at: fixed_time) }
- let(:note) { create(:note_on_merge_request_diff, noteable_id: merge_request.id, project: project) }
+ let(:merge_request) do
+ create(:merge_request, created_at: fixed_time, updated_at: fixed_time,
+ source_project: project)
+ end
+
+ let(:note) do
+ create(:note_on_merge_request_diff, noteable: merge_request,
+ project: project)
+ end
it 'returns the note and merge request diff data' do
expect(data).to have_key(:merge_request)
- expect(data[:merge_request].except('updated_at')).to eq(merge_request.hook_attrs.except('updated_at'))
- expect(data[:merge_request]['updated_at']).to be > merge_request.hook_attrs['updated_at']
+ expect(data[:merge_request].except('updated_at'))
+ .to eq(merge_request.reload.hook_attrs.except('updated_at'))
+ expect(data[:merge_request]['updated_at'])
+ .to be > merge_request.hook_attrs['updated_at']
end
include_examples 'project hook data'
@@ -79,13 +107,22 @@ describe 'Gitlab::NoteDataBuilder', lib: true do
end
describe 'When asking for a note on project snippet' do
- let!(:snippet) { create(:project_snippet, created_at: fixed_time, updated_at: fixed_time) }
- let!(:note) { create(:note_on_project_snippet, noteable_id: snippet.id, project: project) }
+ let!(:snippet) do
+ create(:project_snippet, created_at: fixed_time, updated_at: fixed_time,
+ project: project)
+ end
+
+ let!(:note) do
+ create(:note_on_project_snippet, noteable: snippet,
+ project: project)
+ end
it 'returns the note and project snippet data' do
expect(data).to have_key(:snippet)
- expect(data[:snippet].except('updated_at')).to eq(snippet.hook_attrs.except('updated_at'))
- expect(data[:snippet]['updated_at']).to be > snippet.hook_attrs['updated_at']
+ expect(data[:snippet].except('updated_at'))
+ .to eq(snippet.reload.hook_attrs.except('updated_at'))
+ expect(data[:snippet]['updated_at'])
+ .to be > snippet.hook_attrs['updated_at']
end
include_examples 'project hook data'
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index b963a3e0324..818825b1477 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -51,7 +51,7 @@ describe Notify do
context 'when enabled email_author_in_body' do
before do
- allow(current_application_settings).to receive(:email_author_in_body).and_return(true)
+ allow_any_instance_of(ApplicationSetting).to receive(:email_author_in_body).and_return(true)
end
it 'contains a link to note author' do
@@ -230,7 +230,7 @@ describe Notify do
context 'when enabled email_author_in_body' do
before do
- allow(current_application_settings).to receive(:email_author_in_body).and_return(true)
+ allow_any_instance_of(ApplicationSetting).to receive(:email_author_in_body).and_return(true)
end
it 'contains a link to note author' do
@@ -454,7 +454,7 @@ describe Notify do
context 'when enabled email_author_in_body' do
before do
- allow(current_application_settings).to receive(:email_author_in_body).and_return(true)
+ allow_any_instance_of(ApplicationSetting).to receive(:email_author_in_body).and_return(true)
end
it 'contains a link to note author' do
diff --git a/spec/models/build_spec.rb b/spec/models/build_spec.rb
index 55b7af441d6..5c6c30c20ea 100644
--- a/spec/models/build_spec.rb
+++ b/spec/models/build_spec.rb
@@ -1,18 +1,17 @@
require 'spec_helper'
describe Ci::Build, models: true do
- let(:project) { FactoryGirl.create :project }
- let(:commit) { FactoryGirl.create :ci_commit, project: project }
- let(:build) { FactoryGirl.create :ci_build, commit: commit }
+ let(:project) { create(:project) }
+ let(:commit) { create(:ci_commit, project: project) }
+ let(:build) { create(:ci_build, commit: commit) }
it { is_expected.to validate_presence_of :ref }
it { is_expected.to respond_to :trace_html }
describe '#first_pending' do
- let(:first) { FactoryGirl.create :ci_build, commit: commit, status: 'pending', created_at: Date.yesterday }
- let(:second) { FactoryGirl.create :ci_build, commit: commit, status: 'pending' }
- before { first; second }
+ let!(:first) { create(:ci_build, commit: commit, status: 'pending', created_at: Date.yesterday) }
+ let!(:second) { create(:ci_build, commit: commit, status: 'pending') }
subject { Ci::Build.first_pending }
it { is_expected.to be_a(Ci::Build) }
@@ -219,8 +218,8 @@ describe Ci::Build, models: true do
it { is_expected.to eq(predefined_variables + yaml_variables + secure_variables) }
context 'and trigger variables' do
- let(:trigger) { FactoryGirl.create :ci_trigger, project: project }
- let(:trigger_request) { FactoryGirl.create :ci_trigger_request_with_variables, commit: commit, trigger: trigger }
+ let(:trigger) { create(:ci_trigger, project: project) }
+ let(:trigger_request) { create(:ci_trigger_request_with_variables, commit: commit, trigger: trigger) }
let(:trigger_variables) do
[
{ key: :TRIGGER_KEY, value: 'TRIGGER_VALUE', public: false }
@@ -329,7 +328,7 @@ describe Ci::Build, models: true do
end
context 'if there are runner' do
- let(:runner) { FactoryGirl.create :ci_runner }
+ let(:runner) { create(:ci_runner) }
before do
build.project.runners << runner
@@ -366,7 +365,7 @@ describe Ci::Build, models: true do
it { is_expected.to be_truthy }
context "and there are specific runner" do
- let(:runner) { FactoryGirl.create :ci_runner, contacted_at: 1.second.ago }
+ let(:runner) { create(:ci_runner, contacted_at: 1.second.ago) }
before do
build.project.runners << runner
@@ -415,7 +414,7 @@ describe Ci::Build, models: true do
end
describe '#repo_url' do
- let(:build) { FactoryGirl.create :ci_build }
+ let(:build) { create(:ci_build) }
let(:project) { build.project }
subject { build.repo_url }
@@ -429,10 +428,10 @@ describe Ci::Build, models: true do
end
describe '#depends_on_builds' do
- let!(:build) { FactoryGirl.create :ci_build, commit: commit, name: 'build', stage_idx: 0, stage: 'build' }
- let!(:rspec_test) { FactoryGirl.create :ci_build, commit: commit, name: 'rspec', stage_idx: 1, stage: 'test' }
- let!(:rubocop_test) { FactoryGirl.create :ci_build, commit: commit, name: 'rubocop', stage_idx: 1, stage: 'test' }
- let!(:staging) { FactoryGirl.create :ci_build, commit: commit, name: 'staging', stage_idx: 2, stage: 'deploy' }
+ let!(:build) { create(:ci_build, commit: commit, name: 'build', stage_idx: 0, stage: 'build') }
+ let!(:rspec_test) { create(:ci_build, commit: commit, name: 'rspec', stage_idx: 1, stage: 'test') }
+ let!(:rubocop_test) { create(:ci_build, commit: commit, name: 'rubocop', stage_idx: 1, stage: 'test') }
+ let!(:staging) { create(:ci_build, commit: commit, name: 'staging', stage_idx: 2, stage: 'deploy') }
it 'to have no dependents if this is first build' do
expect(build.depends_on_builds).to be_empty
@@ -453,11 +452,10 @@ describe Ci::Build, models: true do
end
def create_mr(build, commit, factory: :merge_request, created_at: Time.now)
- FactoryGirl.create(factory,
- source_project_id: commit.gl_project_id,
- target_project_id: commit.gl_project_id,
- source_branch: build.ref,
- created_at: created_at)
+ create(factory, source_project_id: commit.gl_project_id,
+ target_project_id: commit.gl_project_id,
+ source_branch: build.ref,
+ created_at: created_at)
end
describe '#merge_request' do
@@ -501,8 +499,8 @@ describe Ci::Build, models: true do
context 'when a Build is created after the MR' do
before do
@merge_request = create_mr(build, commit, factory: :merge_request_with_diffs)
- commit2 = FactoryGirl.create :ci_commit, project: project
- @build2 = FactoryGirl.create :ci_build, commit: commit2
+ commit2 = create(:ci_commit, project: project)
+ @build2 = create(:ci_build, commit: commit2)
commits = [double(id: commit.sha), double(id: commit2.sha)]
allow(@merge_request).to receive(:commits).and_return(commits)
diff --git a/spec/models/ci/runner_project_spec.rb b/spec/models/ci/runner_project_spec.rb
deleted file mode 100644
index 95fc160b238..00000000000
--- a/spec/models/ci/runner_project_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'spec_helper'
-
-describe Ci::RunnerProject, models: true do
- pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index 583827cdf42..fb20578d8d3 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -118,10 +118,10 @@ describe Issue, "Issuable" do
let(:project) { build_stubbed(:empty_project) }
context "by milestone due date" do
- #Correct order is:
- #Issues/MRs with milestones ordered by date
- #Issues/MRs with milestones without dates
- #Issues/MRs without milestones
+ # Correct order is:
+ # Issues/MRs with milestones ordered by date
+ # Issues/MRs with milestones without dates
+ # Issues/MRs without milestones
let!(:issue) { create(:issue, project: project) }
let!(:early_milestone) { create(:milestone, project: project, due_date: 10.days.from_now) }
@@ -189,7 +189,6 @@ describe Issue, "Issuable" do
let(:data) { issue.to_hook_data(user) }
let(:project) { issue.project }
-
it "returns correct hook data" do
expect(data[:object_kind]).to eq("issue")
expect(data[:user]).to eq(user.hook_attrs)
@@ -229,11 +228,11 @@ describe Issue, "Issuable" do
end
describe "votes" do
+ let(:project) { issue.project }
+
before do
- author = create :user
- project = create :empty_project
- issue.notes.awards.create!(note: "thumbsup", author: author, project: project)
- issue.notes.awards.create!(note: "thumbsdown", author: author, project: project)
+ issue.notes.awards.create!(note: "thumbsup", author: user, project: project)
+ issue.notes.awards.create!(note: "thumbsdown", author: user, project: project)
end
it "returns correct values" do
diff --git a/spec/models/legacy_diff_note_spec.rb b/spec/models/legacy_diff_note_spec.rb
index 7c29bef54e4..b2d06853886 100644
--- a/spec/models/legacy_diff_note_spec.rb
+++ b/spec/models/legacy_diff_note_spec.rb
@@ -63,7 +63,9 @@ describe LegacyDiffNote, models: true do
code = Gitlab::Diff::LineCode.generate(diff.new_path, line.new_pos, line.old_pos)
# We're persisting in order to trigger the set_diff callback
- note = create(:note_on_merge_request_diff, noteable: merge, line_code: code)
+ note = create(:note_on_merge_request_diff, noteable: merge,
+ line_code: code,
+ project: merge.source_project)
# Make sure we don't get a false positive from a guard clause
expect(note).to receive(:find_noteable_diff).and_call_original
diff --git a/spec/models/members/project_member_spec.rb b/spec/models/members/project_member_spec.rb
index 9f26d9eb5ce..9f13874b532 100644
--- a/spec/models/members/project_member_spec.rb
+++ b/spec/models/members/project_member_spec.rb
@@ -20,6 +20,48 @@
require 'spec_helper'
describe ProjectMember, models: true do
+ describe 'associations' do
+ it { is_expected.to belong_to(:project).class_name('Project').with_foreign_key(:source_id) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to allow_value('Project').for(:source_type) }
+ it { is_expected.not_to allow_value('project').for(:source_type) }
+ end
+
+ describe 'modules' do
+ it { is_expected.to include_module(Gitlab::ShellAdapter) }
+ end
+
+ describe "#destroy" do
+ let(:owner) { create(:project_member, access_level: ProjectMember::OWNER) }
+ let(:project) { owner.project }
+ let(:master) { create(:project_member, project: project) }
+
+ let(:owner_todos) { (0...2).map { create(:todo, user: owner.user, project: project) } }
+ let(:master_todos) { (0...3).map { create(:todo, user: master.user, project: project) } }
+
+ before do
+ owner_todos
+ master_todos
+ end
+
+ it "destroy itself and delete associated todos" do
+ expect(owner.user.todos.size).to eq(2)
+ expect(master.user.todos.size).to eq(3)
+ expect(Todo.count).to eq(5)
+
+ master_todo_ids = master_todos.map(&:id)
+ master.destroy
+
+ expect(owner.user.todos.size).to eq(2)
+ expect(Todo.count).to eq(2)
+ master_todo_ids.each do |id|
+ expect(Todo.exists?(id)).to eq(false)
+ end
+ end
+ end
+
describe :import_team do
before do
@abilities = Six.new
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 30a8e3ec059..118e1e22a78 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -119,7 +119,8 @@ describe MergeRequest, models: true do
before do
allow(merge_request).to receive(:commits) { [merge_request.source_project.repository.commit] }
- create(:note, commit_id: merge_request.commits.first.id, noteable_type: 'Commit', project: merge_request.project)
+ create(:note_on_commit, commit_id: merge_request.commits.first.id,
+ project: merge_request.project)
create(:note, noteable: merge_request, project: merge_request.project)
end
@@ -129,7 +130,9 @@ describe MergeRequest, models: true do
end
it "should include notes for commits from target project as well" do
- create(:note, commit_id: merge_request.commits.first.id, noteable_type: 'Commit', project: merge_request.target_project)
+ create(:note_on_commit, commit_id: merge_request.commits.first.id,
+ project: merge_request.target_project)
+
expect(merge_request.commits).not_to be_empty
expect(merge_request.mr_and_commit_notes.count).to eq(3)
end
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index d158de6b967..b25150f7055 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -12,6 +12,34 @@ describe Note, models: true do
describe 'validation' do
it { is_expected.to validate_presence_of(:note) }
it { is_expected.to validate_presence_of(:project) }
+
+ context 'when note is on commit' do
+ before { allow(subject).to receive(:for_commit?).and_return(true) }
+
+ it { is_expected.to validate_presence_of(:commit_id) }
+ it { is_expected.not_to validate_presence_of(:noteable_id) }
+ end
+
+ context 'when note is not on commit' do
+ before { allow(subject).to receive(:for_commit?).and_return(false) }
+
+ it { is_expected.not_to validate_presence_of(:commit_id) }
+ it { is_expected.to validate_presence_of(:noteable_id) }
+ end
+
+ context 'when noteable and note project differ' do
+ subject do
+ build(:note, noteable: build_stubbed(:issue),
+ project: build_stubbed(:project))
+ end
+
+ it { is_expected.to be_invalid }
+ end
+
+ context 'when noteable and note project are the same' do
+ subject { create(:note) }
+ it { is_expected.to be_valid }
+ end
end
describe "Commit notes" do
@@ -89,8 +117,8 @@ describe Note, models: true do
end
describe "#all_references" do
- let!(:note1) { create(:note) }
- let!(:note2) { create(:note) }
+ let!(:note1) { create(:note_on_issue) }
+ let!(:note2) { create(:note_on_issue) }
it "reads the rendered note body from the cache" do
expect(Banzai::Renderer).to receive(:render).
@@ -113,7 +141,7 @@ describe Note, models: true do
end
describe '.search' do
- let(:note) { create(:note, note: 'WoW') }
+ let(:note) { create(:note_on_issue, note: 'WoW') }
it 'returns notes with matching content' do
expect(described_class.search(note.note)).to eq([note])
@@ -122,6 +150,25 @@ describe Note, models: true do
it 'returns notes with matching content regardless of the casing' do
expect(described_class.search('WOW')).to eq([note])
end
+
+ context "confidential issues" do
+ let(:user) { create :user }
+ let(:confidential_issue) { create(:issue, :confidential, author: user) }
+ let(:confidential_note) { create :note, note: "Random", noteable: confidential_issue }
+
+ it "returns notes with matching content if user can see the issue" do
+ expect(described_class.search(confidential_note.note, as_user: user)).to eq([confidential_note])
+ end
+
+ it "does not return notes with matching content if user can not see the issue" do
+ user = create :user
+ expect(described_class.search(confidential_note.note, as_user: user)).to be_empty
+ end
+
+ it "does not return notes with matching content for unauthenticated users" do
+ expect(described_class.search(confidential_note.note)).to be_empty
+ end
+ end
end
describe '.grouped_awards' do
@@ -186,12 +233,18 @@ describe Note, models: true do
let(:merge_request) { create :merge_request }
it "converts aliases to actual name" do
- note = create(:note, note: ":+1:", noteable: merge_request)
+ note = create(:note, note: ":+1:",
+ noteable: merge_request,
+ project: merge_request.project)
+
expect(note.reload.note).to eq("thumbsup")
end
it "is not an award emoji when comment is on a diff" do
- note = create(:note_on_merge_request_diff, note: ":blowfish:", noteable: merge_request, line_code: "11d5d2e667e9da4f7f610f81d86c974b146b13bd_0_2")
+ note = create(:note_on_merge_request_diff, note: ":blowfish:",
+ noteable: merge_request,
+ project: merge_request.project,
+ line_code: "11d5d2e667e9da4f7f610f81d86c974b146b13bd_0_2")
note = note.reload
expect(note.note).to eq(":blowfish:")
diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb
index f887ed4bafc..5f618322aab 100644
--- a/spec/models/project_services/hipchat_service_spec.rb
+++ b/spec/models/project_services/hipchat_service_spec.rb
@@ -176,86 +176,117 @@ describe HipchatService, models: true do
context "Note events" do
let(:user) { create(:user) }
let(:project) { create(:project, creator_id: user.id) }
- let(:issue) { create(:issue, project: project) }
- let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
- let(:snippet) { create(:project_snippet, project: project) }
- let(:commit_note) { create(:note_on_commit, author: user, project: project, commit_id: project.repository.commit.id, note: 'a comment on a commit') }
- let(:merge_request_note) { create(:note_on_merge_request, noteable_id: merge_request.id, note: "merge request note") }
- let(:issue_note) { create(:note_on_issue, noteable_id: issue.id, note: "issue note")}
- let(:snippet_note) { create(:note_on_project_snippet, noteable_id: snippet.id, note: "snippet note") }
-
- it "should call Hipchat API for commit comment events" do
- data = Gitlab::NoteDataBuilder.build(commit_note, user)
- hipchat.execute(data)
- expect(WebMock).to have_requested(:post, api_url).once
+ context 'when commit comment event triggered' do
+ let(:commit_note) do
+ create(:note_on_commit, author: user, project: project,
+ commit_id: project.repository.commit.id,
+ note: 'a comment on a commit')
+ end
+
+ it "should call Hipchat API for commit comment events" do
+ data = Gitlab::NoteDataBuilder.build(commit_note, user)
+ hipchat.execute(data)
- message = hipchat.send(:create_message, data)
+ expect(WebMock).to have_requested(:post, api_url).once
- obj_attr = data[:object_attributes]
- commit_id = Commit.truncate_sha(data[:commit][:id])
- title = hipchat.send(:format_title, data[:commit][:message])
+ message = hipchat.send(:create_message, data)
- expect(message).to eq("#{user.name} commented on " \
- "<a href=\"#{obj_attr[:url]}\">commit #{commit_id}</a> in " \
- "<a href=\"#{project.web_url}\">#{project_name}</a>: " \
- "#{title}" \
- "<pre>a comment on a commit</pre>")
+ obj_attr = data[:object_attributes]
+ commit_id = Commit.truncate_sha(data[:commit][:id])
+ title = hipchat.send(:format_title, data[:commit][:message])
+
+ expect(message).to eq("#{user.name} commented on " \
+ "<a href=\"#{obj_attr[:url]}\">commit #{commit_id}</a> in " \
+ "<a href=\"#{project.web_url}\">#{project_name}</a>: " \
+ "#{title}" \
+ "<pre>a comment on a commit</pre>")
+ end
end
- it "should call Hipchat API for merge request comment events" do
- data = Gitlab::NoteDataBuilder.build(merge_request_note, user)
- hipchat.execute(data)
+ context 'when merge request comment event triggered' do
+ let(:merge_request) do
+ create(:merge_request, source_project: project,
+ target_project: project)
+ end
- expect(WebMock).to have_requested(:post, api_url).once
+ let(:merge_request_note) do
+ create(:note_on_merge_request, noteable: merge_request,
+ project: project,
+ note: "merge request note")
+ end
- message = hipchat.send(:create_message, data)
+ it "should call Hipchat API for merge request comment events" do
+ data = Gitlab::NoteDataBuilder.build(merge_request_note, user)
+ hipchat.execute(data)
- obj_attr = data[:object_attributes]
- merge_id = data[:merge_request]['iid']
- title = data[:merge_request]['title']
+ expect(WebMock).to have_requested(:post, api_url).once
- expect(message).to eq("#{user.name} commented on " \
- "<a href=\"#{obj_attr[:url]}\">merge request !#{merge_id}</a> in " \
- "<a href=\"#{project.web_url}\">#{project_name}</a>: " \
- "<b>#{title}</b>" \
- "<pre>merge request note</pre>")
+ message = hipchat.send(:create_message, data)
+
+ obj_attr = data[:object_attributes]
+ merge_id = data[:merge_request]['iid']
+ title = data[:merge_request]['title']
+
+ expect(message).to eq("#{user.name} commented on " \
+ "<a href=\"#{obj_attr[:url]}\">merge request !#{merge_id}</a> in " \
+ "<a href=\"#{project.web_url}\">#{project_name}</a>: " \
+ "<b>#{title}</b>" \
+ "<pre>merge request note</pre>")
+ end
end
- it "should call Hipchat API for issue comment events" do
- data = Gitlab::NoteDataBuilder.build(issue_note, user)
- hipchat.execute(data)
+ context 'when issue comment event triggered' do
+ let(:issue) { create(:issue, project: project) }
+ let(:issue_note) do
+ create(:note_on_issue, noteable: issue, project: project,
+ note: "issue note")
+ end
- message = hipchat.send(:create_message, data)
+ it "should call Hipchat API for issue comment events" do
+ data = Gitlab::NoteDataBuilder.build(issue_note, user)
+ hipchat.execute(data)
- obj_attr = data[:object_attributes]
- issue_id = data[:issue]['iid']
- title = data[:issue]['title']
+ message = hipchat.send(:create_message, data)
- expect(message).to eq("#{user.name} commented on " \
- "<a href=\"#{obj_attr[:url]}\">issue ##{issue_id}</a> in " \
- "<a href=\"#{project.web_url}\">#{project_name}</a>: " \
- "<b>#{title}</b>" \
- "<pre>issue note</pre>")
+ obj_attr = data[:object_attributes]
+ issue_id = data[:issue]['iid']
+ title = data[:issue]['title']
+
+ expect(message).to eq("#{user.name} commented on " \
+ "<a href=\"#{obj_attr[:url]}\">issue ##{issue_id}</a> in " \
+ "<a href=\"#{project.web_url}\">#{project_name}</a>: " \
+ "<b>#{title}</b>" \
+ "<pre>issue note</pre>")
+ end
end
- it "should call Hipchat API for snippet comment events" do
- data = Gitlab::NoteDataBuilder.build(snippet_note, user)
- hipchat.execute(data)
+ context 'when snippet comment event triggered' do
+ let(:snippet) { create(:project_snippet, project: project) }
+ let(:snippet_note) do
+ create(:note_on_project_snippet, noteable: snippet,
+ project: project,
+ note: "snippet note")
+ end
- expect(WebMock).to have_requested(:post, api_url).once
+ it "should call Hipchat API for snippet comment events" do
+ data = Gitlab::NoteDataBuilder.build(snippet_note, user)
+ hipchat.execute(data)
- message = hipchat.send(:create_message, data)
+ expect(WebMock).to have_requested(:post, api_url).once
- obj_attr = data[:object_attributes]
- snippet_id = data[:snippet]['id']
- title = data[:snippet]['title']
+ message = hipchat.send(:create_message, data)
- expect(message).to eq("#{user.name} commented on " \
- "<a href=\"#{obj_attr[:url]}\">snippet ##{snippet_id}</a> in " \
- "<a href=\"#{project.web_url}\">#{project_name}</a>: " \
- "<b>#{title}</b>" \
- "<pre>snippet note</pre>")
+ obj_attr = data[:object_attributes]
+ snippet_id = data[:snippet]['id']
+ title = data[:snippet]['title']
+
+ expect(message).to eq("#{user.name} commented on " \
+ "<a href=\"#{obj_attr[:url]}\">snippet ##{snippet_id}</a> in " \
+ "<a href=\"#{project.web_url}\">#{project_name}</a>: " \
+ "<b>#{title}</b>" \
+ "<pre>snippet note</pre>")
+ end
end
end
diff --git a/spec/models/project_services/slack_service_spec.rb b/spec/models/project_services/slack_service_spec.rb
index a97b7560137..155f3e74e0d 100644
--- a/spec/models/project_services/slack_service_spec.rb
+++ b/spec/models/project_services/slack_service_spec.rb
@@ -142,13 +142,6 @@ describe SlackService, models: true do
let(:slack) { SlackService.new }
let(:user) { create(:user) }
let(:project) { create(:project, creator_id: user.id) }
- let(:issue) { create(:issue, project: project) }
- let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
- let(:snippet) { create(:project_snippet, project: project) }
- let(:commit_note) { create(:note_on_commit, author: user, project: project, commit_id: project.repository.commit.id, note: 'a comment on a commit') }
- let(:merge_request_note) { create(:note_on_merge_request, noteable_id: merge_request.id, note: "merge request note") }
- let(:issue_note) { create(:note_on_issue, noteable_id: issue.id, note: "issue note")}
- let(:snippet_note) { create(:note_on_project_snippet, noteable_id: snippet.id, note: "snippet note") }
let(:webhook_url) { 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685' }
before do
@@ -162,32 +155,61 @@ describe SlackService, models: true do
WebMock.stub_request(:post, webhook_url)
end
- it "should call Slack API for commit comment events" do
- data = Gitlab::NoteDataBuilder.build(commit_note, user)
- slack.execute(data)
+ context 'when commit comment event executed' do
+ let(:commit_note) do
+ create(:note_on_commit, author: user,
+ project: project,
+ commit_id: project.repository.commit.id,
+ note: 'a comment on a commit')
+ end
- expect(WebMock).to have_requested(:post, webhook_url).once
+ it "should call Slack API for commit comment events" do
+ data = Gitlab::NoteDataBuilder.build(commit_note, user)
+ slack.execute(data)
+
+ expect(WebMock).to have_requested(:post, webhook_url).once
+ end
end
- it "should call Slack API for merge request comment events" do
- data = Gitlab::NoteDataBuilder.build(merge_request_note, user)
- slack.execute(data)
+ context 'when merge request comment event executed' do
+ let(:merge_request_note) do
+ create(:note_on_merge_request, project: project,
+ note: "merge request note")
+ end
- expect(WebMock).to have_requested(:post, webhook_url).once
+ it "should call Slack API for merge request comment events" do
+ data = Gitlab::NoteDataBuilder.build(merge_request_note, user)
+ slack.execute(data)
+
+ expect(WebMock).to have_requested(:post, webhook_url).once
+ end
end
- it "should call Slack API for issue comment events" do
- data = Gitlab::NoteDataBuilder.build(issue_note, user)
- slack.execute(data)
+ context 'when issue comment event executed' do
+ let(:issue_note) do
+ create(:note_on_issue, project: project, note: "issue note")
+ end
- expect(WebMock).to have_requested(:post, webhook_url).once
+ it "should call Slack API for issue comment events" do
+ data = Gitlab::NoteDataBuilder.build(issue_note, user)
+ slack.execute(data)
+
+ expect(WebMock).to have_requested(:post, webhook_url).once
+ end
end
- it "should call Slack API for snippet comment events" do
- data = Gitlab::NoteDataBuilder.build(snippet_note, user)
- slack.execute(data)
+ context 'when snippet comment event executed' do
+ let(:snippet_note) do
+ create(:note_on_project_snippet, project: project,
+ note: "snippet note")
+ end
- expect(WebMock).to have_requested(:post, webhook_url).once
+ it "should call Slack API for snippet comment events" do
+ data = Gitlab::NoteDataBuilder.build(snippet_note, user)
+ slack.execute(data)
+
+ expect(WebMock).to have_requested(:post, webhook_url).once
+ end
end
end
end
diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb
index 91ebb612baa..58b57bd4fef 100644
--- a/spec/models/project_wiki_spec.rb
+++ b/spec/models/project_wiki_spec.rb
@@ -16,6 +16,12 @@ describe ProjectWiki, models: true do
end
end
+ describe '#web_url' do
+ it 'returns the full web URL to the wiki' do
+ expect(subject.web_url).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/wikis/home")
+ end
+ end
+
describe "#url_to_repo" do
it "returns the correct ssh url to the repo" do
expect(subject.url_to_repo).to eq(gitlab_shell.url_to_repo(subject.path_with_namespace))
@@ -257,6 +263,13 @@ describe ProjectWiki, models: true do
end
end
+ describe '#hook_attrs' do
+ it 'returns a hash with values' do
+ expect(subject.hook_attrs).to be_a Hash
+ expect(subject.hook_attrs.keys).to contain_exactly(:web_url, :git_ssh_url, :git_http_url, :path_with_namespace, :default_branch)
+ end
+ end
+
private
def create_temp_repo(path)
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 92ec51eabd4..8c2347992f1 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -829,18 +829,6 @@ describe Repository, models: true do
end
end
- describe "#main_language" do
- it 'shows the main language of the project' do
- expect(repository.main_language).to eq("Ruby")
- end
-
- it 'returns nil when the repository is empty' do
- allow(repository).to receive(:empty?).and_return(true)
-
- expect(repository.main_language).to be_nil
- end
- end
-
describe '#before_remove_tag' do
it 'flushes the tag cache' do
expect(repository).to receive(:expire_tag_count_cache)
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 9581990666b..548bec364f8 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -67,7 +67,7 @@ describe User, models: true do
describe 'email' do
context 'when no signup domains listed' do
- before { allow(current_application_settings).to receive(:restricted_signup_domains).and_return([]) }
+ before { allow_any_instance_of(ApplicationSetting).to receive(:restricted_signup_domains).and_return([]) }
it 'accepts any email' do
user = build(:user, email: "info@example.com")
expect(user).to be_valid
@@ -75,7 +75,7 @@ describe User, models: true do
end
context 'when a signup domain is listed and subdomains are allowed' do
- before { allow(current_application_settings).to receive(:restricted_signup_domains).and_return(['example.com', '*.example.com']) }
+ before { allow_any_instance_of(ApplicationSetting).to receive(:restricted_signup_domains).and_return(['example.com', '*.example.com']) }
it 'accepts info@example.com' do
user = build(:user, email: "info@example.com")
expect(user).to be_valid
@@ -93,7 +93,7 @@ describe User, models: true do
end
context 'when a signup domain is listed and subdomains are not allowed' do
- before { allow(current_application_settings).to receive(:restricted_signup_domains).and_return(['example.com']) }
+ before { allow_any_instance_of(ApplicationSetting).to receive(:restricted_signup_domains).and_return(['example.com']) }
it 'accepts info@example.com' do
user = build(:user, email: "info@example.com")
@@ -141,7 +141,7 @@ describe User, models: true do
end
describe '#confirm' do
- before { allow(current_application_settings).to receive(:send_user_confirmation_email).and_return(true) }
+ before { allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(true) }
let(:user) { create(:user, confirmed_at: nil, unconfirmed_email: 'test@gitlab.com') }
it 'returns unconfirmed' do
diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb
index ed1ed5aeb95..beb29a68692 100644
--- a/spec/requests/api/notes_spec.rb
+++ b/spec/requests/api/notes_spec.rb
@@ -258,8 +258,8 @@ describe API::API, api: true do
body: 'Hi!'
end
- it 'responds with 500' do
- expect(response.status).to eq 500
+ it 'responds with resource not found error' do
+ expect(response.status).to eq 404
end
it 'does not create new note' do
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 40b24c125b5..a7690f430c4 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -20,7 +20,7 @@ describe API::API, api: true do
end
context "when authenticated" do
- #These specs are written just in case API authentication is not required anymore
+ # These specs are written just in case API authentication is not required anymore
context "when public level is restricted" do
before do
stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
diff --git a/spec/services/auth/container_registry_authentication_service_spec.rb b/spec/services/auth/container_registry_authentication_service_spec.rb
index 98ef9d21035..67777ad48bc 100644
--- a/spec/services/auth/container_registry_authentication_service_spec.rb
+++ b/spec/services/auth/container_registry_authentication_service_spec.rb
@@ -14,9 +14,24 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
allow_any_instance_of(JSONWebToken::RSAToken).to receive(:key).and_return(rsa_key)
end
- shared_examples 'an authenticated' do
+ shared_examples 'a valid token' do
it { is_expected.to include(:token) }
it { expect(payload).to include('access') }
+
+ context 'a expirable' do
+ let(:expires_at) { Time.at(payload['exp']) }
+ let(:expire_delay) { 10 }
+
+ context 'for default configuration' do
+ it { expect(expires_at).not_to be_within(2.seconds).of(Time.now + expire_delay.minutes) }
+ end
+
+ context 'for changed configuration' do
+ before { stub_application_setting(container_registry_token_expire_delay: expire_delay) }
+
+ it { expect(expires_at).to be_within(2.seconds).of(Time.now + expire_delay.minutes) }
+ end
+ end
end
shared_examples 'a accessible' do
@@ -28,10 +43,15 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
}]
end
- it_behaves_like 'an authenticated'
+ it_behaves_like 'a valid token'
it { expect(payload).to include('access' => access) }
end
+ shared_examples 'an inaccessible' do
+ it_behaves_like 'a valid token'
+ it { expect(payload).to include('access' => []) }
+ end
+
shared_examples 'a pullable' do
it_behaves_like 'a accessible' do
let(:actions) { ['pull'] }
@@ -50,11 +70,6 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
end
end
- shared_examples 'an unauthorized' do
- it { is_expected.to include(http_status: 401) }
- it { is_expected.not_to include(:token) }
- end
-
shared_examples 'a forbidden' do
it { is_expected.to include(http_status: 403) }
it { is_expected.not_to include(:token) }
@@ -75,12 +90,8 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
let(:project) { create(:project) }
let(:current_user) { create(:user) }
- context 'allow to use offline_token' do
- let(:current_params) do
- { offline_token: true }
- end
-
- it_behaves_like 'an authenticated'
+ context 'allow to use scope-less authentication' do
+ it_behaves_like 'a valid token'
end
context 'allow developer to push images' do
@@ -120,19 +131,15 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
{ scope: "repository:#{project.path_with_namespace}:pull,push" }
end
- it_behaves_like 'a forbidden'
+ it_behaves_like 'an inaccessible'
end
end
context 'project authorization' do
let(:current_project) { create(:empty_project) }
- context 'allow to use offline_token' do
- let(:current_params) do
- { offline_token: true }
- end
-
- it_behaves_like 'an authenticated'
+ context 'allow to use scope-less authentication' do
+ it_behaves_like 'a valid token'
end
context 'allow to pull and push images' do
@@ -158,7 +165,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
context 'disallow for private' do
let(:project) { create(:empty_project, :private) }
- it_behaves_like 'a forbidden'
+ it_behaves_like 'an inaccessible'
end
end
@@ -169,7 +176,7 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
context 'disallow for all' do
let(:project) { create(:empty_project, :public) }
- it_behaves_like 'a forbidden'
+ it_behaves_like 'an inaccessible'
end
end
end
@@ -184,18 +191,14 @@ describe Auth::ContainerRegistryAuthenticationService, services: true do
{ scope: "repository:#{project.path_with_namespace}:pull" }
end
- it_behaves_like 'a forbidden'
+ it_behaves_like 'an inaccessible'
end
end
end
context 'unauthorized' do
- context 'disallow to use offline_token' do
- let(:current_params) do
- { offline_token: true }
- end
-
- it_behaves_like 'an unauthorized'
+ context 'disallow to use scope-less authentication' do
+ it_behaves_like 'a forbidden'
end
context 'for invalid scope' do
diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb
index eeab540c2fd..18692f1279a 100644
--- a/spec/services/git_push_service_spec.rb
+++ b/spec/services/git_push_service_spec.rb
@@ -158,49 +158,6 @@ describe GitPushService, services: true do
end
end
- describe "Updates main language" do
- context "before push" do
- it { expect(project.main_language).to eq(nil) }
- end
-
- context "after push" do
- def execute
- execute_service(project, user, @oldrev, @newrev, ref)
- end
-
- context "to master" do
- let(:ref) { @ref }
-
- context 'when main_language is nil' do
- it 'obtains the language from the repository' do
- expect(project.repository).to receive(:main_language)
- execute
- end
-
- it 'sets the project main language' do
- execute
- expect(project.main_language).to eq("Ruby")
- end
- end
-
- context 'when main_language is already set' do
- it 'does not check the repository' do
- execute # do an initial run to simulate lang being preset
- expect(project.repository).not_to receive(:main_language)
- execute
- end
- end
- end
-
- context "to other branch" do
- let(:ref) { 'refs/heads/feature/branch' }
-
- it { expect(project.main_language).to eq(nil) }
- end
- end
- end
-
-
describe "Updates git attributes" do
context "for default branch" do
it "calls the copy attributes method for the first push to the default branch" do
diff --git a/spec/services/groups/create_service_spec.rb b/spec/services/groups/create_service_spec.rb
index a97ac3ead45..71a0b8e2a12 100644
--- a/spec/services/groups/create_service_spec.rb
+++ b/spec/services/groups/create_service_spec.rb
@@ -13,7 +13,7 @@ describe Groups::CreateService, services: true do
end
context "cannot create group with restricted visibility level" do
- before { allow(current_application_settings).to receive(:restricted_visibility_levels).and_return([Gitlab::VisibilityLevel::PUBLIC]) }
+ before { allow_any_instance_of(ApplicationSetting).to receive(:restricted_visibility_levels).and_return([Gitlab::VisibilityLevel::PUBLIC]) }
it { is_expected.not_to be_persisted }
end
end
diff --git a/spec/services/issues/bulk_update_service_spec.rb b/spec/services/issues/bulk_update_service_spec.rb
index e91906d0d49..96f050bbd9b 100644
--- a/spec/services/issues/bulk_update_service_spec.rb
+++ b/spec/services/issues/bulk_update_service_spec.rb
@@ -15,9 +15,7 @@ describe Issues::BulkUpdateService, services: true do
describe :close_issue do
before do
- @issues = 5.times.collect do
- create(:issue, project: @project)
- end
+ @issues = create_list(:issue, 5, project: @project)
@params = {
state_event: 'close',
issues_ids: @issues.map(&:id)
@@ -36,11 +34,8 @@ describe Issues::BulkUpdateService, services: true do
end
describe :reopen_issues do
-
before do
- @issues = 5.times.collect do
- create(:closed_issue, project: @project)
- end
+ @issues = create_list(:closed_issue, 5, project: @project)
@params = {
state_event: 'reopen',
issues_ids: @issues.map(&:id)
diff --git a/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb b/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb
index 82247849814..0861d74aede 100644
--- a/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb
+++ b/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb
@@ -1,8 +1,8 @@
require 'spec_helper'
describe MergeRequests::MergeWhenBuildSucceedsService do
- let(:user) { create(:user) }
- let(:merge_request) { create(:merge_request) }
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
let(:mr_merge_if_green_enabled) do
create(:merge_request, merge_when_build_succeeds: true, merge_user: user,
@@ -10,11 +10,15 @@ describe MergeRequests::MergeWhenBuildSucceedsService do
source_project: project, target_project: project, state: "opened")
end
- let(:project) { create(:project) }
let(:ci_commit) { create(:ci_commit_with_one_job, ref: mr_merge_if_green_enabled.source_branch, project: project) }
let(:service) { MergeRequests::MergeWhenBuildSucceedsService.new(project, user, commit_message: 'Awesome message') }
describe "#execute" do
+ let(:merge_request) do
+ create(:merge_request, target_project: project, source_project: project,
+ source_branch: "feature", target_branch: 'master')
+ end
+
context 'first time enabling' do
before do
allow(merge_request).to receive(:ci_commit).and_return(ci_commit)
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index ee976eb2926..29e0a63d8ce 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -208,8 +208,10 @@ describe SystemNoteService, services: true do
end
describe '.merge_when_build_succeeds' do
- let(:ci_commit) { build :ci_commit_without_jobs }
- let(:noteable) { create :merge_request }
+ let(:ci_commit) { build(:ci_commit_without_jobs )}
+ let(:noteable) do
+ create(:merge_request, source_project: project, target_project: project)
+ end
subject { described_class.merge_when_build_succeeds(noteable, project, author, noteable.last_commit) }
@@ -221,8 +223,10 @@ describe SystemNoteService, services: true do
end
describe '.cancel_merge_when_build_succeeds' do
- let(:ci_commit) { build :ci_commit_without_jobs }
- let(:noteable) { create :merge_request }
+ let(:ci_commit) { build(:ci_commit_without_jobs) }
+ let(:noteable) do
+ create(:merge_request, source_project: project, target_project: project)
+ end
subject { described_class.cancel_merge_when_build_succeeds(noteable, project, author) }
diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb
index cd9fdc6f18e..7a0f078c72b 100644
--- a/spec/support/login_helpers.rb
+++ b/spec/support/login_helpers.rb
@@ -26,11 +26,13 @@ module LoginHelpers
# Internal: Login as the specified user
#
- # user - User instance to login with
- def login_with(user)
+ # user - User instance to login with
+ # remember - Whether or not to check "Remember me" (default: false)
+ def login_with(user, remember: false)
visit new_user_session_path
fill_in "user_login", with: user.email
fill_in "user_password", with: "12345678"
+ check 'user_remember_me' if remember
click_button "Sign in"
Thread.current[:current_user] = user
end
diff --git a/spec/teaspoon_env.rb b/spec/teaspoon_env.rb
index 58f45ff8610..69b2b9b6d5b 100644
--- a/spec/teaspoon_env.rb
+++ b/spec/teaspoon_env.rb
@@ -41,11 +41,11 @@ Teaspoon.configure do |config|
suite.matcher = "{spec/javascripts,app/assets}/**/*_spec.{js,js.coffee,coffee}"
# Load additional JS files, but requiring them in your spec helper is the preferred way to do this.
- #suite.javascripts = []
+ # suite.javascripts = []
# You can include your own stylesheets if you want to change how Teaspoon looks.
# Note: Spec related CSS can and should be loaded using fixtures.
- #suite.stylesheets = ["teaspoon"]
+ # suite.stylesheets = ["teaspoon"]
# This suites spec helper, which can require additional support files. This file is loaded before any of your test
# files are loaded.
@@ -62,19 +62,19 @@ Teaspoon.configure do |config|
# Hooks allow you to use `Teaspoon.hook("fixtures")` before, after, or during your spec run. This will make a
# synchronous Ajax request to the server that will call all of the blocks you've defined for that hook name.
- #suite.hook :fixtures, &proc{}
+ # suite.hook :fixtures, &proc{}
# Determine whether specs loaded into the test harness should be embedded as individual script tags or concatenated
- # into a single file. Similar to Rails' asset `debug: true` and `config.assets.debug = true` options. By default,
+ # into a single file. Similar to Rails' asset `debug: true` and `config.assets.debug = true` options. By default,
# Teaspoon expands all assets to provide more valuable stack traces that reference individual source files.
- #suite.expand_assets = true
+ # suite.expand_assets = true
end
# Example suite. Since we're just filtering to files already within the root test/javascripts, these files will also
# be run in the default suite -- but can be focused into a more specific suite.
- #config.suite :targeted do |suite|
+ # config.suite :targeted do |suite|
# suite.matcher = "spec/javascripts/targeted/*_spec.{js,js.coffee,coffee}"
- #end
+ # end
# CONSOLE RUNNER SPECIFIC
#
@@ -94,45 +94,45 @@ Teaspoon.configure do |config|
# PhantomJS: https://github.com/modeset/teaspoon/wiki/Using-PhantomJS
# Selenium Webdriver: https://github.com/modeset/teaspoon/wiki/Using-Selenium-WebDriver
# Capybara Webkit: https://github.com/modeset/teaspoon/wiki/Using-Capybara-Webkit
- #config.driver = :phantomjs
+ # config.driver = :phantomjs
# Specify additional options for the driver.
#
# PhantomJS: https://github.com/modeset/teaspoon/wiki/Using-PhantomJS
# Selenium Webdriver: https://github.com/modeset/teaspoon/wiki/Using-Selenium-WebDriver
# Capybara Webkit: https://github.com/modeset/teaspoon/wiki/Using-Capybara-Webkit
- #config.driver_options = nil
+ # config.driver_options = nil
# Specify the timeout for the driver. Specs are expected to complete within this time frame or the run will be
# considered a failure. This is to avoid issues that can arise where tests stall.
- #config.driver_timeout = 180
+ # config.driver_timeout = 180
# Specify a server to use with Rack (e.g. thin, mongrel). If nil is provided Rack::Server is used.
- #config.server = nil
+ # config.server = nil
# Specify a port to run on a specific port, otherwise Teaspoon will use a random available port.
- #config.server_port = nil
+ # config.server_port = nil
# Timeout for starting the server in seconds. If your server is slow to start you may have to bump this, or you may
# want to lower this if you know it shouldn't take long to start.
- #config.server_timeout = 20
+ # config.server_timeout = 20
# Force Teaspoon to fail immediately after a failing suite. Can be useful to make Teaspoon fail early if you have
# several suites, but in environments like CI this may not be desirable.
- #config.fail_fast = true
+ # config.fail_fast = true
# Specify the formatters to use when outputting the results.
# Note: Output files can be specified by using `"junit>/path/to/output.xml"`.
#
# Available: :dot, :clean, :documentation, :json, :junit, :pride, :rspec_html, :snowday, :swayze_or_oprah, :tap, :tap_y, :teamcity
- #config.formatters = [:dot]
+ # config.formatters = [:dot]
# Specify if you want color output from the formatters.
- #config.color = true
+ # config.color = true
# Teaspoon pipes all console[log/debug/error] to $stdout. This is useful to catch places where you've forgotten to
# remove them, but in verbose applications this may not be desirable.
- #config.suppress_log = false
+ # config.suppress_log = false
# COVERAGE REPORTS / THRESHOLD ASSERTIONS
#
@@ -149,7 +149,7 @@ Teaspoon.configure do |config|
# Specify that you always want a coverage configuration to be used. Otherwise, specify that you want coverage
# on the CLI.
# Set this to "true" or the name of your coverage config.
- #config.use_coverage = nil
+ # config.use_coverage = nil
# You can have multiple coverage configs by passing a name to config.coverage.
# e.g. config.coverage :ci do |coverage|
@@ -158,21 +158,21 @@ Teaspoon.configure do |config|
# Which coverage reports Istanbul should generate. Correlates directly to what Istanbul supports.
#
# Available: text-summary, text, html, lcov, lcovonly, cobertura, teamcity
- #coverage.reports = ["text-summary", "html"]
+ # coverage.reports = ["text-summary", "html"]
# The path that the coverage should be written to - when there's an artifact to write to disk.
# Note: Relative to `config.root`.
- #coverage.output_path = "coverage"
+ # coverage.output_path = "coverage"
# Assets to be ignored when generating coverage reports. Accepts an array of filenames or regular expressions. The
# default excludes assets from vendor, gems and support libraries.
- #coverage.ignore = [%r{/lib/ruby/gems/}, %r{/vendor/assets/}, %r{/support/}, %r{/(.+)_helper.}]
+ # coverage.ignore = [%r{/lib/ruby/gems/}, %r{/vendor/assets/}, %r{/support/}, %r{/(.+)_helper.}]
# Various thresholds requirements can be defined, and those thresholds will be checked at the end of a run. If any
# aren't met the run will fail with a message. Thresholds can be defined as a percentage (0-100), or nil.
- #coverage.statements = nil
- #coverage.functions = nil
- #coverage.branches = nil
- #coverage.lines = nil
+ # coverage.statements = nil
+ # coverage.functions = nil
+ # coverage.branches = nil
+ # coverage.lines = nil
end
end