diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-05-05 03:10:41 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-05-05 03:10:41 +0300 |
commit | 415153114ac36a0e25b6beb6f0543581bcedc54c (patch) | |
tree | 7766607058528a92efb52f05fe03005a9392a0ea | |
parent | 4f49d2c8cd9b0c54c1055480df5cde2e13d7c76d (diff) |
Add latest changes from gitlab-org/gitlab@master
49 files changed, 491 insertions, 35 deletions
diff --git a/app/controllers/concerns/boards_actions.rb b/app/controllers/concerns/boards_actions.rb index 7bffe1e1141..8c2b0300589 100644 --- a/app/controllers/concerns/boards_actions.rb +++ b/app/controllers/concerns/boards_actions.rb @@ -7,6 +7,7 @@ module BoardsActions included do include BoardsResponses + before_action :authorize_read_board!, only: [:index, :show] before_action :boards, only: :index before_action :board, only: :show before_action :push_licensed_features, only: [:index, :show] diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb index be38fe25842..e1f09d73739 100644 --- a/app/controllers/groups/boards_controller.rb +++ b/app/controllers/groups/boards_controller.rb @@ -5,7 +5,6 @@ class Groups::BoardsController < Groups::ApplicationController include RecordUserLastActivity include Gitlab::Utils::StrongMemoize - before_action :authorize_read_board!, only: [:index, :show] before_action :assign_endpoint_vars before_action do push_frontend_feature_flag(:graphql_board_lists, group, default_enabled: false) diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb index 349649c7b35..9a3e9437426 100644 --- a/app/controllers/projects/boards_controller.rb +++ b/app/controllers/projects/boards_controller.rb @@ -5,7 +5,6 @@ class Projects::BoardsController < Projects::ApplicationController include IssuableCollections before_action :check_issues_available! - before_action :authorize_read_board!, only: [:index, :show] before_action :assign_endpoint_vars before_action do push_frontend_feature_flag(:swimlanes_buffered_rendering, project, default_enabled: :yaml) diff --git a/app/models/concerns/prometheus_adapter.rb b/app/models/concerns/prometheus_adapter.rb index b26d376bb9b..afebc426762 100644 --- a/app/models/concerns/prometheus_adapter.rb +++ b/app/models/concerns/prometheus_adapter.rb @@ -33,7 +33,7 @@ module PrometheusAdapter # This is a light-weight check if a prometheus client is properly configured. def configured? - raise NotImplemented + raise NotImplementedError end # This is a heavy-weight check if a prometheus is properly configured and accessible from GitLab. diff --git a/app/models/user.rb b/app/models/user.rb index 92cbf863d63..581a1bd893b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -205,6 +205,7 @@ class User < ApplicationRecord has_one :user_detail has_one :user_highest_role has_one :user_canonical_email + has_one :credit_card_validation, class_name: '::Users::CreditCardValidation' has_one :atlassian_identity, class_name: 'Atlassian::Identity' has_many :reviews, foreign_key: :author_id, inverse_of: :author @@ -317,6 +318,7 @@ class User < ApplicationRecord accepts_nested_attributes_for :user_preference, update_only: true accepts_nested_attributes_for :user_detail, update_only: true + accepts_nested_attributes_for :credit_card_validation, update_only: true state_machine :state, initial: :active do event :block do @@ -1223,6 +1225,10 @@ class User < ApplicationRecord user_highest_role&.highest_access_level || Gitlab::Access::NO_ACCESS end + def credit_card_validated_at + credit_card_validation&.credit_card_validated_at + end + def accessible_deploy_keys DeployKey.from_union([ DeployKey.where(id: project_deploy_keys.select(:deploy_key_id)), diff --git a/app/models/users/credit_card_validation.rb b/app/models/users/credit_card_validation.rb new file mode 100644 index 00000000000..2ccebc65552 --- /dev/null +++ b/app/models/users/credit_card_validation.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Users + class CreditCardValidation < ApplicationRecord + self.table_name = 'user_credit_card_validations' + + belongs_to :user + end +end diff --git a/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json b/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json index dc4880946b2..7c3720dd2e6 100644 --- a/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json +++ b/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json @@ -161,6 +161,13 @@ "variables": [] }, { + "name": "semgrep", + "label": "Semgrep", + "enabled": true, + "description": "Multi-language scanning", + "variables": [] + }, + { "name": "sobelow", "label": "Sobelow", "enabled" : true, diff --git a/changelogs/unreleased/202423-validate-foreign-key-on-group-hooks.yml b/changelogs/unreleased/202423-validate-foreign-key-on-group-hooks.yml new file mode 100644 index 00000000000..bf39cf13dd4 --- /dev/null +++ b/changelogs/unreleased/202423-validate-foreign-key-on-group-hooks.yml @@ -0,0 +1,5 @@ +--- +title: Validate foreign key on GroupHooks +merge_request: 60527 +author: +type: other diff --git a/changelogs/unreleased/328066-semgrep-config-ui.yml b/changelogs/unreleased/328066-semgrep-config-ui.yml new file mode 100644 index 00000000000..e1a592c9d0c --- /dev/null +++ b/changelogs/unreleased/328066-semgrep-config-ui.yml @@ -0,0 +1,5 @@ +--- +title: Add semgrep to SAST config UI +merge_request: 60460 +author: +type: added diff --git a/changelogs/unreleased/migrate-create-table-user-credit-card-validations.yml b/changelogs/unreleased/migrate-create-table-user-credit-card-validations.yml new file mode 100644 index 00000000000..cabaea5159c --- /dev/null +++ b/changelogs/unreleased/migrate-create-table-user-credit-card-validations.yml @@ -0,0 +1,5 @@ +--- +title: Create table user_credit_card_validations +merge_request: 60626 +author: +type: changed diff --git a/changelogs/unreleased/populate-timelogs-project_id.yml b/changelogs/unreleased/populate-timelogs-project_id.yml new file mode 100644 index 00000000000..db133120b64 --- /dev/null +++ b/changelogs/unreleased/populate-timelogs-project_id.yml @@ -0,0 +1,5 @@ +--- +title: Populate timelogs.project_id +merge_request: 60439 +author: Lee Tickett @leetickett +type: added diff --git a/db/migrate/20210428151144_update_invalid_web_hooks.rb b/db/migrate/20210428151144_update_invalid_web_hooks.rb new file mode 100644 index 00000000000..4f45e7aaa9b --- /dev/null +++ b/db/migrate/20210428151144_update_invalid_web_hooks.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +class UpdateInvalidWebHooks < ActiveRecord::Migration[6.0] + disable_ddl_transaction! + + class WebHook < ActiveRecord::Base + include EachBatch + + self.table_name = 'web_hooks' + end + + def up + WebHook.each_batch(of: 10_000, column: :id) do |relation| + relation.where(type: 'ProjectHook') + .where.not(project_id: nil) + .where.not(group_id: nil) + .update_all(group_id: nil) + end + end + + def down + # no-op + end +end diff --git a/db/migrate/20210428151238_validate_foreign_key_on_group_hooks.rb b/db/migrate/20210428151238_validate_foreign_key_on_group_hooks.rb new file mode 100644 index 00000000000..e7020665b25 --- /dev/null +++ b/db/migrate/20210428151238_validate_foreign_key_on_group_hooks.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class ValidateForeignKeyOnGroupHooks < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + CONSTRAINT_NAME = 'fk_rails_d35697648e' + + def up + validate_foreign_key :web_hooks, :group_id, name: CONSTRAINT_NAME + end + + def down + # no-op + end +end diff --git a/db/migrate/20210429131525_create_user_credit_card_validations.rb b/db/migrate/20210429131525_create_user_credit_card_validations.rb new file mode 100644 index 00000000000..8548274b29a --- /dev/null +++ b/db/migrate/20210429131525_create_user_credit_card_validations.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +class CreateUserCreditCardValidations < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + disable_ddl_transaction! + + def up + with_lock_retries do + create_table :user_credit_card_validations, id: false do |t| + t.references :user, foreign_key: { on_delete: :cascade }, index: false, primary_key: true, default: nil + t.datetime_with_timezone :credit_card_validated_at, null: false + end + end + end + + def down + with_lock_retries do + drop_table :user_credit_card_validations + end + end +end diff --git a/db/post_migrate/20210427212034_schedule_update_timelogs_project_id.rb b/db/post_migrate/20210427212034_schedule_update_timelogs_project_id.rb new file mode 100644 index 00000000000..13b802f7cb4 --- /dev/null +++ b/db/post_migrate/20210427212034_schedule_update_timelogs_project_id.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +class ScheduleUpdateTimelogsProjectId < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + BATCH_SIZE = 50_000 + DELAY_INTERVAL = 2.minutes + MIGRATION = 'UpdateTimelogsProjectId' + + disable_ddl_transaction! + + class Timelog < ActiveRecord::Base + include EachBatch + + self.table_name = 'timelogs' + self.inheritance_column = :_type_disabled + end + + def up + queue_background_migration_jobs_by_range_at_intervals( + Timelog.all, + MIGRATION, + DELAY_INTERVAL, + batch_size: BATCH_SIZE + ) + end + + def down + # no-op + end +end diff --git a/db/schema_migrations/20210427212034 b/db/schema_migrations/20210427212034 new file mode 100644 index 00000000000..4954b5722a9 --- /dev/null +++ b/db/schema_migrations/20210427212034 @@ -0,0 +1 @@ +2ffe65c4abcb8f638198943e1b74de710387438fb7c93addb05ccb3e86729934
\ No newline at end of file diff --git a/db/schema_migrations/20210428151144 b/db/schema_migrations/20210428151144 new file mode 100644 index 00000000000..53771dd9401 --- /dev/null +++ b/db/schema_migrations/20210428151144 @@ -0,0 +1 @@ +468373a97f7bd66197c81f01bebd27256cf96ec8fc226c5d73e579a7ecc3930d
\ No newline at end of file diff --git a/db/schema_migrations/20210428151238 b/db/schema_migrations/20210428151238 new file mode 100644 index 00000000000..3fa6ecefc42 --- /dev/null +++ b/db/schema_migrations/20210428151238 @@ -0,0 +1 @@ +3244023441c2afa450ad76345a494975b4a7154892298daf1ec4223d27fb7ca3
\ No newline at end of file diff --git a/db/schema_migrations/20210429131525 b/db/schema_migrations/20210429131525 new file mode 100644 index 00000000000..4ab6b84eea9 --- /dev/null +++ b/db/schema_migrations/20210429131525 @@ -0,0 +1 @@ +68ac54fa7b4e4ef99e58c31d8f960b6f986fd679c11ead235704c7a75b4617ac
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index b237a7f526c..fce0a085dac 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -18282,6 +18282,11 @@ CREATE SEQUENCE user_canonical_emails_id_seq ALTER SEQUENCE user_canonical_emails_id_seq OWNED BY user_canonical_emails.id; +CREATE TABLE user_credit_card_validations ( + user_id bigint NOT NULL, + credit_card_validated_at timestamp with time zone NOT NULL +); + CREATE TABLE user_custom_attributes ( id integer NOT NULL, created_at timestamp without time zone NOT NULL, @@ -21655,6 +21660,9 @@ ALTER TABLE ONLY user_callouts ALTER TABLE ONLY user_canonical_emails ADD CONSTRAINT user_canonical_emails_pkey PRIMARY KEY (id); +ALTER TABLE ONLY user_credit_card_validations + ADD CONSTRAINT user_credit_card_validations_pkey PRIMARY KEY (user_id); + ALTER TABLE ONLY user_custom_attributes ADD CONSTRAINT user_custom_attributes_pkey PRIMARY KEY (id); @@ -25941,6 +25949,9 @@ ALTER TABLE ONLY lfs_file_locks ALTER TABLE ONLY project_alerting_settings ADD CONSTRAINT fk_rails_27a84b407d FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; +ALTER TABLE ONLY user_credit_card_validations + ADD CONSTRAINT fk_rails_27ebc03cbf FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + ALTER TABLE ONLY dast_site_validations ADD CONSTRAINT fk_rails_285c617324 FOREIGN KEY (dast_site_token_id) REFERENCES dast_site_tokens(id) ON DELETE CASCADE; @@ -26923,7 +26934,7 @@ ALTER TABLE ONLY pool_repositories ADD CONSTRAINT fk_rails_d2711daad4 FOREIGN KEY (source_project_id) REFERENCES projects(id) ON DELETE SET NULL; ALTER TABLE ONLY web_hooks - ADD CONSTRAINT fk_rails_d35697648e FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE NOT VALID; + ADD CONSTRAINT fk_rails_d35697648e FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE; ALTER TABLE ONLY group_group_links ADD CONSTRAINT fk_rails_d3a0488427 FOREIGN KEY (shared_group_id) REFERENCES namespaces(id) ON DELETE CASCADE; diff --git a/doc/development/usage_ping/index.md b/doc/development/usage_ping/index.md index 0e12c620a8a..e79cd127d5a 100644 --- a/doc/development/usage_ping/index.md +++ b/doc/development/usage_ping/index.md @@ -635,11 +635,12 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PF - `category`: event category. Used for getting total counts for events in a category, for easier access to a group of events. - - `redis_slot`: optional Redis slot; default value: event name. Used if needed to calculate totals - for a group of metrics. Ensure keys are in the same slot. For example: + - `redis_slot`: optional Redis slot. Default value: event name. Only event data that is stored in the same slot + can be aggregated. Ensure keys are in the same slot. For example: `users_creating_epics` with `redis_slot: 'users'` builds Redis key `{users}_creating_epics-2020-34`. If `redis_slot` is not defined the Redis key will be `{users_creating_epics}-2020-34`. + Recommended slots to use are: `users`, `projects`. This is the value we count. - `expiry`: expiry time in days. Default: 29 days for daily aggregation and 6 weeks for weekly aggregation. - `aggregation`: may be set to a `:daily` or `:weekly` key. Defines how counting data is stored in Redis. diff --git a/lib/gitlab/background_migration/update_timelogs_project_id.rb b/lib/gitlab/background_migration/update_timelogs_project_id.rb new file mode 100644 index 00000000000..24c9967b88e --- /dev/null +++ b/lib/gitlab/background_migration/update_timelogs_project_id.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # Class to populate project_id for timelogs + class UpdateTimelogsProjectId + BATCH_SIZE = 1000 + + def perform(start_id, stop_id) + (start_id..stop_id).step(BATCH_SIZE).each do |offset| + update_issue_timelogs(offset, offset + BATCH_SIZE) + update_merge_request_timelogs(offset, offset + BATCH_SIZE) + end + end + + def update_issue_timelogs(batch_start, batch_stop) + execute(<<~SQL) + UPDATE timelogs + SET project_id = issues.project_id + FROM issues + WHERE issues.id = timelogs.issue_id + AND timelogs.id BETWEEN #{batch_start} AND #{batch_stop} + AND timelogs.project_id IS NULL; + SQL + end + + def update_merge_request_timelogs(batch_start, batch_stop) + execute(<<~SQL) + UPDATE timelogs + SET project_id = merge_requests.target_project_id + FROM merge_requests + WHERE merge_requests.id = timelogs.merge_request_id + AND timelogs.id BETWEEN #{batch_start} AND #{batch_stop} + AND timelogs.project_id IS NULL; + SQL + end + + def execute(sql) + @connection ||= ::ActiveRecord::Base.connection + @connection.execute(sql) + end + end + end +end diff --git a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml index 3ebccfbba4a..b6f98d5034e 100644 --- a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml @@ -292,7 +292,7 @@ semgrep-sast: # SAST_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to # override the analyzer image with a custom value. This may be subject to change or # breakage across GitLab releases. - SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/semgrep:latest" + SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/semgrep:$SAST_ANALYZER_IMAGE_TAG" rules: - if: $SAST_DISABLED when: never diff --git a/lib/security/ci_configuration/sast_build_action.rb b/lib/security/ci_configuration/sast_build_action.rb index c319fc1637d..d670d5054ae 100644 --- a/lib/security/ci_configuration/sast_build_action.rb +++ b/lib/security/ci_configuration/sast_build_action.rb @@ -3,7 +3,7 @@ module Security module CiConfiguration class SastBuildAction < BaseBuildAction - SAST_DEFAULT_ANALYZERS = 'bandit, brakeman, eslint, flawfinder, gosec, kubesec, nodejs-scan, phpcs-security-audit, pmd-apex, security-code-scan, sobelow, spotbugs' + SAST_DEFAULT_ANALYZERS = 'bandit, brakeman, eslint, flawfinder, gosec, kubesec, nodejs-scan, phpcs-security-audit, pmd-apex, security-code-scan, semgrep, sobelow, spotbugs' def initialize(auto_devops_enabled, params, existing_gitlab_ci_content) super(auto_devops_enabled, existing_gitlab_ci_content) diff --git a/spec/factories/ci/job_artifacts.rb b/spec/factories/ci/job_artifacts.rb index b1adbcd283b..17cd495e217 100644 --- a/spec/factories/ci/job_artifacts.rb +++ b/spec/factories/ci/job_artifacts.rb @@ -277,6 +277,16 @@ FactoryBot.define do end end + trait :sast_minimal do + file_type { :sast } + file_format { :raw } + + after(:build) do |artifact, _| + artifact.file = fixture_file_upload( + Rails.root.join('spec/fixtures/security_reports/master/gl-sast-report-minimal.json'), 'application/json') + end + end + trait :secret_detection do file_type { :secret_detection } file_format { :raw } diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 9b5e4a981a0..7ac44d55687 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -80,6 +80,12 @@ FactoryBot.define do last_sign_in_ip { '127.0.0.1' } end + trait :with_credit_card_validation do + after :create do |user| + create :credit_card_validation, user: user + end + end + trait :two_factor_via_otp do before(:create) do |user| user.otp_required_for_login = true diff --git a/spec/factories/users/credit_card_validations.rb b/spec/factories/users/credit_card_validations.rb new file mode 100644 index 00000000000..09940347708 --- /dev/null +++ b/spec/factories/users/credit_card_validations.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :credit_card_validation, class: 'Users::CreditCardValidation' do + user + + credit_card_validated_at { Time.current } + end +end diff --git a/spec/fixtures/security_reports/master/gl-sast-report-minimal.json b/spec/fixtures/security_reports/master/gl-sast-report-minimal.json new file mode 100644 index 00000000000..60a67453c9b --- /dev/null +++ b/spec/fixtures/security_reports/master/gl-sast-report-minimal.json @@ -0,0 +1,68 @@ +{ + "version": "14.0.0", + "vulnerabilities": [ + { + "category": "sast", + "name": "Cipher with no integrity", + "message": "Cipher with no integrity", + "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:CIPHER_INTEGRITY", + "severity": "Medium", + "confidence": "High", + "scanner": { + "id": "find_sec_bugs", + "name": "Find Security Bugs" + }, + "location": { + "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy", + "start_line": 29, + "end_line": 29, + "class": "com.gitlab.security_products.tests.App", + "method": "insecureCypher" + }, + "identifiers": [ + { + "type": "find_sec_bugs_type", + "name": "Find Security Bugs-CIPHER_INTEGRITY", + "value": "CIPHER_INTEGRITY", + "url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY" + } + ], + "tracking": { + "type": "source", + "items": [ + { + "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy", + "start_line": 29, + "end_line": 29, + "signatures": [ + { + "algorithm": "hash", + "value": "HASHVALUE" + }, + { + "algorithm": "scope_offset", + "value": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:App[0]:insecureCypher[0]:2" + } + ] + } + ] + } + } + ], + "remediations": [], + "scan": { + "scanner": { + "id": "find_sec_bugs", + "name": "Find Security Bugs", + "url": "https://spotbugs.github.io", + "vendor": { + "name": "GitLab" + }, + "version": "4.0.2" + }, + "type": "sast", + "status": "success", + "start_time": "placeholder-value", + "end_time": "placeholder-value" + } +} diff --git a/spec/fixtures/security_reports/master/gl-sast-report.json b/spec/fixtures/security_reports/master/gl-sast-report.json index 9da9fdc3832..3323c1fffe3 100644 --- a/spec/fixtures/security_reports/master/gl-sast-report.json +++ b/spec/fixtures/security_reports/master/gl-sast-report.json @@ -154,8 +154,8 @@ "items": [ { "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy", - "start_line": 47, - "end_line": 47, + "start_line": 29, + "end_line": 29, "signatures": [ { "algorithm": "hash", diff --git a/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js b/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js index d32e582e498..2832de98769 100644 --- a/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js +++ b/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js @@ -40,7 +40,7 @@ describe('AddContextCommitsModal', () => { store, propsData: { contextCommitsPath: '', - targetBranch: 'master', + targetBranch: 'main', mergeRequestIid: 1, projectId: 1, ...props, diff --git a/spec/frontend/api_spec.js b/spec/frontend/api_spec.js index cb29dab86bf..139128e6d4a 100644 --- a/spec/frontend/api_spec.js +++ b/spec/frontend/api_spec.js @@ -930,7 +930,7 @@ describe('Api', () => { describe('createBranch', () => { it('creates new branch', (done) => { - const ref = 'master'; + const ref = 'main'; const branch = 'new-branch-name'; const dummyProjectPath = 'gitlab-org/gitlab-ce'; const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${encodeURIComponent( @@ -1262,7 +1262,7 @@ describe('Api', () => { )}/merge_requests`; const options = { source_branch: 'feature', - target_branch: 'master', + target_branch: 'main', title: 'Add feature', }; diff --git a/spec/frontend/code_navigation/components/app_spec.js b/spec/frontend/code_navigation/components/app_spec.js index ea389fa35c0..798f3bc0ee2 100644 --- a/spec/frontend/code_navigation/components/app_spec.js +++ b/spec/frontend/code_navigation/components/app_spec.js @@ -16,7 +16,7 @@ function factory(initialState = {}) { state: { ...createState(), ...initialState, - definitionPathPrefix: 'https://test.com/blob/master', + definitionPathPrefix: 'https://test.com/blob/main', }, actions: { fetchData, diff --git a/spec/frontend/code_navigation/store/mutations_spec.js b/spec/frontend/code_navigation/store/mutations_spec.js index d4a75da429e..cb10729f4b6 100644 --- a/spec/frontend/code_navigation/store/mutations_spec.js +++ b/spec/frontend/code_navigation/store/mutations_spec.js @@ -12,11 +12,11 @@ describe('Code navigation mutations', () => { it('sets initial data', () => { mutations.SET_INITIAL_DATA(state, { blobs: ['test'], - definitionPathPrefix: 'https://test.com/blob/master', + definitionPathPrefix: 'https://test.com/blob/main', }); expect(state.blobs).toEqual(['test']); - expect(state.definitionPathPrefix).toBe('https://test.com/blob/master'); + expect(state.definitionPathPrefix).toBe('https://test.com/blob/main'); }); }); diff --git a/spec/frontend/commits_spec.js b/spec/frontend/commits_spec.js index 954025091cf..8189ebe6e55 100644 --- a/spec/frontend/commits_spec.js +++ b/spec/frontend/commits_spec.js @@ -10,7 +10,7 @@ describe('Commits List', () => { beforeEach(() => { setFixtures(` - <form class="commits-search-form" action="/h5bp/html5-boilerplate/commits/master"> + <form class="commits-search-form" action="/h5bp/html5-boilerplate/commits/main"> <input id="commits-search"> </form> <ol id="commits-list"></ol> @@ -59,7 +59,7 @@ describe('Commits List', () => { jest.spyOn(window.history, 'replaceState').mockImplementation(() => {}); mock = new MockAdapter(axios); - mock.onGet('/h5bp/html5-boilerplate/commits/master').reply(200, { + mock.onGet('/h5bp/html5-boilerplate/commits/main').reply(200, { html: '<li>Result</li>', }); diff --git a/spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap b/spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap index 15b052fffbb..3f812d3cf4e 100644 --- a/spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap +++ b/spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap @@ -8,7 +8,7 @@ exports[`Contributors charts should render charts when loading completed and the <h4 class="gl-mb-2 gl-mt-5" > - Commits to master + Commits to main </h4> <span> diff --git a/spec/frontend/contributors/component/contributors_spec.js b/spec/frontend/contributors/component/contributors_spec.js index de55be4aa72..cb7e13b9fed 100644 --- a/spec/frontend/contributors/component/contributors_spec.js +++ b/spec/frontend/contributors/component/contributors_spec.js @@ -10,7 +10,7 @@ let mock; let store; const Component = Vue.extend(ContributorsCharts); const endpoint = 'contributors'; -const branch = 'master'; +const branch = 'main'; const chartData = [ { author_name: 'John', author_email: 'jawnnypoo@gmail.com', date: '2019-05-05' }, { author_name: 'John', author_email: 'jawnnypoo@gmail.com', date: '2019-03-03' }, diff --git a/spec/frontend/diffs/mock_data/diff_metadata.js b/spec/frontend/diffs/mock_data/diff_metadata.js index cfa0038c06f..ce79843b8b1 100644 --- a/spec/frontend/diffs/mock_data/diff_metadata.js +++ b/spec/frontend/diffs/mock_data/diff_metadata.js @@ -3,7 +3,7 @@ export const diffMetadata = { size: 1, branch_name: 'update-changelog', source_branch_exists: true, - target_branch_name: 'master', + target_branch_name: 'main', commit: null, context_commits: null, merge_request_diff: { diff --git a/spec/frontend/notes/old_notes_spec.js b/spec/frontend/notes/old_notes_spec.js index 432b660c4b3..0cf43b8fd97 100644 --- a/spec/frontend/notes/old_notes_spec.js +++ b/spec/frontend/notes/old_notes_spec.js @@ -28,7 +28,7 @@ window.gl = window.gl || {}; gl.utils = gl.utils || {}; gl.utils.disableButtonIfEmptyField = () => {}; -// the following test is unreliable and failing in master 2-3 times a day +// the following test is unreliable and failing in main 2-3 times a day // see https://gitlab.com/gitlab-org/gitlab/issues/206906#note_290602581 // eslint-disable-next-line jest/no-disabled-tests describe.skip('Old Notes (~/notes.js)', () => { diff --git a/spec/frontend/ref/stores/mutations_spec.js b/spec/frontend/ref/stores/mutations_spec.js index 11d4fe0e206..de1d5c557ce 100644 --- a/spec/frontend/ref/stores/mutations_spec.js +++ b/spec/frontend/ref/stores/mutations_spec.js @@ -108,7 +108,7 @@ describe('Ref selector Vuex store mutations', () => { const response = { data: [ { - name: 'master', + name: 'main', default: true, // everything except "name" and "default" should be stripped @@ -130,7 +130,7 @@ describe('Ref selector Vuex store mutations', () => { expect(state.matches.branches).toEqual({ list: [ { - name: 'master', + name: 'main', default: true, }, { diff --git a/spec/frontend/reports/grouped_test_report/grouped_test_reports_app_spec.js b/spec/frontend/reports/grouped_test_report/grouped_test_reports_app_spec.js index 55bb7dbe5c0..d29048d640c 100644 --- a/spec/frontend/reports/grouped_test_report/grouped_test_reports_app_spec.js +++ b/spec/frontend/reports/grouped_test_report/grouped_test_reports_app_spec.js @@ -279,9 +279,7 @@ describe('Grouped test reports app', () => { }); it('renders the recent failures count on the test case', () => { - expect(findIssueRecentFailures().text()).toBe( - 'Failed 8 times in master in the last 14 days', - ); + expect(findIssueRecentFailures().text()).toBe('Failed 8 times in main in the last 14 days'); }); }); diff --git a/spec/frontend/reports/grouped_test_report/store/mutations_spec.js b/spec/frontend/reports/grouped_test_report/store/mutations_spec.js index d8642a9b440..b2890d7285f 100644 --- a/spec/frontend/reports/grouped_test_report/store/mutations_spec.js +++ b/spec/frontend/reports/grouped_test_report/store/mutations_spec.js @@ -52,7 +52,7 @@ describe('Reports Store Mutations', () => { system_output: "Failure/Error: is_expected.to eq('gitlab')", recent_failures: { count: 4, - base_branch: 'master', + base_branch: 'main', }, }, ], diff --git a/spec/frontend/reports/mock_data/mock_data.js b/spec/frontend/reports/mock_data/mock_data.js index 68c7439df47..2599b0ac365 100644 --- a/spec/frontend/reports/mock_data/mock_data.js +++ b/spec/frontend/reports/mock_data/mock_data.js @@ -7,7 +7,7 @@ export const failedIssue = { "Failure/Error: is_expected.to eq(3)\n\n expected: 3\n got: -1\n\n (compared using ==)\n./spec/test_spec.rb:12:in `block (4 levels) in \u003ctop (required)\u003e'", recent_failures: { count: 3, - base_branch: 'master', + base_branch: 'main', }, }; diff --git a/spec/frontend/reports/mock_data/recent_failures_report.json b/spec/frontend/reports/mock_data/recent_failures_report.json index bc86d788ee2..c4a5fb78dcd 100644 --- a/spec/frontend/reports/mock_data/recent_failures_report.json +++ b/spec/frontend/reports/mock_data/recent_failures_report.json @@ -12,7 +12,7 @@ "system_output": "Failure/Error: is_expected.to eq(3)\n\n expected: 3\n got: -1\n\n (compared using ==)\n./spec/test_spec.rb:12:in `block (4 levels) in <top (required)>'", "recent_failures": { "count": 8, - "base_branch": "master" + "base_branch": "main" } }, { @@ -38,7 +38,7 @@ "execution_time": 0.000562, "recent_failures": { "count": 3, - "base_branch": "master" + "base_branch": "main" } } ], diff --git a/spec/helpers/learn_gitlab_helper_spec.rb b/spec/helpers/learn_gitlab_helper_spec.rb index 5bbe32166ab..780bb0a1408 100644 --- a/spec/helpers/learn_gitlab_helper_spec.rb +++ b/spec/helpers/learn_gitlab_helper_spec.rb @@ -85,10 +85,14 @@ RSpec.describe LearnGitlabHelper do it { is_expected.to eq(result) } end + end - context 'when not signed in' do - it { is_expected.to eq(false) } + context 'when not signed in' do + before do + stub_experiment_for_subject(learn_gitlab_a: true, learn_gitlab_b: true) end + + it { is_expected.to eq(false) } end end @@ -118,10 +122,14 @@ RSpec.describe LearnGitlabHelper do it { is_expected.to eq(result) } end + end - context 'when not signed in' do - it { is_expected.to eq(nil) } + context 'when not signed in' do + before do + stub_experiment_for_subject(learn_gitlab_a: true, learn_gitlab_b: true) end + + it { is_expected.to eq(nil) } end end end diff --git a/spec/lib/gitlab/background_migration/update_timelogs_project_id_spec.rb b/spec/lib/gitlab/background_migration/update_timelogs_project_id_spec.rb new file mode 100644 index 00000000000..fc4d776b8be --- /dev/null +++ b/spec/lib/gitlab/background_migration/update_timelogs_project_id_spec.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::UpdateTimelogsProjectId, schema: 20210427212034 do + let!(:namespace) { table(:namespaces).create!(name: 'namespace', path: 'namespace') } + let!(:project1) { table(:projects).create!(namespace_id: namespace.id) } + let!(:project2) { table(:projects).create!(namespace_id: namespace.id) } + let!(:issue1) { table(:issues).create!(project_id: project1.id) } + let!(:issue2) { table(:issues).create!(project_id: project2.id) } + let!(:merge_request1) { table(:merge_requests).create!(target_project_id: project1.id, source_branch: 'master', target_branch: 'feature') } + let!(:merge_request2) { table(:merge_requests).create!(target_project_id: project2.id, source_branch: 'master', target_branch: 'feature') } + let!(:timelog1) { table(:timelogs).create!(issue_id: issue1.id, time_spent: 60) } + let!(:timelog2) { table(:timelogs).create!(issue_id: issue1.id, time_spent: 60) } + let!(:timelog3) { table(:timelogs).create!(issue_id: issue2.id, time_spent: 60) } + let!(:timelog4) { table(:timelogs).create!(merge_request_id: merge_request1.id, time_spent: 600) } + let!(:timelog5) { table(:timelogs).create!(merge_request_id: merge_request1.id, time_spent: 600) } + let!(:timelog6) { table(:timelogs).create!(merge_request_id: merge_request2.id, time_spent: 600) } + let!(:timelog7) { table(:timelogs).create!(issue_id: issue2.id, time_spent: 60, project_id: project1.id) } + let!(:timelog8) { table(:timelogs).create!(merge_request_id: merge_request2.id, time_spent: 600, project_id: project1.id) } + + describe '#perform' do + context 'when timelogs belong to issues' do + it 'sets correct project_id' do + subject.perform(timelog1.id, timelog3.id) + + expect(timelog1.reload.project_id).to eq(issue1.project_id) + expect(timelog2.reload.project_id).to eq(issue1.project_id) + expect(timelog3.reload.project_id).to eq(issue2.project_id) + end + end + + context 'when timelogs belong to merge requests' do + it 'sets correct project ids' do + subject.perform(timelog4.id, timelog6.id) + + expect(timelog4.reload.project_id).to eq(merge_request1.target_project_id) + expect(timelog5.reload.project_id).to eq(merge_request1.target_project_id) + expect(timelog6.reload.project_id).to eq(merge_request2.target_project_id) + end + end + + context 'when timelogs already belong to projects' do + it 'does not update the project id' do + subject.perform(timelog7.id, timelog8.id) + + expect(timelog7.reload.project_id).to eq(project1.id) + expect(timelog8.reload.project_id).to eq(project1.id) + end + end + end +end diff --git a/spec/migrations/schedule_update_timelogs_project_id_spec.rb b/spec/migrations/schedule_update_timelogs_project_id_spec.rb new file mode 100644 index 00000000000..e2972d2fd08 --- /dev/null +++ b/spec/migrations/schedule_update_timelogs_project_id_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'spec_helper' +require Rails.root.join('db', 'post_migrate', '20210427212034_schedule_update_timelogs_project_id.rb') + +RSpec.describe ScheduleUpdateTimelogsProjectId do + let!(:namespace) { table(:namespaces).create!(name: 'namespace', path: 'namespace') } + let!(:project) { table(:projects).create!(namespace_id: namespace.id) } + let!(:issue) { table(:issues).create!(project_id: project.id) } + let!(:merge_request) { table(:merge_requests).create!(target_project_id: project.id, source_branch: 'master', target_branch: 'feature') } + let!(:timelog1) { table(:timelogs).create!(issue_id: issue.id, time_spent: 60) } + let!(:timelog2) { table(:timelogs).create!(merge_request_id: merge_request.id, time_spent: 600) } + let!(:timelog3) { table(:timelogs).create!(merge_request_id: merge_request.id, time_spent: 60) } + let!(:timelog4) { table(:timelogs).create!(issue_id: issue.id, time_spent: 600) } + + it 'correctly schedules background migrations' do + stub_const("#{described_class}::BATCH_SIZE", 2) + + Sidekiq::Testing.fake! do + freeze_time do + migrate! + + expect(described_class::MIGRATION) + .to be_scheduled_delayed_migration(2.minutes, timelog1.id, timelog2.id) + + expect(described_class::MIGRATION) + .to be_scheduled_delayed_migration(4.minutes, timelog3.id, timelog4.id) + + expect(BackgroundMigrationWorker.jobs.size).to eq(2) + end + end + end +end diff --git a/spec/migrations/update_invalid_web_hooks_spec.rb b/spec/migrations/update_invalid_web_hooks_spec.rb new file mode 100644 index 00000000000..a65f82d7082 --- /dev/null +++ b/spec/migrations/update_invalid_web_hooks_spec.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'spec_helper' + +require_migration! + +RSpec.describe UpdateInvalidWebHooks do + let(:web_hooks) { table(:web_hooks) } + let(:groups) { table(:namespaces) } + let(:projects) { table(:projects) } + + before do + group = groups.create!(name: 'gitlab', path: 'gitlab-org') + project = projects.create!(namespace_id: group.id) + + web_hooks.create!(group_id: group.id, type: 'GroupHook') + web_hooks.create!(project_id: project.id, type: 'ProjectHook') + web_hooks.create!(group_id: group.id, project_id: project.id, type: 'ProjectHook') + end + + it 'clears group_id when ProjectHook type and project_id are present', :aggregate_failures do + expect(web_hooks.where.not(group_id: nil).where.not(project_id: nil).count).to eq(1) + + migrate! + + expect(web_hooks.where.not(group_id: nil).where.not(project_id: nil).count).to eq(0) + expect(web_hooks.where(type: 'GroupHook').count).to eq(1) + expect(web_hooks.where(type: 'ProjectHook').count).to eq(2) + end +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 07031f16410..0c35b1265ba 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -83,6 +83,7 @@ RSpec.describe User do it { is_expected.to have_one(:user_detail) } it { is_expected.to have_one(:atlassian_identity) } it { is_expected.to have_one(:user_highest_role) } + it { is_expected.to have_one(:credit_card_validation) } it { is_expected.to have_many(:snippets).dependent(:destroy) } it { is_expected.to have_many(:members) } it { is_expected.to have_many(:project_members) } @@ -1387,6 +1388,26 @@ RSpec.describe User do end end + describe '#credit_card_validated_at' do + let_it_be(:user) { create(:user) } + + context 'when credit_card_validation does not exist' do + it 'returns nil' do + expect(user.credit_card_validated_at).to be nil + end + end + + context 'when credit_card_validation exists' do + it 'returns the credit card validated time' do + credit_card_validated_time = Time.current - 1.day + + create(:credit_card_validation, credit_card_validated_at: credit_card_validated_time, user: user) + + expect(user.credit_card_validated_at).to eq(credit_card_validated_time) + end + end + end + describe '#update_tracked_fields!', :clean_gitlab_redis_shared_state do let(:request) { OpenStruct.new(remote_ip: "127.0.0.1") } let(:user) { create(:user) } @@ -5290,6 +5311,26 @@ RSpec.describe User do end end + describe 'user credit card validation' do + context 'when user is initialized' do + let(:user) { build(:user) } + + it { expect(user.credit_card_validation).not_to be_present } + end + + context 'when create user without credit card validation' do + let(:user) { create(:user) } + + it { expect(user.credit_card_validation).not_to be_present } + end + + context 'when user credit card validation exists' do + let(:user) { create(:user, :with_credit_card_validation) } + + it { expect(user.credit_card_validation).to be_persisted } + end + end + describe 'user detail' do context 'when user is initialized' do let(:user) { build(:user) } diff --git a/spec/models/users/credit_card_validation_spec.rb b/spec/models/users/credit_card_validation_spec.rb new file mode 100644 index 00000000000..fb9f6e35038 --- /dev/null +++ b/spec/models/users/credit_card_validation_spec.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Users::CreditCardValidation do + it { is_expected.to belong_to(:user) } +end |