diff --git a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue index fa2f381c8a4..81d59f1ef65 100644 --- a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue +++ b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue @@ -160,7 +160,10 @@ export default { :pipeline-id="pipelineId" :stage-name="showStageName ? group.stageName : ''" css-class-job-name="gl-build-content" - :class="{ 'gl-opacity-3': isFadedOut(group.name) }" + :class="[ + { 'gl-opacity-3': isFadedOut(group.name) }, + 'gl-transition-duration-slow gl-transition-timing-function-ease', + ]" @pipelineActionRequestComplete="$emit('refreshPipelineGraph')" />
diff --git a/app/mailers/previews/notify_preview.rb b/app/mailers/previews/notify_preview.rb index 5fda60a7408..f6b1e503cb5 100644 --- a/app/mailers/previews/notify_preview.rb +++ b/app/mailers/previews/notify_preview.rb @@ -88,6 +88,10 @@ class NotifyPreview < ActionMailer::Preview Notify.issues_csv_email(user, project, '1997,Ford,E350', { truncated: false, rows_expected: 3, rows_written: 3 }).message end + def new_issue_email + Notify.new_issue_email(user.id, issue.id).message + end + def new_merge_request_email Notify.new_merge_request_email(user.id, merge_request.id).message end @@ -200,7 +204,7 @@ class NotifyPreview < ActionMailer::Preview end def issue - @merge_request ||= project.issues.first + @issue ||= project.issues.first end def merge_request diff --git a/app/models/alert_management/http_integration.rb b/app/models/alert_management/http_integration.rb index e98c770c364..2caa9a18445 100644 --- a/app/models/alert_management/http_integration.rb +++ b/app/models/alert_management/http_integration.rb @@ -10,7 +10,7 @@ module AlertManagement attr_encrypted :token, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm' default_value_for(:endpoint_identifier, allows_nil: false) { SecureRandom.hex(8) } diff --git a/app/models/alerting/project_alerting_setting.rb b/app/models/alerting/project_alerting_setting.rb index 8f8c38f11e4..34fa27eb29b 100644 --- a/app/models/alerting/project_alerting_setting.rb +++ b/app/models/alerting/project_alerting_setting.rb @@ -10,7 +10,7 @@ module Alerting attr_encrypted :token, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm' before_validation :ensure_token diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index caed36c9fe3..9ed0ebe49cc 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -497,29 +497,29 @@ class ApplicationSetting < ApplicationRecord algorithm: 'aes-256-cbc', insecure_mode: true - private_class_method def self.encryption_options_base_truncated_aes_256_gcm + private_class_method def self.encryption_options_base_32_aes_256_gcm { mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm', encode: true } end - attr_encrypted :external_auth_client_key, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :external_auth_client_key_pass, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :lets_encrypt_private_key, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :eks_secret_access_key, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :akismet_api_key, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :elasticsearch_aws_secret_access_key, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :recaptcha_private_key, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :recaptcha_site_key, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :slack_app_secret, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :slack_app_verification_token, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :ci_jwt_signing_key, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :secret_detection_token_revocation_token, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :cloud_license_auth_token, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :external_pipeline_validation_service_token, encryption_options_base_truncated_aes_256_gcm + attr_encrypted :external_auth_client_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :external_auth_client_key_pass, encryption_options_base_32_aes_256_gcm + attr_encrypted :lets_encrypt_private_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :eks_secret_access_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :akismet_api_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :elasticsearch_aws_secret_access_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :recaptcha_private_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :recaptcha_site_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :slack_app_secret, encryption_options_base_32_aes_256_gcm + attr_encrypted :slack_app_verification_token, encryption_options_base_32_aes_256_gcm + attr_encrypted :ci_jwt_signing_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :secret_detection_token_revocation_token, encryption_options_base_32_aes_256_gcm + attr_encrypted :cloud_license_auth_token, encryption_options_base_32_aes_256_gcm + attr_encrypted :external_pipeline_validation_service_token, encryption_options_base_32_aes_256_gcm validates :disable_feed_token, inclusion: { in: [true, false], message: _('must be a boolean value') } diff --git a/app/models/atlassian/identity.rb b/app/models/atlassian/identity.rb index 906f2be0fbf..02bbe007e1b 100644 --- a/app/models/atlassian/identity.rb +++ b/app/models/atlassian/identity.rb @@ -11,14 +11,14 @@ module Atlassian attr_encrypted :token, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm', encode: false, encode_iv: false attr_encrypted :refresh_token, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm', encode: false, encode_iv: false diff --git a/app/models/bulk_imports/configuration.rb b/app/models/bulk_imports/configuration.rb index 4c6f745c268..6d9f598583e 100644 --- a/app/models/bulk_imports/configuration.rb +++ b/app/models/bulk_imports/configuration.rb @@ -12,11 +12,11 @@ class BulkImports::Configuration < ApplicationRecord allow_nil: true attr_encrypted :url, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, mode: :per_attribute_iv, algorithm: 'aes-256-gcm' attr_encrypted :access_token, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, mode: :per_attribute_iv, algorithm: 'aes-256-gcm' end diff --git a/app/models/clusters/applications/prometheus.rb b/app/models/clusters/applications/prometheus.rb index 3160a000705..2b5390b981f 100644 --- a/app/models/clusters/applications/prometheus.rb +++ b/app/models/clusters/applications/prometheus.rb @@ -22,7 +22,7 @@ module Clusters attr_encrypted :alert_manager_token, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm' after_destroy do diff --git a/app/models/clusters/providers/aws.rb b/app/models/clusters/providers/aws.rb index bfd01775620..af2eba42721 100644 --- a/app/models/clusters/providers/aws.rb +++ b/app/models/clusters/providers/aws.rb @@ -18,7 +18,7 @@ module Clusters attr_encrypted :secret_access_key, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm' validates :role_arn, diff --git a/app/models/concerns/packages/debian/distribution.rb b/app/models/concerns/packages/debian/distribution.rb index 08fb9ccf3ea..267c7a4d201 100644 --- a/app/models/concerns/packages/debian/distribution.rb +++ b/app/models/concerns/packages/debian/distribution.rb @@ -84,7 +84,7 @@ module Packages attr_encrypted :signing_keys, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm', encode: false, encode_iv: false diff --git a/app/models/error_tracking/project_error_tracking_setting.rb b/app/models/error_tracking/project_error_tracking_setting.rb index 9a9fbc6a801..956b5d6470f 100644 --- a/app/models/error_tracking/project_error_tracking_setting.rb +++ b/app/models/error_tracking/project_error_tracking_setting.rb @@ -38,7 +38,7 @@ module ErrorTracking attr_encrypted :token, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm' after_save :clear_reactive_cache! diff --git a/app/models/incident_management/project_incident_management_setting.rb b/app/models/incident_management/project_incident_management_setting.rb index 4887265be88..3d4cb2f1912 100644 --- a/app/models/incident_management/project_incident_management_setting.rb +++ b/app/models/incident_management/project_incident_management_setting.rb @@ -12,7 +12,7 @@ module IncidentManagement attr_encrypted :pagerduty_token, mode: :per_attribute_iv, - key: ::Settings.attr_encrypted_db_key_base_truncated, + key: ::Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm', encode: false, # No need to encode for binary column https://github.com/attr-encrypted/attr_encrypted#the-encode-encode_iv-encode_salt-and-default_encoding-options encode_iv: false diff --git a/app/models/pages_domain_acme_order.rb b/app/models/pages_domain_acme_order.rb index 411456cc237..8427176fa72 100644 --- a/app/models/pages_domain_acme_order.rb +++ b/app/models/pages_domain_acme_order.rb @@ -14,7 +14,7 @@ class PagesDomainAcmeOrder < ApplicationRecord attr_encrypted :private_key, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm', encode: true diff --git a/app/models/serverless/domain_cluster.rb b/app/models/serverless/domain_cluster.rb index 9f914d5c3f8..0d54a97370e 100644 --- a/app/models/serverless/domain_cluster.rb +++ b/app/models/serverless/domain_cluster.rb @@ -12,7 +12,7 @@ module Serverless attr_encrypted :key, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm' validates :pages_domain, :knative, presence: true diff --git a/app/views/admin/background_jobs/show.html.haml b/app/views/admin/background_jobs/show.html.haml index 9ba72caa88e..bab9fa02928 100644 --- a/app/views/admin/background_jobs/show.html.haml +++ b/app/views/admin/background_jobs/show.html.haml @@ -1,7 +1,10 @@ - page_title _("Background Jobs") -%h3.page-title Background Jobs -%p.light GitLab uses #{link_to "sidekiq", "http://sidekiq.org/"} library for async job processing +%h3.page-title= _('Background Jobs') +%p.light + - sidekiq_link_url = 'http://sidekiq.org/' + - sidekiq_link_start = ''.html_safe % { url: sidekiq_link_url } + = html_escape(_('GitLab uses %{linkStart}Sidekiq%{linkEnd} to process background jobs')) % { linkStart: sidekiq_link_start, linkEnd: ''.html_safe } %hr .card.gl-rounded-0 diff --git a/app/views/admin/users/_projects.html.haml b/app/views/admin/users/_projects.html.haml index 81cfb71af16..a9f5c560b41 100644 --- a/app/views/admin/users/_projects.html.haml +++ b/app/views/admin/users/_projects.html.haml @@ -1,13 +1,13 @@ - if local_assigns.has_key?(:contributed_projects) && contributed_projects.present? .card.contributed-projects - .card-header Projects contributed to + .card-header= _('Projects contributed to') = render 'shared/projects/list', projects: contributed_projects.sort_by(&:star_count).reverse, projects_limit: 5, stars: true, avatar: false - if local_assigns.has_key?(:projects) && projects.present? .card - .card-header Personal projects + .card-header= _('Personal projects') = render 'shared/projects/list', projects: projects.sort_by(&:star_count).reverse, projects_limit: 10, stars: true, avatar: false diff --git a/app/views/admin/users/projects.html.haml b/app/views/admin/users/projects.html.haml index 70a497f14ff..3ff726e1945 100644 --- a/app/views/admin/users/projects.html.haml +++ b/app/views/admin/users/projects.html.haml @@ -5,7 +5,7 @@ - if @user.groups.any? .card - .card-header Group projects + .card-header= _('Group projects') %ul.hover-list - @user.group_members.includes(:source).each do |group_member| # rubocop: disable CodeReuse/ActiveRecord - group = group_member.group @@ -24,12 +24,12 @@ - if @personal_projects.present? = render 'admin/users/projects', projects: @personal_projects - else - .nothing-here-block This user has no personal projects. + .nothing-here-block= _('This user has no personal projects.') .col-md-6 .card - .card-header Joined projects (#{@joined_projects.count}) + .card-header= _('Joined projects (%{projects_count})') % { projects_count: @joined_projects.count } %ul.hover-list - @joined_projects.sort_by(&:full_name).each do |project| - member = project.team.find_member(@user.id) @@ -41,10 +41,10 @@ - if member .float-right - if member.owner? - %span.light Owner + %span.light= _('Owner') - else %span.light.vertical-align-middle= member.human_access - if member.respond_to? :project - = link_to project_project_member_path(project, member), data: { confirm: remove_member_message(member) }, remote: true, method: :delete, class: "btn btn-sm btn-danger gl-button btn-icon gl-ml-3", title: 'Remove user from project' do + = link_to project_project_member_path(project, member), data: { confirm: remove_member_message(member) }, remote: true, method: :delete, class: "btn btn-sm btn-danger gl-button btn-icon gl-ml-3", title: _('Remove user from project') do = sprite_icon('close', size: 16, css_class: 'gl-icon') diff --git a/app/views/notify/new_issue_email.html.haml b/app/views/notify/new_issue_email.html.haml index 7f0a50e9248..3219ee34736 100644 --- a/app/views/notify/new_issue_email.html.haml +++ b/app/views/notify/new_issue_email.html.haml @@ -1,5 +1,6 @@ %p.details - #{link_to @issue.author_name, user_url(@issue.author)} created an issue #{issue_reference_link(@issue)}: + = html_escape(_('%{user} created an issue: %{issue_link}')) % { user: link_to(@issue.author_name, user_url(@issue.author)), + issue_link: issue_reference_link(@issue) } - if @issue.assignees.any? %p diff --git a/app/views/notify/new_issue_email.text.erb b/app/views/notify/new_issue_email.text.erb index bd61db3ee76..7c78d67316d 100644 --- a/app/views/notify/new_issue_email.text.erb +++ b/app/views/notify/new_issue_email.text.erb @@ -1,4 +1,5 @@ -<%= sanitize_name(@issue.author_name) %> <%= 'created an issue:' %> <%= url_for(project_issue_url(@issue.project, @issue)) %> +<%= _('%{user} created an issue: %{issue_link}') % { user: sanitize_name(@issue.author_name), + issue_link: url_for(project_issue_url(@issue.project, @issue)) } %> <%= assignees_label(@issue) if @issue.assignees.any? %> diff --git a/app/views/notify/new_merge_request_email.html.haml b/app/views/notify/new_merge_request_email.html.haml index 8fdba10e7a1..c8a0a6591a6 100644 --- a/app/views/notify/new_merge_request_email.html.haml +++ b/app/views/notify/new_merge_request_email.html.haml @@ -1,8 +1,6 @@ %p.details - = html_escape(_('%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:')) % {userLinkStart: "".html_safe, - user: @merge_request.author_name, - mrLinkStart: "".html_safe, - linkEnd: ''.html_safe} + = html_escape(_('%{user} created a merge request: %{mr_link}')) % { user: link_to(@merge_request.author_name, user_url(@merge_request.author)), + mr_link: merge_request_reference_link(@merge_request) } %p .branch diff --git a/app/views/notify/new_merge_request_email.text.erb b/app/views/notify/new_merge_request_email.text.erb index 6148af4890e..09e8ca36225 100644 --- a/app/views/notify/new_merge_request_email.text.erb +++ b/app/views/notify/new_merge_request_email.text.erb @@ -1,7 +1,9 @@ -<%= sanitize_name(@merge_request.author_name) %> <%= 'created a merge request:' %> <%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %> +<%= _('%{user} created a merge request: %{mr_link}') % { user: sanitize_name(@merge_request.author_name), + mr_link: url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) } +%> <%= merge_path_description(@merge_request, 'to') %> -<%= 'Author:' %> <%= @merge_request.author_name %> +<%= "#{_('Author')}: #{sanitize_name(@merge_request.author_name)}" %> <%= assignees_label(@merge_request) if @merge_request.assignees.any? %> <%= reviewers_label(@merge_request) if @merge_request.reviewers.any? %> <%= render_if_exists 'notify/merge_request_approvers', presenter: @mr_presenter %> diff --git a/changelogs/unreleased/328338-inconsistent-initial-line-in-merge-request-and-issue-creation-emai.yml b/changelogs/unreleased/328338-inconsistent-initial-line-in-merge-request-and-issue-creation-emai.yml new file mode 100644 index 00000000000..0ab2e34b031 --- /dev/null +++ b/changelogs/unreleased/328338-inconsistent-initial-line-in-merge-request-and-issue-creation-emai.yml @@ -0,0 +1,5 @@ +--- +title: Make new issue, merge request, and epic emails more consistent +merge_request: 59718 +author: +type: changed diff --git a/changelogs/unreleased/Externalise-strings-in-_projects-html-haml.yml b/changelogs/unreleased/Externalise-strings-in-_projects-html-haml.yml new file mode 100644 index 00000000000..993790530a4 --- /dev/null +++ b/changelogs/unreleased/Externalise-strings-in-_projects-html-haml.yml @@ -0,0 +1,5 @@ +--- +title: Externalise strings in users/_projects.html.haml +merge_request: 58110 +author: nuwe1 +type: other diff --git a/changelogs/unreleased/Externalize-strings-in--background_jobs-show-html-haml.yml b/changelogs/unreleased/Externalize-strings-in--background_jobs-show-html-haml.yml new file mode 100644 index 00000000000..59775b6ebc6 --- /dev/null +++ b/changelogs/unreleased/Externalize-strings-in--background_jobs-show-html-haml.yml @@ -0,0 +1,5 @@ +--- +title: Externalize strings in /background_jobs/show.html.haml +merge_request: 58141 +author: nuwe1 +type: other diff --git a/changelogs/unreleased/Externalize-strings-in-projects-hmtl-haml.yml b/changelogs/unreleased/Externalize-strings-in-projects-hmtl-haml.yml new file mode 100644 index 00000000000..0e2af207cc6 --- /dev/null +++ b/changelogs/unreleased/Externalize-strings-in-projects-hmtl-haml.yml @@ -0,0 +1,5 @@ +--- +title: Externalize strings in users/projects.html.haml +merge_request: 58122 +author: nuwe1 +type: other diff --git a/changelogs/unreleased/ab-ci_job_artifacts.yml b/changelogs/unreleased/ab-ci_job_artifacts.yml new file mode 100644 index 00000000000..0406472c414 --- /dev/null +++ b/changelogs/unreleased/ab-ci_job_artifacts.yml @@ -0,0 +1,5 @@ +--- +title: Initialize int8 migration for ci_job_artifacts +merge_request: 59786 +author: +type: other diff --git a/changelogs/unreleased/sh-fix-webhook-defaults.yml b/changelogs/unreleased/sh-fix-webhook-defaults.yml new file mode 100644 index 00000000000..791e77df0f0 --- /dev/null +++ b/changelogs/unreleased/sh-fix-webhook-defaults.yml @@ -0,0 +1,5 @@ +--- +title: Set Web hook defaults to intended default values +merge_request: 59814 +author: +type: fixed diff --git a/config/secrets.yml.example b/config/secrets.yml.example index 6b408ac6031..aadf13d53b2 100644 --- a/config/secrets.yml.example +++ b/config/secrets.yml.example @@ -1,7 +1,7 @@ production: # db_key_base is used to encrypt for Variables. Ensure that you don't lose it. # If you change or lose this key you will be unable to access variables stored in database. - # Make sure the secret is at least 30 characters and all random, + # Make sure the secret is at least 32 characters and all random, # no regular words or you'll be exposed to dictionary attacks. # db_key_base: diff --git a/config/settings.rb b/config/settings.rb index 3369f2a4480..a88f6d89ce4 100644 --- a/config/settings.rb +++ b/config/settings.rb @@ -126,16 +126,18 @@ class Settings < Settingslogic File.expand_path(path, Rails.root) end - # Ruby 2.4+ requires passing in the exact required length for OpenSSL keys - # (https://github.com/ruby/ruby/commit/ce635262f53b760284d56bb1027baebaaec175d1). - # Previous versions quietly truncated the input. - # - # Use this when using :per_attribute_iv mode for attr_encrypted. - # We have to truncate the string to 32 bytes for a 256-bit cipher. + # Don't use this in new code, use attr_encrypted_db_key_base_32 instead! def attr_encrypted_db_key_base_truncated Gitlab::Application.secrets.db_key_base[0..31] end + # Ruby 2.4+ requires passing in the exact required length for OpenSSL keys + # (https://github.com/ruby/ruby/commit/ce635262f53b760284d56bb1027baebaaec175d1). + # Previous versions quietly truncated the input. + # + # Makes sure the key is exactly 32 bytes long, either by + # truncating or right-padding it with ASCII 0s. Use this when + # using :per_attribute_iv mode for attr_encrypted. def attr_encrypted_db_key_base_32 Gitlab::Utils.ensure_utf8_size(attr_encrypted_db_key_base, bytes: 32.bytes) end diff --git a/db/migrate/20191120115530_encrypt_plaintext_attributes_on_application_settings.rb b/db/migrate/20191120115530_encrypt_plaintext_attributes_on_application_settings.rb index e6b9a40ad4f..3ae5e3265e8 100644 --- a/db/migrate/20191120115530_encrypt_plaintext_attributes_on_application_settings.rb +++ b/db/migrate/20191120115530_encrypt_plaintext_attributes_on_application_settings.rb @@ -17,21 +17,21 @@ class EncryptPlaintextAttributesOnApplicationSettings < ActiveRecord::Migration[ class ApplicationSetting < ActiveRecord::Base self.table_name = 'application_settings' - def self.encryption_options_base_truncated_aes_256_gcm + def self.encryption_options_base_32_aes_256_gcm { mode: :per_attribute_iv, - key: Gitlab::Application.secrets.db_key_base[0..31], + key: Gitlab::Utils.ensure_utf8_size(Rails.application.secrets.db_key_base, bytes: 32.bytes), algorithm: 'aes-256-gcm', encode: true } end - attr_encrypted :akismet_api_key, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :elasticsearch_aws_secret_access_key, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :recaptcha_private_key, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :recaptcha_site_key, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :slack_app_secret, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :slack_app_verification_token, encryption_options_base_truncated_aes_256_gcm + attr_encrypted :akismet_api_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :elasticsearch_aws_secret_access_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :recaptcha_private_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :recaptcha_site_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :slack_app_secret, encryption_options_base_32_aes_256_gcm + attr_encrypted :slack_app_verification_token, encryption_options_base_32_aes_256_gcm def akismet_api_key decrypt(:akismet_api_key, self[:encrypted_akismet_api_key]) || self[:akismet_api_key] diff --git a/db/migrate/20201008013434_generate_ci_jwt_signing_key.rb b/db/migrate/20201008013434_generate_ci_jwt_signing_key.rb index 7983a56f439..5d7b6349fe6 100644 --- a/db/migrate/20201008013434_generate_ci_jwt_signing_key.rb +++ b/db/migrate/20201008013434_generate_ci_jwt_signing_key.rb @@ -8,7 +8,7 @@ class GenerateCiJwtSigningKey < ActiveRecord::Migration[6.0] attr_encrypted :ci_jwt_signing_key, { mode: :per_attribute_iv, - key: Rails.application.secrets.db_key_base[0..31], + key: Gitlab::Utils.ensure_utf8_size(Rails.application.secrets.db_key_base, bytes: 32.bytes), algorithm: 'aes-256-gcm', encode: true } diff --git a/db/migrate/20210420012444_change_web_hook_events_default.rb b/db/migrate/20210420012444_change_web_hook_events_default.rb new file mode 100644 index 00000000000..b5a63a5a2a8 --- /dev/null +++ b/db/migrate/20210420012444_change_web_hook_events_default.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class ChangeWebHookEventsDefault < ActiveRecord::Migration[6.0] + def up + change_column_default :web_hooks, :push_events, true + change_column_default :web_hooks, :issues_events, false + change_column_default :web_hooks, :merge_requests_events, false + change_column_default :web_hooks, :tag_push_events, false + end + + # This is a NOP because this migration is supposed to restore the + # intended schema, not revert it. + def down + end +end diff --git a/db/migrate/20210420120734_initialize_conversion_of_ci_job_artifacts_to_bigint.rb b/db/migrate/20210420120734_initialize_conversion_of_ci_job_artifacts_to_bigint.rb new file mode 100644 index 00000000000..715fe8b830a --- /dev/null +++ b/db/migrate/20210420120734_initialize_conversion_of_ci_job_artifacts_to_bigint.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +class InitializeConversionOfCiJobArtifactsToBigint < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + TABLE = :ci_job_artifacts + COLUMNS = %i(id job_id) + TARGET_COLUMNS = COLUMNS.map { |col| "#{col}_convert_to_bigint" } + + def up + initialize_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + def down + trigger_name = rename_trigger_name(TABLE, COLUMNS, TARGET_COLUMNS) + remove_rename_triggers_for_postgresql TABLE, trigger_name + + TARGET_COLUMNS.each do |column| + remove_column TABLE, column + end + end +end diff --git a/db/post_migrate/20210420121149_backfill_conversion_of_ci_job_artifacts.rb b/db/post_migrate/20210420121149_backfill_conversion_of_ci_job_artifacts.rb new file mode 100644 index 00000000000..1fe1f9eed56 --- /dev/null +++ b/db/post_migrate/20210420121149_backfill_conversion_of_ci_job_artifacts.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +class BackfillConversionOfCiJobArtifacts < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def up + return unless should_run? + + backfill_conversion_of_integer_to_bigint :ci_job_artifacts, %i(id job_id), batch_size: 15000, sub_batch_size: 100 + end + + def down + return unless should_run? + + Gitlab::Database::BackgroundMigration::BatchedMigration + .where(job_class_name: 'CopyColumnUsingBackgroundMigrationJob') + .where(table_name: 'ci_job_artifacts', column_name: 'id') + .where('job_arguments = ?', [%w[id job_id], %w[id_convert_to_bigint job_id_convert_to_bigint]].to_json) + .delete_all + end + + private + + def should_run? + Gitlab.dev_or_test_env? || Gitlab.com? + end +end diff --git a/db/schema_migrations/20210420012444 b/db/schema_migrations/20210420012444 new file mode 100644 index 00000000000..5c098f44bc8 --- /dev/null +++ b/db/schema_migrations/20210420012444 @@ -0,0 +1 @@ +f0bf8c79c1981ecd95c933f37ec5b0187ee6321792d96db26d863b192843c5ab \ No newline at end of file diff --git a/db/schema_migrations/20210420120734 b/db/schema_migrations/20210420120734 new file mode 100644 index 00000000000..124fb5b28fe --- /dev/null +++ b/db/schema_migrations/20210420120734 @@ -0,0 +1 @@ +5404ecd22f943671c076b0e870a487ec822cb3d594c223ad4db5b1584394ceb6 \ No newline at end of file diff --git a/db/schema_migrations/20210420121149 b/db/schema_migrations/20210420121149 new file mode 100644 index 00000000000..1326ed9a6f6 --- /dev/null +++ b/db/schema_migrations/20210420121149 @@ -0,0 +1 @@ +58cd21a02a395564acf9abcc39c3daafc5db90aa0b3f29133644f21bb669cdf6 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 83394e38a80..90e69f4518c 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -115,6 +115,16 @@ BEGIN END; $$; +CREATE FUNCTION trigger_be1804f21693() RETURNS trigger + LANGUAGE plpgsql + AS $$ +BEGIN + NEW."id_convert_to_bigint" := NEW."id"; + NEW."job_id_convert_to_bigint" := NEW."job_id"; + RETURN NEW; +END; +$$; + CREATE TABLE audit_events ( id bigint NOT NULL, author_id integer NOT NULL, @@ -10572,6 +10582,8 @@ CREATE TABLE ci_job_artifacts ( file_sha256 bytea, file_format smallint, file_location smallint, + id_convert_to_bigint bigint DEFAULT 0 NOT NULL, + job_id_convert_to_bigint bigint DEFAULT 0 NOT NULL, CONSTRAINT check_27f0f6dbab CHECK ((file_store IS NOT NULL)) ); @@ -24664,6 +24676,8 @@ CREATE TRIGGER trigger_07c94931164e BEFORE INSERT OR UPDATE ON push_event_payloa CREATE TRIGGER trigger_69523443cc10 BEFORE INSERT OR UPDATE ON events FOR EACH ROW EXECUTE PROCEDURE trigger_69523443cc10(); +CREATE TRIGGER trigger_be1804f21693 BEFORE INSERT OR UPDATE ON ci_job_artifacts FOR EACH ROW EXECUTE PROCEDURE trigger_be1804f21693(); + CREATE TRIGGER trigger_has_external_issue_tracker_on_delete AFTER DELETE ON services FOR EACH ROW WHEN ((((old.category)::text = 'issue_tracker'::text) AND (old.active = true) AND (old.project_id IS NOT NULL))) EXECUTE PROCEDURE set_has_external_issue_tracker(); CREATE TRIGGER trigger_has_external_issue_tracker_on_insert AFTER INSERT ON services FOR EACH ROW WHEN ((((new.category)::text = 'issue_tracker'::text) AND (new.active = true) AND (new.project_id IS NOT NULL))) EXECUTE PROCEDURE set_has_external_issue_tracker(); diff --git a/doc/user/group/index.md b/doc/user/group/index.md index d070277beed..cf7addc6db6 100644 --- a/doc/user/group/index.md +++ b/doc/user/group/index.md @@ -577,7 +577,8 @@ To disable group mentions: ## Enable delayed project removal **(PREMIUM)** -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) in GitLab 13.2. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) in GitLab 13.2. +> - [Inheritance and enforcement added](https://gitlab.com/gitlab-org/gitlab/-/issues/321724) in GitLab 13.11. By default, projects in a group are deleted immediately. Optionally, on [Premium](https://about.gitlab.com/pricing/) or higher tiers, @@ -591,10 +592,11 @@ To enable delayed deletion of projects: 1. Go to the group's **Settings > General** page. 1. Expand the **Permissions, LFS, 2FA** section. 1. Check **Enable delayed project removal**. +1. Optional. To prevent subgroups from changing this setting, select **Enforce for all subgroups**. 1. Select **Save changes**. NOTE: -The group setting for delayed deletion is not inherited by subgroups and has to be individually defined for each group. +In GitLab 13.11 and above the group setting for delayed project removal is inherited by subgroups. As discussed in [Cascading settings](../../development/cascading_settings.md) inheritance can be overridden, unless enforced by an ancestor. ## Prevent project forking outside group **(PREMIUM)** diff --git a/lib/gitlab/database/background_migration/batched_migration_wrapper.rb b/lib/gitlab/database/background_migration/batched_migration_wrapper.rb index c276f8ce75b..110c00e284e 100644 --- a/lib/gitlab/database/background_migration/batched_migration_wrapper.rb +++ b/lib/gitlab/database/background_migration/batched_migration_wrapper.rb @@ -19,10 +19,10 @@ module Gitlab execute_batch(batch_tracking_record) batch_tracking_record.status = :succeeded - rescue => e + rescue Exception # rubocop:disable Lint/RescueException batch_tracking_record.status = :failed - raise e + raise ensure finish_tracking_execution(batch_tracking_record) track_prometheus_metrics(batch_tracking_record) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 2669cb6231b..880cb5beba7 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -958,9 +958,6 @@ msgstr "" msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc." msgstr "" -msgid "%{userLinkStart}%{user}%{linkEnd} created a %{mrLinkStart}merge request%{linkEnd}:" -msgstr "" - msgid "%{userName} (cannot merge)" msgstr "" @@ -976,6 +973,15 @@ msgstr "" msgid "%{username}'s avatar" msgstr "" +msgid "%{user} created a merge request: %{mr_link}" +msgstr "" + +msgid "%{user} created an epic: %{epic_link}" +msgstr "" + +msgid "%{user} created an issue: %{issue_link}" +msgstr "" + msgid "%{value} s" msgstr "" @@ -14836,6 +14842,9 @@ msgstr "" msgid "GitLab uses %{jaeger_link} to monitor distributed systems." msgstr "" +msgid "GitLab uses %{linkStart}Sidekiq%{linkEnd} to process background jobs" +msgstr "" + msgid "GitLab version" msgstr "" @@ -15325,6 +15334,9 @@ msgstr "" msgid "Group project URLs are prefixed with the group namespace" msgstr "" +msgid "Group projects" +msgstr "" + msgid "Group requires separate account" msgstr "" @@ -18412,6 +18424,9 @@ msgstr "" msgid "Joined %{user_created_time}" msgstr "" +msgid "Joined projects (%{projects_count})" +msgstr "" + msgid "Jul" msgstr "" @@ -23255,6 +23270,9 @@ msgstr "" msgid "Personal project creation is not allowed. Please contact your administrator with questions" msgstr "" +msgid "Personal projects" +msgstr "" + msgid "Phabricator Server Import" msgstr "" @@ -25358,6 +25376,9 @@ msgstr "" msgid "Projects are graded based on the highest severity vulnerability present" msgstr "" +msgid "Projects contributed to" +msgstr "" + msgid "Projects shared with %{group_name}" msgstr "" @@ -26568,6 +26589,9 @@ msgstr "" msgid "Remove user from group" msgstr "" +msgid "Remove user from project" +msgstr "" + msgid "Removed" msgstr "" @@ -32562,6 +32586,9 @@ msgstr "" msgid "This user has no identities" msgstr "" +msgid "This user has no personal projects." +msgstr "" + msgid "This user has previously committed to the %{name} project." msgstr "" diff --git a/spec/controllers/admin/groups_controller_spec.rb b/spec/controllers/admin/groups_controller_spec.rb index 8441a52b454..8e31ef12adf 100644 --- a/spec/controllers/admin/groups_controller_spec.rb +++ b/spec/controllers/admin/groups_controller_spec.rb @@ -55,7 +55,7 @@ RSpec.describe Admin::GroupsController do access_level: Gitlab::Access::GUEST } - expect(response).to set_flash.to 'Users were successfully added.' + expect(controller).to set_flash.to 'Users were successfully added.' expect(response).to redirect_to(admin_group_path(group)) expect(group.users).to include group_user end @@ -67,7 +67,7 @@ RSpec.describe Admin::GroupsController do access_level: Gitlab::Access::GUEST } - expect(response).to set_flash.to 'Users were successfully added.' + expect(controller).to set_flash.to 'Users were successfully added.' expect(response).to redirect_to(admin_group_path(group)) end @@ -78,7 +78,7 @@ RSpec.describe Admin::GroupsController do access_level: Gitlab::Access::GUEST } - expect(response).to set_flash.to 'No users specified.' + expect(controller).to set_flash.to 'No users specified.' expect(response).to redirect_to(admin_group_path(group)) expect(group.users).not_to include group_user end diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 3d34db6c2c0..fec81c6a979 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -725,7 +725,7 @@ RSpec.describe ApplicationController do format.csv do stream_csv_headers('test.csv') - self.response_body = fixture_file_upload('spec/fixtures/csv_comma.csv') + self.response_body = Rack::Test::UploadedFile.new('spec/fixtures/csv_comma.csv') end end end diff --git a/spec/controllers/concerns/confirm_email_warning_spec.rb b/spec/controllers/concerns/confirm_email_warning_spec.rb index 24ee6fb30d2..334c156e1ae 100644 --- a/spec/controllers/concerns/confirm_email_warning_spec.rb +++ b/spec/controllers/concerns/confirm_email_warning_spec.rb @@ -18,7 +18,7 @@ RSpec.describe ConfirmEmailWarning do RSpec::Matchers.define :set_confirm_warning_for do |email| match do |response| - expect(response).to set_flash.now[:warning].to include("Please check your email (#{email}) to verify that you own this address and unlock the power of CI/CD.") + expect(controller).to set_flash.now[:warning].to include("Please check your email (#{email}) to verify that you own this address and unlock the power of CI/CD.") end end diff --git a/spec/controllers/concerns/redirects_for_missing_path_on_tree_spec.rb b/spec/controllers/concerns/redirects_for_missing_path_on_tree_spec.rb index 5c3b6e13ee3..ccd5570f2bd 100644 --- a/spec/controllers/concerns/redirects_for_missing_path_on_tree_spec.rb +++ b/spec/controllers/concerns/redirects_for_missing_path_on_tree_spec.rb @@ -27,7 +27,7 @@ RSpec.describe RedirectsForMissingPathOnTree, type: :controller do get :fake, params: { project_id: project.id, ref: 'theref', file_path: long_file_path } expect(response).to redirect_to project_tree_path(project, 'theref') - expect(response.flash[:notice]).to eq(expected_message) + expect(controller).to set_flash[:notice].to eq(expected_message) end end end diff --git a/spec/controllers/groups/group_members_controller_spec.rb b/spec/controllers/groups/group_members_controller_spec.rb index 19655687028..ceea19af2f5 100644 --- a/spec/controllers/groups/group_members_controller_spec.rb +++ b/spec/controllers/groups/group_members_controller_spec.rb @@ -130,7 +130,7 @@ RSpec.describe Groups::GroupMembersController do access_level: Gitlab::Access::GUEST } - expect(response).to set_flash.to 'Users were successfully added.' + expect(controller).to set_flash.to 'Users were successfully added.' expect(response).to redirect_to(group_group_members_path(group)) expect(group.users).to include group_user end @@ -142,7 +142,7 @@ RSpec.describe Groups::GroupMembersController do access_level: Gitlab::Access::GUEST } - expect(response).to set_flash.to 'No users specified.' + expect(controller).to set_flash.to 'No users specified.' expect(response).to redirect_to(group_group_members_path(group)) expect(group.users).not_to include group_user end @@ -180,7 +180,7 @@ RSpec.describe Groups::GroupMembersController do it 'adds user to members' do subject - expect(response).to set_flash.to 'Users were successfully added.' + expect(controller).to set_flash.to 'Users were successfully added.' expect(response).to redirect_to(group_group_members_path(group)) expect(group.users).to include group_user end @@ -330,7 +330,7 @@ RSpec.describe Groups::GroupMembersController do it '[HTML] removes user from members' do delete :destroy, params: { group_id: group, id: member } - expect(response).to set_flash.to 'User was successfully removed from group.' + expect(controller).to set_flash.to 'User was successfully removed from group.' expect(response).to redirect_to(group_group_members_path(group)) expect(group.members).not_to include member expect(sub_group.members).to include sub_member @@ -339,7 +339,7 @@ RSpec.describe Groups::GroupMembersController do it '[HTML] removes user from members including subgroups and projects' do delete :destroy, params: { group_id: group, id: member, remove_sub_memberships: true } - expect(response).to set_flash.to 'User was successfully removed from group and any subgroups and projects.' + expect(controller).to set_flash.to 'User was successfully removed from group and any subgroups and projects.' expect(response).to redirect_to(group_group_members_path(group)) expect(group.members).not_to include member expect(sub_group.members).not_to include sub_member @@ -377,7 +377,7 @@ RSpec.describe Groups::GroupMembersController do it 'removes user from members' do delete :leave, params: { group_id: group } - expect(response).to set_flash.to "You left the \"#{group.name}\" group." + expect(controller).to set_flash.to "You left the \"#{group.name}\" group." expect(response).to redirect_to(dashboard_groups_path) expect(group.users).not_to include user end @@ -410,7 +410,7 @@ RSpec.describe Groups::GroupMembersController do it 'removes user from members' do delete :leave, params: { group_id: group } - expect(response).to set_flash.to 'Your access request to the group has been withdrawn.' + expect(controller).to set_flash.to 'Your access request to the group has been withdrawn.' expect(response).to redirect_to(group_path(group)) expect(group.requesters).to be_empty expect(group.users).not_to include user @@ -427,7 +427,7 @@ RSpec.describe Groups::GroupMembersController do it 'creates a new GroupMember that is not a team member' do post :request_access, params: { group_id: group } - expect(response).to set_flash.to 'Your request for access has been queued for review.' + expect(controller).to set_flash.to 'Your request for access has been queued for review.' expect(response).to redirect_to(group_path(group)) expect(group.requesters.exists?(user_id: user)).to be_truthy expect(group.users).not_to include user diff --git a/spec/controllers/groups/settings/ci_cd_controller_spec.rb b/spec/controllers/groups/settings/ci_cd_controller_spec.rb index 880d5fe8951..db16579c3e7 100644 --- a/spec/controllers/groups/settings/ci_cd_controller_spec.rb +++ b/spec/controllers/groups/settings/ci_cd_controller_spec.rb @@ -128,7 +128,7 @@ RSpec.describe Groups::Settings::CiCdController do end it 'returns a flash alert' do - expect(response).to set_flash[:alert] + expect(controller).to set_flash[:alert] .to eq("There was a problem updating Auto DevOps pipeline: [\"Error 1\"].") end end @@ -137,7 +137,7 @@ RSpec.describe Groups::Settings::CiCdController do it 'returns a flash notice' do subject - expect(response).to set_flash[:notice] + expect(controller).to set_flash[:notice] .to eq('Auto DevOps pipeline was updated for the group') end end @@ -209,7 +209,7 @@ RSpec.describe Groups::Settings::CiCdController do end it 'returns a flash alert' do - expect(response).to set_flash[:alert] + expect(controller).to set_flash[:alert] .to eq("There was a problem updating the pipeline settings: [\"Error 1\"].") end end @@ -218,7 +218,7 @@ RSpec.describe Groups::Settings::CiCdController do it 'returns a flash notice' do subject - expect(response).to set_flash[:notice] + expect(controller).to set_flash[:notice] .to eq('Pipeline settings was updated for the group') end end diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index 3e016a5e8d2..1564501c4d8 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -1704,7 +1704,7 @@ RSpec.describe Projects::IssuesController do request_csv expect(response).to redirect_to(project_issues_path(project)) - expect(response.flash[:notice]).to match(/\AYour CSV export has started/i) + expect(controller).to set_flash[:notice].to match(/\AYour CSV export has started/i) end end diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 337a4a19b2e..a04bda9902b 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -2229,7 +2229,7 @@ RSpec.describe Projects::MergeRequestsController do subject expect(response).to redirect_to(project_merge_requests_path(project)) - expect(response.flash[:notice]).to match(/\AYour CSV export has started/i) + expect(controller).to set_flash[:notice].to match(/\AYour CSV export has started/i) end it 'enqueues an IssuableExportCsvWorker worker' do diff --git a/spec/controllers/projects/performance_monitoring/dashboards_controller_spec.rb b/spec/controllers/projects/performance_monitoring/dashboards_controller_spec.rb index 923581d9367..939366e5b0b 100644 --- a/spec/controllers/projects/performance_monitoring/dashboards_controller_spec.rb +++ b/spec/controllers/projects/performance_monitoring/dashboards_controller_spec.rb @@ -64,7 +64,7 @@ RSpec.describe Projects::PerformanceMonitoring::DashboardsController do post :create, params: params expect(response).to have_gitlab_http_status :created - expect(response).to set_flash[:notice].to eq("Your dashboard has been copied. You can edit it here.") + expect(controller).to set_flash[:notice].to eq("Your dashboard has been copied. You can edit it here.") expect(json_response).to eq('status' => 'success', 'dashboard' => { 'path' => ".gitlab/dashboards/#{file_name}" }) end @@ -203,7 +203,7 @@ RSpec.describe Projects::PerformanceMonitoring::DashboardsController do put :update, params: params expect(response).to have_gitlab_http_status :created - expect(response).to set_flash[:notice].to eq("Your dashboard has been updated. You can edit it here.") + expect(controller).to set_flash[:notice].to eq("Your dashboard has been updated. You can edit it here.") expect(json_response).to eq('status' => 'success', 'dashboard' => { 'default' => false, 'display_name' => "custom_dashboard.yml", 'path' => ".gitlab/dashboards/#{file_name}", 'system_dashboard' => false }) end diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb index 46a0fc8edb0..bb817fc94b2 100644 --- a/spec/controllers/projects/project_members_controller_spec.rb +++ b/spec/controllers/projects/project_members_controller_spec.rb @@ -199,7 +199,7 @@ RSpec.describe Projects::ProjectMembersController do access_level: Gitlab::Access::GUEST } - expect(response).to set_flash.to 'Users were successfully added.' + expect(controller).to set_flash.to 'Users were successfully added.' expect(response).to redirect_to(project_project_members_path(project)) end @@ -215,7 +215,7 @@ RSpec.describe Projects::ProjectMembersController do access_level: Gitlab::Access::GUEST } - expect(response).to set_flash.to 'Message' + expect(controller).to set_flash.to 'Message' expect(response).to redirect_to(project_project_members_path(project)) end end @@ -276,7 +276,7 @@ RSpec.describe Projects::ProjectMembersController do it 'adds user to members' do subject - expect(response).to set_flash.to 'Users were successfully added.' + expect(controller).to set_flash.to 'Users were successfully added.' expect(response).to redirect_to(project_project_members_path(project)) expect(project.users).to include project_user end @@ -489,7 +489,7 @@ RSpec.describe Projects::ProjectMembersController do project_id: project } - expect(response).to set_flash.to "You left the \"#{project.human_name}\" project." + expect(controller).to set_flash.to "You left the \"#{project.human_name}\" project." expect(response).to redirect_to(dashboard_projects_path) expect(project.users).not_to include user end @@ -523,7 +523,7 @@ RSpec.describe Projects::ProjectMembersController do project_id: project } - expect(response).to set_flash.to 'Your access request to the project has been withdrawn.' + expect(controller).to set_flash.to 'Your access request to the project has been withdrawn.' expect(response).to redirect_to(project_path(project)) expect(project.requesters).to be_empty expect(project.users).not_to include user @@ -543,7 +543,7 @@ RSpec.describe Projects::ProjectMembersController do project_id: project } - expect(response).to set_flash.to 'Your request for access has been queued for review.' + expect(controller).to set_flash.to 'Your request for access has been queued for review.' expect(response).to redirect_to( project_path(project) ) @@ -639,7 +639,7 @@ RSpec.describe Projects::ProjectMembersController do it 'imports source project members' do expect(project.team_members).to include member - expect(response).to set_flash.to 'Successfully imported' + expect(controller).to set_flash.to 'Successfully imported' expect(response).to redirect_to( project_project_members_path(project) ) diff --git a/spec/controllers/projects/services_controller_spec.rb b/spec/controllers/projects/services_controller_spec.rb index 488a34b74df..687a979edc1 100644 --- a/spec/controllers/projects/services_controller_spec.rb +++ b/spec/controllers/projects/services_controller_spec.rb @@ -271,7 +271,7 @@ RSpec.describe Projects::ServicesController do expect(response).to redirect_to(edit_project_service_path(project, service)) expected_alert = "You can now manage your Prometheus settings on the Operations page. Fields on this page has been deprecated." - expect(response).to set_flash.now[:alert].to(expected_alert) + expect(controller).to set_flash.now[:alert].to(expected_alert) end it 'does not modify service' do @@ -317,7 +317,7 @@ RSpec.describe Projects::ServicesController do it 'renders deprecation warning notice' do expected_alert = "You can now manage your Prometheus settings on the Operations page. Fields on this page has been deprecated." - expect(response).to set_flash.now[:alert].to(expected_alert) + expect(controller).to set_flash.now[:alert].to(expected_alert) end end @@ -328,7 +328,7 @@ RSpec.describe Projects::ServicesController do end it 'does not render deprecation warning notice' do - expect(response).not_to set_flash.now[:alert] + expect(controller).not_to set_flash.now[:alert] end end end diff --git a/spec/controllers/projects/settings/ci_cd_controller_spec.rb b/spec/controllers/projects/settings/ci_cd_controller_spec.rb index 4c7ae02ed50..dc7066f6b61 100644 --- a/spec/controllers/projects/settings/ci_cd_controller_spec.rb +++ b/spec/controllers/projects/settings/ci_cd_controller_spec.rb @@ -162,7 +162,9 @@ RSpec.describe Projects::Settings::CiCdController do context 'when the project repository is empty' do it 'sets a notice flash' do - expect(subject).to set_flash[:notice] + subject + + expect(controller).to set_flash[:notice] end it 'does not queue a CreatePipelineWorker' do @@ -178,7 +180,9 @@ RSpec.describe Projects::Settings::CiCdController do it 'displays a toast message' do allow(CreatePipelineWorker).to receive(:perform_async).with(project.id, user.id, project.default_branch, :web, any_args) - expect(subject).to set_flash[:toast] + subject + + expect(controller).to set_flash[:toast] end it 'queues a CreatePipelineWorker' do @@ -239,7 +243,9 @@ RSpec.describe Projects::Settings::CiCdController do let(:params) { { build_timeout_human_readable: '5m' } } it 'set specified timeout' do - expect(subject).to set_flash[:alert] + subject + + expect(controller).to set_flash[:alert] expect(response).to redirect_to(namespace_project_settings_ci_cd_path) end end diff --git a/spec/controllers/projects/static_site_editor_controller_spec.rb b/spec/controllers/projects/static_site_editor_controller_spec.rb index 73b0e3bba69..26161b5fb5c 100644 --- a/spec/controllers/projects/static_site_editor_controller_spec.rb +++ b/spec/controllers/projects/static_site_editor_controller_spec.rb @@ -102,7 +102,7 @@ RSpec.describe Projects::StaticSiteEditorController do it 'redirects to project page and flashes error message' do expect(response).to redirect_to(project_path(project)) - expect(response).to set_flash[:alert].to('invalid') + expect(controller).to set_flash[:alert].to('invalid') end end diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index abdafa2880a..c233e5b7c15 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -85,8 +85,7 @@ RSpec.describe SessionsController do it 'does not authenticate user' do post(:create, params: { user: { login: 'invalid', password: 'invalid' } }) - expect(response) - .to set_flash.now[:alert].to(/Invalid login or password/) + expect(controller).to set_flash.now[:alert].to(/Invalid login or password/) end end @@ -348,7 +347,7 @@ RSpec.describe SessionsController do otp_user_id: user.id ) - expect(response).to set_flash.now[:alert].to(/Invalid login or password/) + expect(controller).to set_flash.now[:alert].to(/Invalid login or password/) end end @@ -396,7 +395,7 @@ RSpec.describe SessionsController do end it 'warns about invalid OTP code' do - expect(response).to set_flash.now[:alert] + expect(controller).to set_flash.now[:alert] .to(/Invalid two-factor code/) end end diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb index b06d581d2c0..f8bd0ffff64 100644 --- a/spec/factories/ci/builds.rb +++ b/spec/factories/ci/builds.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -include ActionDispatch::TestProcess - FactoryBot.define do factory :ci_build, class: 'Ci::Build', parent: :ci_processable do name { 'test' } diff --git a/spec/factories/ci/job_artifacts.rb b/spec/factories/ci/job_artifacts.rb index bfd8506566b..b1adbcd283b 100644 --- a/spec/factories/ci/job_artifacts.rb +++ b/spec/factories/ci/job_artifacts.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -include ActionDispatch::TestProcess - FactoryBot.define do factory :ci_job_artifact, class: 'Ci::JobArtifact' do job factory: :ci_build diff --git a/spec/factories/lfs_objects.rb b/spec/factories/lfs_objects.rb index 35fc4db8519..59c6ea5f55a 100644 --- a/spec/factories/lfs_objects.rb +++ b/spec/factories/lfs_objects.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -include ActionDispatch::TestProcess - FactoryBot.define do factory :lfs_object do sequence(:oid) { |n| "b68143e6463773b1b6c6fd009a76c32aeec041faff32ba2ed42fd7f708a%05x" % n } diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb index 299d08972b7..c15ec91d2ce 100644 --- a/spec/factories/notes.rb +++ b/spec/factories/notes.rb @@ -2,8 +2,6 @@ require_relative '../support/helpers/repo_helpers' -include ActionDispatch::TestProcess - FactoryBot.define do factory :note do project diff --git a/spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb b/spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb index 00d13f23d36..b8b91cc61f2 100644 --- a/spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb +++ b/spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb @@ -112,19 +112,24 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationWrapper, ' end context 'when the migration job raises an error' do - it 'marks the tracking record as failed before raising the error' do - expect(job_instance).to receive(:perform) - .with(1, 10, 'events', 'id', 1, 'id', 'other_id') - .and_raise(RuntimeError, 'Something broke!') + shared_examples 'an error is raised' do |error_class| + it 'marks the tracking record as failed' do + expect(job_instance).to receive(:perform) + .with(1, 10, 'events', 'id', 1, 'id', 'other_id') + .and_raise(error_class) - freeze_time do - expect { subject }.to raise_error(RuntimeError, 'Something broke!') + freeze_time do + expect { subject }.to raise_error(error_class) - reloaded_job_record = job_record.reload + reloaded_job_record = job_record.reload - expect(reloaded_job_record).to be_failed - expect(reloaded_job_record.finished_at).to eq(Time.current) + expect(reloaded_job_record).to be_failed + expect(reloaded_job_record.finished_at).to eq(Time.current) + end end end + + it_behaves_like 'an error is raised', RuntimeError.new('Something broke!') + it_behaves_like 'an error is raised', SignalException.new('SIGTERM') end end diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 94a081ae0c9..b073b647532 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -118,7 +118,7 @@ RSpec.describe Notify do it 'contains a link to issue author' do is_expected.to have_body_text(issue.author_name) - is_expected.to have_body_text 'created an issue' + is_expected.to have_body_text 'created an issue:' is_expected.to have_link(issue.to_reference, href: project_issue_url(issue.project, issue)) end @@ -356,11 +356,11 @@ RSpec.describe Notify do it 'contains a link to merge request author' do is_expected.to have_body_text merge_request.author_name - is_expected.to have_body_text 'created a' + is_expected.to have_body_text 'created a merge request:' end it 'contains a link to the merge request url' do - is_expected.to have_link('merge request', href: project_merge_request_url(merge_request.target_project, merge_request)) + is_expected.to have_link(merge_request.to_reference, href: project_merge_request_url(merge_request.target_project, merge_request)) end end diff --git a/spec/migrations/change_web_hook_events_default_spec.rb b/spec/migrations/change_web_hook_events_default_spec.rb new file mode 100644 index 00000000000..3b1a65ece17 --- /dev/null +++ b/spec/migrations/change_web_hook_events_default_spec.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require 'spec_helper' +require Rails.root.join('db', 'migrate', '20210420012444_change_web_hook_events_default.rb') + +RSpec.describe ChangeWebHookEventsDefault do + let(:web_hooks) { table(:web_hooks) } + let(:projects) { table(:projects) } + let(:groups) { table(:namespaces) } + + let(:group) { groups.create!(name: 'gitlab', path: 'gitlab-org') } + let(:project) { projects.create!(name: 'gitlab', path: 'gitlab', namespace_id: group.id) } + let(:hook) { web_hooks.create!(project_id: project.id, type: 'ProjectHook') } + let(:group_hook) { web_hooks.create!(group_id: group.id, type: 'GroupHook') } + + before do + # Simulate the wrong schema + %w(push_events issues_events merge_requests_events tag_push_events).each do |column| + ActiveRecord::Base.connection.execute "ALTER TABLE web_hooks ALTER COLUMN #{column} DROP DEFAULT" + end + end + + it 'sets default values' do + migrate! + + expect(hook.push_events).to be true + expect(hook.issues_events).to be false + expect(hook.merge_requests_events).to be false + expect(hook.tag_push_events).to be false + + expect(group_hook.push_events).to be true + expect(group_hook.issues_events).to be false + expect(group_hook.merge_requests_events).to be false + expect(group_hook.tag_push_events).to be false + end +end diff --git a/spec/migrations/generate_ci_jwt_signing_key_spec.rb b/spec/migrations/generate_ci_jwt_signing_key_spec.rb index 4cfaa8701aa..249af3bcb50 100644 --- a/spec/migrations/generate_ci_jwt_signing_key_spec.rb +++ b/spec/migrations/generate_ci_jwt_signing_key_spec.rb @@ -11,7 +11,7 @@ RSpec.describe GenerateCiJwtSigningKey do attr_encrypted :ci_jwt_signing_key, { mode: :per_attribute_iv, - key: Rails.application.secrets.db_key_base[0..31], + key: Gitlab::Utils.ensure_utf8_size(Rails.application.secrets.db_key_base, bytes: 32.bytes), algorithm: 'aes-256-gcm', encode: true } diff --git a/spec/requests/api/graphql_spec.rb b/spec/requests/api/graphql_spec.rb index 6566bfc7992..a336d74b135 100644 --- a/spec/requests/api/graphql_spec.rb +++ b/spec/requests/api/graphql_spec.rb @@ -101,7 +101,7 @@ RSpec.describe 'GraphQL' do login_as(user) get('/') - post '/api/graphql', params: { query: query }, headers: { 'X-CSRF-Token' => response.session['_csrf_token'] } + post '/api/graphql', params: { query: query }, headers: { 'X-CSRF-Token' => session['_csrf_token'] } expect(graphql_data['echo']).to eq("\"#{user.username}\" says: Hello world") end diff --git a/spec/support/factory_bot.rb b/spec/support/factory_bot.rb index 5761e05d541..5f22fa11e9e 100644 --- a/spec/support/factory_bot.rb +++ b/spec/support/factory_bot.rb @@ -2,6 +2,14 @@ FactoryBot::SyntaxRunner.class_eval do include RSpec::Mocks::ExampleMethods + + # FactoryBot doesn't allow yet to add a helper that can be used in factories + # While the fixture_file_upload helper is reasonable to be used there: + # + # https://github.com/thoughtbot/factory_bot/issues/564#issuecomment-389491577 + def fixture_file_upload(*args, **kwargs) + Rack::Test::UploadedFile.new(*args, **kwargs) + end end # Patching FactoryBot to allow stubbing non AR models diff --git a/spec/support/renameable_upload.rb b/spec/support/renameable_upload.rb index f7f00181605..08e8d07ed4d 100644 --- a/spec/support/renameable_upload.rb +++ b/spec/support/renameable_upload.rb @@ -5,7 +5,7 @@ class RenameableUpload < SimpleDelegator # Get a fixture file with a new unique name, and the same extension def self.unique_file(name) - upload = new(fixture_file_upload("spec/fixtures/#{name}")) + upload = new(Rack::Test::UploadedFile.new("spec/fixtures/#{name}")) ext = File.extname(name) new_name = File.basename(FactoryBot.generate(:filename), '.*') upload.original_filename = new_name + ext diff --git a/spec/support/shared_examples/controllers/access_tokens_controller_shared_examples.rb b/spec/support/shared_examples/controllers/access_tokens_controller_shared_examples.rb index dd71107455f..70a684c12bf 100644 --- a/spec/support/shared_examples/controllers/access_tokens_controller_shared_examples.rb +++ b/spec/support/shared_examples/controllers/access_tokens_controller_shared_examples.rb @@ -40,7 +40,7 @@ RSpec.shared_examples 'project access tokens available #create' do it 'returns success message' do subject - expect(response.flash[:notice]).to match('Your new project access token has been created.') + expect(controller).to set_flash[:notice].to match('Your new project access token has been created.') end it 'creates project access token' do @@ -88,7 +88,7 @@ RSpec.shared_examples 'project access tokens available #create' do it 'shows a failure alert' do subject - expect(response.flash[:alert]).to match("Failed to create new project access token: Failed!") + expect(controller).to set_flash[:alert].to match("Failed to create new project access token: Failed!") end end end