From b125fb4bcb637bd842db7d018d8f9c60303d9beb Mon Sep 17 00:00:00 2001 From: Matt Lee Date: Fri, 20 Jan 2017 10:55:32 -0500 Subject: WIP: This makes the default sort order for branches 'recently updated' rather than by name. --- app/controllers/projects/branches_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index 89d84809e3a..07a0a51855b 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -7,7 +7,7 @@ class Projects::BranchesController < Projects::ApplicationController before_action :authorize_push_code!, only: [:new, :create, :destroy, :destroy_all_merged] def index - @sort = params[:sort].presence || sort_value_name + @sort = params[:sort].presence || sort_value_recently_updated @branches = BranchesFinder.new(@repository, params).execute @branches = Kaminari.paginate_array(@branches).page(params[:page]) -- cgit v1.2.3 From ac1667f286242a9af7709b3f6711ef08380abd3e Mon Sep 17 00:00:00 2001 From: Chad Malchow Date: Tue, 4 Apr 2017 17:39:32 +0000 Subject: added article from techbeacon on CI --- doc/university/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/university/README.md b/doc/university/README.md index c1661f0b52b..88dac143356 100644 --- a/doc/university/README.md +++ b/doc/university/README.md @@ -121,6 +121,7 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project 1. [Setting up GitLab CI for iOS projects](https://about.gitlab.com/2016/03/10/setting-up-gitlab-ci-for-ios-projects/) 1. [IBM: Continuous Delivery vs Continuous Deployment - Video](https://www.youtube.com/watch?v=igwFj8PPSnw) 1. [Amazon: Transition to Continuous Delivery - Video](https://www.youtube.com/watch?v=esEFaY0FDKc) +2. [TechBeacon: Doing continuous delivery? Focus first on reducing release cycle times](https://techbeacon.com/doing-continuous-delivery-focus-first-reducing-release-cycle-times) 1. See **[Integrations](#integrations)** for integrations with other CI services. #### 2.4. Workflow -- cgit v1.2.3 From 7e165327712e24efa94673cfd180ebb361eaa7bd Mon Sep 17 00:00:00 2001 From: Simon Knox Date: Tue, 25 Jul 2017 19:02:13 +1000 Subject: fix :focus styles for selected filter dropdown items --- app/assets/stylesheets/framework/filters.scss | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss index 41184907abb..2b2afdb0e3e 100644 --- a/app/assets/stylesheets/framework/filters.scss +++ b/app/assets/stylesheets/framework/filters.scss @@ -413,13 +413,16 @@ background-color: $dropdown-hover-color; color: $white-light; text-decoration: none; + outline: 0; .avatar { border-color: $white-light; } } -.filter-dropdown-item { +.droplab-dropdown .dropdown-menu .filter-dropdown-item { + padding: 0; + .btn { border: none; width: 100%; @@ -454,14 +457,11 @@ } .dropdown-user { - display: -webkit-flex; display: flex; } .dropdown-user-details { - display: -webkit-flex; display: flex; - -webkit-flex-direction: column; flex-direction: column; > span { -- cgit v1.2.3 From 3a90f6a418857d342427c3c7e1b6689c5e97bbee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=AAnis=20Volpato=20Martins?= Date: Tue, 25 Jul 2017 18:12:33 -0300 Subject: Docs: fix HAProxy name and exporter's link --- doc/user/project/integrations/prometheus_library/haproxy.md | 8 ++++---- doc/user/project/integrations/prometheus_library/metrics.md | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/user/project/integrations/prometheus_library/haproxy.md b/doc/user/project/integrations/prometheus_library/haproxy.md index 309da610cc0..f2939f047a3 100644 --- a/doc/user/project/integrations/prometheus_library/haproxy.md +++ b/doc/user/project/integrations/prometheus_library/haproxy.md @@ -1,7 +1,7 @@ -# Monitoring HA Proxy +# Monitoring HAProxy > [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12621) in GitLab 9.4 -GitLab has support for automatically detecting and monitoring HA Proxy. This is provided by leveraging the [HA Proxy Exporter](https://github.com/hnlq715/nginx-vts-exporter), which translates HA Proxy statistics into a Prometheus readable form. +GitLab has support for automatically detecting and monitoring HAProxy. This is provided by leveraging the [HAProxy Exporter](https://github.com/prometheus/haproxy_exporter), which translates HAProxy statistics into a Prometheus readable form. ## Metrics supported @@ -10,9 +10,9 @@ GitLab has support for automatically detecting and monitoring HA Proxy. This is | Throughput (req/sec) | sum(rate(haproxy_frontend_http_requests_total{%{environment_filter}}[2m])) | | HTTP Error Rate (%) | sum(rate(haproxy_frontend_http_requests_total{code="5xx",%{environment_filter}}[2m])) / sum(rate(haproxy_frontend_http_requests_total{%{environment_filter}}[2m])) | -## Configuring Prometheus to monitor for HA Proxy metrics +## Configuring Prometheus to monitor for HAProxy metrics -To get started with NGINX monitoring, you should install and configure the [HA Proxy exporter](https://github.com/prometheus/haproxy_exporter) which parses these statistics and translates them into a Prometheus monitoring endpoint. +To get started with NGINX monitoring, you should install and configure the [HAProxy exporter](https://github.com/prometheus/haproxy_exporter) which parses these statistics and translates them into a Prometheus monitoring endpoint. ## Specifying the Environment label diff --git a/doc/user/project/integrations/prometheus_library/metrics.md b/doc/user/project/integrations/prometheus_library/metrics.md index 546e1f51df5..6bdffce9c55 100644 --- a/doc/user/project/integrations/prometheus_library/metrics.md +++ b/doc/user/project/integrations/prometheus_library/metrics.md @@ -4,7 +4,7 @@ GitLab offers automatic detection of select [Prometheus exporters](https://prometheus.io/docs/instrumenting/exporters/). Currently supported exporters are: * [Kubernetes](kubernetes.md) * [NGINX](nginx.md) -* [HA Proxy](haproxy.md) +* [HAProxy](haproxy.md) * [Amazon Cloud Watch](cloudwatch.md) We have tried to surface the most important metrics for each exporter, and will be continuing to add support for additional exporters in future releases. If you would like to add support for other official exporters, [contributions](#adding-to-the-library) are welcome. -- cgit v1.2.3 From af8667bc7218a7c84773d661d0eafda00c0d1d82 Mon Sep 17 00:00:00 2001 From: Paulo Bezerra Date: Tue, 25 Jul 2017 18:30:23 -0300 Subject: Enhance pt-BR translation in Project and Repository pages --- locale/pt_BR/gitlab.po | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po index 78cf6d2dacc..ee00b816b84 100644 --- a/locale/pt_BR/gitlab.po +++ b/locale/pt_BR/gitlab.po @@ -413,14 +413,14 @@ msgstr[0] "Fork" msgstr[1] "Forks" msgid "ForkedFromProjectPath|Forked from" -msgstr "Forked de" +msgstr "Fork criado a partir de" msgid "From issue creation until deploy to production" msgstr "Da abertura de tarefas até a implantação para a produção" msgid "From merge request merge until deploy to production" msgstr "" -"Da aceitação da solicitação de incorporação até a implantação em produção" +"Do merge request até a implantação em produção" msgid "Go to your fork" msgstr "Ir para seu fork" @@ -576,7 +576,7 @@ msgid "NotificationEvent|Successful pipeline" msgstr "Pipeline bem sucedido" msgid "NotificationLevel|Custom" -msgstr "Personalizar" +msgstr "Personalizado" msgid "NotificationLevel|Disabled" msgstr "Desabilitado" @@ -881,9 +881,9 @@ msgid "" "the issue to a milestone, or add the issue to a list on your Issue Board. " "Begin creating issues to see data for this stage." msgstr "" -"A etapa de relatos mostra o tempo que leva desde a criação de uma issue até " -"sua atribuição a um marco, ou sua adição a uma lista no seu Issue Board. " -"Comece a criar issues para ver dados para esta etapa." +"A etapa de planejamento mostra o tempo que se leva desde a criação de uma " +"issue até sua atribuição à um milestone, ou sua adição a uma lista no seu " +"Issue Board. Comece a criar issues para ver dados para esta etapa." msgid "The phase of the development lifecycle." msgstr "A fase do ciclo de vida do desenvolvimento." @@ -974,7 +974,7 @@ msgid "Time before an issue gets scheduled" msgstr "Tempo até que uma issue seja agendada" msgid "Time before an issue starts implementation" -msgstr "Tempo até que uma issue comece a ser implementado" +msgstr "Tempo até que uma issue comece a ser implementada" msgid "Time between merge request creation and merge/close" msgstr "" -- cgit v1.2.3 From a94e91a45b8fb861060a901b5bcfa218d597a208 Mon Sep 17 00:00:00 2001 From: Alex Lossent Date: Thu, 27 Jul 2017 14:52:42 +0200 Subject: Log web hook execution timeout events If a web hook HTTP request is sent but no response comes within a certain time (10s by default), the hook execution fails and will be retried. This commit makes such timeouts visible in the web hook log, like connection timeouts already are. Also log "no route to host" errors. --- app/services/web_hook_service.rb | 2 +- spec/services/web_hook_service_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/services/web_hook_service.rb b/app/services/web_hook_service.rb index a5110a23cad..27c3ba197ac 100644 --- a/app/services/web_hook_service.rb +++ b/app/services/web_hook_service.rb @@ -44,7 +44,7 @@ class WebHookService http_status: response.code, message: response.to_s } - rescue SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED, Net::OpenTimeout => e + rescue SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Net::OpenTimeout, Net::ReadTimeout => e log_execution( trigger: hook_name, url: hook.url, diff --git a/spec/services/web_hook_service_spec.rb b/spec/services/web_hook_service_spec.rb index 7ff37c22963..76f35443e55 100644 --- a/spec/services/web_hook_service_spec.rb +++ b/spec/services/web_hook_service_spec.rb @@ -53,7 +53,7 @@ describe WebHookService, services: true do end it 'handles exceptions' do - exceptions = [SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED, Net::OpenTimeout] + exceptions = [SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Net::OpenTimeout, Net::ReadTimeout] exceptions.each do |exception_class| exception = exception_class.new('Exception message') -- cgit v1.2.3 From 2cc1658489fe2d2de4052db36b21a788195cfc1b Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Tue, 25 Jul 2017 10:41:43 +0200 Subject: Project New moved to external File --- app/assets/javascripts/projects/project_new.js | 43 ++++++++++++++++++++++++ app/views/projects/new.html.haml | 45 ++------------------------ config/webpack.config.js | 1 + 3 files changed, 46 insertions(+), 43 deletions(-) create mode 100644 app/assets/javascripts/projects/project_new.js diff --git a/app/assets/javascripts/projects/project_new.js b/app/assets/javascripts/projects/project_new.js new file mode 100644 index 00000000000..4f87df8e160 --- /dev/null +++ b/app/assets/javascripts/projects/project_new.js @@ -0,0 +1,43 @@ +document.addEventListener('DOMContentLoaded', () => { + const importBtnTooltip = 'Please enter a valid project name.'; + const $importBtnWrapper = $('.import_gitlab_project'); + + $('.how_to_import_link').bind('click', function (e) { + e.preventDefault(); + $(this).next('.modal').show(); + }); + + $('.modal-header .close').bind('click', () => { + $('.modal').hide(); + }); + + $('.btn_import_gitlab_project').bind('click', () => { + const importHref = $('a.btn_import_gitlab_project').attr('href'); + $('.btn_import_gitlab_project').attr('href', `${importHref}?namespace_id=${$('#project_namespace_id').val()}&path=${$('#project_path').val()}`); + }); + + $('.btn_import_gitlab_project').attr('disabled', $('#project_path').val().trim().length === 0); + $importBtnWrapper.attr('title', importBtnTooltip); + + $('#new_project').submit(() => { + const $path = $('#project_path'); + $path.val($path.val().trim()); + }); + + $('#project_path').keyup(() => { + if ($(this).val().trim().length !== 0) { + $('.btn_import_gitlab_project').attr('disabled', false); + $importBtnWrapper.attr('title', ''); + $importBtnWrapper.removeClass('has-tooltip'); + } else { + $('.btn_import_gitlab_project').attr('disabled', true); + $importBtnWrapper.addClass('has-tooltip'); + } + }); + + $('#project_import_url').disable(); + $('.import_git').click(() => { + const $projectImportUrl = $('#project_import_url'); + $projectImportUrl.attr('disabled', !$projectImportUrl.attr('disabled')); + }); +}); diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index 87cc23fc649..25109f0f414 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -4,6 +4,8 @@ - page_title 'New Project' - header_title "Projects", dashboard_projects_path - visibility_level = params.dig(:project, :visibility_level) || default_project_visibility +- content_for :page_specific_javascripts do + = webpack_bundle_tag 'project_new' .project-edit-container .project-edit-errors @@ -111,46 +113,3 @@ %i.fa.fa-spinner.fa-spin Creating project & repository. %p Please wait a moment, this page will automatically refresh when ready. - -:javascript - var importBtnTooltip = "Please enter a valid project name."; - var $importBtnWrapper = $('.import_gitlab_project'); - - $('.how_to_import_link').bind('click', function (e) { - e.preventDefault(); - var import_modal = $(this).next(".modal").show(); - }); - - $('.modal-header .close').bind('click', function() { - $(".modal").hide(); - }); - - $('.btn_import_gitlab_project').bind('click', function() { - var _href = $("a.btn_import_gitlab_project").attr("href"); - $(".btn_import_gitlab_project").attr("href", _href + '?namespace_id=' + $("#project_namespace_id").val() + '&path=' + $("#project_path").val()); - }); - - $('.btn_import_gitlab_project').attr('disabled', $('#project_path').val().trim().length === 0); - $importBtnWrapper.attr('title', importBtnTooltip); - - $('#new_project').submit(function(){ - var $path = $('#project_path'); - $path.val($path.val().trim()); - }); - - $('#project_path').keyup(function(){ - if($(this).val().trim().length !== 0) { - $('.btn_import_gitlab_project').attr('disabled', false); - $importBtnWrapper.attr('title',''); - $importBtnWrapper.removeClass('has-tooltip'); - } else { - $('.btn_import_gitlab_project').attr('disabled',true); - $importBtnWrapper.addClass('has-tooltip'); - } - }); - - $('#project_import_url').disable(); - $('.import_git').click(function( event ) { - $projectImportUrl = $('#project_import_url'); - $projectImportUrl.attr('disabled', !$projectImportUrl.attr('disabled')); - }); diff --git a/config/webpack.config.js b/config/webpack.config.js index f08daa2fddb..902c60b84cb 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -56,6 +56,7 @@ var config = { pipelines: './pipelines/pipelines_bundle.js', pipelines_details: './pipelines/pipeline_details_bundle.js', profile: './profile/profile_bundle.js', + project_new: './projects/project_new.js', prometheus_metrics: './prometheus_metrics', protected_branches: './protected_branches', protected_tags: './protected_tags', -- cgit v1.2.3 From 364a2a2759feb28c3dbc006b79ec81c123aba7bc Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Tue, 25 Jul 2017 10:44:45 +0200 Subject: Set New Tags to ignore Inline JS --- app/views/projects/tags/new.html.haml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml index f1bbaf40387..ceb2547034a 100644 --- a/app/views/projects/tags/new.html.haml +++ b/app/views/projects/tags/new.html.haml @@ -41,6 +41,7 @@ = button_tag 'Create tag', class: 'btn btn-create', tabindex: 3 = link_to 'Cancel', project_tags_path(@project), class: 'btn btn-cancel' +-# haml-lint:disable InlineJavaScript :javascript window.gl = window.gl || { }; window.gl.availableRefs = #{@project.repository.ref_names.to_json}; -- cgit v1.2.3 From 24d9142cabcf8b09a9954c2ccd9b429c86ba683d Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Tue, 25 Jul 2017 10:51:21 +0200 Subject: Inline JS of Wiki Sidebar to dispatcher --- app/assets/javascripts/dispatcher.js | 1 + app/views/projects/wikis/_sidebar.html.haml | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index 1dc6edacfed..99d9ab3cacd 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -511,6 +511,7 @@ import PerformanceBar from './performance_bar'; shortcut_handler = new ShortcutsWiki(); new ZenMode(); new gl.GLForm($('.wiki-form'), true); + new Sidebar(); break; case 'snippets': shortcut_handler = new ShortcutsNavigation(); diff --git a/app/views/projects/wikis/_sidebar.html.haml b/app/views/projects/wikis/_sidebar.html.haml index 62873d3aa66..e71ce1f357f 100644 --- a/app/views/projects/wikis/_sidebar.html.haml +++ b/app/views/projects/wikis/_sidebar.html.haml @@ -19,6 +19,3 @@ More Pages = render 'projects/wikis/new' - -:javascript - new Sidebar(); -- cgit v1.2.3 From 395e34bd0fd32e6f8d8145f14d71ea3c1350b46f Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Tue, 25 Jul 2017 11:45:08 +0200 Subject: Changed the data for New Tag to a script block --- app/assets/javascripts/dispatcher.js | 2 +- app/views/projects/tags/new.html.haml | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index 99d9ab3cacd..6aa0d10ea5d 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -250,7 +250,7 @@ import PerformanceBar from './performance_bar'; case 'projects:tags:new': new ZenMode(); new gl.GLForm($('.tag-form'), true); - new RefSelectDropdown($('.js-branch-select'), window.gl.availableRefs); + new RefSelectDropdown($('.js-branch-select'), JSON.parse(document.getElementById('availableRefs').innerHTML)); break; case 'projects:snippets:new': case 'projects:snippets:edit': diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml index ceb2547034a..521b4d927bc 100644 --- a/app/views/projects/tags/new.html.haml +++ b/app/views/projects/tags/new.html.haml @@ -40,8 +40,4 @@ .form-actions = button_tag 'Create tag', class: 'btn btn-create', tabindex: 3 = link_to 'Cancel', project_tags_path(@project), class: 'btn btn-cancel' - --# haml-lint:disable InlineJavaScript -:javascript - window.gl = window.gl || { }; - window.gl.availableRefs = #{@project.repository.ref_names.to_json}; +%script#availableRefs{ type: "application/json" }= @project.repository.ref_names.to_json.html_safe -- cgit v1.2.3 From 84a3ab25fe9dd9002c8c47976d7f17fc2a897071 Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Tue, 25 Jul 2017 12:12:30 +0200 Subject: Moved Inline JS for Pipelines Charts + new Pipeline to dispatcher --- app/assets/javascripts/dispatcher.js | 4 ++++ .../javascripts/pipelines/pipelines_times.js | 27 ++++++++++++++++++++++ .../projects/pipelines/charts/_pipeline_times.haml | 5 ++++ app/views/projects/pipelines/new.html.haml | 5 +--- config/webpack.config.js | 3 ++- 5 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 app/assets/javascripts/pipelines/pipelines_times.js diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index 6aa0d10ea5d..4c84a88274d 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -8,6 +8,7 @@ /* global LabelsSelect */ /* global MilestoneSelect */ /* global Commit */ +/* global NewBranchForm */ /* global NotificationsForm */ /* global NotificationsDropdown */ /* global GroupAvatar */ @@ -316,6 +317,9 @@ import PerformanceBar from './performance_bar'; case 'projects:edit': setupProjectEdit(); break; + case 'projects:pipelines:new': + new NewBranchForm($('.js-new-pipeline-form'), JSON.parse(document.getElementById('availableRefs').innerHTML)); + break; case 'projects:pipelines:builds': case 'projects:pipelines:failures': case 'projects:pipelines:show': diff --git a/app/assets/javascripts/pipelines/pipelines_times.js b/app/assets/javascripts/pipelines/pipelines_times.js new file mode 100644 index 00000000000..b5e7a0e53d9 --- /dev/null +++ b/app/assets/javascripts/pipelines/pipelines_times.js @@ -0,0 +1,27 @@ +import Chart from 'vendor/Chart'; + +document.addEventListener('DOMContentLoaded', () => { + const chartData = JSON.parse(document.getElementById('pipelinesTimesChartsData').innerHTML); + const data = { + labels: chartData.labels, + datasets: [{ + fillColor: 'rgba(220,220,220,0.5)', + strokeColor: 'rgba(220,220,220,1)', + barStrokeWidth: 1, + barValueSpacing: 1, + barDatasetSpacing: 1, + data: chartData.values, + }], + }; + const ctx = $('#build_timesChart').get(0).getContext('2d'); + const options = { + scaleOverlay: true, + responsive: true, + maintainAspectRatio: false, + }; + if (window.innerWidth < 768) { + // Scale fonts if window width lower than 768px (iPad portrait) + options.scaleFontSize = 8; + } + new Chart(ctx).Bar(data, options); +}); diff --git a/app/views/projects/pipelines/charts/_pipeline_times.haml b/app/views/projects/pipelines/charts/_pipeline_times.haml index 1292f580a81..55477a922e7 100644 --- a/app/views/projects/pipelines/charts/_pipeline_times.haml +++ b/app/views/projects/pipelines/charts/_pipeline_times.haml @@ -1,9 +1,14 @@ +- content_for :page_specific_javascripts do + = webpack_bundle_tag('pipelines_times') + %div %p.light = _("Commit duration in minutes for last 30 commits") %canvas#build_timesChart{ height: 200 } +%script#pipelinesTimesChartsData{ type: "application/json" }= { :labels => @charts[:pipeline_times].labels, :values => @charts[:pipeline_times].pipeline_times }.to_json.html_safe + :javascript var data = { labels : #{@charts[:pipeline_times].labels.to_json}, diff --git a/app/views/projects/pipelines/new.html.haml b/app/views/projects/pipelines/new.html.haml index c966df62856..4ad37d0e882 100644 --- a/app/views/projects/pipelines/new.html.haml +++ b/app/views/projects/pipelines/new.html.haml @@ -20,7 +20,4 @@ = f.submit 'Create pipeline', class: 'btn btn-create', tabindex: 3 = link_to 'Cancel', project_pipelines_path(@project), class: 'btn btn-cancel' -:javascript - var availableRefs = #{@project.repository.ref_names.to_json}; - - new NewBranchForm($('.js-new-pipeline-form'), availableRefs) +%script#availableRefs{ type: "application/json" }= @project.repository.ref_names.to_json.html_safe diff --git a/config/webpack.config.js b/config/webpack.config.js index 902c60b84cb..9a9399cbf02 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -54,7 +54,8 @@ var config = { notebook_viewer: './blob/notebook_viewer.js', pdf_viewer: './blob/pdf_viewer.js', pipelines: './pipelines/pipelines_bundle.js', - pipelines_details: './pipelines/pipeline_details_bundle.js', + pipelines_details: './pipelines/pipeline_details_bundle.js', + pipelines_times: './pipelines/pipelines_times.js', profile: './profile/profile_bundle.js', project_new: './projects/project_new.js', prometheus_metrics: './prometheus_metrics', -- cgit v1.2.3 From 57d2db4c0730a75c4ac932adc3613949550a0279 Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Tue, 25 Jul 2017 12:48:45 +0200 Subject: TreeContent moved to external JS --- app/assets/javascripts/dispatcher.js | 3 +++ app/views/projects/tree/_tree_content.html.haml | 8 +------- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index 4c84a88274d..bb15b14bb98 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -373,6 +373,9 @@ import PerformanceBar from './performance_bar'; shortcut_handler = new ShortcutsNavigation(); new TreeView(); new BlobViewer(); + $('#tree-slider').waitForImages(function() { + gl.utils.ajaxGet(document.querySelector('.js-tree-content').dataset.logsPath); + }); break; case 'projects:find_file:show': shortcut_handler = true; diff --git a/app/views/projects/tree/_tree_content.html.haml b/app/views/projects/tree/_tree_content.html.haml index 6560bd5ab3f..bdd1623c075 100644 --- a/app/views/projects/tree/_tree_content.html.haml +++ b/app/views/projects/tree/_tree_content.html.haml @@ -1,4 +1,4 @@ -.tree-content-holder +.tree-content-holder.js-tree-content{ 'data-logs-path': escape_javascript(@logs_path)} .table-holder %table.table#tree-slider{ class: "table_#{@hex_path} tree-table" } %thead @@ -22,9 +22,3 @@ - if can_edit_tree? = render 'projects/blob/upload', title: _('Upload New File'), placeholder: _('Upload New File'), button_title: _('Upload file'), form_path: project_create_blob_path(@project, @id), method: :post = render 'projects/blob/new_dir' - -:javascript - // Load last commit log for each file in tree - $('#tree-slider').waitForImages(function() { - gl.utils.ajaxGet("#{escape_javascript(@logs_path)}"); - }); -- cgit v1.2.3 From f149a76b2d9ab8f5249a8d613c4c3f9153201d3e Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Tue, 25 Jul 2017 13:19:27 +0200 Subject: Converted Pipelines Charts --- .../javascripts/pipelines/pipelines_charts.js | 38 ++++++++++++++++++++++ .../projects/pipelines/charts/_pipeline_times.haml | 22 ------------- .../projects/pipelines/charts/_pipelines.haml | 36 +++++--------------- config/webpack.config.js | 1 + 4 files changed, 47 insertions(+), 50 deletions(-) create mode 100644 app/assets/javascripts/pipelines/pipelines_charts.js diff --git a/app/assets/javascripts/pipelines/pipelines_charts.js b/app/assets/javascripts/pipelines/pipelines_charts.js new file mode 100644 index 00000000000..001faf4be33 --- /dev/null +++ b/app/assets/javascripts/pipelines/pipelines_charts.js @@ -0,0 +1,38 @@ +import Chart from 'vendor/Chart'; + +document.addEventListener('DOMContentLoaded', () => { + const chartData = JSON.parse(document.getElementById('pipelinesChartsData').innerHTML); + const buildChart = (chartScope) => { + const data = { + labels: chartScope.labels, + datasets: [{ + fillColor: '#7f8fa4', + strokeColor: '#7f8fa4', + pointColor: '#7f8fa4', + pointStrokeColor: '#EEE', + data: chartScope.totalValues, + }, + { + fillColor: '#44aa22', + strokeColor: '#44aa22', + pointColor: '#44aa22', + pointStrokeColor: '#fff', + data: chartScope.successValues, + }, + ], + }; + const ctx = $(`#${chartScope.scope}Chart`).get(0).getContext('2d'); + const options = { + scaleOverlay: true, + responsive: true, + maintainAspectRatio: false, + }; + if (window.innerWidth < 768) { + // Scale fonts if window width lower than 768px (iPad portrait) + options.scaleFontSize = 8; + } + new Chart(ctx).Line(data, options); + }; + + chartData.forEach(scope => buildChart(scope)); +}); diff --git a/app/views/projects/pipelines/charts/_pipeline_times.haml b/app/views/projects/pipelines/charts/_pipeline_times.haml index 55477a922e7..a5dbd1b1532 100644 --- a/app/views/projects/pipelines/charts/_pipeline_times.haml +++ b/app/views/projects/pipelines/charts/_pipeline_times.haml @@ -8,25 +8,3 @@ %canvas#build_timesChart{ height: 200 } %script#pipelinesTimesChartsData{ type: "application/json" }= { :labels => @charts[:pipeline_times].labels, :values => @charts[:pipeline_times].pipeline_times }.to_json.html_safe - -:javascript - var data = { - labels : #{@charts[:pipeline_times].labels.to_json}, - datasets : [ - { - fillColor : "rgba(220,220,220,0.5)", - strokeColor : "rgba(220,220,220,1)", - barStrokeWidth: 1, - barValueSpacing: 1, - barDatasetSpacing: 1, - data : #{@charts[:pipeline_times].pipeline_times.to_json} - } - ] - } - var ctx = $("#build_timesChart").get(0).getContext("2d"); - var options = { scaleOverlay: true, responsive: true, maintainAspectRatio: false }; - if (window.innerWidth < 768) { - // Scale fonts if window width lower than 768px (iPad portrait) - options.scaleFontSize = 8 - } - new Chart(ctx).Bar(data, options); diff --git a/app/views/projects/pipelines/charts/_pipelines.haml b/app/views/projects/pipelines/charts/_pipelines.haml index be884448087..9de22b39d23 100644 --- a/app/views/projects/pipelines/charts/_pipelines.haml +++ b/app/views/projects/pipelines/charts/_pipelines.haml @@ -1,3 +1,6 @@ +- content_for :page_specific_javascripts do + = webpack_bundle_tag('pipelines_charts') + %h4= _("Pipelines charts") %p   @@ -26,31 +29,8 @@ = _("Jobs for last year") %canvas#yearChart.padded{ height: 250 } -- [:week, :month, :year].each do |scope| - :javascript - var data = { - labels : #{@charts[scope].labels.to_json}, - datasets : [ - { - fillColor : "#7f8fa4", - strokeColor : "#7f8fa4", - pointColor : "#7f8fa4", - pointStrokeColor : "#EEE", - data : #{@charts[scope].total.to_json} - }, - { - fillColor : "#44aa22", - strokeColor : "#44aa22", - pointColor : "#44aa22", - pointStrokeColor : "#fff", - data : #{@charts[scope].success.to_json} - } - ] - } - var ctx = $("##{scope}Chart").get(0).getContext("2d"); - var options = { scaleOverlay: true, responsive: true, maintainAspectRatio: false }; - if (window.innerWidth < 768) { - // Scale fonts if window width lower than 768px (iPad portrait) - options.scaleFontSize = 8 - } - new Chart(ctx).Line(data, options); +%script#pipelinesChartsData{ type: "application/json" } + - chartData = [] + - [:week, :month, :year].each do |scope| + - chartData.push({ 'scope' => scope, 'labels' => @charts[scope].labels, 'totalValues' => @charts[scope].total, 'successValues' => @charts[scope].success }) + = chartData.to_json.html_safe diff --git a/config/webpack.config.js b/config/webpack.config.js index 9a9399cbf02..18d28256a8b 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -54,6 +54,7 @@ var config = { notebook_viewer: './blob/notebook_viewer.js', pdf_viewer: './blob/pdf_viewer.js', pipelines: './pipelines/pipelines_bundle.js', + pipelines_charts: './pipelines/pipelines_charts.js', pipelines_details: './pipelines/pipeline_details_bundle.js', pipelines_times: './pipelines/pipelines_times.js', profile: './profile/profile_bundle.js', -- cgit v1.2.3 From cad80263ade171b9e6bb80156d3222323e6be691 Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Tue, 25 Jul 2017 15:02:24 +0200 Subject: Fixes New Project Bug --- app/assets/javascripts/projects/project_new.js | 6 +++--- app/views/projects/pipelines/charts/_pipelines.haml | 2 +- app/views/projects/tree/_tree_content.html.haml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/projects/project_new.js b/app/assets/javascripts/projects/project_new.js index 4f87df8e160..e3fcf218cfb 100644 --- a/app/assets/javascripts/projects/project_new.js +++ b/app/assets/javascripts/projects/project_new.js @@ -2,9 +2,9 @@ document.addEventListener('DOMContentLoaded', () => { const importBtnTooltip = 'Please enter a valid project name.'; const $importBtnWrapper = $('.import_gitlab_project'); - $('.how_to_import_link').bind('click', function (e) { + $('.how_to_import_link').bind('click', (e) => { e.preventDefault(); - $(this).next('.modal').show(); + $('.how_to_import_link').next('.modal').show(); }); $('.modal-header .close').bind('click', () => { @@ -25,7 +25,7 @@ document.addEventListener('DOMContentLoaded', () => { }); $('#project_path').keyup(() => { - if ($(this).val().trim().length !== 0) { + if ($('#project_path').val().trim().length !== 0) { $('.btn_import_gitlab_project').attr('disabled', false); $importBtnWrapper.attr('title', ''); $importBtnWrapper.removeClass('has-tooltip'); diff --git a/app/views/projects/pipelines/charts/_pipelines.haml b/app/views/projects/pipelines/charts/_pipelines.haml index 9de22b39d23..02f1ef4b6da 100644 --- a/app/views/projects/pipelines/charts/_pipelines.haml +++ b/app/views/projects/pipelines/charts/_pipelines.haml @@ -30,7 +30,7 @@ %canvas#yearChart.padded{ height: 250 } %script#pipelinesChartsData{ type: "application/json" } - - chartData = [] + - chartData = [] - [:week, :month, :year].each do |scope| - chartData.push({ 'scope' => scope, 'labels' => @charts[scope].labels, 'totalValues' => @charts[scope].total, 'successValues' => @charts[scope].success }) = chartData.to_json.html_safe diff --git a/app/views/projects/tree/_tree_content.html.haml b/app/views/projects/tree/_tree_content.html.haml index bdd1623c075..ac3c784375d 100644 --- a/app/views/projects/tree/_tree_content.html.haml +++ b/app/views/projects/tree/_tree_content.html.haml @@ -1,4 +1,4 @@ -.tree-content-holder.js-tree-content{ 'data-logs-path': escape_javascript(@logs_path)} +.tree-content-holder.js-tree-content{ 'data-logs-path': escape_javascript(@logs_path) } .table-holder %table.table#tree-slider{ class: "table_#{@hex_path} tree-table" } %thead -- cgit v1.2.3 From 79793dd16294a5f75b790d53c6f5aae5a33774f4 Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Tue, 25 Jul 2017 16:10:48 +0200 Subject: Due to more async loading the tests could fail, trying to fix it with wait_for_requests --- spec/features/projects/user_browses_files_spec.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/features/projects/user_browses_files_spec.rb b/spec/features/projects/user_browses_files_spec.rb index 263a3a29a66..d2a57981379 100644 --- a/spec/features/projects/user_browses_files_spec.rb +++ b/spec/features/projects/user_browses_files_spec.rb @@ -87,6 +87,8 @@ describe 'User browses files' do visit(project_tree_path(project, "'test'")) + wait_for_requests + expect(page).to have_css('.tree-commit-link', visible: true) expect(page).not_to have_content('Loading commit data...') end @@ -100,6 +102,8 @@ describe 'User browses files' do visit(project_tree_path(project, 'fix/.testdir')) + wait_for_requests + expect(page).to have_css('.tree-commit-link', visible: true) expect(page).not_to have_content('Loading commit data...') end -- cgit v1.2.3 From 49f2c6c11c0d3428afcf67e2f6f10748af5641a8 Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Tue, 25 Jul 2017 16:10:48 +0200 Subject: Revert "Due to more async loading the tests could fail, trying to fix it with wait_for_requests" This reverts commit 0c33f384bb2fd2bd97efa4d3fec2888393683fb1. --- spec/features/projects/user_browses_files_spec.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/spec/features/projects/user_browses_files_spec.rb b/spec/features/projects/user_browses_files_spec.rb index d2a57981379..263a3a29a66 100644 --- a/spec/features/projects/user_browses_files_spec.rb +++ b/spec/features/projects/user_browses_files_spec.rb @@ -87,8 +87,6 @@ describe 'User browses files' do visit(project_tree_path(project, "'test'")) - wait_for_requests - expect(page).to have_css('.tree-commit-link', visible: true) expect(page).not_to have_content('Loading commit data...') end @@ -102,8 +100,6 @@ describe 'User browses files' do visit(project_tree_path(project, 'fix/.testdir')) - wait_for_requests - expect(page).to have_css('.tree-commit-link', visible: true) expect(page).not_to have_content('Loading commit data...') end -- cgit v1.2.3 From f05bcf54ab25728e53bca8e24ceb8c7db2157cfa Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Wed, 26 Jul 2017 10:07:39 +0200 Subject: Maybe that fixes the escaping in the URL --- app/views/projects/tree/_tree_content.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/tree/_tree_content.html.haml b/app/views/projects/tree/_tree_content.html.haml index ac3c784375d..3fb2fba9973 100644 --- a/app/views/projects/tree/_tree_content.html.haml +++ b/app/views/projects/tree/_tree_content.html.haml @@ -1,4 +1,4 @@ -.tree-content-holder.js-tree-content{ 'data-logs-path': escape_javascript(@logs_path) } +.tree-content-holder.js-tree-content{ 'data-logs-path': "#{escape_javascript(@logs_path)}" } .table-holder %table.table#tree-slider{ class: "table_#{@hex_path} tree-table" } %thead -- cgit v1.2.3 From bede3e5f31b79f0cd423895ecb1341dae0eb8e35 Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Wed, 26 Jul 2017 19:37:20 +0200 Subject: Fixed the strange escaping --- app/views/projects/tree/_tree_content.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/tree/_tree_content.html.haml b/app/views/projects/tree/_tree_content.html.haml index 3fb2fba9973..b5221bcfc82 100644 --- a/app/views/projects/tree/_tree_content.html.haml +++ b/app/views/projects/tree/_tree_content.html.haml @@ -1,4 +1,4 @@ -.tree-content-holder.js-tree-content{ 'data-logs-path': "#{escape_javascript(@logs_path)}" } +.tree-content-holder.js-tree-content{ 'data-logs-path': @logs_path }" } .table-holder %table.table#tree-slider{ class: "table_#{@hex_path} tree-table" } %thead -- cgit v1.2.3 From b762b254335372881ede4f6aa8c4dbb0aaf655da Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Thu, 27 Jul 2017 09:29:55 +0200 Subject: Left a bracket in the line :-/ --- app/views/projects/tree/_tree_content.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/tree/_tree_content.html.haml b/app/views/projects/tree/_tree_content.html.haml index b5221bcfc82..820b947804e 100644 --- a/app/views/projects/tree/_tree_content.html.haml +++ b/app/views/projects/tree/_tree_content.html.haml @@ -1,4 +1,4 @@ -.tree-content-holder.js-tree-content{ 'data-logs-path': @logs_path }" } +.tree-content-holder.js-tree-content{ 'data-logs-path': @logs_path } .table-holder %table.table#tree-slider{ class: "table_#{@hex_path} tree-table" } %thead -- cgit v1.2.3 From c4938045062a1aea90d29ffb3ac38e6cdd40780e Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Thu, 27 Jul 2017 18:44:03 +0300 Subject: Explain all possible values of 'only' and 'except' --- doc/ci/yaml/README.md | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index e12ef6e2685..1869782fe6e 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -441,13 +441,25 @@ There are a few rules that apply to the usage of refs policy: * `only` and `except` are inclusive. If both `only` and `except` are defined in a job specification, the ref is filtered by `only` and `except`. * `only` and `except` allow the use of regular expressions. -* `only` and `except` allow the use of special keywords: -`api`, `branches`, `external`, `tags`, `pushes`, `schedules`, `triggers`, and `web` * `only` and `except` allow to specify a repository path to filter jobs for forks. +In addition, `only` and `except` allow the use of special keywords: + +| **Value** | **Description** | +| --------- | ---------------- | +| `branches` | When a branch is pushed. | +| `tags` | When a tag is pushed. | +| `api` | When pipeline has been triggered by a second pipelines API (not triggers API). | +| `external` | When using CI services other than GitLab. | +| `pipelines` | For multi-project triggers, created using the API with `CI_JOB_TOKEN`. | +| `pushes` | Pipeline is triggered by a `git push` by the user. | +| `schedules` | For [scheduled pipelines][schedules]. | +| `triggers` | For pipelines created using a trigger token. | +| `web` | For pipelines created using **Run pipeline** button in GitLab UI (under your project's **Pipelines**). | + In the example below, `job` will run only for refs that start with `issue-`, -whereas all branches will be skipped. +whereas all branches will be skipped: ```yaml job: @@ -460,7 +472,7 @@ job: ``` In this example, `job` will run only for refs that are tagged, or if a build is -explicitly requested via an API trigger or a [Pipeline Schedule](../../user/project/pipelines/schedules.md). +explicitly requested via an API trigger or a [Pipeline Schedule][schedules]: ```yaml job: @@ -1532,3 +1544,4 @@ CI with various languages. [ce-7983]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7983 [ce-7447]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7447 [ce-3442]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3442 +[schedules]: ../../user/project/pipelines/schedules.md -- cgit v1.2.3 From 29a8827752b884f5e4cad4ec78cf5b655aa5c769 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 28 Jul 2017 10:56:50 +0200 Subject: Improve deploy environment chatops slash command We now match deployment actions better. If there is more than one deployment action matched, we check if there is an action which name equals to environment name, instead of raising an error about too many actions defined. --- lib/gitlab/slash_commands/deploy.rb | 33 +++++++------ lib/gitlab/slash_commands/presenters/deploy.rb | 11 ++--- spec/lib/gitlab/slash_commands/deploy_spec.rb | 56 +++++++++++++++++----- .../slash_commands/presenters/deploy_spec.rb | 20 ++------ 4 files changed, 69 insertions(+), 51 deletions(-) diff --git a/lib/gitlab/slash_commands/deploy.rb b/lib/gitlab/slash_commands/deploy.rb index e71eb15d604..93e00ab75a1 100644 --- a/lib/gitlab/slash_commands/deploy.rb +++ b/lib/gitlab/slash_commands/deploy.rb @@ -21,29 +21,34 @@ module Gitlab from = match[:from] to = match[:to] - actions = find_actions(from, to) + action = find_action(from, to) - if actions.none? - Gitlab::SlashCommands::Presenters::Deploy.new(nil).no_actions - elsif actions.one? - action = play!(from, to, actions.first) - Gitlab::SlashCommands::Presenters::Deploy.new(action).present(from, to) + if action.nil? + Gitlab::SlashCommands::Presenters::Deploy + .new(action).action_not_found else - Gitlab::SlashCommands::Presenters::Deploy.new(actions).too_many_actions + deployment = action.play(current_user) + + Gitlab::SlashCommands::Presenters::Deploy + .new(deployment).present(from, to) end end private - def play!(from, to, action) - action.play(current_user) - end - - def find_actions(from, to) + def find_action(from, to) environment = project.environments.find_by(name: from) - return [] unless environment + return unless environment - environment.actions_for(to).select(&:starts_environment?) + actions = environment.actions_for(to).select do |action| + action.starts_environment? + end + + if actions.many? + actions.find { |action| action.name == to.to_s } + else + actions.first + end end end end diff --git a/lib/gitlab/slash_commands/presenters/deploy.rb b/lib/gitlab/slash_commands/presenters/deploy.rb index b8dc77bd37b..b72586394bc 100644 --- a/lib/gitlab/slash_commands/presenters/deploy.rb +++ b/lib/gitlab/slash_commands/presenters/deploy.rb @@ -3,17 +3,14 @@ module Gitlab module Presenters class Deploy < Presenters::Base def present(from, to) - message = "Deployment started from #{from} to #{to}. [Follow its progress](#{resource_url})." + message = "Deployment started from #{from} to #{to}. " \ + "[Follow its progress](#{resource_url})." in_channel_response(text: message) end - def no_actions - ephemeral_response(text: "No action found to be executed") - end - - def too_many_actions - ephemeral_response(text: "Too many actions defined") + def action_not_found + ephemeral_response(text: "Couldn't find a deployment action.") end end end diff --git a/spec/lib/gitlab/slash_commands/deploy_spec.rb b/spec/lib/gitlab/slash_commands/deploy_spec.rb index e52aaed7328..17ebd088936 100644 --- a/spec/lib/gitlab/slash_commands/deploy_spec.rb +++ b/spec/lib/gitlab/slash_commands/deploy_spec.rb @@ -22,7 +22,7 @@ describe Gitlab::SlashCommands::Deploy do context 'if no environment is defined' do it 'does not execute an action' do expect(subject[:response_type]).to be(:ephemeral) - expect(subject[:text]).to eq("No action found to be executed") + expect(subject[:text]).to eq "Couldn't find a deployment action." end end @@ -35,12 +35,12 @@ describe Gitlab::SlashCommands::Deploy do context 'without actions' do it 'does not execute an action' do expect(subject[:response_type]).to be(:ephemeral) - expect(subject[:text]).to eq("No action found to be executed") + expect(subject[:text]).to eq "Couldn't find a deployment action." end end - context 'with action' do - let!(:manual1) do + context 'when single action has been matched' do + before do create(:ci_build, :manual, pipeline: pipeline, name: 'first', environment: 'production') @@ -48,31 +48,61 @@ describe Gitlab::SlashCommands::Deploy do it 'returns success result' do expect(subject[:response_type]).to be(:in_channel) - expect(subject[:text]).to start_with('Deployment started from staging to production') + expect(subject[:text]) + .to start_with('Deployment started from staging to production') end + end + + context 'when more than one action has been matched' do + context 'when there is no specific actions with a environment name' do + before do + create(:ci_build, :manual, pipeline: pipeline, + name: 'first', + environment: 'production') - context 'when duplicate action exists' do - let!(:manual2) do create(:ci_build, :manual, pipeline: pipeline, name: 'second', environment: 'production') end - it 'returns error' do + it 'returns error about too many actions defined' do + expect(subject[:text]).to eq("Couldn't find a deployment action.") expect(subject[:response_type]).to be(:ephemeral) - expect(subject[:text]).to eq('Too many actions defined') end end - context 'when teardown action exists' do - let!(:teardown) do + context 'when one of the actions is environement specific action' do + before do + create(:ci_build, :manual, pipeline: pipeline, + name: 'first', + environment: 'production') + + create(:ci_build, :manual, pipeline: pipeline, + name: 'production', + environment: 'production') + end + + it 'deploys to production' do + expect(subject[:text]) + .to start_with('Deployment started from staging to production') + expect(subject[:response_type]).to be(:in_channel) + end + end + + context 'when one of the actions is a teardown action' do + before do + create(:ci_build, :manual, pipeline: pipeline, + name: 'first', + environment: 'production') + create(:ci_build, :manual, :teardown_environment, pipeline: pipeline, name: 'teardown', environment: 'production') end - it 'returns the success message' do + it 'deploys to production' do + expect(subject[:text]) + .to start_with('Deployment started from staging to production') expect(subject[:response_type]).to be(:in_channel) - expect(subject[:text]).to start_with('Deployment started from staging to production') end end end diff --git a/spec/lib/gitlab/slash_commands/presenters/deploy_spec.rb b/spec/lib/gitlab/slash_commands/presenters/deploy_spec.rb index dee3c77db27..eb94578c8e7 100644 --- a/spec/lib/gitlab/slash_commands/presenters/deploy_spec.rb +++ b/spec/lib/gitlab/slash_commands/presenters/deploy_spec.rb @@ -17,8 +17,8 @@ describe Gitlab::SlashCommands::Presenters::Deploy do end end - describe '#no_actions' do - subject { described_class.new(nil).no_actions } + describe '#action_not_found' do + subject { described_class.new(nil).action_not_found } it { is_expected.to have_key(:text) } it { is_expected.to have_key(:response_type) } @@ -27,21 +27,7 @@ describe Gitlab::SlashCommands::Presenters::Deploy do it 'tells the user there is no action' do expect(subject[:response_type]).to be(:ephemeral) - expect(subject[:text]).to eq("No action found to be executed") - end - end - - describe '#too_many_actions' do - subject { described_class.new([]).too_many_actions } - - it { is_expected.to have_key(:text) } - it { is_expected.to have_key(:response_type) } - it { is_expected.to have_key(:status) } - it { is_expected.not_to have_key(:attachments) } - - it 'tells the user there is no action' do - expect(subject[:response_type]).to be(:ephemeral) - expect(subject[:text]).to eq("Too many actions defined") + expect(subject[:text]).to eq "Couldn't find a deployment action." end end end -- cgit v1.2.3 From 8663b63af34f7b79930ad94c39e128c4c28e2a1d Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Fri, 28 Jul 2017 10:57:11 +0200 Subject: Updated Event Handlers based on MR discussion --- app/assets/javascripts/projects/project_new.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/projects/project_new.js b/app/assets/javascripts/projects/project_new.js index e3fcf218cfb..2091b275c3d 100644 --- a/app/assets/javascripts/projects/project_new.js +++ b/app/assets/javascripts/projects/project_new.js @@ -2,30 +2,30 @@ document.addEventListener('DOMContentLoaded', () => { const importBtnTooltip = 'Please enter a valid project name.'; const $importBtnWrapper = $('.import_gitlab_project'); - $('.how_to_import_link').bind('click', (e) => { + $('.how_to_import_link').on('click', (e) => { e.preventDefault(); $('.how_to_import_link').next('.modal').show(); }); - $('.modal-header .close').bind('click', () => { + $('.modal-header .close').on('click', () => { $('.modal').hide(); }); - $('.btn_import_gitlab_project').bind('click', () => { + $('.btn_import_gitlab_project').on('click', () => { const importHref = $('a.btn_import_gitlab_project').attr('href'); $('.btn_import_gitlab_project').attr('href', `${importHref}?namespace_id=${$('#project_namespace_id').val()}&path=${$('#project_path').val()}`); }); - $('.btn_import_gitlab_project').attr('disabled', $('#project_path').val().trim().length === 0); + $('.btn_import_gitlab_project').attr('disabled', !$('#project_path').val().trim().length); $importBtnWrapper.attr('title', importBtnTooltip); - $('#new_project').submit(() => { + $('#new_project').on('submit', () => { const $path = $('#project_path'); $path.val($path.val().trim()); }); - $('#project_path').keyup(() => { - if ($('#project_path').val().trim().length !== 0) { + $('#project_path').on('keyup', () => { + if ($('#project_path').val().trim().length) { $('.btn_import_gitlab_project').attr('disabled', false); $importBtnWrapper.attr('title', ''); $importBtnWrapper.removeClass('has-tooltip'); @@ -36,7 +36,7 @@ document.addEventListener('DOMContentLoaded', () => { }); $('#project_import_url').disable(); - $('.import_git').click(() => { + $('.import_git').on('click', () => { const $projectImportUrl = $('#project_import_url'); $projectImportUrl.attr('disabled', !$projectImportUrl.attr('disabled')); }); -- cgit v1.2.3 From 712aa2a81c5764c91ca2d2d3d877c975beed6121 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 28 Jul 2017 11:02:10 +0200 Subject: Add changelog entry for deploy chatops command fix --- .../fix-gb-fix-chatops-deploy-multiple-actions-matching.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelogs/unreleased/fix-gb-fix-chatops-deploy-multiple-actions-matching.yml diff --git a/changelogs/unreleased/fix-gb-fix-chatops-deploy-multiple-actions-matching.yml b/changelogs/unreleased/fix-gb-fix-chatops-deploy-multiple-actions-matching.yml new file mode 100644 index 00000000000..62488a0a2e3 --- /dev/null +++ b/changelogs/unreleased/fix-gb-fix-chatops-deploy-multiple-actions-matching.yml @@ -0,0 +1,4 @@ +--- +title: Improve deploy environment chatops slash command +merge_request: 13150 +author: -- cgit v1.2.3 From 08a241d606633fa2b2c7c32c84b3d846dece035b Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Fri, 28 Jul 2017 11:07:57 +0200 Subject: Moved the duplicate Available Refs to a default in RefSelectDropdown --- app/assets/javascripts/dispatcher.js | 4 ++-- app/assets/javascripts/ref_select_dropdown.js | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index bb15b14bb98..29dcd460e93 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -251,7 +251,7 @@ import PerformanceBar from './performance_bar'; case 'projects:tags:new': new ZenMode(); new gl.GLForm($('.tag-form'), true); - new RefSelectDropdown($('.js-branch-select'), JSON.parse(document.getElementById('availableRefs').innerHTML)); + new RefSelectDropdown($('.js-branch-select')); break; case 'projects:snippets:new': case 'projects:snippets:edit': @@ -318,7 +318,7 @@ import PerformanceBar from './performance_bar'; setupProjectEdit(); break; case 'projects:pipelines:new': - new NewBranchForm($('.js-new-pipeline-form'), JSON.parse(document.getElementById('availableRefs').innerHTML)); + new NewBranchForm($('.js-new-pipeline-form')); break; case 'projects:pipelines:builds': case 'projects:pipelines:failures': diff --git a/app/assets/javascripts/ref_select_dropdown.js b/app/assets/javascripts/ref_select_dropdown.js index 215cd6fbdfd..65e4101352c 100644 --- a/app/assets/javascripts/ref_select_dropdown.js +++ b/app/assets/javascripts/ref_select_dropdown.js @@ -1,7 +1,8 @@ class RefSelectDropdown { constructor($dropdownButton, availableRefs) { + const availableRefsValue = availableRefs || JSON.parse(document.getElementById('availableRefs').innerHTML); $dropdownButton.glDropdown({ - data: availableRefs, + data: availableRefsValue, filterable: true, filterByText: true, remote: false, -- cgit v1.2.3 From e2f73c8685cc73066553adc25013b4125cccc849 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 28 Jul 2017 11:09:12 +0200 Subject: Update docs regarding deploy chatops slash command --- doc/integration/slash_commands.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/doc/integration/slash_commands.md b/doc/integration/slash_commands.md index 5d880ba785c..288ad1f7f5e 100644 --- a/doc/integration/slash_commands.md +++ b/doc/integration/slash_commands.md @@ -2,7 +2,11 @@ Slash commands in Mattermost and Slack allow you to control GitLab and view GitLab content right inside your chat client, without having to leave it. For Slack, this requires a [project service configuration](../user/project/integrations/slack_slash_commands.md). Simply type the command as a message in your chat client to activate it. -Commands are scoped to a project, with a trigger term that is specified during configuration. (We suggest you use the project name as the trigger term for simplicty and clarity.) Taking the trigger term as `project-name`, the commands are: +Commands are scoped to a project, with a trigger term that is specified during configuration. + +We suggest you use the project name as the trigger term for simplicity and clarity. + +Taking the trigger term as `project-name`, the commands are: | Command | Effect | @@ -12,3 +16,18 @@ Commands are scoped to a project, with a trigger term that is specified during c | `/project-name issue show ` | Shows the issue with id `` | | `/project-name issue search ` | Shows up to 5 issues matching `` | | `/project-name deploy to ` | Deploy from the `` environment to the `` environment | + +## Issue commands + +It is possible to create new issue, display issue details and search up to 5 issues. + +## Deploy command + +In order to deploy to an environment, GitLab will try to find a deployment +action in the pipeline. + +If there is only one action for a given environment, it is going to be triggered. +If there is more than one action defined, GitLab will try to find an action +which name equals the environment name we want to deploy to. + +Command will return an error when no matching action has been found. -- cgit v1.2.3 From 07bcabb305f62e445c77ca8081b473adf21f56da Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 28 Jul 2017 12:16:07 +0200 Subject: Improve wording related to deploy chatops command --- doc/integration/slash_commands.md | 2 +- lib/gitlab/slash_commands/presenters/deploy.rb | 2 +- spec/lib/gitlab/slash_commands/command_spec.rb | 2 +- spec/lib/gitlab/slash_commands/deploy_spec.rb | 6 +++--- spec/lib/gitlab/slash_commands/presenters/deploy_spec.rb | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/integration/slash_commands.md b/doc/integration/slash_commands.md index 288ad1f7f5e..aa52b5415cf 100644 --- a/doc/integration/slash_commands.md +++ b/doc/integration/slash_commands.md @@ -24,7 +24,7 @@ It is possible to create new issue, display issue details and search up to 5 iss ## Deploy command In order to deploy to an environment, GitLab will try to find a deployment -action in the pipeline. +manual action in the pipeline. If there is only one action for a given environment, it is going to be triggered. If there is more than one action defined, GitLab will try to find an action diff --git a/lib/gitlab/slash_commands/presenters/deploy.rb b/lib/gitlab/slash_commands/presenters/deploy.rb index b72586394bc..ebae0f57f9b 100644 --- a/lib/gitlab/slash_commands/presenters/deploy.rb +++ b/lib/gitlab/slash_commands/presenters/deploy.rb @@ -10,7 +10,7 @@ module Gitlab end def action_not_found - ephemeral_response(text: "Couldn't find a deployment action.") + ephemeral_response(text: "Couldn't find a deployment manual action.") end end end diff --git a/spec/lib/gitlab/slash_commands/command_spec.rb b/spec/lib/gitlab/slash_commands/command_spec.rb index f0ecf59406a..88f73bf90cd 100644 --- a/spec/lib/gitlab/slash_commands/command_spec.rb +++ b/spec/lib/gitlab/slash_commands/command_spec.rb @@ -80,7 +80,7 @@ describe Gitlab::SlashCommands::Command do it 'returns error' do expect(subject[:response_type]).to be(:ephemeral) - expect(subject[:text]).to include('Too many actions defined') + expect(subject[:text]).to include("Couldn't find a deployment manual action.") end end end diff --git a/spec/lib/gitlab/slash_commands/deploy_spec.rb b/spec/lib/gitlab/slash_commands/deploy_spec.rb index 17ebd088936..c3fb7d5adea 100644 --- a/spec/lib/gitlab/slash_commands/deploy_spec.rb +++ b/spec/lib/gitlab/slash_commands/deploy_spec.rb @@ -22,7 +22,7 @@ describe Gitlab::SlashCommands::Deploy do context 'if no environment is defined' do it 'does not execute an action' do expect(subject[:response_type]).to be(:ephemeral) - expect(subject[:text]).to eq "Couldn't find a deployment action." + expect(subject[:text]).to eq "Couldn't find a deployment manual action." end end @@ -35,7 +35,7 @@ describe Gitlab::SlashCommands::Deploy do context 'without actions' do it 'does not execute an action' do expect(subject[:response_type]).to be(:ephemeral) - expect(subject[:text]).to eq "Couldn't find a deployment action." + expect(subject[:text]).to eq "Couldn't find a deployment manual action." end end @@ -66,7 +66,7 @@ describe Gitlab::SlashCommands::Deploy do end it 'returns error about too many actions defined' do - expect(subject[:text]).to eq("Couldn't find a deployment action.") + expect(subject[:text]).to eq("Couldn't find a deployment manual action.") expect(subject[:response_type]).to be(:ephemeral) end end diff --git a/spec/lib/gitlab/slash_commands/presenters/deploy_spec.rb b/spec/lib/gitlab/slash_commands/presenters/deploy_spec.rb index eb94578c8e7..d16d122c64e 100644 --- a/spec/lib/gitlab/slash_commands/presenters/deploy_spec.rb +++ b/spec/lib/gitlab/slash_commands/presenters/deploy_spec.rb @@ -27,7 +27,7 @@ describe Gitlab::SlashCommands::Presenters::Deploy do it 'tells the user there is no action' do expect(subject[:response_type]).to be(:ephemeral) - expect(subject[:text]).to eq "Couldn't find a deployment action." + expect(subject[:text]).to eq "Couldn't find a deployment manual action." end end end -- cgit v1.2.3 From 5899294583219c34c8fd5afea02587f80b5c4c48 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Fri, 28 Jul 2017 13:47:41 +0300 Subject: Add link to JIRA article in docs --- doc/user/project/integrations/jira.md | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/doc/user/project/integrations/jira.md b/doc/user/project/integrations/jira.md index cfa4c8a93f8..4f583879a4e 100644 --- a/doc/user/project/integrations/jira.md +++ b/doc/user/project/integrations/jira.md @@ -1,18 +1,22 @@ # GitLab JIRA integration -GitLab can be configured to interact with JIRA. Configuration happens via -user name and password. Connecting to a JIRA server via CAS is not possible. +GitLab can be configured to interact with [JIRA], a project management platform. -Each project can be configured to connect to a different JIRA instance, see the -[configuration](#configuration) section. If you have one JIRA instance you can -pre-fill the settings page with a default template. To configure the template -see the [Services Templates][services-templates] document. +Once your GitLab project is connected to JIRA, you can reference and close the +issues in JIRA directly from GitLab. -Once the project is connected to JIRA, you can reference and close the issues -in JIRA directly from GitLab. +For a use case, check out this article of [How and why to integrate GitLab with +JIRA](https://www.programmableweb.com/news/how-and-why-to-integrate-gitlab-jira/how-to/2017/04/25). ## Configuration +Each GitLab project can be configured to connect to a different JIRA instance. +If you have one JIRA instance you can pre-fill the settings page with a default +template, see the [Services Templates][services-templates] docs. + +Configuration happens via user name and password. Connecting to a JIRA server +via CAS is not possible. + In order to enable the JIRA service in GitLab, you need to first configure the project in JIRA and then enter the correct values in GitLab. @@ -213,3 +217,4 @@ your project needs to close a ticket. [services-templates]: services_templates.md [jira-repo-old-docs]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-13-stable/doc/project_services/jira.md +[jira]: https://www.atlassian.com/software/jira -- cgit v1.2.3 From 6ef87a20832d1a2581cb85e60eda46f999c55a81 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Wed, 19 Jul 2017 16:03:50 +0200 Subject: Merge issuable "reopened" state into "opened" Having two states that essentially mean the same thing is very much like having a boolean "true" and boolean "mostly-true": it's rather silly. This commit merges the "reopened" state into the "opened" state while taking care of system notes still showing messages along the lines of "Alice reopened this issue". A big benefit from having only two states (opened and closed) is that indexing and querying becomes simpler and more performant. For example, to get all the opened queries we no longer have to query both states: SELECT * FROM issues WHERE project_id = 2 AND state IN ('opened', 'reopened'); Instead we can query a single state directly, which can be much faster: SELECT * FROM issues WHERE project_id = 2 AND state = 'opened'; Further, only having two states makes indexing easier as we will only ever filter (and thus scan an index) using a single value. Partial indexes could help but aren't supported on MySQL, complicating the development process and not being helpful for MySQL. --- .../stores/mr_widget_store.js | 2 +- app/finders/issuable_finder.rb | 1 - app/models/concerns/issuable.rb | 5 ++-- app/models/issue.rb | 5 ++-- app/models/merge_request.rb | 13 ++++----- app/models/project_services/drone_ci_service.rb | 2 +- app/services/issues/reopen_service.rb | 6 ++-- app/services/merge_requests/base_service.rb | 6 ++-- app/services/merge_requests/reopen_service.rb | 2 +- .../merge-issuable-reopened-into-opened-state.yml | 4 +++ ...01_merge_issuable_reopened_into_opened_state.rb | 32 ++++++++++++++++++++++ spec/factories/issues.rb | 6 +--- spec/factories/merge_requests.rb | 6 +--- .../banzai/filter/issuable_state_filter_spec.rb | 10 +------ spec/requests/api/issues_spec.rb | 2 +- spec/requests/api/v3/issues_spec.rb | 2 +- spec/services/boards/issues/list_service_spec.rb | 2 +- spec/services/boards/issues/move_service_spec.rb | 2 +- .../delete_merged_branches_service_spec.rb | 2 +- .../merge_requests/get_urls_service_spec.rb | 2 +- .../services/merge_requests/reopen_service_spec.rb | 2 +- 21 files changed, 65 insertions(+), 49 deletions(-) create mode 100644 changelogs/unreleased/merge-issuable-reopened-into-opened-state.yml create mode 100644 db/post_migrate/20170719150301_merge_issuable_reopened_into_opened_state.rb diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js index 72a13108404..fddafb0ddfa 100644 --- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js +++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js @@ -65,7 +65,7 @@ export default class MergeRequestStore { this.mergeCheckPath = data.merge_check_path; this.mergeActionsContentPath = data.commit_change_content_path; this.isRemovingSourceBranch = this.isRemovingSourceBranch || false; - this.isOpen = data.state === 'opened' || data.state === 'reopened' || false; + this.isOpen = data.state === 'opened'; this.hasMergeableDiscussionsState = data.mergeable_discussions_state === false; this.canRemoveSourceBranch = currentUser.can_remove_source_branch || false; this.canMerge = !!data.merge_path; diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb index 6fe17a2b99d..08a843ada97 100644 --- a/app/finders/issuable_finder.rb +++ b/app/finders/issuable_finder.rb @@ -81,7 +81,6 @@ class IssuableFinder end counts[:all] = counts.values.sum - counts[:opened] += counts[:reopened] counts end diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 13fe9d09c69..935ffe343ff 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -71,9 +71,8 @@ module Issuable scope :of_projects, ->(ids) { where(project_id: ids) } scope :of_milestones, ->(ids) { where(milestone_id: ids) } scope :with_milestone, ->(title) { left_joins_milestones.where(milestones: { title: title }) } - scope :opened, -> { with_state(:opened, :reopened) } + scope :opened, -> { with_state(:opened) } scope :only_opened, -> { with_state(:opened) } - scope :only_reopened, -> { with_state(:reopened) } scope :closed, -> { with_state(:closed) } scope :left_joins_milestones, -> { joins("LEFT OUTER JOIN milestones ON #{table_name}.milestone_id = milestones.id") } @@ -234,7 +233,7 @@ module Issuable end def open? - opened? || reopened? + opened? end def user_notes_count diff --git a/app/models/issue.rb b/app/models/issue.rb index 400bb55d2f0..1c948c8957e 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -62,15 +62,14 @@ class Issue < ActiveRecord::Base state_machine :state, initial: :opened do event :close do - transition [:reopened, :opened] => :closed + transition [:opened] => :closed end event :reopen do - transition closed: :reopened + transition closed: :opened end state :opened - state :reopened state :closed before_transition any => :closed do |issue| diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index a910099b4c1..81e0776e79c 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -42,23 +42,23 @@ class MergeRequest < ActiveRecord::Base state_machine :state, initial: :opened do event :close do - transition [:reopened, :opened] => :closed + transition [:opened] => :closed end event :mark_as_merged do - transition [:reopened, :opened, :locked] => :merged + transition [:opened, :locked] => :merged end event :reopen do - transition closed: :reopened + transition closed: :opened end event :lock_mr do - transition [:reopened, :opened] => :locked + transition [:opened] => :locked end event :unlock_mr do - transition locked: :reopened + transition locked: :opened end after_transition any => :locked do |merge_request, transition| @@ -72,7 +72,6 @@ class MergeRequest < ActiveRecord::Base end state :opened - state :reopened state :closed state :merged state :locked @@ -368,7 +367,7 @@ class MergeRequest < ActiveRecord::Base errors.add :branch_conflict, "You can not use same project/branch for source and target" end - if opened? || reopened? + if opened? similar_mrs = self.target_project.merge_requests.where(source_branch: source_branch, target_branch: target_branch, source_project_id: source_project.try(:id)).opened similar_mrs = similar_mrs.where('id not in (?)', self.id) if self.id if similar_mrs.any? diff --git a/app/models/project_services/drone_ci_service.rb b/app/models/project_services/drone_ci_service.rb index f6cade9c290..c93f1632652 100644 --- a/app/models/project_services/drone_ci_service.rb +++ b/app/models/project_services/drone_ci_service.rb @@ -114,7 +114,7 @@ class DroneCiService < CiService end def merge_request_valid?(data) - %w(opened reopened).include?(data[:object_attributes][:state]) && + data[:object_attributes][:state] == 'opened' && data[:object_attributes][:merge_status] == 'unchecked' end end diff --git a/app/services/issues/reopen_service.rb b/app/services/issues/reopen_service.rb index 73b2e85cba3..35de4337b15 100644 --- a/app/services/issues/reopen_service.rb +++ b/app/services/issues/reopen_service.rb @@ -5,7 +5,7 @@ module Issues if issue.reopen event_service.reopen_issue(issue, current_user) - create_note(issue) + create_note(issue, 'reopened') notification_service.reopen_issue(issue, current_user) execute_hooks(issue, 'reopen') invalidate_cache_counts(issue, users: issue.assignees) @@ -16,8 +16,8 @@ module Issues private - def create_note(issue) - SystemNoteService.change_status(issue, issue.project, current_user, issue.state, nil) + def create_note(issue, state = issue.state) + SystemNoteService.change_status(issue, issue.project, current_user, state, nil) end end end diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb index 3542a41ac83..35ccff26262 100644 --- a/app/services/merge_requests/base_service.rb +++ b/app/services/merge_requests/base_service.rb @@ -1,7 +1,7 @@ module MergeRequests class BaseService < ::IssuableBaseService - def create_note(merge_request) - SystemNoteService.change_status(merge_request, merge_request.target_project, current_user, merge_request.state, nil) + def create_note(merge_request, state = merge_request.state) + SystemNoteService.change_status(merge_request, merge_request.target_project, current_user, state, nil) end def create_title_change_note(issuable, old_title) @@ -44,7 +44,7 @@ module MergeRequests end # Returns all origin and fork merge requests from `@project` satisfying passed arguments. - def merge_requests_for(source_branch, mr_states: [:opened, :reopened]) + def merge_requests_for(source_branch, mr_states: [:opened]) MergeRequest .with_state(mr_states) .where(source_branch: source_branch, source_project_id: @project.id) diff --git a/app/services/merge_requests/reopen_service.rb b/app/services/merge_requests/reopen_service.rb index 52f6d511f98..b9c65be36ec 100644 --- a/app/services/merge_requests/reopen_service.rb +++ b/app/services/merge_requests/reopen_service.rb @@ -5,7 +5,7 @@ module MergeRequests if merge_request.reopen event_service.reopen_mr(merge_request, current_user) - create_note(merge_request) + create_note(merge_request, 'reopened') notification_service.reopen_mr(merge_request, current_user) execute_hooks(merge_request, 'reopen') merge_request.reload_diff(current_user) diff --git a/changelogs/unreleased/merge-issuable-reopened-into-opened-state.yml b/changelogs/unreleased/merge-issuable-reopened-into-opened-state.yml new file mode 100644 index 00000000000..5d7af8971e5 --- /dev/null +++ b/changelogs/unreleased/merge-issuable-reopened-into-opened-state.yml @@ -0,0 +1,4 @@ +--- +title: Merge issuable "reopened" state into "opened" +merge_request: +author: diff --git a/db/post_migrate/20170719150301_merge_issuable_reopened_into_opened_state.rb b/db/post_migrate/20170719150301_merge_issuable_reopened_into_opened_state.rb new file mode 100644 index 00000000000..acc0fc7a0ac --- /dev/null +++ b/db/post_migrate/20170719150301_merge_issuable_reopened_into_opened_state.rb @@ -0,0 +1,32 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class MergeIssuableReopenedIntoOpenedState < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + class Issue < ActiveRecord::Base + self.table_name = 'issues' + + include EachBatch + end + + class MergeRequest < ActiveRecord::Base + self.table_name = 'merge_requests' + + include EachBatch + end + + def up + [Issue, MergeRequest].each do |model| + say "Changing #{model.table_name}.state from 'reopened' to 'opened'" + + model.where(state: 'reopened').each_batch do |batch| + batch.update_all(state: 'opened') + end + end + end +end diff --git a/spec/factories/issues.rb b/spec/factories/issues.rb index f1fd1fd7f73..a16695cb7c1 100644 --- a/spec/factories/issues.rb +++ b/spec/factories/issues.rb @@ -16,12 +16,8 @@ FactoryGirl.define do state :closed end - trait :reopened do - state :reopened - end - factory :closed_issue, traits: [:closed] - factory :reopened_issue, traits: [:reopened] + factory :reopened_issue, traits: [:opened] factory :labeled_issue do transient do diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb index 253a025af48..1bc530d06db 100644 --- a/spec/factories/merge_requests.rb +++ b/spec/factories/merge_requests.rb @@ -44,10 +44,6 @@ FactoryGirl.define do state :opened end - trait :reopened do - state :reopened - end - trait :locked do state :locked end @@ -74,7 +70,7 @@ FactoryGirl.define do factory :merged_merge_request, traits: [:merged] factory :closed_merge_request, traits: [:closed] - factory :reopened_merge_request, traits: [:reopened] + factory :reopened_merge_request, traits: [:opened] factory :merge_request_with_diffs, traits: [:with_diffs] factory :merge_request_with_diff_notes do after(:create) do |mr| diff --git a/spec/lib/banzai/filter/issuable_state_filter_spec.rb b/spec/lib/banzai/filter/issuable_state_filter_spec.rb index 7cf2f4282f8..bc7cae1df8d 100644 --- a/spec/lib/banzai/filter/issuable_state_filter_spec.rb +++ b/spec/lib/banzai/filter/issuable_state_filter_spec.rb @@ -107,14 +107,6 @@ describe Banzai::Filter::IssuableStateFilter do expect(doc.css('a').last.text).to eq(issue.to_reference) end - it 'ignores reopened issue references' do - issue = create_issue(:reopened) - link = create_link(issue.to_reference, issue: issue.id, reference_type: 'issue') - doc = filter(link, context) - - expect(doc.css('a').last.text).to eq(issue.to_reference) - end - it 'appends state to closed issue references' do link = create_link(closed_issue.to_reference, issue: closed_issue.id, reference_type: 'issue') doc = filter(link, context) @@ -139,7 +131,7 @@ describe Banzai::Filter::IssuableStateFilter do end it 'ignores reopened merge request references' do - merge_request = create_merge_request(:reopened) + merge_request = create_merge_request(:opened) link = create_link( merge_request.to_reference, diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index 33cea02153e..2c44be4e447 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -1259,7 +1259,7 @@ describe API::Issues do put api("/projects/#{project.id}/issues/#{closed_issue.iid}", user), state_event: 'reopen' expect(response).to have_http_status(200) - expect(json_response['state']).to eq 'reopened' + expect(json_response['state']).to eq 'opened' end context 'when an admin or owner makes the request' do diff --git a/spec/requests/api/v3/issues_spec.rb b/spec/requests/api/v3/issues_spec.rb index cc81922697a..4dff09b6df8 100644 --- a/spec/requests/api/v3/issues_spec.rb +++ b/spec/requests/api/v3/issues_spec.rb @@ -1114,7 +1114,7 @@ describe API::V3::Issues do put v3_api("/projects/#{project.id}/issues/#{closed_issue.id}", user), state_event: 'reopen' expect(response).to have_http_status(200) - expect(json_response['state']).to eq 'reopened' + expect(json_response['state']).to eq 'opened' end context 'when an admin or owner makes the request' do diff --git a/spec/services/boards/issues/list_service_spec.rb b/spec/services/boards/issues/list_service_spec.rb index 2c293088097..b1b5d807a78 100644 --- a/spec/services/boards/issues/list_service_spec.rb +++ b/spec/services/boards/issues/list_service_spec.rb @@ -20,7 +20,7 @@ describe Boards::Issues::ListService do let!(:opened_issue1) { create(:labeled_issue, project: project, labels: [bug]) } let!(:opened_issue2) { create(:labeled_issue, project: project, labels: [p2]) } - let!(:reopened_issue1) { create(:issue, :reopened, project: project) } + let!(:reopened_issue1) { create(:issue, :opened, project: project) } let!(:list1_issue1) { create(:labeled_issue, project: project, labels: [p2, development]) } let!(:list1_issue2) { create(:labeled_issue, project: project, labels: [development]) } diff --git a/spec/services/boards/issues/move_service_spec.rb b/spec/services/boards/issues/move_service_spec.rb index 7dd1a601700..15a32350ae2 100644 --- a/spec/services/boards/issues/move_service_spec.rb +++ b/spec/services/boards/issues/move_service_spec.rb @@ -73,7 +73,7 @@ describe Boards::Issues::MoveService do issue.reload expect(issue.labels).to contain_exactly(bug, testing) - expect(issue).to be_reopened + expect(issue).to be_opened end end diff --git a/spec/services/delete_merged_branches_service_spec.rb b/spec/services/delete_merged_branches_service_spec.rb index 954c5d3ab73..4b872d667cf 100644 --- a/spec/services/delete_merged_branches_service_spec.rb +++ b/spec/services/delete_merged_branches_service_spec.rb @@ -43,7 +43,7 @@ describe DeleteMergedBranchesService do context 'open merge requests' do it 'does not delete branches from open merge requests' do fork_link = create(:forked_project_link, forked_from_project: project) - create(:merge_request, :reopened, source_project: project, target_project: project, source_branch: 'branch-merged', target_branch: 'master') + create(:merge_request, :opened, source_project: project, target_project: project, source_branch: 'branch-merged', target_branch: 'master') create(:merge_request, :opened, source_project: fork_link.forked_to_project, target_project: project, target_branch: 'improve/awesome', source_branch: 'master') service.execute diff --git a/spec/services/merge_requests/get_urls_service_spec.rb b/spec/services/merge_requests/get_urls_service_spec.rb index 4a7d8ab4c6c..672d86e4028 100644 --- a/spec/services/merge_requests/get_urls_service_spec.rb +++ b/spec/services/merge_requests/get_urls_service_spec.rb @@ -78,7 +78,7 @@ describe MergeRequests::GetUrlsService do end context 'pushing to existing branch and merge request is reopened' do - let!(:merge_request) { create(:merge_request, :reopened, source_project: project, source_branch: source_branch) } + let!(:merge_request) { create(:merge_request, :opened, source_project: project, source_branch: source_branch) } let(:changes) { existing_branch_changes } it_behaves_like 'show_merge_request_url' end diff --git a/spec/services/merge_requests/reopen_service_spec.rb b/spec/services/merge_requests/reopen_service_spec.rb index ce1e9f2ff45..f02af0c582e 100644 --- a/spec/services/merge_requests/reopen_service_spec.rb +++ b/spec/services/merge_requests/reopen_service_spec.rb @@ -28,7 +28,7 @@ describe MergeRequests::ReopenService do end it { expect(merge_request).to be_valid } - it { expect(merge_request).to be_reopened } + it { expect(merge_request).to be_opened } it 'executes hooks with reopen action' do expect(service).to have_received(:execute_hooks) -- cgit v1.2.3 From fdfb4bbe5c659e02734258615b57b5f012afb2b4 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Fri, 28 Jul 2017 13:59:57 +0100 Subject: Fix diff commenting results just after changing view When you change the diff view (inline / side-by-side), we set a cookie based on that new view. When you add a comment, we choose the style to use in the response based on that cookie. However, when you have just changed diff style, the request cookie will contain the old value, so we should use the view param instead. --- app/helpers/diff_helper.rb | 2 +- ...a-wrong-place-after-changing-diff-view-to-inline.yml | 4 ++++ spec/helpers/diff_helper_spec.rb | 17 +++++++++++++++-- 3 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 changelogs/unreleased/35695-comment-appears-in-a-wrong-place-after-changing-diff-view-to-inline.yml diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index 926502bf239..91ddd73fac1 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -15,7 +15,7 @@ module DiffHelper def diff_view @diff_view ||= begin diff_views = %w(inline parallel) - diff_view = cookies[:diff_view] + diff_view = params[:view] || cookies[:diff_view] diff_view = diff_views.first unless diff_views.include?(diff_view) diff_view.to_sym end diff --git a/changelogs/unreleased/35695-comment-appears-in-a-wrong-place-after-changing-diff-view-to-inline.yml b/changelogs/unreleased/35695-comment-appears-in-a-wrong-place-after-changing-diff-view-to-inline.yml new file mode 100644 index 00000000000..1c9ad20bc95 --- /dev/null +++ b/changelogs/unreleased/35695-comment-appears-in-a-wrong-place-after-changing-diff-view-to-inline.yml @@ -0,0 +1,4 @@ +--- +title: Fix display of new diff comments after changing b between diff views +merge_request: +author: diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb index 0d909e6e140..060c112e20d 100644 --- a/spec/helpers/diff_helper_spec.rb +++ b/spec/helpers/diff_helper_spec.rb @@ -12,19 +12,32 @@ describe DiffHelper do let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: diff_refs, repository: repository) } describe 'diff_view' do + it 'uses the view param over the cookie' do + controller.params[:view] = 'parallel' + helper.request.cookies[:diff_view] = 'inline' + + expect(helper.diff_view).to eq :parallel + end + + it 'returns the default value when the view param is invalid' do + controller.params[:view] = 'invalid' + + expect(helper.diff_view).to eq :inline + end + it 'returns a valid value when cookie is set' do helper.request.cookies[:diff_view] = 'parallel' expect(helper.diff_view).to eq :parallel end - it 'returns a default value when cookie is invalid' do + it 'returns the default value when cookie is invalid' do helper.request.cookies[:diff_view] = 'invalid' expect(helper.diff_view).to eq :inline end - it 'returns a default value when cookie is nil' do + it 'returns the default value when cookie is nil' do expect(helper.request.cookies).to be_empty expect(helper.diff_view).to eq :inline -- cgit v1.2.3 From 329391ced723a62b20d0ce9bb4746e0f4074f395 Mon Sep 17 00:00:00 2001 From: bart Date: Fri, 28 Jul 2017 13:28:47 +0000 Subject: Update gitlab_flow.md, Teatro seems to be completely dead, see also https://forum.gitlab.com/t/gitlab-flow-documentation-teatro/7774 --- doc/workflow/gitlab_flow.md | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/workflow/gitlab_flow.md b/doc/workflow/gitlab_flow.md index ea28968fbb2..9d466ae1971 100644 --- a/doc/workflow/gitlab_flow.md +++ b/doc/workflow/gitlab_flow.md @@ -91,7 +91,6 @@ This workflow where commits only flow downstream ensures that everything has bee If you need to cherry-pick a commit with a hotfix it is common to develop it on a feature branch and merge it into master with a merge request, do not delete the feature branch. If master is good to go (it should be if you are practicing [continuous delivery](http://martinfowler.com/bliki/ContinuousDelivery.html)) you then merge it to the other branches. If this is not possible because more manual testing is required you can send merge requests from the feature branch to the downstream branches. -An 'extreme' version of environment branches are setting up an environment for each feature branch as done by [Teatro](https://teatro.io/). ## Release branches with GitLab flow -- cgit v1.2.3 From d020eabf2938858830125ace467b13695eb85962 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 28 Jul 2017 15:39:39 +0200 Subject: Add log messages to clarify log messages about API CSRF token verification failure --- lib/gitlab/request_forgery_protection.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/gitlab/request_forgery_protection.rb b/lib/gitlab/request_forgery_protection.rb index 48dd0487790..ccfe0d6bed3 100644 --- a/lib/gitlab/request_forgery_protection.rb +++ b/lib/gitlab/request_forgery_protection.rb @@ -7,6 +7,14 @@ module Gitlab class Controller < ActionController::Base protect_from_forgery with: :exception + rescue_from ActionController::InvalidAuthenticityToken do |e| + logger.warn "This CSRF token verification failure is handled internally by `GitLab::RequestForgeryProtection`" + logger.warn "Unlike the logs may suggest, this does not result in an actual 422 response to the user" + logger.warn "For API requests, the only effect is that `current_user` will be `nil` for the duration of the request" + + raise e + end + def index head :ok end -- cgit v1.2.3 From 60797a42b419841e14f50f85bf8daa2a115a72f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Thu, 27 Jul 2017 11:15:57 +0200 Subject: Ensure Gitlab::Application.routes.default_url_options are set correctly in Capybara + :js specs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- config/initializers/1_settings.rb | 2 +- lib/api/helpers/related_resources_helpers.rb | 2 +- spec/features/dashboard/issues_spec.rb | 12 +----------- spec/models/project_wiki_spec.rb | 2 +- spec/spec_helper.rb | 1 + spec/support/capybara.rb | 9 ++++++++- 6 files changed, 13 insertions(+), 15 deletions(-) diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 02d3161f769..63f4c8c9e0a 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -223,7 +223,7 @@ Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_c Settings.gitlab['host'] ||= ENV['GITLAB_HOST'] || 'localhost' Settings.gitlab['ssh_host'] ||= Settings.gitlab.host Settings.gitlab['https'] = false if Settings.gitlab['https'].nil? -Settings.gitlab['port'] ||= Settings.gitlab.https ? 443 : 80 +Settings.gitlab['port'] ||= ENV['GITLAB_PORT'] || (Settings.gitlab.https ? 443 : 80) Settings.gitlab['relative_url_root'] ||= ENV['RAILS_RELATIVE_URL_ROOT'] || '' Settings.gitlab['protocol'] ||= Settings.gitlab.https ? "https" : "http" Settings.gitlab['email_enabled'] ||= true if Settings.gitlab['email_enabled'].nil? diff --git a/lib/api/helpers/related_resources_helpers.rb b/lib/api/helpers/related_resources_helpers.rb index 769cc1457fc..1f677529b07 100644 --- a/lib/api/helpers/related_resources_helpers.rb +++ b/lib/api/helpers/related_resources_helpers.rb @@ -12,7 +12,7 @@ module API end def expose_url(path) - url_options = Rails.application.routes.default_url_options + url_options = Gitlab::Application.routes.default_url_options protocol, host, port = url_options.slice(:protocol, :host, :port).values URI::HTTP.build(scheme: protocol, host: host, port: port, path: path).to_s diff --git a/spec/features/dashboard/issues_spec.rb b/spec/features/dashboard/issues_spec.rb index 7c0bf8de14c..82adde6258f 100644 --- a/spec/features/dashboard/issues_spec.rb +++ b/spec/features/dashboard/issues_spec.rb @@ -79,15 +79,7 @@ RSpec.describe 'Dashboard Issues' do end end - it 'shows the new issue page', js: true do - original_defaults = Gitlab::Application.routes.default_url_options - - Gitlab::Application.routes.default_url_options = { - host: Capybara.current_session.server.host, - port: Capybara.current_session.server.port, - protocol: 'http' - } - + it 'shows the new issue page', :js do find('.new-project-item-select-button').trigger('click') wait_for_requests find('.select2-results li').click @@ -97,8 +89,6 @@ RSpec.describe 'Dashboard Issues' do page.within('#content-body') do expect(page).to have_selector('.issue-form') end - - Gitlab::Application.routes.default_url_options = original_defaults end end end diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb index 7fcbeb459e0..c6ceb092810 100644 --- a/spec/models/project_wiki_spec.rb +++ b/spec/models/project_wiki_spec.rb @@ -21,7 +21,7 @@ describe ProjectWiki do describe '#web_url' do it 'returns the full web URL to the wiki' do - expect(subject.web_url).to match("https?://[^\/]+/#{project.path_with_namespace}/wikis/home") + expect(subject.web_url).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/wikis/home") end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e7329210896..85335643921 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -59,6 +59,7 @@ RSpec.configure do |config| config.include Gitlab::Routing, type: :routing config.include MigrationsHelpers, :migration config.include StubFeatureFlags + config.include StubENV config.infer_spec_type_from_file_location! diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb index 3e5d6cf1364..c45c4a4310d 100644 --- a/spec/support/capybara.rb +++ b/spec/support/capybara.rb @@ -36,7 +36,14 @@ RSpec.configure do |config| $capybara_server_already_started = true end - config.after(:each, :js) do |example| + config.before(:example, :js) do + allow(Gitlab::Application.routes).to receive(:default_url_options).and_return( + host: Capybara.current_session.server.host, + port: Capybara.current_session.server.port, + protocol: 'http') + end + + config.after(:example, :js) do |example| # capybara/rspec already calls Capybara.reset_sessions! in an `after` hook, # but `block_and_wait_for_requests_complete` is called before it so by # calling it explicitely here, we prevent any new requests from being fired -- cgit v1.2.3 From 0e355e5c9293c712b5df65896371af0ba71c19b2 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 27 Jul 2017 14:58:02 +0200 Subject: Load and process at most 100 commits when pushing into default branch --- app/services/git_push_service.rb | 31 +++++++++++++++------- .../unreleased/dm-large-push-performance.yml | 4 +++ lib/gitlab/data_builder/push.rb | 4 +-- spec/services/git_push_service_spec.rb | 6 ++--- 4 files changed, 29 insertions(+), 16 deletions(-) create mode 100644 changelogs/unreleased/dm-large-push-performance.yml diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index 20d1fb29289..57ce2a472aa 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -45,6 +45,7 @@ class GitPushService < BaseService elsif push_to_existing_branch? # Collect data for this git push @push_commits = @project.repository.commits_between(params[:oldrev], params[:newrev]) + process_commit_messages # Update the bare repositories info/attributes file using the contents of the default branches @@ -64,15 +65,21 @@ class GitPushService < BaseService def update_caches if is_default_branch? - paths = Set.new + if push_to_new_branch? + # If this is the initial push into the default branch, the file type caches + # will already be reset as a result of `Project#change_head`. + types = [] + else + paths = Set.new - @push_commits.each do |commit| - commit.raw_deltas.each do |diff| - paths << diff.new_path + @push_commits.last(PROCESS_COMMIT_LIMIT).each do |commit| + commit.raw_deltas.each do |diff| + paths << diff.new_path + end end - end - types = Gitlab::FileDetector.types_in_paths(paths.to_a) + types = Gitlab::FileDetector.types_in_paths(paths.to_a) + end else types = [] end @@ -84,7 +91,7 @@ class GitPushService < BaseService def process_commit_messages default = is_default_branch? - push_commits.last(PROCESS_COMMIT_LIMIT).each do |commit| + @push_commits.last(PROCESS_COMMIT_LIMIT).each do |commit| if commit.matches_cross_reference_regex? ProcessCommitWorker .perform_async(project.id, current_user.id, commit.to_hash, default) @@ -103,7 +110,7 @@ class GitPushService < BaseService EventCreateService.new.push(@project, current_user, build_push_data) Ci::CreatePipelineService.new(@project, current_user, build_push_data).execute(:push) - + SystemHookPushWorker.perform_async(build_push_data.dup, :push_hooks) @project.execute_hooks(build_push_data.dup, :push_hooks) @project.execute_services(build_push_data.dup, :push_hooks) @@ -123,7 +130,10 @@ class GitPushService < BaseService end def process_default_branch - @push_commits = project.repository.commits(params[:newrev]) + @push_commits_count = project.repository.commit_count_for_ref(params[:ref]) + + offset = [@push_commits_count - PROCESS_COMMIT_LIMIT, 0].max + @push_commits = project.repository.commits(params[:newrev], offset: offset, limit: PROCESS_COMMIT_LIMIT) # Ensure HEAD points to the default branch in case it is not master project.change_head(branch_name) @@ -152,7 +162,8 @@ class GitPushService < BaseService params[:oldrev], params[:newrev], params[:ref], - push_commits) + @push_commits, + commits_count: @push_commits_count) end def push_to_existing_branch? diff --git a/changelogs/unreleased/dm-large-push-performance.yml b/changelogs/unreleased/dm-large-push-performance.yml new file mode 100644 index 00000000000..f5fe1bd3b28 --- /dev/null +++ b/changelogs/unreleased/dm-large-push-performance.yml @@ -0,0 +1,4 @@ +--- +title: Improve performance of large (initial) push into default branch +merge_request: +author: diff --git a/lib/gitlab/data_builder/push.rb b/lib/gitlab/data_builder/push.rb index 8c8729b6557..5c5f507d44d 100644 --- a/lib/gitlab/data_builder/push.rb +++ b/lib/gitlab/data_builder/push.rb @@ -24,11 +24,11 @@ module Gitlab # total_commits_count: Fixnum # } # - def build(project, user, oldrev, newrev, ref, commits = [], message = nil) + def build(project, user, oldrev, newrev, ref, commits = [], message = nil, commits_count: nil) commits = Array(commits) # Total commits count - commits_count = commits.size + commits_count ||= commits.size # Get latest 20 commits ASC commits_limited = commits.last(20) diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index f801506f1b6..cf9e63676b7 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -663,8 +663,7 @@ describe GitPushService, services: true do end it 'only schedules a limited number of commits' do - allow(service).to receive(:push_commits) - .and_return(Array.new(1000, double(:commit, to_hash: {}, matches_cross_reference_regex?: true))) + service.push_commits = Array.new(1000, double(:commit, to_hash: {}, matches_cross_reference_regex?: true)) expect(ProcessCommitWorker).to receive(:perform_async).exactly(100).times @@ -672,8 +671,7 @@ describe GitPushService, services: true do end it "skips commits which don't include cross-references" do - allow(service).to receive(:push_commits) - .and_return([double(:commit, to_hash: {}, matches_cross_reference_regex?: false)]) + service.push_commits = [double(:commit, to_hash: {}, matches_cross_reference_regex?: false)] expect(ProcessCommitWorker).not_to receive(:perform_async) -- cgit v1.2.3 From 9442c33584d9667551447aa2d579aec03fb18d50 Mon Sep 17 00:00:00 2001 From: Athar Hameed Date: Fri, 28 Jul 2017 15:23:40 +0000 Subject: Fix 500 error when rendering avatar for deleted project creator --- app/views/shared/projects/_project.html.haml | 2 +- ...n-rendering-avatar-for-deleted-project-creator.yml | 4 ++++ spec/views/shared/projects/_project.html.haml_spec.rb | 19 +++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/fix-500-error-when-rendering-avatar-for-deleted-project-creator.yml create mode 100644 spec/views/shared/projects/_project.html.haml_spec.rb diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml index 4bdbc26a4c3..f4f155c8d94 100644 --- a/app/views/shared/projects/_project.html.haml +++ b/app/views/shared/projects/_project.html.haml @@ -14,7 +14,7 @@ - if avatar .avatar-container.s40 = link_to project_path(project), class: dom_class(project) do - - if use_creator_avatar + - if project.creator && use_creator_avatar = image_tag avatar_icon(project.creator.email, 40), class: "avatar s40", alt:'' - else = project_icon(project, alt: '', class: 'avatar project-avatar s40') diff --git a/changelogs/unreleased/fix-500-error-when-rendering-avatar-for-deleted-project-creator.yml b/changelogs/unreleased/fix-500-error-when-rendering-avatar-for-deleted-project-creator.yml new file mode 100644 index 00000000000..be6f1ea00fb --- /dev/null +++ b/changelogs/unreleased/fix-500-error-when-rendering-avatar-for-deleted-project-creator.yml @@ -0,0 +1,4 @@ +--- +title: Modify if condition to be more readable +merge_request: +author: diff --git a/spec/views/shared/projects/_project.html.haml_spec.rb b/spec/views/shared/projects/_project.html.haml_spec.rb new file mode 100644 index 00000000000..43334c2c236 --- /dev/null +++ b/spec/views/shared/projects/_project.html.haml_spec.rb @@ -0,0 +1,19 @@ +require 'spec_helper' + +describe 'shared/projects/_project.html.haml' do + let(:project) { create(:empty_project) } + + it 'should render creator avatar if project has a creator' do + render 'shared/projects/project', use_creator_avatar: true, project: project + + expect(rendered).to have_selector('img.avatar') + end + + it 'should render a generic avatar if project does not have a creator' do + project.creator = nil + + render 'shared/projects/project', use_creator_avatar: true, project: project + + expect(rendered).to have_selector('.project-avatar') + end +end -- cgit v1.2.3 From 75d04f6a29a5506ffd53c227517411febdc54910 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Thu, 27 Jul 2017 15:36:39 +0100 Subject: Fix replying to commit comments on MRs from forks A commit comment shows in the MR, but if the MR is from a fork, it will have a different project ID to the MR's target project. In that case, add an note_project_id param so that we can pick the correct project for the note. --- app/assets/javascripts/notes.js | 4 ++ app/controllers/concerns/notes_actions.rb | 22 +++++++- app/helpers/notes_helper.rb | 6 ++- app/views/shared/notes/_form.html.haml | 1 + ...-replying-to-commit-comment-in-mr-from-fork.yml | 4 ++ spec/controllers/projects/notes_controller_spec.rb | 62 +++++++++++++++++++++- .../merge_requests/created_from_fork_spec.rb | 27 ++++++++++ 7 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 changelogs/unreleased/fix-replying-to-commit-comment-in-mr-from-fork.yml diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index b2c503d1656..dfa07a2def4 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -529,6 +529,7 @@ export default class Notes { form.find('#note_line_code').remove(); form.find('#note_position').remove(); form.find('#note_type').val(''); + form.find('#note_project_id').remove(); form.find('#in_reply_to_discussion_id').remove(); form.find('.js-comment-resolve-button').closest('comment-and-resolve-btn').remove(); this.parentTimeline = form.parents('.timeline'); @@ -556,6 +557,7 @@ export default class Notes { form.find('#note_noteable_id').val(), form.find('#note_commit_id').val(), form.find('#note_type').val(), + form.find('#note_project_id').val(), form.find('#in_reply_to_discussion_id').val(), // LegacyDiffNote @@ -848,6 +850,8 @@ export default class Notes { form.find('#in_reply_to_discussion_id').val(discussionID); } + form.find('#note_project_id').val(dataHolder.data('discussionProjectId')); + form.attr('data-line-code', dataHolder.data('lineCode')); form.find('#line_type').val(dataHolder.data('lineType')); diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb index a57d9e6e6c0..af5f683bab5 100644 --- a/app/controllers/concerns/notes_actions.rb +++ b/app/controllers/concerns/notes_actions.rb @@ -4,6 +4,7 @@ module NotesActions included do before_action :authorize_admin_note!, only: [:update, :destroy] + before_action :note_project, only: [:create] end def index @@ -28,7 +29,8 @@ module NotesActions merge_request_diff_head_sha: params[:merge_request_diff_head_sha], in_reply_to_discussion_id: params[:in_reply_to_discussion_id] ) - @note = Notes::CreateService.new(project, current_user, create_params).execute + + @note = Notes::CreateService.new(note_project, current_user, create_params).execute if @note.is_a?(Note) Banzai::NoteRenderer.render([@note], @project, current_user) @@ -177,4 +179,22 @@ module NotesActions def notes_finder @notes_finder ||= NotesFinder.new(project, current_user, finder_params) end + + def note_project + return @note_project if defined?(@note_project) + return nil unless project + + note_project_id = params[:note_project_id] + + @note_project = + if note_project_id.present? + Project.find(note_project_id) + else + project + end + + return access_denied! unless can?(current_user, :create_note, @note_project) + + @note_project + end end diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb index 0a0881d95cf..8f4e39b8b23 100644 --- a/app/helpers/notes_helper.rb +++ b/app/helpers/notes_helper.rb @@ -62,7 +62,11 @@ module NotesHelper def link_to_reply_discussion(discussion, line_type = nil) return unless current_user - data = { discussion_id: discussion.reply_id, line_type: line_type } + data = { + discussion_id: discussion.reply_id, + discussion_project_id: discussion.project&.id, + line_type: line_type + } button_tag 'Reply...', class: 'btn btn-text-field js-discussion-reply-button', data: data, title: 'Add a reply' diff --git a/app/views/shared/notes/_form.html.haml b/app/views/shared/notes/_form.html.haml index c6b5dcc3647..725bf916592 100644 --- a/app/views/shared/notes/_form.html.haml +++ b/app/views/shared/notes/_form.html.haml @@ -10,6 +10,7 @@ = hidden_field_tag :line_type = hidden_field_tag :merge_request_diff_head_sha, @note.noteable.try(:diff_head_sha) = hidden_field_tag :in_reply_to_discussion_id + = hidden_field_tag :note_project_id = note_target_fields(@note) = f.hidden_field :noteable_type diff --git a/changelogs/unreleased/fix-replying-to-commit-comment-in-mr-from-fork.yml b/changelogs/unreleased/fix-replying-to-commit-comment-in-mr-from-fork.yml new file mode 100644 index 00000000000..f4136460626 --- /dev/null +++ b/changelogs/unreleased/fix-replying-to-commit-comment-in-mr-from-fork.yml @@ -0,0 +1,4 @@ +--- +title: Fix replying to commit comments on merge requests created from forks +merge_request: +author: diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb index 45f4cf9180d..3b88d5b0d7d 100644 --- a/spec/controllers/projects/notes_controller_spec.rb +++ b/spec/controllers/projects/notes_controller_spec.rb @@ -131,7 +131,7 @@ describe Projects::NotesController do before do sign_in(user) - project.team << [user, :developer] + project.add_developer(user) end it "returns status 302 for html" do @@ -165,6 +165,66 @@ describe Projects::NotesController do expect(response).to have_http_status(302) end end + + context 'when creating a commit comment from an MR fork' do + let(:project) { create(:project) } + + let(:fork_project) do + create(:project).tap do |fork| + create(:forked_project_link, forked_to_project: fork, forked_from_project: project) + end + end + + let(:merge_request) do + create(:merge_request, source_project: fork_project, target_project: project, source_branch: 'feature', target_branch: 'master') + end + + let(:existing_comment) do + create(:note_on_commit, note: 'a note', project: fork_project, commit_id: merge_request.commit_shas.first) + end + + def post_create(extra_params = {}) + post :create, { + note: { note: 'some other note' }, + namespace_id: project.namespace, + project_id: project, + target_type: 'merge_request', + target_id: merge_request.id, + note_project_id: fork_project.id, + in_reply_to_discussion_id: existing_comment.discussion_id + }.merge(extra_params) + end + + context 'when the note_project_id is not correct' do + it 'returns a 404' do + post_create(note_project_id: Project.maximum(:id).succ) + + expect(response).to have_http_status(404) + end + end + + context 'when the user has no access to the fork' do + it 'returns a 404' do + post_create + + expect(response).to have_http_status(404) + end + end + + context 'when the user has access to the fork' do + let(:discussion) { fork_project.notes.find_discussion(existing_comment.discussion_id) } + + before do + fork_project.add_developer(user) + + existing_comment + end + + it 'creates the note' do + expect { post_create }.to change { fork_project.notes.count }.by(1) + end + end + end end describe 'DELETE destroy' do diff --git a/spec/features/merge_requests/created_from_fork_spec.rb b/spec/features/merge_requests/created_from_fork_spec.rb index 9b7795ace62..d706d01dde0 100644 --- a/spec/features/merge_requests/created_from_fork_spec.rb +++ b/spec/features/merge_requests/created_from_fork_spec.rb @@ -25,6 +25,33 @@ feature 'Merge request created from fork' do expect(page).to have_content 'Test merge request' end + context 'when a commit comment exists on the merge request' do + given(:comment) { 'A commit comment' } + given(:reply) { 'A reply comment' } + + background do + create(:note_on_commit, note: comment, + project: fork_project, + commit_id: merge_request.commit_shas.first) + end + + scenario 'user can reply to the comment', js: true do + visit_merge_request(merge_request) + + expect(page).to have_content(comment) + + page.within('.discussion-notes') do + find('.btn-text-field').click + find('#note_note').send_keys(reply) + find('.comment-btn').click + end + + wait_for_requests + + expect(page).to have_content(reply) + end + end + context 'source project is deleted' do background do MergeRequests::MergeService.new(project, user).execute(merge_request) -- cgit v1.2.3 From 05f90b861fbc60cba1912e6a74cb7a4c126e6b7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kim=20=22BKC=22=20Carlb=C3=A4cker?= Date: Wed, 19 Jul 2017 17:34:14 +0200 Subject: Migrate GitGarbageCollectWorker to Gitaly --- app/workers/git_garbage_collect_worker.rb | 39 ++++++++++++++++++- lib/gitlab/gitaly_client/repository_service.rb | 18 ++++++++- spec/workers/git_garbage_collect_worker_spec.rb | 52 ++++++++++++++++++++----- 3 files changed, 97 insertions(+), 12 deletions(-) diff --git a/app/workers/git_garbage_collect_worker.rb b/app/workers/git_garbage_collect_worker.rb index d369b639ae9..c95497dfaba 100644 --- a/app/workers/git_garbage_collect_worker.rb +++ b/app/workers/git_garbage_collect_worker.rb @@ -5,6 +5,12 @@ class GitGarbageCollectWorker sidekiq_options retry: false + GITALY_MIGRATED_TASKS = { + gc: :garbage_collect, + full_repack: :repack_full, + incremental_repack: :repack_incremental + }.freeze + def perform(project_id, task = :gc, lease_key = nil, lease_uuid = nil) project = Project.find(project_id) task = task.to_sym @@ -15,8 +21,14 @@ class GitGarbageCollectWorker Gitlab::GitLogger.info(description) - output, status = Gitlab::Popen.popen(cmd, repo_path) - Gitlab::GitLogger.error("#{description} failed:\n#{output}") unless status.zero? + gitaly_migrate(GITALY_MIGRATED_TASKS[task]) do |is_enabled| + if is_enabled + gitaly_call(task, project.repository.raw_repository) + else + output, status = Gitlab::Popen.popen(cmd, repo_path) + Gitlab::GitLogger.error("#{description} failed:\n#{output}") unless status.zero? + end + end # Refresh the branch cache in case garbage collection caused a ref lookup to fail flush_ref_caches(project) if task == :gc @@ -26,6 +38,19 @@ class GitGarbageCollectWorker private + ## `repository` has to be a Gitlab::Git::Repository + def gitaly_call(task, repository) + client = Gitlab::GitalyClient::RepositoryService.new(repository) + case task + when :gc + client.garbage_collect(bitmaps_enabled?) + when :full_repack + client.repack_full(bitmaps_enabled?) + when :incremental_repack + client.repack_incremental + end + end + def command(task) case task when :gc @@ -55,4 +80,14 @@ class GitGarbageCollectWorker config_value = write_bitmaps ? 'true' : 'false' %W[git -c repack.writeBitmaps=#{config_value}] end + + def gitaly_migrate(method, &block) + Gitlab::GitalyClient.migrate(method, &block) + rescue GRPC::NotFound => e + Gitlab::GitLogger.error("#{method} failed:\nRepository not found") + raise Gitlab::Git::Repository::NoRepository.new(e) + rescue GRPC::BadStatus => e + Gitlab::GitLogger.error("#{method} failed:\n#{e}") + raise Gitlab::Git::CommandError.new(e) + end end diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb index f5d84ea8762..13e75b256a7 100644 --- a/lib/gitlab/gitaly_client/repository_service.rb +++ b/lib/gitlab/gitaly_client/repository_service.rb @@ -4,12 +4,28 @@ module Gitlab def initialize(repository) @repository = repository @gitaly_repo = repository.gitaly_repository + @storage = repository.storage end def exists? request = Gitaly::RepositoryExistsRequest.new(repository: @gitaly_repo) - GitalyClient.call(@repository.storage, :repository_service, :exists, request).exists + GitalyClient.call(@storage, :repository_service, :exists, request).exists + end + + def garbage_collect(create_bitmap) + request = Gitaly::GarbageCollectRequest.new(repository: @gitaly_repo, create_bitmap: create_bitmap) + GitalyClient.call(@storage, :repository_service, :garbage_collect, request) + end + + def repack_full(create_bitmap) + request = Gitaly::RepackFullRequest.new(repository: @gitaly_repo, create_bitmap: create_bitmap) + GitalyClient.call(@storage, :repository_service, :repack_full, request) + end + + def repack_incremental + request = Gitaly::RepackIncrementalRequest.new(repository: @gitaly_repo) + GitalyClient.call(@storage, :repository_service, :repack_incremental, request) end end end diff --git a/spec/workers/git_garbage_collect_worker_spec.rb b/spec/workers/git_garbage_collect_worker_spec.rb index 309b3172da1..05f971dfd13 100644 --- a/spec/workers/git_garbage_collect_worker_spec.rb +++ b/spec/workers/git_garbage_collect_worker_spec.rb @@ -9,17 +9,51 @@ describe GitGarbageCollectWorker do subject { described_class.new } describe "#perform" do - it "flushes ref caches when the task is 'gc'" do - expect(subject).to receive(:command).with(:gc).and_return([:the, :command]) - expect(Gitlab::Popen).to receive(:popen) - .with([:the, :command], project.repository.path_to_repo).and_return(["", 0]) + shared_examples 'flushing ref caches' do |gitaly| + it "flushes ref caches when the task if 'gc'" do + expect(subject).to receive(:command).with(:gc).and_return([:the, :command]) + + if gitaly + expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(:garbage_collect) + .and_return(nil) + else + expect(Gitlab::Popen).to receive(:popen) + .with([:the, :command], project.repository.path_to_repo).and_return(["", 0]) + end + + expect_any_instance_of(Repository).to receive(:after_create_branch).and_call_original + expect_any_instance_of(Repository).to receive(:branch_names).and_call_original + expect_any_instance_of(Repository).to receive(:branch_count).and_call_original + expect_any_instance_of(Repository).to receive(:has_visible_content?).and_call_original + + subject.perform(project.id) + end + end + + context "with Gitaly turned on" do + it_should_behave_like 'flushing ref caches', true + end + + context "with Gitaly turned off", skip_gitaly_mock: true do + it_should_behave_like 'flushing ref caches', false + end - expect_any_instance_of(Repository).to receive(:after_create_branch).and_call_original - expect_any_instance_of(Repository).to receive(:branch_names).and_call_original - expect_any_instance_of(Repository).to receive(:branch_count).and_call_original - expect_any_instance_of(Repository).to receive(:has_visible_content?).and_call_original + context "repack_full" do + it "calls Gitaly" do + expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(:repack_full) + .and_return(nil) - subject.perform(project.id) + subject.perform(project.id, :full_repack) + end + end + + context "repack_incremental" do + it "calls Gitaly" do + expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(:repack_incremental) + .and_return(nil) + + subject.perform(project.id, :incremental_repack) + end end shared_examples 'gc tasks' do -- cgit v1.2.3 From 04e4210785ffd088458e24f08a9f94376558c0dc Mon Sep 17 00:00:00 2001 From: Dan Dunckel Date: Fri, 28 Jul 2017 09:52:37 -0600 Subject: Update documentation of user creation by replacing the 'confirm' param with 'skip_confirmation' --- doc/api/users.md | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/doc/api/users.md b/doc/api/users.md index 6e5ec3231c5..57a13eb477d 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -241,26 +241,26 @@ POST /users Parameters: -- `email` (required) - Email -- `password` (optional) - Password -- `reset_password` (optional) - Send user password reset link - true or false(default) -- `username` (required) - Username -- `name` (required) - Name -- `skype` (optional) - Skype ID -- `linkedin` (optional) - LinkedIn -- `twitter` (optional) - Twitter account -- `website_url` (optional) - Website URL -- `organization` (optional) - Organization name -- `projects_limit` (optional) - Number of projects user can create -- `extern_uid` (optional) - External UID -- `provider` (optional) - External provider name -- `bio` (optional) - User's biography -- `location` (optional) - User's location -- `admin` (optional) - User is admin - true or false (default) -- `can_create_group` (optional) - User can create groups - true or false -- `confirm` (optional) - Require confirmation - true (default) or false -- `external` (optional) - Flags the user as external - true or false(default) -- `avatar` (optional) - Image file for user's avatar +- `email` (required) - Email +- `password` (optional) - Password +- `reset_password` (optional) - Send user password reset link - true or false(default) +- `username` (required) - Username +- `name` (required) - Name +- `skype` (optional) - Skype ID +- `linkedin` (optional) - LinkedIn +- `twitter` (optional) - Twitter account +- `website_url` (optional) - Website URL +- `organization` (optional) - Organization name +- `projects_limit` (optional) - Number of projects user can create +- `extern_uid` (optional) - External UID +- `provider` (optional) - External provider name +- `bio` (optional) - User's biography +- `location` (optional) - User's location +- `admin` (optional) - User is admin - true or false (default) +- `can_create_group` (optional) - User can create groups - true or false +- `skip_confirmation` (optional) - Skip confirmation - true or false (default) +- `external` (optional) - Flags the user as external - true or false(default) +- `avatar` (optional) - Image file for user's avatar ## User modification -- cgit v1.2.3 From c734aa8608a82a4b263042b0f4d8d71fd21562cd Mon Sep 17 00:00:00 2001 From: tauriedavis Date: Mon, 27 Mar 2017 12:49:19 -0700 Subject: Add copy about search terms to ux guide --- doc/development/ux_guide/copy.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/development/ux_guide/copy.md b/doc/development/ux_guide/copy.md index 794c8eb6bfe..12e8d0a31bb 100644 --- a/doc/development/ux_guide/copy.md +++ b/doc/development/ux_guide/copy.md @@ -106,6 +106,14 @@ When using verbs or adjectives: * If the context clearly refers to the object, use them alone. Example: `Edit` or `Closed` * If the context isn’t clear enough, use them with the object. Example: `Edit issue` or `Closed issues` +### Search + +| Term | Use | +| ---- | --- | +| Search | When using all metadata to add criteria that match/don't match. Search can also affect ordering, by ranking best results. | +| Filter | When taking a single criteria that removes items within a list that match/don't match. Filters do not affect ordering. | +| Sort | Orders a list based on a single or grouped criteria | + ### Projects and Groups | Term | Use | :no_entry_sign: Don't | -- cgit v1.2.3 From a2ba403e27183073ad9a4894cfe6c39f94e63964 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 28 Jul 2017 18:19:25 +0200 Subject: Fix a spec that was assuming to be on the wrong page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/features/issues/create_branch_merge_request_spec.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/spec/features/issues/create_branch_merge_request_spec.rb b/spec/features/issues/create_branch_merge_request_spec.rb index c10b99a4386..f59f687cf51 100644 --- a/spec/features/issues/create_branch_merge_request_spec.rb +++ b/spec/features/issues/create_branch_merge_request_spec.rb @@ -15,16 +15,14 @@ feature 'Create Branch/Merge Request Dropdown on issue page', js: true do visit project_issue_path(project, issue) select_dropdown_option('create-mr') + + expect(page).to have_content('WIP: Resolve "Cherry-Coloured Funk"') + expect(current_path).to eq(project_merge_request_path(project, MergeRequest.first)) - wait_for_requests + visit project_issue_path(project, issue) expect(page).to have_content("created branch 1-cherry-coloured-funk") expect(page).to have_content("mentioned in merge request !1") - - visit project_merge_request_path(project, MergeRequest.first) - - expect(page).to have_content('WIP: Resolve "Cherry-Coloured Funk"') - expect(current_path).to eq(project_merge_request_path(project, MergeRequest.first)) end it 'allows creating a branch from the issue page' do -- cgit v1.2.3 From e77e9b0077bb49aa05a16a3d04690219b2c8205e Mon Sep 17 00:00:00 2001 From: Richard Clamp Date: Fri, 28 Jul 2017 16:27:10 +0000 Subject: Fixup POST /v3/:id/hooks and PUT /v3/:id/hooks/:hook_id --- changelogs/unreleased/12673-fix_v3_project_hooks_build_events | 4 ++++ lib/api/v3/project_hooks.rb | 8 ++++++-- spec/requests/api/v3/project_hooks_spec.rb | 6 +++--- 3 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 changelogs/unreleased/12673-fix_v3_project_hooks_build_events diff --git a/changelogs/unreleased/12673-fix_v3_project_hooks_build_events b/changelogs/unreleased/12673-fix_v3_project_hooks_build_events new file mode 100644 index 00000000000..59bc646406f --- /dev/null +++ b/changelogs/unreleased/12673-fix_v3_project_hooks_build_events @@ -0,0 +1,4 @@ +--- +title: "Fix v3 api project_hooks POST and PUT operations for build_events" +merge_request: 12673 +author: Richard Clamp diff --git a/lib/api/v3/project_hooks.rb b/lib/api/v3/project_hooks.rb index 94614bfc8b6..51014591a93 100644 --- a/lib/api/v3/project_hooks.rb +++ b/lib/api/v3/project_hooks.rb @@ -56,7 +56,9 @@ module API use :project_hook_properties end post ":id/hooks" do - hook = user_project.hooks.new(declared_params(include_missing: false)) + attrs = declared_params(include_missing: false) + attrs[:job_events] = attrs.delete(:build_events) if attrs.key?(:build_events) + hook = user_project.hooks.new(attrs) if hook.save present hook, with: ::API::V3::Entities::ProjectHook @@ -77,7 +79,9 @@ module API put ":id/hooks/:hook_id" do hook = user_project.hooks.find(params.delete(:hook_id)) - if hook.update_attributes(declared_params(include_missing: false)) + attrs = declared_params(include_missing: false) + attrs[:job_events] = attrs.delete(:build_events) if attrs.key?(:build_events) + if hook.update_attributes(attrs) present hook, with: ::API::V3::Entities::ProjectHook else error!("Invalid url given", 422) if hook.errors[:url].present? diff --git a/spec/requests/api/v3/project_hooks_spec.rb b/spec/requests/api/v3/project_hooks_spec.rb index 1969d1c7f2b..b0eddbb5dd2 100644 --- a/spec/requests/api/v3/project_hooks_spec.rb +++ b/spec/requests/api/v3/project_hooks_spec.rb @@ -87,7 +87,7 @@ describe API::ProjectHooks, 'ProjectHooks' do it "adds hook to project" do expect do post v3_api("/projects/#{project.id}/hooks", user), - url: "http://example.com", issues_events: true, wiki_page_events: true + url: "http://example.com", issues_events: true, wiki_page_events: true, build_events: true end.to change {project.hooks.count}.by(1) expect(response).to have_http_status(201) @@ -97,7 +97,7 @@ describe API::ProjectHooks, 'ProjectHooks' do expect(json_response['merge_requests_events']).to eq(false) expect(json_response['tag_push_events']).to eq(false) expect(json_response['note_events']).to eq(false) - expect(json_response['build_events']).to eq(false) + expect(json_response['build_events']).to eq(true) expect(json_response['pipeline_events']).to eq(false) expect(json_response['wiki_page_events']).to eq(true) expect(json_response['enable_ssl_verification']).to eq(true) @@ -135,7 +135,7 @@ describe API::ProjectHooks, 'ProjectHooks' do describe "PUT /projects/:id/hooks/:hook_id" do it "updates an existing project hook" do put v3_api("/projects/#{project.id}/hooks/#{hook.id}", user), - url: 'http://example.org', push_events: false + url: 'http://example.org', push_events: false, build_events: true expect(response).to have_http_status(200) expect(json_response['url']).to eq('http://example.org') expect(json_response['issues_events']).to eq(hook.issues_events) -- cgit v1.2.3 From 8aaaefa5f68914613ab02a18c20244e733930fa8 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 28 Jul 2017 12:52:40 -0400 Subject: Fix spec/features/projects/branches_spec See https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8666 --- spec/features/projects/branches_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb index 6e787de2dd6..ad4527a0b74 100644 --- a/spec/features/projects/branches_spec.rb +++ b/spec/features/projects/branches_spec.rb @@ -29,7 +29,7 @@ describe 'Branches' do it 'sorts the branches by name' do visit project_branches_path(project) - click_button "Name" # Open sorting dropdown + click_button "Last updated" # Open sorting dropdown click_link "Name" sorted = repository.branches_sorted_by(:name).first(20).map do |branch| @@ -41,7 +41,7 @@ describe 'Branches' do it 'sorts the branches by last updated' do visit project_branches_path(project) - click_button "Name" # Open sorting dropdown + click_button "Last updated" # Open sorting dropdown click_link "Last updated" sorted = repository.branches_sorted_by(:updated_desc).first(20).map do |branch| @@ -53,7 +53,7 @@ describe 'Branches' do it 'sorts the branches by oldest updated' do visit project_branches_path(project) - click_button "Name" # Open sorting dropdown + click_button "Last updated" # Open sorting dropdown click_link "Oldest updated" sorted = repository.branches_sorted_by(:updated_asc).first(20).map do |branch| -- cgit v1.2.3 From ebd5f5148894888c118e95239fc437141c8e6b41 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Fri, 28 Jul 2017 12:49:07 -0500 Subject: fix relative_url_root support for webpack chunks --- app/helpers/webpack_helper.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/helpers/webpack_helper.rb b/app/helpers/webpack_helper.rb index 0386df22374..33453dd178f 100644 --- a/app/helpers/webpack_helper.rb +++ b/app/helpers/webpack_helper.rb @@ -34,6 +34,8 @@ module WebpackHelper end def webpack_public_path - "#{webpack_public_host}/#{Rails.application.config.webpack.public_path}/" + relative_path = Rails.application.config.relative_url_root + webpack_path = Rails.application.config.webpack.public_path + File.join(webpack_public_host.to_s, relative_path.to_s, webpack_path.to_s, '') end end -- cgit v1.2.3 From 2307eb80b576b4537e96e551bd17e2eced1d04a3 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 28 Jul 2017 18:55:27 +0100 Subject: Fixed breadcrumb titles aggressively collapsing Closes #35323 --- app/assets/stylesheets/new_nav.scss | 3 ++- changelogs/unreleased/breadcrumbs-collapsed-title-width-fix.yml | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/breadcrumbs-collapsed-title-width-fix.yml diff --git a/app/assets/stylesheets/new_nav.scss b/app/assets/stylesheets/new_nav.scss index 360ffda8d71..781d4cc8833 100644 --- a/app/assets/stylesheets/new_nav.scss +++ b/app/assets/stylesheets/new_nav.scss @@ -325,6 +325,7 @@ header.navbar-gitlab-new { .breadcrumbs-links { flex: 1; + min-width: 0; align-self: center; color: $gl-text-color-quaternary; @@ -343,7 +344,7 @@ header.navbar-gitlab-new { } .title { - white-space: nowrap; + display: inline-block; > a { &:last-of-type:not(:first-child) { diff --git a/changelogs/unreleased/breadcrumbs-collapsed-title-width-fix.yml b/changelogs/unreleased/breadcrumbs-collapsed-title-width-fix.yml new file mode 100644 index 00000000000..988fdacb5fd --- /dev/null +++ b/changelogs/unreleased/breadcrumbs-collapsed-title-width-fix.yml @@ -0,0 +1,4 @@ +--- +title: Fixed breadcrumbs title aggressively collapsing +merge_request: +author: -- cgit v1.2.3 From eac8ae0fe00bcbb7e3cf04c4d0b6328cb4ddcc62 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Fri, 28 Jul 2017 12:56:43 -0500 Subject: add CHANGELOG.md entry for !13165 --- .../unreleased/35567-fix-relative-urls-in-webpack-public-path.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelogs/unreleased/35567-fix-relative-urls-in-webpack-public-path.yml diff --git a/changelogs/unreleased/35567-fix-relative-urls-in-webpack-public-path.yml b/changelogs/unreleased/35567-fix-relative-urls-in-webpack-public-path.yml new file mode 100644 index 00000000000..41b506681f9 --- /dev/null +++ b/changelogs/unreleased/35567-fix-relative-urls-in-webpack-public-path.yml @@ -0,0 +1,5 @@ +--- +title: Fix asynchronous javascript paths when GitLab is installed under a relative + URL +merge_request: 13165 +author: -- cgit v1.2.3 From b2f91602981ebeeb76e39c87c7f58f1dfa0f60dd Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 28 Jul 2017 15:20:49 -0400 Subject: De-duplicate two specs in spec/services/notification_service_spec There were two specs that were testing the exact same thing as the spec above it, but with additional expectations. So we opted to keep the "more expectations" tests and deleted the duplicates. We've also deleted one nested `before` block that was duplicating setup of its parent context. --- spec/services/notification_service_spec.rb | 47 +++++++----------------------- 1 file changed, 10 insertions(+), 37 deletions(-) diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 49d6fc7853f..5b69426cbaa 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -694,17 +694,6 @@ describe NotificationService do let!(:subscriber_to_label_1) { create(:user) { |u| label_1.toggle_subscription(u, project) } } let!(:subscriber_to_label_2) { create(:user) { |u| label_2.toggle_subscription(u, project) } } - it "emails subscribers of the issue's added labels only" do - notification.relabeled_issue(issue, [group_label_2, label_2], @u_disabled) - - should_not_email(subscriber_to_label_1) - should_not_email(subscriber_to_group_label_1) - should_not_email(subscriber_to_group_label_2_on_another_project) - should_email(subscriber_1_to_group_label_2) - should_email(subscriber_2_to_group_label_2) - should_email(subscriber_to_label_2) - end - it "emails the current user if they've opted into notifications about their activity" do subscriber_to_label_2.notified_of_own_activity = true notification.relabeled_issue(issue, [group_label_2, label_2], subscriber_to_label_2) @@ -721,6 +710,12 @@ describe NotificationService do it "doesn't send email to anyone but subscribers of the given labels" do notification.relabeled_issue(issue, [group_label_2, label_2], @u_disabled) + should_not_email(subscriber_to_label_1) + should_not_email(subscriber_to_group_label_1) + should_not_email(subscriber_to_group_label_2_on_another_project) + should_email(subscriber_1_to_group_label_2) + should_email(subscriber_2_to_group_label_2) + should_email(subscriber_to_label_2) should_not_email(issue.assignees.first) should_not_email(issue.author) should_not_email(@u_watcher) @@ -730,12 +725,6 @@ describe NotificationService do should_not_email(@watcher_and_subscriber) should_not_email(@unsubscriber) should_not_email(@u_participating) - should_not_email(subscriber_to_label_1) - should_not_email(subscriber_to_group_label_1) - should_not_email(subscriber_to_group_label_2_on_another_project) - should_email(subscriber_1_to_group_label_2) - should_email(subscriber_2_to_group_label_2) - should_email(subscriber_to_label_2) end context 'confidential issues' do @@ -878,11 +867,6 @@ describe NotificationService do end describe '#new_merge_request' do - before do - update_custom_notification(:new_merge_request, @u_guest_custom, resource: project) - update_custom_notification(:new_merge_request, @u_custom_global) - end - it do notification.new_merge_request(merge_request, @u_disabled) @@ -1008,7 +992,7 @@ describe NotificationService do let!(:subscriber_to_label_1) { create(:user) { |u| label_1.toggle_subscription(u, project) } } let!(:subscriber_to_label_2) { create(:user) { |u| label_2.toggle_subscription(u, project) } } - it "emails subscribers of the merge request's added labels only" do + it "doesn't send email to anyone but subscribers of the given labels" do notification.relabeled_merge_request(merge_request, [group_label_2, label_2], @u_disabled) should_not_email(subscriber_to_label_1) @@ -1017,11 +1001,6 @@ describe NotificationService do should_email(subscriber_1_to_group_label_2) should_email(subscriber_2_to_group_label_2) should_email(subscriber_to_label_2) - end - - it "doesn't send email to anyone but subscribers of the given labels" do - notification.relabeled_merge_request(merge_request, [group_label_2, label_2], @u_disabled) - should_not_email(merge_request.assignee) should_not_email(merge_request.author) should_not_email(@u_watcher) @@ -1031,12 +1010,6 @@ describe NotificationService do should_not_email(@unsubscriber) should_not_email(@u_participating) should_not_email(@u_lazy_participant) - should_not_email(subscriber_to_label_1) - should_not_email(subscriber_to_group_label_1) - should_not_email(subscriber_to_group_label_2_on_another_project) - should_email(subscriber_1_to_group_label_2) - should_email(subscriber_2_to_group_label_2) - should_email(subscriber_to_label_2) end end @@ -1081,12 +1054,12 @@ describe NotificationService do should_email(merge_request.assignee) should_email(@u_watcher) + should_email(@u_guest_watcher) + should_email(@u_guest_custom) + should_email(@u_custom_global) should_email(@u_participant_mentioned) should_email(@subscriber) should_email(@watcher_and_subscriber) - should_email(@u_guest_watcher) - should_email(@u_custom_global) - should_email(@u_guest_custom) should_not_email(@unsubscriber) should_not_email(@u_participating) should_not_email(@u_disabled) -- cgit v1.2.3 From a07fe9d7f8f922020472ed54b060430a6da3da69 Mon Sep 17 00:00:00 2001 From: Alex Ives Date: Mon, 24 Jul 2017 22:11:22 -0500 Subject: Fixes #29385: Add /shrug and /tableflip commands - Updated DSL to support substitution definitions - Added substitution definition, inherits from command definition - Added tabelflip and shrug substitutions to interpret service - Added support for substitution definitions to the extractor for preview mode. - Added substitution handling in the interpret service Signed-off-by: Alex Ives --- app/services/quick_actions/interpret_service.rb | 16 +++++++++ changelogs/unreleased/29385-add_shrug_command.yml | 4 +++ lib/gitlab/quick_actions/dsl.rb | 29 ++++++++++++--- lib/gitlab/quick_actions/extractor.rb | 22 ++++++++++++ .../quick_actions/substitution_definition.rb | 24 +++++++++++++ spec/lib/gitlab/quick_actions/dsl_spec.rb | 16 ++++++++- spec/lib/gitlab/quick_actions/extractor_spec.rb | 37 +++++++++++++++++++ .../quick_actions/substitution_definition_spec.rb | 42 ++++++++++++++++++++++ .../quick_actions/interpret_service_spec.rb | 42 +++++++++++++++++++++- 9 files changed, 225 insertions(+), 7 deletions(-) create mode 100644 changelogs/unreleased/29385-add_shrug_command.yml create mode 100644 lib/gitlab/quick_actions/substitution_definition.rb create mode 100644 spec/lib/gitlab/quick_actions/substitution_definition_spec.rb diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb index 5dc1b91d2c0..c22bf7498bb 100644 --- a/app/services/quick_actions/interpret_service.rb +++ b/app/services/quick_actions/interpret_service.rb @@ -4,6 +4,9 @@ module QuickActions attr_reader :issuable + SHRUG = '¯\\_(ツ)_/¯'.freeze + TABLEFLIP = '(╯°□°)╯︵ ┻━┻'.freeze + # Takes a text and interprets the commands that are extracted from it. # Returns the content without commands, and hash of changes to be applied to a record. def execute(content, issuable) @@ -14,6 +17,7 @@ module QuickActions content, commands = extractor.extract_commands(content, context) extract_updates(commands, context) + [content, @updates] end @@ -423,6 +427,18 @@ module QuickActions @updates[:spend_time] = { duration: :reset, user: current_user } end + desc "Append the comment with #{SHRUG}" + params '' + substitution :shrug do |comment| + "#{comment} #{SHRUG}" + end + + desc "Append the comment with #{TABLEFLIP}" + params '' + substitution :tableflip do |comment| + "#{comment} #{TABLEFLIP}" + end + # This is a dummy command, so that it appears in the autocomplete commands desc 'CC' params '@user' diff --git a/changelogs/unreleased/29385-add_shrug_command.yml b/changelogs/unreleased/29385-add_shrug_command.yml new file mode 100644 index 00000000000..14b8f486d5c --- /dev/null +++ b/changelogs/unreleased/29385-add_shrug_command.yml @@ -0,0 +1,4 @@ +--- +title: Add /shrug and /tableflip commands +merge_request: 10068 +author: Alex Ives diff --git a/lib/gitlab/quick_actions/dsl.rb b/lib/gitlab/quick_actions/dsl.rb index a4a97236ffc..536765305e1 100644 --- a/lib/gitlab/quick_actions/dsl.rb +++ b/lib/gitlab/quick_actions/dsl.rb @@ -105,9 +105,32 @@ module Gitlab # # Awesome code block # end def command(*command_names, &block) + define_command(CommandDefinition, *command_names, &block) + end + + # Registers a new substitution which is recognizable from body of email or + # comment. + # It accepts aliases and takes a block with the formatted content. + # + # Example: + # + # command :my_substitution, :alias_for_my_substitution do |text| + # "#{text} MY AWESOME SUBSTITUTION" + # end + def substitution(*substitution_names, &block) + define_command(SubstitutionDefinition, *substitution_names, &block) + end + + def definition_by_name(name) + command_definitions_by_name[name.to_sym] + end + + private + + def define_command(klass, *command_names, &block) name, *aliases = command_names - definition = CommandDefinition.new( + definition = klass.new( name, aliases: aliases, description: @description, @@ -130,10 +153,6 @@ module Gitlab @condition_block = nil @parse_params_block = nil end - - def definition_by_name(name) - command_definitions_by_name[name.to_sym] - end end end end diff --git a/lib/gitlab/quick_actions/extractor.rb b/lib/gitlab/quick_actions/extractor.rb index 09576be7156..3ebfa3bd4b8 100644 --- a/lib/gitlab/quick_actions/extractor.rb +++ b/lib/gitlab/quick_actions/extractor.rb @@ -46,6 +46,8 @@ module Gitlab end end + content, commands = perform_substitutions(content, commands) + [content.strip, commands] end @@ -110,6 +112,26 @@ module Gitlab }mx end + def perform_substitutions(content, commands) + return unless content + + substitution_definitions = self.command_definitions.select do |definition| + definition.is_a?(Gitlab::QuickActions::SubstitutionDefinition) + end + + substitution_definitions.each do |substitution| + match_data = substitution.match(content) + if match_data + command = [substitution.name.to_s] + command << match_data[1] unless match_data[1].empty? + commands << command + end + content = substitution.perform_substitution(self, content) + end + + [content, commands] + end + def command_names(opts) command_definitions.flat_map do |command| next if command.noop? diff --git a/lib/gitlab/quick_actions/substitution_definition.rb b/lib/gitlab/quick_actions/substitution_definition.rb new file mode 100644 index 00000000000..032c49ed159 --- /dev/null +++ b/lib/gitlab/quick_actions/substitution_definition.rb @@ -0,0 +1,24 @@ +module Gitlab + module QuickActions + class SubstitutionDefinition < CommandDefinition + # noop?=>true means these won't get extracted or removed by Gitlab::QuickActions::Extractor#extract_commands + # QuickActions::InterpretService#perform_substitutions handles them separately + def noop? + true + end + + def match(content) + content.match %r{^/#{all_names.join('|')} ?(.*)$} + end + + def perform_substitution(context, content) + return unless content + + all_names.each do |a_name| + content.gsub!(%r{/#{a_name} ?(.*)$}, execute_block(action_block, context, '\1')) + end + content + end + end + end +end diff --git a/spec/lib/gitlab/quick_actions/dsl_spec.rb b/spec/lib/gitlab/quick_actions/dsl_spec.rb index a4bb3f911d7..ff59dc48bcb 100644 --- a/spec/lib/gitlab/quick_actions/dsl_spec.rb +++ b/spec/lib/gitlab/quick_actions/dsl_spec.rb @@ -42,13 +42,18 @@ describe Gitlab::QuickActions::Dsl do command :with_params_parsing do |parsed| parsed end + + params '' + substitution :something do |text| + "#{text} Some complicated thing you want in here" + end end end describe '.command_definitions' do it 'returns an array with commands definitions' do no_args_def, explanation_with_aliases_def, dynamic_description_def, - cc_def, cond_action_def, with_params_parsing_def = + cc_def, cond_action_def, with_params_parsing_def, substitution_def = DummyClass.command_definitions expect(no_args_def.name).to eq(:no_args) @@ -104,6 +109,15 @@ describe Gitlab::QuickActions::Dsl do expect(with_params_parsing_def.condition_block).to be_nil expect(with_params_parsing_def.action_block).to be_a_kind_of(Proc) expect(with_params_parsing_def.parse_params_block).to be_a_kind_of(Proc) + + expect(substitution_def.name).to eq(:something) + expect(substitution_def.aliases).to eq([]) + expect(substitution_def.description).to eq('') + expect(substitution_def.explanation).to eq('') + expect(substitution_def.params).to eq(['']) + expect(substitution_def.condition_block).to be_nil + expect(substitution_def.action_block.call('text')).to eq('text Some complicated thing you want in here') + expect(substitution_def.parse_params_block).to be_nil end end end diff --git a/spec/lib/gitlab/quick_actions/extractor_spec.rb b/spec/lib/gitlab/quick_actions/extractor_spec.rb index 9d32938e155..f7c288f2393 100644 --- a/spec/lib/gitlab/quick_actions/extractor_spec.rb +++ b/spec/lib/gitlab/quick_actions/extractor_spec.rb @@ -9,6 +9,11 @@ describe Gitlab::QuickActions::Extractor do command(:assign) { } command(:labels) { } command(:power) { } + command(:noop_command) + substitution(:substitution) { 'foo' } + substitution :shrug do |comment| + "#{comment} SHRUG" + end end.command_definitions end @@ -177,6 +182,38 @@ describe Gitlab::QuickActions::Extractor do expect(msg).to eq "hello\nworld" end + it 'does not extract noop commands' do + msg = %(hello\nworld\n/reopen\n/noop_command) + msg, commands = extractor.extract_commands(msg) + + expect(commands).to eq [['reopen']] + expect(msg).to eq "hello\nworld\n/noop_command" + end + + it 'extracts and performs substitution commands' do + msg = %(hello\nworld\n/reopen\n/substitution) + msg, commands = extractor.extract_commands(msg) + + expect(commands).to eq [['reopen'], ['substitution']] + expect(msg).to eq "hello\nworld\nfoo" + end + + it 'extracts and performs substitution commands' do + msg = %(hello\nworld\n/reopen\n/shrug this is great?) + msg, commands = extractor.extract_commands(msg) + + expect(commands).to eq [['reopen'], ['shrug', 'this is great?']] + expect(msg).to eq "hello\nworld\nthis is great? SHRUG" + end + + it 'extracts and performs substitution commands with comments' do + msg = %(hello\nworld\n/reopen\n/substitution wow this is a thing.) + msg, commands = extractor.extract_commands(msg) + + expect(commands).to eq [['reopen'], ['substitution', 'wow this is a thing.']] + expect(msg).to eq "hello\nworld\nfoo" + end + it 'extracts multiple commands' do msg = %(hello\n/power @user.name %9.10 ~"bar baz.2" label\nworld\n/reopen) msg, commands = extractor.extract_commands(msg) diff --git a/spec/lib/gitlab/quick_actions/substitution_definition_spec.rb b/spec/lib/gitlab/quick_actions/substitution_definition_spec.rb new file mode 100644 index 00000000000..1bb8bc51c96 --- /dev/null +++ b/spec/lib/gitlab/quick_actions/substitution_definition_spec.rb @@ -0,0 +1,42 @@ +require 'spec_helper' + +describe Gitlab::QuickActions::SubstitutionDefinition do + let(:content) do + < Date: Fri, 28 Jul 2017 10:07:46 +0000 Subject: Merge branch '35643-impersonate-spec' into '9-4-stable-patch-2' Resolve "Impersonation Tokens creation spec failure in admin_users_impersonation_tokens_spec.rb" See merge request !13145 --- spec/features/admin/admin_users_impersonation_tokens_spec.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spec/features/admin/admin_users_impersonation_tokens_spec.rb b/spec/features/admin/admin_users_impersonation_tokens_spec.rb index 97ffc54415c..034682dae27 100644 --- a/spec/features/admin/admin_users_impersonation_tokens_spec.rb +++ b/spec/features/admin/admin_users_impersonation_tokens_spec.rb @@ -32,11 +32,13 @@ describe 'Admin > Users > Impersonation Tokens', js: true do check "api" check "read_user" - expect { click_on "Create impersonation token" }.to change { PersonalAccessTokensFinder.new(impersonation: true).execute.count } + click_on "Create impersonation token" + expect(active_impersonation_tokens).to have_text(name) expect(active_impersonation_tokens).to have_text('In') expect(active_impersonation_tokens).to have_text('api') expect(active_impersonation_tokens).to have_text('read_user') + expect(PersonalAccessTokensFinder.new(impersonation: true).execute.count).to equal(1) end end -- cgit v1.2.3 From 987b53e321076a3ea53c76819ab777152938c778 Mon Sep 17 00:00:00 2001 From: Florian Lemaitre Date: Fri, 28 Jul 2017 21:41:40 +0000 Subject: Projects logo are not centered vertically on projects page --- app/assets/stylesheets/framework/avatar.scss | 4 ++++ ...044-projects-logo-are-not-centered-vertically-on-projects-page.yml | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 changelogs/unreleased/35044-projects-logo-are-not-centered-vertically-on-projects-page.yml diff --git a/app/assets/stylesheets/framework/avatar.scss b/app/assets/stylesheets/framework/avatar.scss index 0dfa7a31d31..cb41df8a88d 100644 --- a/app/assets/stylesheets/framework/avatar.scss +++ b/app/assets/stylesheets/framework/avatar.scss @@ -88,6 +88,10 @@ overflow: hidden; display: flex; + a { + display: flex; + } + .avatar { border-radius: 0; border: none; diff --git a/changelogs/unreleased/35044-projects-logo-are-not-centered-vertically-on-projects-page.yml b/changelogs/unreleased/35044-projects-logo-are-not-centered-vertically-on-projects-page.yml new file mode 100644 index 00000000000..9de4dbefd35 --- /dev/null +++ b/changelogs/unreleased/35044-projects-logo-are-not-centered-vertically-on-projects-page.yml @@ -0,0 +1,4 @@ +--- +title: Fix project logos that are not centered vertically on list pages +merge_request: 13124 +author: Florian Lemaitre -- cgit v1.2.3 From 48fcb06c2a33c1f56f4aab76c843a41103d4ef93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matija=20=C4=8Cupi=C4=87?= Date: Sat, 29 Jul 2017 03:01:48 +0200 Subject: Bump google-protobuf to 3.3.0 --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 627750e2c1d..05a70704513 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -323,7 +323,7 @@ GEM multi_json (~> 1.10) retriable (~> 1.4) signet (~> 0.6) - google-protobuf (3.2.0.2) + google-protobuf (3.3.0) googleauth (0.5.1) faraday (~> 0.9) jwt (~> 1.4) -- cgit v1.2.3 From 2d60d1de8d99fd80f6b1adfb90b7a275d69d000b Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Sat, 29 Jul 2017 01:14:33 +0900 Subject: fix --- db/schema.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index 0abdb987b77..5fbbdea6eaa 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -254,32 +254,32 @@ ActiveRecord::Schema.define(version: 20170725145659) do add_index "ci_builds", ["updated_at"], name: "index_ci_builds_on_updated_at", using: :btree add_index "ci_builds", ["user_id"], name: "index_ci_builds_on_user_id", using: :btree - create_table "ci_pipeline_schedule_variables", force: :cascade do |t| + create_table "ci_group_variables", force: :cascade do |t| t.string "key", null: false t.text "value" t.text "encrypted_value" t.string "encrypted_value_salt" t.string "encrypted_value_iv" - t.integer "pipeline_schedule_id", null: false + t.integer "group_id", null: false + t.boolean "protected", default: false, null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false end - add_index "ci_pipeline_schedule_variables", ["pipeline_schedule_id", "key"], name: "index_ci_pipeline_schedule_variables_on_schedule_id_and_key", unique: true, using: :btree + add_index "ci_group_variables", ["group_id", "key"], name: "index_ci_group_variables_on_group_id_and_key", unique: true, using: :btree - create_table "ci_group_variables", force: :cascade do |t| + create_table "ci_pipeline_schedule_variables", force: :cascade do |t| t.string "key", null: false t.text "value" t.text "encrypted_value" t.string "encrypted_value_salt" t.string "encrypted_value_iv" - t.integer "group_id", null: false - t.boolean "protected", default: false, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.integer "pipeline_schedule_id", null: false + t.datetime "created_at" + t.datetime "updated_at" end - add_index "ci_group_variables", ["group_id", "key"], name: "index_ci_group_variables_on_group_id_and_key", unique: true, using: :btree + add_index "ci_pipeline_schedule_variables", ["pipeline_schedule_id", "key"], name: "index_ci_pipeline_schedule_variables_on_schedule_id_and_key", unique: true, using: :btree create_table "ci_pipeline_schedules", force: :cascade do |t| t.string "description" @@ -1624,8 +1624,8 @@ ActiveRecord::Schema.define(version: 20170725145659) do add_foreign_key "ci_builds", "ci_pipelines", column: "auto_canceled_by_id", name: "fk_a2141b1522", on_delete: :nullify add_foreign_key "ci_builds", "ci_stages", column: "stage_id", name: "fk_3a9eaa254d", on_delete: :cascade add_foreign_key "ci_builds", "projects", name: "fk_befce0568a", on_delete: :cascade - add_foreign_key "ci_pipeline_schedule_variables", "ci_pipeline_schedules", column: "pipeline_schedule_id", name: "fk_41c35fda51", on_delete: :cascade add_foreign_key "ci_group_variables", "namespaces", column: "group_id", name: "fk_33ae4d58d8", on_delete: :cascade + add_foreign_key "ci_pipeline_schedule_variables", "ci_pipeline_schedules", column: "pipeline_schedule_id", name: "fk_41c35fda51", on_delete: :cascade add_foreign_key "ci_pipeline_schedules", "projects", name: "fk_8ead60fcc4", on_delete: :cascade add_foreign_key "ci_pipeline_schedules", "users", column: "owner_id", name: "fk_9ea99f58d2", on_delete: :nullify add_foreign_key "ci_pipeline_variables", "ci_pipelines", column: "pipeline_id", name: "fk_f29c5f4380", on_delete: :cascade -- cgit v1.2.3 From 643b9274ecc84ccfb16f5e12c01f8644b1a15bb9 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Sat, 29 Jul 2017 12:14:18 +0100 Subject: Fix top bar in jobs view for microsoft edge --- app/assets/stylesheets/pages/builds.scss | 1 + changelogs/unreleased/35672-edge-top-bar.yml | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 changelogs/unreleased/35672-edge-top-bar.yml diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index b6fc628c02b..6591b801f82 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -86,6 +86,7 @@ position: absolute; right: 0; left: 0; + top: 0; } .truncated-info { diff --git a/changelogs/unreleased/35672-edge-top-bar.yml b/changelogs/unreleased/35672-edge-top-bar.yml new file mode 100644 index 00000000000..0424dee19af --- /dev/null +++ b/changelogs/unreleased/35672-edge-top-bar.yml @@ -0,0 +1,4 @@ +--- +title: Properly affixes nav bar in job view in microsoft edge +merge_request: +author: -- cgit v1.2.3 From 06a760e1392c540318058bd30ce644b20015caaf Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 30 Jul 2017 09:51:08 -0500 Subject: Add a note about EFS and GitLab log files [ci skip] --- doc/administration/high_availability/nfs.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/administration/high_availability/nfs.md b/doc/administration/high_availability/nfs.md index bd6b7327aed..90a2e9298bf 100644 --- a/doc/administration/high_availability/nfs.md +++ b/doc/administration/high_availability/nfs.md @@ -46,6 +46,10 @@ GitLab does not recommend using EFS with GitLab. many small files are written in a serialized manner are not well-suited for EFS. EBS with an NFS server on top will perform much better. +In addition, avoid storing GitLab log files (e.g. those in `/var/log/gitlab`) +because this will also affect performance. We recommend that the log files be +stored on a local volume. + For more details on another person's experience with EFS, see [Amazon's Elastic File System: Burst Credits](https://www.rawkode.io/2017/04/amazons-elastic-file-system-burst-credits/) -- cgit v1.2.3 From acc0d8484505ed199fe8b9d2529d8f298d95bb80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Mon, 31 Jul 2017 08:07:51 +0000 Subject: Moves the Performance Bar to the top instead of being at the bottom --- app/assets/stylesheets/framework/header.scss | 4 +++ app/assets/stylesheets/framework/layout.scss | 4 +++ app/assets/stylesheets/framework/nav.scss | 20 +++++++++++++ app/assets/stylesheets/framework/sidebar.scss | 4 +++ app/assets/stylesheets/framework/variables.scss | 1 + app/assets/stylesheets/new_sidebar.scss | 12 ++++++-- app/assets/stylesheets/pages/builds.scss | 14 +++++++-- app/assets/stylesheets/pages/issuable.scss | 8 +++++ app/assets/stylesheets/pages/merge_requests.scss | 4 +++ app/assets/stylesheets/performance_bar.scss | 14 +++++++-- app/helpers/application_helper.rb | 6 +++- app/helpers/nav_helper.rb | 33 ++++++++++++++------- app/views/layouts/_page.html.haml | 4 +-- app/views/layouts/application.html.haml | 5 ++-- app/views/peek/views/_host.html.haml | 2 ++ .../monitoring/performance/img/performance_bar.png | Bin 186116 -> 170256 bytes 16 files changed, 111 insertions(+), 24 deletions(-) create mode 100644 app/views/peek/views/_host.html.haml diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 605f4284bb5..df847094864 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -315,6 +315,10 @@ header { } } +.with-performance-bar header.navbar-gitlab { + top: $performance-bar-height; +} + .navbar-nav { li { .badge { diff --git a/app/assets/stylesheets/framework/layout.scss b/app/assets/stylesheets/framework/layout.scss index 4a9d41b4fda..67c3287ed74 100644 --- a/app/assets/stylesheets/framework/layout.scss +++ b/app/assets/stylesheets/framework/layout.scss @@ -120,3 +120,7 @@ of the body element here, we negate cascading side effects but allow momentum sc .page-with-sidebar { -webkit-overflow-scrolling: auto; } + +.with-performance-bar .page-with-sidebar { + margin-top: $header-height + $performance-bar-height; +} diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 35b4d77a5ab..88e7ba117d5 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -347,6 +347,10 @@ } } +.with-performance-bar .layout-nav { + margin-top: $header-height + $performance-bar-height; +} + .scrolling-tabs-container { position: relative; @@ -441,6 +445,22 @@ } } +.with-performance-bar .page-with-layout-nav { + .right-sidebar { + top: ($header-height + 1) * 2 + $performance-bar-height; + } + + &.page-with-sub-nav { + .right-sidebar { + top: ($header-height + 1) * 3 + $performance-bar-height; + + &.affix { + top: $header-height + $performance-bar-height; + } + } + } +} + .nav-block { &.activities { border-bottom: 1px solid $border-color; diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index 49b2f0e43a4..09b60ad1676 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -89,6 +89,10 @@ } } +.with-performance-bar .right-sidebar.affix { + top: $header-height + $performance-bar-height; +} + @mixin maintain-sidebar-dimensions { display: block; width: $gutter-width; diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index cf0a1ad57d0..0df6f24bfe6 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -204,6 +204,7 @@ $divergence-graph-separator-bg: #ccc; $general-hover-transition-duration: 100ms; $general-hover-transition-curve: linear; $highlight-changes-color: rgb(235, 255, 232); +$performance-bar-height: 35px; /* diff --git a/app/assets/stylesheets/new_sidebar.scss b/app/assets/stylesheets/new_sidebar.scss index ae43197a1a6..54f3e8d882c 100644 --- a/app/assets/stylesheets/new_sidebar.scss +++ b/app/assets/stylesheets/new_sidebar.scss @@ -118,7 +118,7 @@ $new-sidebar-width: 220px; z-index: 400; width: $new-sidebar-width; transition: left $sidebar-transition-duration; - top: 50px; + top: $header-height; bottom: 0; left: 0; overflow: auto; @@ -163,6 +163,10 @@ $new-sidebar-width: 220px; } } +.with-performance-bar .nav-sidebar { + top: $header-height + $performance-bar-height; +} + .sidebar-sub-level-items { display: none; padding-bottom: 8px; @@ -260,7 +264,7 @@ $new-sidebar-width: 220px; // Make issue boards full-height now that sub-nav is gone .boards-list { - height: calc(100vh - 50px); + height: calc(100vh - #{$header-height}); @media (min-width: $screen-sm-min) { height: 475px; // Needed for PhantomJS @@ -270,6 +274,10 @@ $new-sidebar-width: 220px; } } +.with-performance-bar .boards-list { + height: calc(100vh - #{$header-height} - #{$performance-bar-height}); +} + // Change color of all horizontal tabs to match the new indigo color .nav-links li.active a { diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index b6fc628c02b..7f14c149198 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -64,10 +64,10 @@ color: $gl-text-color; position: sticky; position: -webkit-sticky; - top: 50px; + top: $header-height; &.affix { - top: 50px; + top: $header-height; } // with sidebar @@ -171,6 +171,16 @@ } } +.with-performance-bar .build-page { + .top-bar { + top: $header-height + $performance-bar-height; + + &.affix { + top: $header-height + $performance-bar-height; + } + } +} + .build-header { .ci-header-container, .header-action-buttons { diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index eb269df46fe..6da14320914 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -445,6 +445,14 @@ } } +.with-performance-bar .right-sidebar { + top: $header-height + $performance-bar-height; + + .issuable-sidebar { + height: calc(100% - #{$header-height} - #{$performance-bar-height}); + } +} + .detail-page-description { padding: 16px 0; diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 2db967547dd..4693b2434c7 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -759,6 +759,10 @@ } } +.with-performance-bar .merge-request-tabs-holder { + top: $header-height + $performance-bar-height; +} + .merge-request-tabs { display: flex; margin-bottom: 0; diff --git a/app/assets/stylesheets/performance_bar.scss b/app/assets/stylesheets/performance_bar.scss index 2890b6b1e49..6e539e39ca1 100644 --- a/app/assets/stylesheets/performance_bar.scss +++ b/app/assets/stylesheets/performance_bar.scss @@ -3,9 +3,16 @@ @import "peek/views/rblineprof"; #peek { - height: 35px; + position: fixed; + left: 0; + top: 0; + width: 100%; + z-index: 2000; + overflow-x: hidden; + + height: $performance-bar-height; background: $black; - line-height: 35px; + line-height: $performance-bar-height; color: $perf-bar-text; &.disabled { @@ -25,7 +32,8 @@ } .wrapper { - width: 1000px; + width: 80%; + height: $performance-bar-height; margin: 0 auto; } diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 1c165700b19..14dc9bd9d62 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -264,7 +264,11 @@ module ApplicationHelper end def page_class - "issue-boards-page" if current_controller?(:boards) + class_names = [] + class_names << 'issue-boards-page' if current_controller?(:boards) + class_names << 'with-performance-bar' if performance_bar_enabled? + + class_names end # Returns active css class when condition returns true diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb index b769462abc2..b1205b8529b 100644 --- a/app/helpers/nav_helper.rb +++ b/app/helpers/nav_helper.rb @@ -1,38 +1,49 @@ module NavHelper + def page_with_sidebar_class + class_name = page_gutter_class + class_name << 'page-with-new-sidebar' if defined?(@new_sidebar) && @new_sidebar + + class_name + end + def page_gutter_class if current_path?('merge_requests#show') || current_path?('projects/merge_requests/conflicts#show') || current_path?('issues#show') || current_path?('milestones#show') if cookies[:collapsed_gutter] == 'true' - "page-gutter right-sidebar-collapsed" + %w[page-gutter right-sidebar-collapsed] else - "page-gutter right-sidebar-expanded" + %w[page-gutter right-sidebar-expanded] end elsif current_path?('jobs#show') - "page-gutter build-sidebar right-sidebar-expanded" + %w[page-gutter build-sidebar right-sidebar-expanded] elsif current_path?('wikis#show') || current_path?('wikis#edit') || current_path?('wikis#update') || current_path?('wikis#history') || current_path?('wikis#git_access') - "page-gutter wiki-sidebar right-sidebar-expanded" + %w[page-gutter wiki-sidebar right-sidebar-expanded] + else + [] end end def nav_header_class - class_name = '' - class_name << " with-horizontal-nav" if defined?(nav) && nav + class_names = [] + class_names << 'with-horizontal-nav' if defined?(nav) && nav - class_name + class_names end def layout_nav_class - class_name = '' - class_name << " page-with-layout-nav" if defined?(nav) && nav - class_name << " page-with-sub-nav" if content_for?(:sub_nav) + return [] if show_new_nav? - class_name + class_names = [] + class_names << 'page-with-layout-nav' if defined?(nav) && nav + class_names << 'page-with-sub-nav' if content_for?(:sub_nav) + + class_names end def nav_control_class diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml index 873220cc73d..c4f8cd71395 100644 --- a/app/views/layouts/_page.html.haml +++ b/app/views/layouts/_page.html.haml @@ -1,4 +1,4 @@ -.page-with-sidebar{ class: "#{('page-with-new-sidebar' if defined?(@new_sidebar) && @new_sidebar)} #{page_gutter_class}" } +.page-with-sidebar{ class: page_with_sidebar_class } - if show_new_nav? - if defined?(nav) && nav = render "layouts/nav/#{nav}" @@ -9,7 +9,7 @@ = render "layouts/nav/#{nav}" - if content_for?(:sub_nav) = yield :sub_nav - .content-wrapper{ class: "#{(layout_nav_class unless show_new_nav?)}" } + .content-wrapper{ class: layout_nav_class } - if show_new_nav? .mobile-overlay .alert-wrapper diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 38b95d11fd4..b53f382fa3d 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -1,8 +1,9 @@ !!! 5 -%html{ lang: I18n.locale, class: "#{page_class}" } +%html{ lang: I18n.locale, class: page_class } = render "layouts/head" %body{ class: @body_class, data: { page: body_data_page, project: "#{@project.path if @project}", group: "#{@group.path if @group}", find_file: find_file_path } } = render "layouts/init_auto_complete" if @gfm_form + = render 'peek/bar' - if show_new_nav? = render "layouts/header/new" - else @@ -10,5 +11,3 @@ = render 'layouts/page', sidebar: sidebar, nav: nav = yield :scripts_body - - = render 'peek/bar' diff --git a/app/views/peek/views/_host.html.haml b/app/views/peek/views/_host.html.haml new file mode 100644 index 00000000000..40769b5c6f6 --- /dev/null +++ b/app/views/peek/views/_host.html.haml @@ -0,0 +1,2 @@ +%span.current-host + = truncate(view.hostname) diff --git a/doc/administration/monitoring/performance/img/performance_bar.png b/doc/administration/monitoring/performance/img/performance_bar.png index d38293d2ed6..b3c6bc474e3 100644 Binary files a/doc/administration/monitoring/performance/img/performance_bar.png and b/doc/administration/monitoring/performance/img/performance_bar.png differ -- cgit v1.2.3 From ebd2ed8f644ba4f0fcaff979d4de41f773b31fdd Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 31 Jul 2017 11:42:50 +0200 Subject: Pass OmniAuth formatted options to OmniAuth::LDAP::Adaptor --- changelogs/unreleased/dm-ldap-authentication-ssl-verification.yml | 4 ++++ lib/gitlab/ldap/authentication.rb | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/dm-ldap-authentication-ssl-verification.yml diff --git a/changelogs/unreleased/dm-ldap-authentication-ssl-verification.yml b/changelogs/unreleased/dm-ldap-authentication-ssl-verification.yml new file mode 100644 index 00000000000..59462a6666d --- /dev/null +++ b/changelogs/unreleased/dm-ldap-authentication-ssl-verification.yml @@ -0,0 +1,4 @@ +--- +title: Fix LDAP authentication to Git repository or container registry +merge_request: +author: diff --git a/lib/gitlab/ldap/authentication.rb b/lib/gitlab/ldap/authentication.rb index 4745311402c..ed1de73f8c6 100644 --- a/lib/gitlab/ldap/authentication.rb +++ b/lib/gitlab/ldap/authentication.rb @@ -42,7 +42,7 @@ module Gitlab end def adapter - OmniAuth::LDAP::Adaptor.new(config.options.symbolize_keys) + OmniAuth::LDAP::Adaptor.new(config.omniauth_options) end def config -- cgit v1.2.3 From c9c0a12713461abc8d61690b7c319253eb8980de Mon Sep 17 00:00:00 2001 From: Marcia Ramos Date: Mon, 31 Jul 2017 09:44:07 +0000 Subject: New doc topic user/project/index --- doc/README.md | 13 +++-- doc/user/index.md | 2 +- doc/user/profile/index.md | 2 +- doc/user/project/index.md | 107 +++++++++++++++++++++++++++++++++++ doc/user/project/koding.md | 2 +- doc/user/project/repository/index.md | 2 +- 6 files changed, 118 insertions(+), 10 deletions(-) create mode 100644 doc/user/project/index.md diff --git a/doc/README.md b/doc/README.md index cc63ecb7eab..8bb8e147cd1 100644 --- a/doc/README.md +++ b/doc/README.md @@ -44,16 +44,17 @@ Shortcuts to GitLab's most visited docs: ### Projects and groups -- [Create a project](gitlab-basics/create-project.md) -- [Fork a project](gitlab-basics/fork-project.md) -- [Importing and exporting projects between instances](user/project/settings/import_export.md). -- [Project access](public_access/public_access.md): Setting up your project's visibility to public, internal, or private. +- [Projects](user/project/index.md): + - [Create a project](gitlab-basics/create-project.md) + - [Fork a project](gitlab-basics/fork-project.md) + - [Importing and exporting projects between instances](user/project/settings/import_export.md). + - [Project access](public_access/public_access.md): Setting up your project's visibility to public, internal, or private. + - [GitLab Pages](user/project/pages/index.md): Build, test, and deploy your static website with GitLab Pages. - [Groups](user/group/index.md): Organize your projects in groups. - - [GitLab Subgroups](user/group/subgroups/index.md) + - [Subgroups](user/group/subgroups/index.md) - [Search through GitLab](user/search/index.md): Search for issues, merge requests, projects, groups, todos, and issues in Issue Boards. - [Snippets](user/snippets.md): Snippets allow you to create little bits of code. - [Wikis](user/project/wiki/index.md): Enhance your repository documentation with built-in wikis. -- [GitLab Pages](user/project/pages/index.md): Build, test, and deploy your static website with GitLab Pages. ### Repository diff --git a/doc/user/index.md b/doc/user/index.md index 522cf932349..1281cc6e4f0 100644 --- a/doc/user/index.md +++ b/doc/user/index.md @@ -66,7 +66,7 @@ For more use cases please check our [Technical Articles](../articles/index.md). ## Projects -In GitLab, you can create projects for numerous reasons, such as, host +In GitLab, you can create [projects](project/index.md) for numerous reasons, such as, host your code, use it as an issue tracker, collaborate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD. Or, you can do it all at once, from one single project. diff --git a/doc/user/profile/index.md b/doc/user/profile/index.md index 0e3747817d2..7d25970fcb1 100644 --- a/doc/user/profile/index.md +++ b/doc/user/profile/index.md @@ -23,7 +23,7 @@ On your profile page, you will see the following information: - Personal information - Activity stream: see your activity streamline and the history of your contributions - Groups: [groups](../group/index.md) you're a member of -- Contributed projects: projects you contributed to +- Contributed projects: [projects](../project/index.md) you contributed to - Personal projects: your personal projects (respecting the project's visibility level) - Snippets: your personal code [snippets](../snippets.md#personal-snippets) diff --git a/doc/user/project/index.md b/doc/user/project/index.md new file mode 100644 index 00000000000..91a19600951 --- /dev/null +++ b/doc/user/project/index.md @@ -0,0 +1,107 @@ +# Projects + +In GitLab, you can create projects for hosting +your codebase, use it as an issue tracker, collaborate on code, and continuously +build, test, and deploy your app with built-in GitLab CI/CD. + +Your projects can be [available](../../public_access/public_access.md) +publicly, internally, or privately, at your choice. GitLab does not limit +the number of private projects you create. + +## Project's features + +When you create a project in GitLab, you'll have access to a large number of +[features](https://about.gitlab.com/features/): + +**Issues and merge requests:** + +- [Issue tracker](issues/index.md): Discuss implementations with your team within issues + - [Issue Boards](issue_board.md): Organize and prioritize your workflow + - [Multiple Issue Boards](https://docs.gitlab.com/ee/user/project/issue_board.html#multiple-issue-boards) (**EES/EEP**): Allow your teams to create their own workflows (Issue Boards) for the same project +- [Repositories](repository/index.md): Host your code in a fully +integrated platform + - [Protected branches](protected_branches.md): Prevent collaborators + from messing with history or pushing code without review + - [Protected tags](protected_tags.md): Control over who has + permission to create tags, and prevent accidental update or deletion +- [Merge Requests](merge_requests/index.md): Apply your branching +strategy and get reviewed by your team + - [Merge Request Approvals](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html) (**EES/EEP**): Ask for approval before + implementing a change + - [Fix merge conflicts from the UI](merge_requests/resolve_conflicts.md): + Your Git diff tool right from GitLab's UI + - [Review Apps](../../ci/review_apps/index.md): Live preview the results + of the changes proposed in a merge request in a per-branch basis +- [Labels](labels.md): Organize issues and merge requests by labels +- [Time Tracking](../../workflow/time_tracking.md): Track estimate time +and time spent on + the conclusion of an issue or merge request +- [Milestones](milestones/index.md): Work towards a target date +- [Description templates](description_templates.md): Define context-specific +templates for issue and merge request description fields for your project +- [Slash commands (quick actions)](quick_actions.md): Textual shortcuts for +common actions on issues or merge requests + +**GitLab CI/CD:** + +- [GitLab CI/CD](../../ci/README.md): GitLab's built-in [Continuous Integration, Delivery, and Deployment](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) tool + - [Container Registry](container_registry.md): Build and push Docker + images out-of-the-box + - [Auto Deploy](../../ci/autodeploy/index.md): Configure GitLab CI/CD + to automatically set up your app's deployment + - [Enable and disable GitLab CI](../../ci/enable_or_disable_ci.md) + - [Pipelines](../../ci/pipelines.md#pipelines): Configure and visualize + your GitLab CI/CD pipelines from the UI + - [Scheduled Pipelines](pipelines/schedules.md): Schedule a pipeline + to start at a chosen time + - [Pipeline Graphs](../../ci/pipelines.md#pipeline-graphs): View your + entire pipeline from the UI + - [Job artifacts](pipelines/job_artifacts.md): Define, + browse, and download job artifacts + - [Pipeline settings](pipelines/settings.md): Set up Git strategy (choose the default way your repository is fetched from GitLab in a job), + timeout (defines the maximum amount of time in minutes that a job is able run), custom path for `.gitlab-ci.yml`, test coverage parsing, pipeline's visibility, and much more +- [GitLab Pages](pages/index.md): Build, test, and deploy your static +website with GitLab Pages + +**Other features:** + +- [Cycle Analytics](cycle_analytics.md): Review your development lifecycle +- [Koding integration](koding.md) (not available on GitLab.com): Integrate +with Koding to have access to a web terminal right from the GitLab UI +- [Syntax highlighting](highlighting.md): An alternative to customize +your code blocks, overriding GitLab's default choice of language + +### Project's integrations + +[Integrate your project](integrations/index.md) with Jira, Mattermost, +Kubernetes, Slack, and a lot more. + +## New project + +Learn how to [create a new project](../../gitlab-basics/create-project.md) in GitLab. + +### Fork a project + +You can [fork a project](../../gitlab-basics/fork-project.md) in order to: + +- Collaborate on code by forking a project and creating a merge request +from your fork to the upstream project +- Fork a sample project to work on the top of that + +## Import or export a project + +- Import a project from: + - [GitHub to GitLab](../../workflow/importing/import_projects_from_github.md) + - [BitBucket to GitLab](../../workflow/importing/import_projects_from_bitbucket.md) + - [Gitea to GitLab](../../workflow/importing/import_projects_from_gitea.md) + - [FogBugz to GitLab](../../workflow/importing/import_projects_from_fogbugz.md) +- [Export a project from GitLab](settings/import_export.md#exporting-a-project-and-its-data) +- [Importing and exporting projects between GitLab instances](settings/import_export.md) + +## Leave a project + +**Leave project** will only display on the project's dashboard +when a project is part of a group (under a +[group namespace](../group/index.md#namespaces)). +If you choose to leave a project you will no longer be a project +member, therefore, unable to contribute. diff --git a/doc/user/project/koding.md b/doc/user/project/koding.md index c56a1efe3c2..455e2ee47b4 100644 --- a/doc/user/project/koding.md +++ b/doc/user/project/koding.md @@ -1,4 +1,4 @@ -# Koding & GitLab +# Koding integration > [Introduced][ce-5909] in GitLab 8.11. diff --git a/doc/user/project/repository/index.md b/doc/user/project/repository/index.md index bb41eb41795..4b2c435a120 100644 --- a/doc/user/project/repository/index.md +++ b/doc/user/project/repository/index.md @@ -2,7 +2,7 @@ A [repository](https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository) is what you use to store your codebase in GitLab and change it with version control. -A repository is part of a project, which has a lot of other features. +A repository is part of a [project](../index.md), which has a lot of other features. ## Create a repository -- cgit v1.2.3 From 78829db98234ebe2cdf4264396352d6cc39d106d Mon Sep 17 00:00:00 2001 From: winh Date: Mon, 31 Jul 2017 12:12:16 +0200 Subject: Fix badge positioning in new navigation for Firefox --- app/views/layouts/nav/_new_admin_sidebar.html.haml | 2 +- app/views/layouts/nav/_new_group_sidebar.html.haml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/layouts/nav/_new_admin_sidebar.html.haml b/app/views/layouts/nav/_new_admin_sidebar.html.haml index 95443de40c2..8db3e69aed4 100644 --- a/app/views/layouts/nav/_new_admin_sidebar.html.haml +++ b/app/views/layouts/nav/_new_admin_sidebar.html.haml @@ -91,8 +91,8 @@ = nav_link(controller: :abuse_reports) do = link_to admin_abuse_reports_path, title: "Abuse Reports" do %span - Abuse Reports %span.badge.count= number_with_delimiter(AbuseReport.count(:all)) + Abuse Reports - if akismet_enabled? = nav_link(controller: :spam_logs) do diff --git a/app/views/layouts/nav/_new_group_sidebar.html.haml b/app/views/layouts/nav/_new_group_sidebar.html.haml index a7897c09e79..4fd9e213ead 100644 --- a/app/views/layouts/nav/_new_group_sidebar.html.haml +++ b/app/views/layouts/nav/_new_group_sidebar.html.haml @@ -28,9 +28,9 @@ = nav_link(path: ['groups#issues', 'labels#index', 'milestones#index']) do = link_to issues_group_path(@group), title: 'Issues' do %span - Issues - issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute %span.badge.count= number_with_delimiter(issues.count) + Issues %ul.sidebar-sub-level-items = nav_link(path: 'groups#issues', html_options: { class: 'home' }) do @@ -51,9 +51,9 @@ = nav_link(path: 'groups#merge_requests') do = link_to merge_requests_group_path(@group), title: 'Merge Requests' do %span - Merge Requests - merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened', non_archived: true).execute %span.badge.count= number_with_delimiter(merge_requests.count) + Merge Requests = nav_link(path: 'group_members#index') do = link_to group_group_members_path(@group), title: 'Members' do %span -- cgit v1.2.3 From 38dc8c0c57cb880b52d20e13deac1fa6f8393d3e Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Mon, 31 Jul 2017 13:30:34 +0100 Subject: Explain what the regression label means --- PROCESS.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/PROCESS.md b/PROCESS.md index 3b97a4e8c75..2b3d142bf77 100644 --- a/PROCESS.md +++ b/PROCESS.md @@ -128,7 +128,7 @@ information, see ### After the 7th -Once the stable branch is frozen, only fixes for regressions (bugs introduced in that same release) +Once the stable branch is frozen, only fixes for [regressions](#regressions) and security issues will be cherry-picked into the stable branch. Any merge requests cherry-picked into the stable branch for a previous release will also be picked into the latest stable branch. These fixes will be shipped in the next RC for that release if it is before the 22nd. @@ -158,6 +158,24 @@ release should have the correct milestone assigned _and_ have the label Merge requests without a milestone and this label will not be merged into any stable branches. +### Regressions + +A regression for a particular monthly release is a bug that exists in that +release, but wasn't present in the release before. This includes bugs in +features that were only added in that monthly release. Every regression **must** +have the milestone of the release it was introduced in - if a regression doesn't +have a milestone, it might be 'just' a bug! + +For instance, if 10.5.0 adds a feature, and that feature doesn't work correctly, +then this is a regression in 10.5. If 10.5.1 then fixes that, but 10.5.3 somehow +reintroduces the bug, then this bug is still a regression in 10.5. + +Because GitLab.com runs release candidates of new releases, a regression can be +reported in a release before its 'official' release date on the 22nd of the +month. When we say 'the most recent monthly release', this can refer to either +the version currently running on GitLab.com, or the most recent version +available in the package repositories. + ## Release retrospective and kickoff ### Retrospective -- cgit v1.2.3 From b720c22fb46009acda19b5cd170d3b64227c89b1 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 31 Jul 2017 20:30:18 +0800 Subject: Avoid expect_any_instance_of because it doesn't work well with prepend. We need to backport this --- spec/services/projects/transfer_service_spec.rb | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb index ae32e85b2a7..36db1aab557 100644 --- a/spec/services/projects/transfer_service_spec.rb +++ b/spec/services/projects/transfer_service_spec.rb @@ -37,18 +37,18 @@ describe Projects::TransferService do end it 'executes system hooks' do - expect_any_instance_of(described_class).to receive(:execute_system_hooks) - - transfer_project(project, user, group) + transfer_project(project, user, group) do |service| + expect(service).to receive(:execute_system_hooks) + end end end context 'when transfer fails' do let!(:original_path) { project_path(project) } - def attempt_project_transfer + def attempt_project_transfer(&block) expect do - transfer_project(project, user, group) + transfer_project(project, user, group, &block) end.to raise_error(ActiveRecord::ActiveRecordError) end @@ -80,9 +80,9 @@ describe Projects::TransferService do end it "doesn't run system hooks" do - expect_any_instance_of(described_class).not_to receive(:execute_system_hooks) - - attempt_project_transfer + attempt_project_transfer do |service| + expect(service).not_to receive(:execute_system_hooks) + end end end @@ -120,7 +120,11 @@ describe Projects::TransferService do end def transfer_project(project, user, new_namespace) - Projects::TransferService.new(project, user).execute(new_namespace) + service = Projects::TransferService.new(project, user) + + yield(service) if block_given? + + service.execute(new_namespace) end context 'visibility level' do -- cgit v1.2.3