diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index 9a12db258d569916a0466a61ed937d87b1419a9f..150f24a5d5bcf0c3a99fbc0748ae08a24da02e81 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -74,7 +74,7 @@ module IssuablesHelper end end - def serialize_issuable(issuable, serializer: nil) + def serialize_issuable(issuable, opts = {}) serializer_klass = case issuable when Issue IssueSerializer @@ -84,7 +84,7 @@ module IssuablesHelper serializer_klass .new(current_user: current_user, project: issuable.project) - .represent(issuable, serializer: serializer) + .represent(issuable, opts) .to_json end diff --git a/app/mailers/emails/notes.rb b/app/mailers/emails/notes.rb index 70d296fe3b833537715f6b967e1f68b5ca35ec1c..506c8d251b76f2865763dfd38c6f21ab6f8b5adc 100644 --- a/app/mailers/emails/notes.rb +++ b/app/mailers/emails/notes.rb @@ -60,7 +60,7 @@ module Emails # `note_id` is a `Note` when originating in `NotifyPreview` @note = note_id.is_a?(Note) ? note_id : Note.find(note_id) @project = @note.project - @group = @note.noteable.try(:group) + @group = @project.try(:group) || @note.noteable.try(:group) if (@project || @group) && @note.persisted? @sent_notification = SentNotification.record_note(@note, recipient_id, reply_key) diff --git a/app/models/issue.rb b/app/models/issue.rb index 6da6fbe55cb80d34c7830fe71feb4fe127f73f9d..30e29911758b7c504e139c595740a416094459a9 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -254,6 +254,10 @@ class Issue < ApplicationRecord merge_requests_closing_issues.count end + def labels_hook_attrs + labels.map(&:hook_attrs) + end + private def ensure_metrics diff --git a/app/models/note.rb b/app/models/note.rb index 15271c68a9e26404ee201777c4e61cf1a19c5d31..b55af7d9b5e79548a5236feede46cb83df02babf 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -457,7 +457,7 @@ class Note < ApplicationRecord end def banzai_render_context(field) - super.merge(noteable: noteable) + super.merge(noteable: noteable, system_note: system?) end def retrieve_upload(_identifier, paths) diff --git a/app/serializers/merge_request_widget_entity.rb b/app/serializers/merge_request_widget_entity.rb index a428930dbbfd10e52446279f20255bc7017e719e..43aced598a9149971728cfa20960b6ff553afed6 100644 --- a/app/serializers/merge_request_widget_entity.rb +++ b/app/serializers/merge_request_widget_entity.rb @@ -114,7 +114,10 @@ class MergeRequestWidgetEntity < IssuableEntity presenter(merge_request).ci_status end - expose :issues_links do + # Rendering and redacting Markdown can be expensive. These links are + # just nice to have in the merge request widget, so only + # include them if they are explicitly requested on first load. + expose :issues_links, if: -> (_, opts) { opts[:issues_links] } do expose :assign_to_closing do |merge_request| presenter(merge_request).assign_to_closing_issues_link end diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml index f593f4e049e4b93f9a877bc9bb68083383821098..2084ca6f905545a4333de43f707f2714fed358c0 100644 --- a/app/views/projects/merge_requests/show.html.haml +++ b/app/views/projects/merge_requests/show.html.haml @@ -19,7 +19,7 @@ -# haml-lint:disable InlineJavaScript :javascript window.gl = window.gl || {}; - window.gl.mrWidgetData = #{serialize_issuable(@merge_request, serializer: 'widget')} + window.gl.mrWidgetData = #{serialize_issuable(@merge_request, serializer: 'widget', issues_links: true)} window.gl.mrWidgetData.squash_before_merge_help_path = '#{help_page_path("user/project/merge_requests/squash_and_merge")}'; window.gl.mrWidgetData.troubleshooting_docs_path = '#{help_page_path('user/project/merge_requests/index.md', anchor: 'troubleshooting')}'; diff --git a/changelogs/unreleased/59702-fix-notification-flags-for-ms-teams.yml b/changelogs/unreleased/59702-fix-notification-flags-for-ms-teams.yml new file mode 100644 index 0000000000000000000000000000000000000000..14a8da95ed983f80d13df2f44a19ef25029d5fe4 --- /dev/null +++ b/changelogs/unreleased/59702-fix-notification-flags-for-ms-teams.yml @@ -0,0 +1,5 @@ +--- +title: Fix missing API notification flags for Microsoft Teams +merge_request: 29824 +author: Seiji Suenaga +type: fixed diff --git a/changelogs/unreleased/63513-ensure-gitlab-jsoncache-includes-the-gitlab-version-in-the-cache-key.yml b/changelogs/unreleased/63513-ensure-gitlab-jsoncache-includes-the-gitlab-version-in-the-cache-key.yml new file mode 100644 index 0000000000000000000000000000000000000000..b5715902630e504abbef92c1dae69ded23dccb8f --- /dev/null +++ b/changelogs/unreleased/63513-ensure-gitlab-jsoncache-includes-the-gitlab-version-in-the-cache-key.yml @@ -0,0 +1,5 @@ +--- +title: Include the GitLab version in the cache key for Gitlab::JsonCache +merge_request: 29938 +author: +type: fixed diff --git a/changelogs/unreleased/bug-63162-duplicate_path_in_links.yml b/changelogs/unreleased/bug-63162-duplicate_path_in_links.yml new file mode 100644 index 0000000000000000000000000000000000000000..d3f246492fbee26b82cf5e81db46fa76aad65272 --- /dev/null +++ b/changelogs/unreleased/bug-63162-duplicate_path_in_links.yml @@ -0,0 +1,5 @@ +--- +title: Fixed 'diff version changes' link not working +merge_request: 29825 +author: +type: fixed diff --git a/changelogs/unreleased/fix-labels-in-hooks.yml b/changelogs/unreleased/fix-labels-in-hooks.yml new file mode 100644 index 0000000000000000000000000000000000000000..c0904a860c51228e34aa28d97367ec2f486f3cc5 --- /dev/null +++ b/changelogs/unreleased/fix-labels-in-hooks.yml @@ -0,0 +1,5 @@ +--- +title: Fix label serialization in issue and note hooks +merge_request: 29850 +author: +type: fixed diff --git a/changelogs/unreleased/fix-notes-emails-with-group-settings.yml b/changelogs/unreleased/fix-notes-emails-with-group-settings.yml new file mode 100644 index 0000000000000000000000000000000000000000..77dae8418a8587167a59d673048046edfa74c2bb --- /dev/null +++ b/changelogs/unreleased/fix-notes-emails-with-group-settings.yml @@ -0,0 +1,5 @@ +--- +title: Fix comment emails not respecting group-level notification email +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/sh-omit-issues-links-on-poll.yml b/changelogs/unreleased/sh-omit-issues-links-on-poll.yml new file mode 100644 index 0000000000000000000000000000000000000000..21e51d3534fd1ef7aca169b1491ae88968f47995 --- /dev/null +++ b/changelogs/unreleased/sh-omit-issues-links-on-poll.yml @@ -0,0 +1,5 @@ +--- +title: Omit issues links in merge request entity API response +merge_request: 29917 +author: +type: performance diff --git a/changelogs/unreleased/sh-quiet-backup-secrets-log.yml b/changelogs/unreleased/sh-quiet-backup-secrets-log.yml new file mode 100644 index 0000000000000000000000000000000000000000..cf3e90c0cb1624041f9cb53e66caa8a001ba4a2e --- /dev/null +++ b/changelogs/unreleased/sh-quiet-backup-secrets-log.yml @@ -0,0 +1,5 @@ +--- +title: Silence backup warnings when CRON=1 in use +merge_request: 30033 +author: +type: fixed diff --git a/changelogs/unreleased/sh-recover-ee-schema-backport-migration-failure.yml b/changelogs/unreleased/sh-recover-ee-schema-backport-migration-failure.yml new file mode 100644 index 0000000000000000000000000000000000000000..1695e2827eba27f3a0c9be4df03ab0cbacd53aa9 --- /dev/null +++ b/changelogs/unreleased/sh-recover-ee-schema-backport-migration-failure.yml @@ -0,0 +1,5 @@ +--- +title: Prevent EE backport migrations from running if CE is not migrated +merge_request: 30002 +author: +type: fixed diff --git a/db/migrate/20190402150158_backport_enterprise_schema.rb b/db/migrate/20190402150158_backport_enterprise_schema.rb index 610a8808383d32d3a2f663b8ea465d7f01bdee77..8762cc53ed71a27f21bbad565aac2fe2a8ea0673 100644 --- a/db/migrate/20190402150158_backport_enterprise_schema.rb +++ b/db/migrate/20190402150158_backport_enterprise_schema.rb @@ -117,6 +117,8 @@ class BackportEnterpriseSchema < ActiveRecord::Migration[5.0] end def up + check_schema! + create_missing_tables update_appearances @@ -868,6 +870,52 @@ class BackportEnterpriseSchema < ActiveRecord::Migration[5.0] remove_column_if_exists(:geo_nodes, :internal_url) end + # Some users may have upgraded to EE at some point but downgraded to + # CE v11.11.3. As a result, their EE tables may not be in the right + # state. Here we check for these such cases and attempt to guide the + # user into recovering from this state by upgrading to v11.11.3 EE + # before installing v12.0.0 CE. + def check_schema! + # The following cases will fail later when this migration attempts + # to add a foreign key for non-existent columns. + columns_to_check = [ + [:epics, :parent_id], # Added in GitLab 11.7 + [:geo_event_log, :cache_invalidation_event_id], # Added in GitLab 11.4 + [:vulnerability_feedback, :merge_request_id] # Added in GitLab 11.9 + ].freeze + + columns_to_check.each do |table, column| + check_ee_columns!(table, column) + end + end + + def check_ee_columns!(table, column) + return unless table_exists?(table) + return if column_exists?(table, column) + + raise_ee_migration_error!(table, column) + end + + def raise_ee_migration_error!(table, column) + message = "Your database is missing the '#{column}' column from the '#{table}' table that is present for GitLab EE." + + message += + if ::Gitlab.ee? + "\nUpgrade your GitLab instance to 11.11.3 EE first!" + else + <<~MSG + + Even though it looks like you're running a CE installation, it appears + you may have installed GitLab EE at some point. To migrate to GitLab 12.0: + + 1. Install GitLab 11.11.3 EE + 2. Install GitLab 12.0.x CE + MSG + end + + raise Exception.new(message) + end + def create_missing_tables create_table_if_not_exists "approval_merge_request_rule_sources", id: :bigserial do |t| t.bigint "approval_merge_request_rule_id", null: false diff --git a/doc/administration/high_availability/README.md b/doc/administration/high_availability/README.md index d9c80b1ec593db4dd05a89e97ad270d302328d41..0c4f926c57973dab6ac7e65450d628a096233b35 100644 --- a/doc/administration/high_availability/README.md +++ b/doc/administration/high_availability/README.md @@ -65,6 +65,7 @@ larger one. - 1 Redis node - 1 NFS/Gitaly storage server - 2 or more GitLab application nodes (Unicorn, Workhorse, Sidekiq) +- 1 Monitoring node (Prometheus, Grafana) #### Installation Instructions @@ -76,6 +77,7 @@ you can continue with the next step. 1. [Redis](redis.md#redis-in-a-scaled-environment) 1. [Gitaly](gitaly.md) (recommended) or [NFS](nfs.md) 1. [GitLab application nodes](gitlab.md) +1. [Monitoring node (Prometheus and Grafana)](monitoring_node.md) ### Full Scaling @@ -90,6 +92,7 @@ in size, indicating that there is contention or not enough resources. - 2 or more NFS/Gitaly storage servers - 2 or more Sidekiq nodes - 2 or more GitLab application nodes (Unicorn, Workhorse) +- 1 Monitoring node (Prometheus, Grafana) ## High Availability Architecture Examples @@ -133,6 +136,7 @@ the contention. - 3 Consul/Sentinel nodes - 2 or more GitLab application nodes (Unicorn, Workhorse, Sidekiq, PGBouncer) - 1 NFS/Gitaly server +- 1 Monitoring node (Prometheus, Grafana) ![Horizontal architecture diagram](img/horizontal.png) @@ -192,6 +196,7 @@ with the added complexity of many more nodes to configure, manage and monitor. - 2 or more API nodes (All requests to `/api`) - 2 or more Web nodes (All other web requests) - 2 or more NFS/Gitaly servers +- 1 Monitoring node (Prometheus, Grafana) ![Fully Distributed architecture diagram](img/fully-distributed.png) @@ -205,4 +210,5 @@ separately: 1. [NFS Client and Host setup](nfs_host_client_setup.md) 1. [Configure the GitLab application servers](gitlab.md) 1. [Configure the load balancers](load_balancer.md) +1. [Monitoring node (Prometheus and Grafana)](monitoring_node.md) diff --git a/doc/administration/high_availability/database.md b/doc/administration/high_availability/database.md index 3b874e5d312957f648e8dd57fbb202b02ebdbe3b..0aab7d6a58f252d88e84cd63a46cb7f7067b98a3 100644 --- a/doc/administration/high_availability/database.md +++ b/doc/administration/high_availability/database.md @@ -82,7 +82,8 @@ deploy the bundled PostgreSQL. 1. Note the PostgreSQL node's IP address or hostname, port, and plain text password. These will be necessary when configuring the GitLab application servers later. - +1. [Enable monitoring](#enable-monitoring) + Advanced configuration options are supported and can be added if needed. @@ -399,6 +400,7 @@ check the [Troubleshooting section](#troubleshooting) before proceeding. ``` 1. [Reconfigure GitLab] for the changes to take effect. +1. [Enable Monitoring](#enable-monitoring) > Please note: > @@ -1086,6 +1088,25 @@ the previous section: the `gitlab` database user 1. [Reconfigure GitLab] for the changes to take effect +## Enable Monitoring + +> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/3786) in GitLab 12.0. + +If you enable Monitoring, it must be enabled on **all** database servers. + +1. Create/edit `/etc/gitlab/gitlab.rb` and add the following configuration: + + ```ruby + # Enable service discovery for Prometheus + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + postgres_exporter['listen_address'] = '0.0.0.0:9187' + ``` + +1. Run `sudo gitlab-ctl reconfigure` to compile the configuration. + ## Troubleshooting #### Consul and PostgreSQL changes not taking effect. diff --git a/doc/administration/high_availability/gitaly.md b/doc/administration/high_availability/gitaly.md index 1d8e6c999cbc594feb8fce74326047f6934a7154..90e5f71d8351c65b2e2a9f6f9a3f6e71d7fc2699 100644 --- a/doc/administration/high_availability/gitaly.md +++ b/doc/administration/high_availability/gitaly.md @@ -19,3 +19,28 @@ Continue configuration of other components by going back to: - [Scaled Architectures](README.md#scalable-architecture-examples) - [High Availability Architectures](README.md#high-availability-architecture-examples) + +## Enable Monitoring + +> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/3786) in GitLab 12.0. + + 1. Create/edit `/etc/gitlab/gitlab.rb` and add the following configuration: + + ```ruby + # Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Replace placeholders + # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z + # with the addresses of the Consul server nodes + consul['configuration'] = { + retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + gitaly['prometheus_listen_addr'] = "0.0.0.0:9236" + ``` + + 1. Run `sudo gitlab-ctl reconfigure` to compile the configuration. diff --git a/doc/administration/high_availability/gitlab.md b/doc/administration/high_availability/gitlab.md index 888426ece5cc7125e233f991af1bc64d4aa505cc..1a530bb62550412595d02e445e434896923c21c9 100644 --- a/doc/administration/high_availability/gitlab.md +++ b/doc/administration/high_availability/gitlab.md @@ -76,6 +76,8 @@ registry['gid'] = 9002 ``` +1. [Enable monitoring](#enable-monitoring) + > **Note:** To maintain uniformity of links across HA clusters, the `external_url` on the first application server as well as the additional application servers should point to the external url that users will use to access GitLab. @@ -88,7 +90,8 @@ [Nginx documentation](http://docs.gitlab.com/omnibus/settings/nginx.html#enable-https) for more information. > - > **Note:** It is best to set the `uid` and `gid`s prior to the initial reconfigure of GitLab. Omnibus will not recursively `chown` directories if set after the initial reconfigure. + > **Note:** It is best to set the `uid` and `gid`s prior to the initial reconfigure + of GitLab. Omnibus will not recursively `chown` directories if set after the initial reconfigure. ## First GitLab application server @@ -129,6 +132,46 @@ need some extra configuration. 1. Run `sudo gitlab-ctl reconfigure` to compile the configuration. +## Enable Monitoring + +> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/3786) in GitLab 12.0. + +If you enable Monitoring, it must be enabled on **all** GitLab servers. + +1. Create/edit `/etc/gitlab/gitlab.rb` and add the following configuration: + + ```ruby + # Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Replace placeholders + # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z + # with the addresses of the Consul server nodes + consul['configuration'] = { + retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + gitlab_workhorse['prometheus_listen_addr'] = '0.0.0.0:9229' + sidekiq['listen_address'] = "0.0.0.0" + unicorn['listen'] = '0.0.0.0' + + # Add the monitoring node's IP address to the monitoring whitelist and allow it to scrape the NGINX metrics + # Replace placeholder + # monitoring.gitlab.example.com + # with the addresses gathered for the monitoring node + gitlab_rails['monitoring_whitelist'] = ['monitoring.gitlab.example.com'] + nginx['status']['options']['allow'] = ['monitoring.gitlab.example.com'] + ``` + +1. Run `sudo gitlab-ctl reconfigure` to compile the configuration. + +> **Warning:** After changing `unicorn['listen']` in `gitlab.rb`, and running `sudo gitlab-ctl reconfigure`, + it can take an extended period of time for unicorn to complete reloading after receiving a `HUP`. + For more information, see the [issue](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/4401). + ## Troubleshooting - `mount: wrong fs type, bad option, bad superblock on` diff --git a/doc/administration/high_availability/monitoring_node.md b/doc/administration/high_availability/monitoring_node.md new file mode 100644 index 0000000000000000000000000000000000000000..d16bf7dc0f06657d9f20b7193d379d6d895d6736 --- /dev/null +++ b/doc/administration/high_availability/monitoring_node.md @@ -0,0 +1,67 @@ +# Configuring a Monitoring node for Scaling and High Availability + +> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/3786) in GitLab 12.0. + +## Standalone Monitoring node using GitLab Omnibus + +The GitLab Omnibus package can be used to configure a standalone Monitoring node running Prometheus and Grafana. +The monitoring node is not highly available. See [Scaling and High Availability](README.md) +for an overview of GitLab scaling and high availability options. + +The steps below are the minimum necessary to configure a Monitoring node running Prometheus and Grafana with +Omnibus: + +1. SSH into the Monitoring node. +1. [Download/install](https://about.gitlab.com/installation) the Omnibus GitLab + package you want using **steps 1 and 2** from the GitLab downloads page. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + external_url 'http://gitlab.example.com' + + # Enable Prometheus + prometheus['enable'] = true + prometheus['listen_address'] = '0.0.0.0:9090' + prometheus['monitor_kubernetes'] = false + + # Enable Grafana + grafana['enable'] = true + grafana['admin_password'] = 'toomanysecrets' + + # Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Replace placeholders + # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z + # with the addresses of the Consul server nodes + consul['configuration'] = { + retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z), + } + + # Disable all other services + gitlab_rails['auto_migrate'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_monitor['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = true + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + sidekiq['enable'] = false + unicorn['enable'] = false + node_exporter['enable'] = false + ``` + +1. Run `sudo gitlab-ctl reconfigure` to compile the configuration. + +## Migrating to Service Discovery + +Once monitoring using Service Discovery is enabled with `consul['monitoring_service_discovery'] = true`, +ensure that `prometheus['scrape_configs']` is not set in `/etc/gitlab/gitlab.rb`. Setting both +`consul['monitoring_service_discovery'] = true` and `prometheus['scrape_configs']` in `/etc/gitlab/gitlab.rb` +will result in errors. diff --git a/doc/administration/high_availability/redis.md b/doc/administration/high_availability/redis.md index 1aaa709fc8fea0d45e2d1b7edbfcb0a52a760ae0..f61a8834af3eb3d1cfd4ae054d4d258c9aae33ae 100644 --- a/doc/administration/high_availability/redis.md +++ b/doc/administration/high_availability/redis.md @@ -74,6 +74,7 @@ Omnibus: 1. Note the Redis node's IP address or hostname, port, and Redis password. These will be necessary when configuring the GitLab application servers later. +1. [Enable Monitoring](#enable-monitoring) Advanced configuration options are supported and can be added if needed. @@ -749,6 +750,33 @@ gitlab_rails['redis_sentinels'] = [ [Reconfigure Omnibus GitLab][reconfigure] for the changes to take effect. +## Enable Monitoring + +> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/3786) in GitLab 12.0. + + If you enable Monitoring, it must be enabled on **all** Redis servers. + + 1. Create/edit `/etc/gitlab/gitlab.rb` and add the following configuration: + + ```ruby + # Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Replace placeholders + # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z + # with the addresses of the Consul server nodes + consul['configuration'] = { + retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + ``` + + 1. Run `sudo gitlab-ctl reconfigure` to compile the configuration. + ## Advanced configuration Omnibus GitLab configures some things behind the curtains to make the sysadmins' diff --git a/doc/api/services.md b/doc/api/services.md index f38f96f64ad1c73e0614b8b330b443703679fd9d..042fee4a21a61bcc615a34cf4a516f3d731621cb 100644 --- a/doc/api/services.md +++ b/doc/api/services.md @@ -1023,6 +1023,8 @@ Parameters: | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | | `webhook` | string | true | The Microsoft Teams webhook. For example, `https://outlook.office.com/webhook/...` | +| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines | +| `notify_only_default_branch` | boolean | false | Send notifications only for the default branch | | `push_events` | boolean | false | Enable notifications for push events | | `issues_events` | boolean | false | Enable notifications for issue events | | `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events | diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md index df455857dee4995eec82b52c9e7069c4d58ba967..bef533c05c7397ebbdb7115367ff29e40d251466 100644 --- a/doc/ci/variables/README.md +++ b/doc/ci/variables/README.md @@ -480,7 +480,7 @@ Below you can find supported syntax reference: > Example: `$VARIABLE == "some value"` - > Example: `$VARIABLE != "some value"` _(added in 11.11)_ + > Example: `$VARIABLE != "some value"` (introduced in GitLab 11.11) You can use equality operator `==` or `!=` to compare a variable content to a string. We support both, double quotes and single quotes to define a string @@ -491,7 +491,7 @@ Below you can find supported syntax reference: > Example: `$VARIABLE == null` - > Example: `$VARIABLE != null` _(added in 11.11)_ + > Example: `$VARIABLE != null` (introduced in GitLab 11.11) It sometimes happens that you want to check whether a variable is defined or not. To do that, you can compare a variable to `null` keyword, like @@ -502,7 +502,7 @@ Below you can find supported syntax reference: > Example: `$VARIABLE == ""` - > Example: `$VARIABLE != ""` _(added in 11.11)_ + > Example: `$VARIABLE != ""` (introduced in GitLab 11.11) If you want to check whether a variable is defined, but is empty, you can simply compare it against an empty string, like `$VAR == ''` or non-empty @@ -512,7 +512,7 @@ Below you can find supported syntax reference: > Example: `$VARIABLE_1 == $VARIABLE_2` - > Example: `$VARIABLE_1 != $VARIABLE_2` _(added in 11.11)_ + > Example: `$VARIABLE_1 != $VARIABLE_2` (introduced in GitLab 11.11) It is possible to compare two variables. This is going to compare values of these variables. @@ -528,11 +528,11 @@ Below you can find supported syntax reference: `$STAGING` value needs to a string, with length higher than zero. Variable that contains only whitespace characters is not an empty variable. -1. Pattern matching _(added in 11.0)_ +1. Pattern matching (introduced in GitLab 11.0) > Example: `$VARIABLE =~ /^content.*/` - > Example: `$VARIABLE_1 !~ /^content.*/` _(added in 11.11)_ + > Example: `$VARIABLE_1 !~ /^content.*/` (introduced in GitLab 11.11) It is possible perform pattern matching against a variable and regular expression. Expression like this evaluates to truth if matches are found @@ -541,7 +541,7 @@ Below you can find supported syntax reference: Pattern matching is case-sensitive by default. Use `i` flag modifier, like `/pattern/i` to make a pattern case-insensitive. -1. Conjunction / Disjunction +1. Conjunction / Disjunction ([introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/27925) in GitLab 12.0) > Example: `$VARIABLE1 =~ /^content.*/ && $VARIABLE2 == "something"` diff --git a/doc/development/architecture.md b/doc/development/architecture.md index 5f32cd7eba284fe12732c1f5ea56c0e2f8eb2475..fc161fa09a90336de48f94d8699662b98d763d5b 100644 --- a/doc/development/architecture.md +++ b/doc/development/architecture.md @@ -141,13 +141,13 @@ Component statuses are linked to configuration documentation for each component. | [Consul](#consul) | Database node discovery, failover | [⚙][consul-omnibus] | [❌][consul-charts] | [❌][consul-charts] | [✅](../user/gitlab_com/index.md#consul) | ❌ | ❌ | EE Only | | [GitLab self-monitoring: Prometheus](#prometheus) | Time-series database, metrics collection, and query service | [✅][prometheus-omnibus] | [✅][prometheus-charts] | [⚙][prometheus-charts] | [✅](../user/gitlab_com/index.md#prometheus) | ❌ | ❌ | CE & EE | | [GitLab self-monitoring: Alertmanager](#alertmanager) | Deduplicates, groups, and routes alerts from Prometheus | [⚙][alertmanager-omnibus] | [✅][alertmanager-charts] | [⚙][alertmanager-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE | -| [GitLab self-monitoring: Grafana](#grafana) | Metrics dashboard | [⚙][grafana-omnibus] | [⤓][grafana-charts] | [⤓][grafana-charts] | [✅](https://dashboards.gitlab.com/d/RZmbBr7mk/gitlab-triage?refresh=30s) | ❌ | ❌ | CE & EE | +| [GitLab self-monitoring: Grafana](#grafana) | Metrics dashboard | [✅][grafana-omnibus] | [⤓][grafana-charts] | [⤓][grafana-charts] | [✅](https://dashboards.gitlab.com/d/RZmbBr7mk/gitlab-triage?refresh=30s) | ❌ | ❌ | CE & EE | | [GitLab self-monitoring: Sentry](#sentry) | Track errors generated by the GitLab instance | [⤓][sentry-omnibus] | [❌][sentry-charts] | [❌][sentry-charts] | [✅](https://about.gitlab.com/handbook/support/workflows/services/gitlab_com/500_errors.html#searching-sentry) | [⤓][gitlab-yml] | [⤓][gitlab-yml] | CE & EE | | [GitLab self-monitoring: Jaeger](#jaeger) | View traces generated by the GitLab instance | [❌][jaeger-omnibus] | [❌][jaeger-charts] | [❌][jaeger-charts] | [❌](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/4104) | [⤓][jaeger-source] | [⚙][jaeger-gdk] | CE & EE | | [Redis Exporter](#redis-exporter) | Prometheus endpoint with Redis metrics | [✅][redis-exporter-omnibus] | [✅][redis-exporter-charts] | [✅][redis-exporter-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE | | [Postgres Exporter](#postgres-exporter) | Prometheus endpoint with PostgreSQL metrics | [✅][postgres-exporter-omnibus] | [✅][postgres-exporter-charts] | [✅][postgres-exporter-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE | | [PgBouncer Exporter](#pgbouncer-exporter) | Prometheus endpoint with PgBouncer metrics | [⚙][pgbouncer-exporter-omnibus] | [❌][pgbouncer-exporter-charts] | [❌][pgbouncer-exporter-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE | -| [GitLab Monitor](#gitlab-monitor) | Generates a variety of GitLab metrics | [✅][gitlab-monitor-omnibus] | [❌][gitab-monitor-charts] | [❌][gitab-monitor-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE | +| [GitLab Monitor](#gitlab-monitor) | Generates a variety of GitLab metrics | [✅][gitlab-monitor-omnibus] | [✅][gitab-monitor-charts] | [✅][gitab-monitor-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE | | [Node Exporter](#node-exporter) | Prometheus endpoint with system metrics | [✅][node-exporter-omnibus] | [❌][node-exporter-charts] | [❌][node-exporter-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE | | [Mattermost](#mattermost) | Open-source Slack alternative | [⚙][mattermost-omnibus] | [⤓][mattermost-charts] | [⤓][mattermost-charts] | [⤓](../user/project/integrations/mattermost_slash_commands.md#manual-configuration), [⤓](../user/project/integrations/mattermost.html) | ❌ | ❌ | CE & EE | | [MinIO](#minio) | Object storage service | [⤓][minio-omnibus] | [✅][minio-charts] | [✅][minio-charts] | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#storage-architecture) | ❌ | [⚙][minio-gdk] | CE & EE | @@ -681,7 +681,7 @@ We've also detailed [our architecture of GitLab.com](https://about.gitlab.com/ha [pgbouncer-exporter-omnibus]: ../administration/monitoring/prometheus/pgbouncer_exporter.md [pgbouncer-exporter-charts]: https://docs.gitlab.com/charts/installation/deployment.html#postgresql [gitlab-monitor-omnibus]: ../administration/monitoring/prometheus/gitlab_monitor_exporter.md -[gitab-monitor-charts]: https://gitlab.com/charts/gitlab/issues/319 +[gitab-monitor-charts]: https://docs.gitlab.com/charts/charts/gitlab/gitlab-monitor/index.html [node-exporter-omnibus]: ../administration/monitoring/prometheus/node_exporter.md [node-exporter-charts]: https://gitlab.com/charts/gitlab/issues/1332 [mattermost-omnibus]: https://docs.gitlab.com/omnibus/gitlab-mattermost/ diff --git a/doc/user/admin_area/settings/visibility_and_access_controls.md b/doc/user/admin_area/settings/visibility_and_access_controls.md index a1229484388f14e0d37f8cd8520bea596eb087c0..63879935fd8d19baefa2024df5b5d8c3e8c72048 100644 --- a/doc/user/admin_area/settings/visibility_and_access_controls.md +++ b/doc/user/admin_area/settings/visibility_and_access_controls.md @@ -4,12 +4,15 @@ type: reference # Visibility and access controls -GitLab allows admins to: +GitLab allows administrators to: - Control access and visibility to GitLab resources including branches and projects. - Select from which hosting sites code can be imported into GitLab. - Select the protocols permitted to access GitLab. - Enable or disable repository mirroring. +- Prevent non-administrators from deleting projects + ([introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5615) in GitLab 12.0). + **[PREMIUM ONLY]** To access the visibility and access control options: diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md index 34d4507210eac51bed1363563df7d7031c4d8fd2..a4e5b19bdc7271e5d25697317dc5490b1556a39e 100644 --- a/doc/user/application_security/dependency_scanning/index.md +++ b/doc/user/application_security/dependency_scanning/index.md @@ -346,7 +346,7 @@ the report JSON unless stated otherwise. Presence of optional fields depends on | `vulnerabilities[].scanner` | A node that describes the analyzer used to find this vulnerability. | | `vulnerabilities[].scanner.id` | Id of the scanner as a snake_case string. | | `vulnerabilities[].scanner.name` | Name of the scanner, for display purposes. | -| `vulnerabilities[].location` | A node that tells where the vulnerability is located. | +| `vulnerabilities[].location` | A node that tells where the vulnerability is located. | | `vulnerabilities[].location.file` | Path to the dependencies file (e.g., `yarn.lock`). Optional. | | `vulnerabilities[].location.dependency` | A node that describes the dependency of a project where the vulnerability is located. | | `vulnerabilities[].location.dependency.package` | A node that provides the information on the package where the vulnerability is located. | @@ -379,17 +379,17 @@ Once a vulnerability is found, you can interact with it. Read more on how to ## Dependency List -> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/10075) -in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0. +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/10075) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0. -An additional benefit of Dependency Scanning is the ability to get a list of your project's dependencies with their versions. +An additional benefit of Dependency Scanning is the ability to get a list of your +project's dependencies with their versions. This list can be generated only for +[languages and package managers](#supported-languages-and-package-managers) +supported by Gemnasium. -This list can be generated only for [languages and package managers](#supported-languages-and-package-managers) supported by [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium/general). - -To see the generated dependency list, navigate to the Dependency List page under your project's left sidebar menu **Project > Dependency List**. +To see the generated dependency list, navigate to your project's **Project > Dependency List**. ## Contributing to the vulnerability database You can search the [gemnasium-db](https://gitlab.com/gitlab-org/security-products/gemnasium-db) project to find a vulnerability in the Gemnasium database. -You can also [submit new vulnerabilities](https://gitlab.com/gitlab-org/security-products/gemnasium-db/blob/master/CONTRIBUTING.md). \ No newline at end of file +You can also [submit new vulnerabilities](https://gitlab.com/gitlab-org/security-products/gemnasium-db/blob/master/CONTRIBUTING.md). diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md index 1d640966013269e6f1a4d26a173f6bed57c7a82e..6c430ff7cd953e848dc4c9c5c268e52532802176 100644 --- a/doc/user/project/quick_actions.md +++ b/doc/user/project/quick_actions.md @@ -35,7 +35,7 @@ discussions, and descriptions: | `/label ~label1 ~label2` | Add label(s). Label names can also start without ~ but mixed syntax is not supported. | ✓ | ✓ | | `/unlabel ~label1 ~label2` | Remove all or specific label(s)| ✓ | ✓ | | `/relabel ~label1 ~label2` | Replace label | ✓ | ✓ | -| /copy_metadata #issue | !merge_request | Copy labels and milestone from other issue or merge request in the project | ✓ | ✓ | +| /copy_metadata <#issue | !merge_request> | Copy labels and milestone from other issue or merge request in the project | ✓ | ✓ | | /estimate <1w 3d 2h 14m> | Set time estimate | ✓ | ✓ | | `/remove_estimate` | Remove time estimate | ✓ | ✓ | | /spend <time(1h 30m | -1h 5m)> <date(YYYY-MM-DD)> | Add or subtract spent time; optionally, specify the date that time was spent on | ✓ | ✓ | @@ -44,14 +44,14 @@ discussions, and descriptions: | `/unlock` | Unlock the discussion | ✓ | ✓ | | /due <in 2 days | this Friday | December 31st>| Set due date | ✓ | | | `/remove_due_date` | Remove due date | ✓ | | -| `/weight 0,1,2, ...` | Set weight **[STARTER]** | ✓ | | +| /weight <0 | 1 | 2 | ...> | Set weight **[STARTER]** | ✓ | | | `/clear_weight` | Clears weight **[STARTER]** | ✓ | | -| `/epic <&epic | group&epic | Epic URL>` | Add to epic **[ULTIMATE]** | ✓ | | +| /epic <&epic | group&epic | Epic URL> | Add to epic **[ULTIMATE]** | ✓ | | | `/remove_epic` | Removes from epic **[ULTIMATE]** | ✓ | | | `/promote` | Promote issue to epic **[ULTIMATE]** | ✓ | | | `/confidential` | Make confidential | ✓ | | -| `/duplicate #issue` | Mark this issue as a duplicate of another issue | ✓ | -| `/move path/to/project` | Move this issue to another project | ✓ | | +| `/duplicate <#issue>` | Mark this issue as a duplicate of another issue | ✓ | +| `/move ` | Move this issue to another project | ✓ | | | `/target_branch ` | Set target branch | | ✓ | | `/wip` | Toggle the Work In Progress status | | ✓ | | `/approve` | Approve the merge request | | ✓ | @@ -85,3 +85,5 @@ The following quick actions are applicable for epics threads and description: | `/label ~label1 ~label2` | Add label(s) | | `/unlabel ~label1 ~label2` | Remove all or specific label(s) | | `/relabel ~label1 ~label2` | Replace label | +| /child_epic <&epic | group&epic | Epic URL> | Adds child epic to epic ([introduced in GitLab 12.0](https://gitlab.com/gitlab-org/gitlab-ee/issues/7330)) | +| /remove_child_epic <&epic | group&epic | Epic URL> | Removes child epic from epic ([introduced in GitLab 12.0](https://gitlab.com/gitlab-org/gitlab-ee/issues/7330)) | diff --git a/lib/api/helpers/services_helpers.rb b/lib/api/helpers/services_helpers.rb index 44c577204b8083bc1118f726a364d954029403f0..cf2e9d01356efb52e246ded5e46f7407eb4263fa 100644 --- a/lib/api/helpers/services_helpers.rb +++ b/lib/api/helpers/services_helpers.rb @@ -683,8 +683,9 @@ module API name: :webhook, type: String, desc: 'The Microsoft Teams webhook. e.g. https://outlook.office.com/webhook/…' - } - ], + }, + chat_notification_flags + ].flatten, 'mattermost' => [ chat_notification_settings, chat_notification_flags, diff --git a/lib/banzai/filter/relative_link_filter.rb b/lib/banzai/filter/relative_link_filter.rb index 199b3533cf408c7eff128b4fe639e7de4b8ea1e9..80c84c0f6226f3a848f0664335c548a3cc94348d 100644 --- a/lib/banzai/filter/relative_link_filter.rb +++ b/lib/banzai/filter/relative_link_filter.rb @@ -17,6 +17,8 @@ module Banzai include Gitlab::Utils::StrongMemoize def call + return doc if context[:system_note] + @uri_types = {} clear_memoization(:linkable_files) diff --git a/lib/gitlab/data_builder/note.rb b/lib/gitlab/data_builder/note.rb index 16e62622ed4ebc41efe988a427c14f02c1d97a74..2c4ef73a68839ce0fc0861e88d9e4197f1543c76 100644 --- a/lib/gitlab/data_builder/note.rb +++ b/lib/gitlab/data_builder/note.rb @@ -44,7 +44,7 @@ module Gitlab data[:commit] = build_data_for_commit(project, user, note) elsif note.for_issue? data[:issue] = note.noteable.hook_attrs - data[:issue][:labels] = note.noteable.labels(&:hook_attrs) + data[:issue][:labels] = note.noteable.labels_hook_attrs elsif note.for_merge_request? data[:merge_request] = note.noteable.hook_attrs elsif note.for_snippet? diff --git a/lib/gitlab/hook_data/issue_builder.rb b/lib/gitlab/hook_data/issue_builder.rb index cfc9ebe4f924b7e3573a5136fe8e1bb4add30e04..e5f86ca02b5176f8ea1d556fa8757b6f913c61c2 100644 --- a/lib/gitlab/hook_data/issue_builder.rb +++ b/lib/gitlab/hook_data/issue_builder.rb @@ -45,7 +45,7 @@ module Gitlab human_time_estimate: issue.human_time_estimate, assignee_ids: issue.assignee_ids, assignee_id: issue.assignee_ids.first, # This key is deprecated - labels: issue.labels + labels: issue.labels_hook_attrs } issue.attributes.with_indifferent_access.slice(*self.class.safe_hook_attributes) diff --git a/lib/gitlab/json_cache.rb b/lib/gitlab/json_cache.rb index e4bc437d78723251b74ed6970db59686a5057779..d01183d7845195702e818f2c85eabdb5cc5ddef3 100644 --- a/lib/gitlab/json_cache.rb +++ b/lib/gitlab/json_cache.rb @@ -22,10 +22,10 @@ module Gitlab expanded_cache_key = [namespace, key].compact if cache_key_with_version - expanded_cache_key << Rails.version + expanded_cache_key << [Gitlab::VERSION, Rails.version] end - expanded_cache_key.join(':') + expanded_cache_key.flatten.join(':').freeze end def expire(key) @@ -58,7 +58,7 @@ module Gitlab private def parse_value(raw, klass) - value = ActiveSupport::JSON.decode(raw) + value = ActiveSupport::JSON.decode(raw.to_s) case value when Hash then parse_entry(value, klass) diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake index c531eb1d2163b77b161ec95fe6f66d3890ab6773..2bf71701b5738a7dc17f7474d64333102b0d0740 100644 --- a/lib/tasks/gitlab/backup.rake +++ b/lib/tasks/gitlab/backup.rake @@ -21,10 +21,10 @@ namespace :gitlab do backup.cleanup backup.remove_old - puts "Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data \n" \ + progress.puts "Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data \n" \ "and are not included in this backup. You will need these files to restore a backup.\n" \ "Please back them up manually.".color(:red) - puts "Backup task is done." + progress.puts "Backup task is done." end # Restore backup of GitLab system diff --git a/spec/lib/banzai/filter/relative_link_filter_spec.rb b/spec/lib/banzai/filter/relative_link_filter_spec.rb index dad0a5535c04aa2e458b0f50de3caaa87406827d..8ff971114d61c54872cf1c6d7f0009cb03ed9780 100644 --- a/spec/lib/banzai/filter/relative_link_filter_spec.rb +++ b/spec/lib/banzai/filter/relative_link_filter_spec.rb @@ -101,6 +101,13 @@ describe Banzai::Filter::RelativeLinkFilter do .to eq "/#{project_path}/blob/#{ref}/doc/api/README.md" end + it 'does not modify relative URLs in system notes' do + path = "#{project_path}/merge_requests/1/diffs" + doc = filter(link(path), system_note: true) + + expect(doc.at_css('a')['href']).to eq path + end + it 'ignores absolute URLs with two leading slashes' do doc = filter(link('//doc/api/README.md')) expect(doc.at_css('a')['href']).to eq '//doc/api/README.md' diff --git a/spec/lib/gitlab/data_builder/note_spec.rb b/spec/lib/gitlab/data_builder/note_spec.rb index ed9a1e2352906f7f4d346ec72c423fb180bab424..1b5dd2538e035013d8392ccde6272ebeb9de87dc 100644 --- a/spec/lib/gitlab/data_builder/note_spec.rb +++ b/spec/lib/gitlab/data_builder/note_spec.rb @@ -38,9 +38,11 @@ describe Gitlab::DataBuilder::Note do end describe 'When asking for a note on issue' do + let(:label) { create(:label, project: project) } + let(:issue) do - create(:issue, created_at: fixed_time, updated_at: fixed_time, - project: project) + create(:labeled_issue, created_at: fixed_time, updated_at: fixed_time, + project: project, labels: [label]) end let(:note) do @@ -48,13 +50,16 @@ describe Gitlab::DataBuilder::Note do end it 'returns the note and issue-specific data' do + without_timestamps = lambda { |label| label.except('created_at', 'updated_at') } + hook_attrs = issue.reload.hook_attrs + expect(data).to have_key(:issue) - expect(data[:issue].except('updated_at')) - .to eq(issue.reload.hook_attrs.except('updated_at')) + expect(data[:issue].except('updated_at', 'labels')) + .to eq(hook_attrs.except('updated_at', 'labels')) expect(data[:issue]['updated_at']) - .to be >= issue.hook_attrs['updated_at'] - expect(data[:issue]['labels']) - .to eq(issue.hook_attrs['labels']) + .to be >= hook_attrs['updated_at'] + expect(data[:issue]['labels'].map(&without_timestamps)) + .to eq(hook_attrs['labels'].map(&without_timestamps)) end context 'with confidential issue' do diff --git a/spec/lib/gitlab/hook_data/issue_builder_spec.rb b/spec/lib/gitlab/hook_data/issue_builder_spec.rb index f066c0e3813b675b500d8c0fda97909558d23cba..b06d05c1c7fed44c268780062f0306b4ff5b0f14 100644 --- a/spec/lib/gitlab/hook_data/issue_builder_spec.rb +++ b/spec/lib/gitlab/hook_data/issue_builder_spec.rb @@ -1,7 +1,8 @@ require 'spec_helper' describe Gitlab::HookData::IssueBuilder do - set(:issue) { create(:issue) } + set(:label) { create(:label) } + set(:issue) { create(:labeled_issue, labels: [label], project: label.project) } let(:builder) { described_class.new(issue) } describe '#build' do @@ -39,6 +40,7 @@ describe Gitlab::HookData::IssueBuilder do expect(data).to include(:human_time_estimate) expect(data).to include(:human_total_time_spent) expect(data).to include(:assignee_ids) + expect(data).to include('labels' => [label.hook_attrs]) end context 'when the issue has an image in the description' do diff --git a/spec/lib/gitlab/json_cache_spec.rb b/spec/lib/gitlab/json_cache_spec.rb index b82c09af30689052b0d365f5f5a735981fa88a5e..59160741c45fc00e45d8494fef3df9e39d9d01af 100644 --- a/spec/lib/gitlab/json_cache_spec.rb +++ b/spec/lib/gitlab/json_cache_spec.rb @@ -6,7 +6,7 @@ describe Gitlab::JsonCache do let(:backend) { double('backend').as_null_object } let(:namespace) { 'geo' } let(:key) { 'foo' } - let(:expanded_key) { "#{namespace}:#{key}:#{Rails.version}" } + let(:expanded_key) { "#{namespace}:#{key}:#{Gitlab::VERSION}:#{Rails.version}" } set(:broadcast_message) { create(:broadcast_message) } subject(:cache) { described_class.new(namespace: namespace, backend: backend) } @@ -35,42 +35,68 @@ describe Gitlab::JsonCache do describe '#cache_key' do context 'when namespace is not defined' do - it 'expands out the key with Rails version' do - cache = described_class.new(cache_key_with_version: true) + context 'when cache_key_with_version is true' do + it 'expands out the key with GitLab, and Rails versions' do + cache = described_class.new(cache_key_with_version: true) - cache_key = cache.cache_key(key) + cache_key = cache.cache_key(key) - expect(cache_key).to eq("#{key}:#{Rails.version}") + expect(cache_key).to eq("#{key}:#{Gitlab::VERSION}:#{Rails.version}") + end end - end - context 'when cache_key_with_version is true' do - it 'expands out the key with namespace and Rails version' do - cache = described_class.new(namespace: namespace, cache_key_with_version: true) + context 'when cache_key_with_version is false' do + it 'returns the key' do + cache = described_class.new(namespace: nil, cache_key_with_version: false) - cache_key = cache.cache_key(key) + cache_key = cache.cache_key(key) - expect(cache_key).to eq("#{namespace}:#{key}:#{Rails.version}") + expect(cache_key).to eq(key) + end end end - context 'when cache_key_with_version is false' do - it 'expands out the key with namespace' do - cache = described_class.new(namespace: namespace, cache_key_with_version: false) + context 'when namespace is nil' do + context 'when cache_key_with_version is true' do + it 'expands out the key with GitLab, and Rails versions' do + cache = described_class.new(cache_key_with_version: true) - cache_key = cache.cache_key(key) + cache_key = cache.cache_key(key) - expect(cache_key).to eq("#{namespace}:#{key}") + expect(cache_key).to eq("#{key}:#{Gitlab::VERSION}:#{Rails.version}") + end + end + + context 'when cache_key_with_version is false' do + it 'returns the key' do + cache = described_class.new(namespace: nil, cache_key_with_version: false) + + cache_key = cache.cache_key(key) + + expect(cache_key).to eq(key) + end end end - context 'when namespace is nil, and cache_key_with_version is false' do - it 'returns the key' do - cache = described_class.new(namespace: nil, cache_key_with_version: false) + context 'when namespace is set' do + context 'when cache_key_with_version is true' do + it 'expands out the key with namespace and Rails version' do + cache = described_class.new(namespace: namespace, cache_key_with_version: true) + + cache_key = cache.cache_key(key) + + expect(cache_key).to eq("#{namespace}:#{key}:#{Gitlab::VERSION}:#{Rails.version}") + end + end + + context 'when cache_key_with_version is false' do + it 'expands out the key with namespace' do + cache = described_class.new(namespace: namespace, cache_key_with_version: false) - cache_key = cache.cache_key(key) + cache_key = cache.cache_key(key) - expect(cache_key).to eq(key) + expect(cache_key).to eq("#{namespace}:#{key}") + end end end end @@ -106,6 +132,16 @@ describe Gitlab::JsonCache do expect(cache.read(key)).to be_nil end + context 'when the cached value is a boolean' do + it 'parses the cached value' do + allow(backend).to receive(:read) + .with(expanded_key) + .and_return(true) + + expect(cache.read(key, BroadcastMessage)).to eq(true) + end + end + context 'when the cached value is a hash' do it 'parses the cached value' do allow(backend).to receive(:read) diff --git a/spec/mailers/emails/pages_domains_spec.rb b/spec/mailers/emails/pages_domains_spec.rb index 2f594dbf9d1310eaaab0d725ee1c343fa9fd26ca..eae83cd64d362c2b3eaba94fb444fa0cd8e852e9 100644 --- a/spec/mailers/emails/pages_domains_spec.rb +++ b/spec/mailers/emails/pages_domains_spec.rb @@ -9,7 +9,7 @@ describe Emails::PagesDomains do set(:user) { project.creator } shared_examples 'a pages domain email' do - let(:test_recipient) { user } + let(:recipient) { user } it_behaves_like 'an email sent to a user' it_behaves_like 'an email sent from GitLab' diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index cbbb22ad78c0f9f49684056eb8d0ccb57256fdd0..a190f29d677bf7f094bdc6f985ec096613ba3b2d 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -45,7 +45,7 @@ describe Notify do context 'for a project' do shared_examples 'an assignee email' do - let(:test_recipient) { assignee } + let(:recipient) { assignee } it_behaves_like 'an email sent to a user' @@ -55,7 +55,7 @@ describe Notify do aggregate_failures do expect(sender.display_name).to eq(current_user.name) expect(sender.address).to eq(gitlab_sender) - expect(subject).to deliver_to(assignee.email) + expect(subject).to deliver_to(recipient.notification_email) end end end @@ -559,12 +559,13 @@ describe Notify do let(:host) { Gitlab.config.gitlab.host } context 'in discussion' do - set(:first_note) { create(:discussion_note_on_issue) } - set(:second_note) { create(:discussion_note_on_issue, in_reply_to: first_note) } - set(:third_note) { create(:discussion_note_on_issue, in_reply_to: second_note) } + set(:first_note) { create(:discussion_note_on_issue, project: project) } + set(:second_note) { create(:discussion_note_on_issue, in_reply_to: first_note, project: project) } + set(:third_note) { create(:discussion_note_on_issue, in_reply_to: second_note, project: project) } subject { described_class.note_issue_email(recipient.id, third_note.id) } + it_behaves_like 'an email sent to a user' it_behaves_like 'appearance header and footer enabled' it_behaves_like 'appearance header and footer not enabled' @@ -584,10 +585,11 @@ describe Notify do end context 'individual issue comments' do - set(:note) { create(:note_on_issue) } + set(:note) { create(:note_on_issue, project: project) } subject { described_class.note_issue_email(recipient.id, note.id) } + it_behaves_like 'an email sent to a user' it_behaves_like 'appearance header and footer enabled' it_behaves_like 'appearance header and footer not enabled' @@ -616,13 +618,13 @@ describe Notify do it_behaves_like 'a user cannot unsubscribe through footer link' it 'has the correct subject and body' do - is_expected.to have_referable_subject(project_snippet, reply: true) + is_expected.to have_referable_subject(project_snippet, include_group: true, reply: true) is_expected.to have_body_text project_snippet_note.note end end describe 'project was moved' do - let(:test_recipient) { user } + let(:recipient) { user } subject { described_class.project_was_moved_email(project.id, user.id, "gitlab/gitlab") } it_behaves_like 'an email sent to a user' @@ -823,7 +825,7 @@ describe Notify do it 'has the correct subject and body' do aggregate_failures do - is_expected.to have_subject("Re: #{project.name} | #{commit.title} (#{commit.short_id})") + is_expected.to have_subject("Re: #{project.name} | #{project.group.name} | #{commit.title} (#{commit.short_id})") is_expected.to have_body_text(commit.short_id) end end @@ -849,7 +851,7 @@ describe Notify do it 'has the correct subject and body' do aggregate_failures do - is_expected.to have_referable_subject(merge_request, reply: true) + is_expected.to have_referable_subject(merge_request, include_group: true, reply: true) is_expected.to have_body_text note_on_merge_request_path end end @@ -875,7 +877,7 @@ describe Notify do it 'has the correct subject and body' do aggregate_failures do - is_expected.to have_referable_subject(issue, reply: true) + is_expected.to have_referable_subject(issue, include_group: true, reply: true) is_expected.to have_body_text(note_on_issue_path) end end @@ -939,7 +941,7 @@ describe Notify do it_behaves_like 'appearance header and footer not enabled' it 'has the correct subject' do - is_expected.to have_subject "Re: #{project.name} | #{commit.title} (#{commit.short_id})" + is_expected.to have_subject "Re: #{project.name} | #{project.group.name} | #{commit.title} (#{commit.short_id})" end it 'contains a link to the commit' do @@ -967,7 +969,7 @@ describe Notify do it_behaves_like 'appearance header and footer not enabled' it 'has the correct subject' do - is_expected.to have_referable_subject(merge_request, reply: true) + is_expected.to have_referable_subject(merge_request, include_group: true, reply: true) end it 'contains a link to the merge request note' do @@ -995,7 +997,7 @@ describe Notify do it_behaves_like 'appearance header and footer not enabled' it 'has the correct subject' do - is_expected.to have_referable_subject(issue, reply: true) + is_expected.to have_referable_subject(issue, include_group: true, reply: true) end it 'contains a link to the issue note' do diff --git a/spec/migrations/backport_enterprise_schema_spec.rb b/spec/migrations/backport_enterprise_schema_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..8d2d9d4953a6816fd69f019f6ba6d140d615ac57 --- /dev/null +++ b/spec/migrations/backport_enterprise_schema_spec.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require 'spec_helper' + +require Rails.root.join('db', 'migrate', '20190402150158_backport_enterprise_schema.rb') + +describe BackportEnterpriseSchema, :migration, schema: 20190329085614 do + include MigrationsHelpers + + def drop_if_exists(table) + active_record_base.connection.drop_table(table) if active_record_base.connection.table_exists?(table) + end + + describe '#up' do + it 'creates new EE tables' do + migrate! + + expect(active_record_base.connection.table_exists?(:epics)).to be true + expect(active_record_base.connection.table_exists?(:geo_nodes)).to be true + end + + context 'missing EE columns' do + before do + drop_if_exists(:epics) + + active_record_base.connection.create_table "epics" do |t| + t.integer :group_id, null: false, index: true + t.integer :author_id, null: false, index: true + end + end + + after do + drop_if_exists(:epics) + end + + it 'flags an error' do + expect { migrate! }.to raise_error(/Your database is missing.*that is present for GitLab EE/) + end + end + end +end diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index a5c7e9db2a15b4d2a45f4447c5b4f5309b8af5d9..d5b016dc8f6eacb8e484766648432394d0d20781 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -862,4 +862,13 @@ describe Issue do end end end + + describe "#labels_hook_attrs" do + let(:label) { create(:label) } + let(:issue) { create(:labeled_issue, labels: [label]) } + + it "returns a list of label hook attributes" do + expect(issue.labels_hook_attrs).to eq([label.hook_attrs]) + end + end end diff --git a/spec/models/project_services/microsoft_teams_service_spec.rb b/spec/models/project_services/microsoft_teams_service_spec.rb index c025d7c882ef7740032c8fddb7f6cfd7853abc5d..3ffe633868f42a917e4bb073271ed59df0dcbac4 100644 --- a/spec/models/project_services/microsoft_teams_service_spec.rb +++ b/spec/models/project_services/microsoft_teams_service_spec.rb @@ -289,6 +289,18 @@ describe MicrosoftTeamsService do expect(result).to be_falsy end end + + context 'when disabled' do + let(:pipeline) do + create(:ci_pipeline, :failed, project: project, ref: 'not-the-default-branch') + end + + before do + chat_service.notify_only_default_branch = false + end + + it_behaves_like 'call Microsoft Teams API' + end end end end diff --git a/spec/serializers/merge_request_widget_entity_spec.rb b/spec/serializers/merge_request_widget_entity_spec.rb index a27c22191f4ec44e538a30dbdb84e6ae72d4b10b..ffbfac9b3269f12161e26cdb644ecf792c206fc3 100644 --- a/spec/serializers/merge_request_widget_entity_spec.rb +++ b/spec/serializers/merge_request_widget_entity_spec.rb @@ -32,6 +32,19 @@ describe MergeRequestWidgetEntity do end end + describe 'issues links' do + it 'includes issues links when requested' do + data = described_class.new(resource, request: request, issues_links: true).as_json + + expect(data).to include(:issues_links) + expect(data[:issues_links]).to include(:assign_to_closing, :closing, :mentioned_but_not_closing) + end + + it 'omits issue links by default' do + expect(subject).not_to include(:issues_links) + end + end + describe 'pipeline' do let(:pipeline) { create(:ci_empty_pipeline, project: project, ref: resource.source_branch, sha: resource.source_branch_sha, head_pipeline_of: resource) } diff --git a/spec/support/helpers/email_helpers.rb b/spec/support/helpers/email_helpers.rb index ed049daba80d7cd3f67433ecc695914e6fda9fe4..a7175491fa0767bf2ca37fdbda43f664972ffae2 100644 --- a/spec/support/helpers/email_helpers.rb +++ b/spec/support/helpers/email_helpers.rb @@ -37,8 +37,19 @@ module EmailHelpers ActionMailer::Base.deliveries.find { |d| d.to.include?(user.notification_email) } end - def have_referable_subject(referable, include_project: true, reply: false) - prefix = (include_project && referable.project ? "#{referable.project.name} | " : '').freeze + def have_referable_subject(referable, include_project: true, include_group: false, reply: false) + context = [] + + context << referable.project.name if include_project && referable.project + context << referable.project.group.name if include_group && referable.project.group + + prefix = + if context.any? + context.join(' | ') + ' | ' + else + '' + end + prefix = "Re: #{prefix}" if reply suffix = "#{referable.title} (#{referable.to_reference})" diff --git a/spec/support/shared_examples/notify_shared_examples.rb b/spec/support/shared_examples/notify_shared_examples.rb index 897c9106d772c1d062ca5080a0dee02afd50b931..4d43317e17ef861d9b0ca338b732a3f28cff15f5 100644 --- a/spec/support/shared_examples/notify_shared_examples.rb +++ b/spec/support/shared_examples/notify_shared_examples.rb @@ -45,18 +45,18 @@ shared_examples 'an email sent to a user' do let(:group_notification_email) { 'user+group@example.com' } it 'is sent to user\'s global notification email address' do - expect(subject).to deliver_to(test_recipient.notification_email) + expect(subject).to deliver_to(recipient.notification_email) end context 'that is part of a project\'s group' do it 'is sent to user\'s group notification email address when set' do - create(:notification_setting, user: test_recipient, source: project.group, notification_email: group_notification_email) + create(:notification_setting, user: recipient, source: project.group, notification_email: group_notification_email) expect(subject).to deliver_to(group_notification_email) end it 'is sent to user\'s global notification email address when no group email set' do - create(:notification_setting, user: test_recipient, source: project.group, notification_email: '') - expect(subject).to deliver_to(test_recipient.notification_email) + create(:notification_setting, user: recipient, source: project.group, notification_email: '') + expect(subject).to deliver_to(recipient.notification_email) end end @@ -67,17 +67,17 @@ shared_examples 'an email sent to a user' do it 'is sent to user\'s subgroup notification email address when set' do # Set top-level group notification email address to make sure it doesn't get selected - create(:notification_setting, user: test_recipient, source: group, notification_email: group_notification_email) + create(:notification_setting, user: recipient, source: group, notification_email: group_notification_email) subgroup_notification_email = 'user+subgroup@example.com' - create(:notification_setting, user: test_recipient, source: subgroup, notification_email: subgroup_notification_email) + create(:notification_setting, user: recipient, source: subgroup, notification_email: subgroup_notification_email) expect(subject).to deliver_to(subgroup_notification_email) end it 'is sent to user\'s group notification email address when set and subgroup email address not set' do - create(:notification_setting, user: test_recipient, source: subgroup, notification_email: '') - expect(subject).to deliver_to(test_recipient.notification_email) + create(:notification_setting, user: recipient, source: subgroup, notification_email: '') + expect(subject).to deliver_to(recipient.notification_email) end end end