Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
4f49d2c8cd
commit
415153114a
49 changed files with 491 additions and 35 deletions
|
@ -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]
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)),
|
||||
|
|
9
app/models/users/credit_card_validation.rb
Normal file
9
app/models/users/credit_card_validation.rb
Normal file
|
@ -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
|
|
@ -160,6 +160,13 @@
|
|||
"description": ".NET Core, .NET Framework",
|
||||
"variables": []
|
||||
},
|
||||
{
|
||||
"name": "semgrep",
|
||||
"label": "Semgrep",
|
||||
"enabled": true,
|
||||
"description": "Multi-language scanning",
|
||||
"variables": []
|
||||
},
|
||||
{
|
||||
"name": "sobelow",
|
||||
"label": "Sobelow",
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Validate foreign key on GroupHooks
|
||||
merge_request: 60527
|
||||
author:
|
||||
type: other
|
5
changelogs/unreleased/328066-semgrep-config-ui.yml
Normal file
5
changelogs/unreleased/328066-semgrep-config-ui.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add semgrep to SAST config UI
|
||||
merge_request: 60460
|
||||
author:
|
||||
type: added
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Create table user_credit_card_validations
|
||||
merge_request: 60626
|
||||
author:
|
||||
type: changed
|
5
changelogs/unreleased/populate-timelogs-project_id.yml
Normal file
5
changelogs/unreleased/populate-timelogs-project_id.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Populate timelogs.project_id
|
||||
merge_request: 60439
|
||||
author: Lee Tickett @leetickett
|
||||
type: added
|
24
db/migrate/20210428151144_update_invalid_web_hooks.rb
Normal file
24
db/migrate/20210428151144_update_invalid_web_hooks.rb
Normal file
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
1
db/schema_migrations/20210427212034
Normal file
1
db/schema_migrations/20210427212034
Normal file
|
@ -0,0 +1 @@
|
|||
2ffe65c4abcb8f638198943e1b74de710387438fb7c93addb05ccb3e86729934
|
1
db/schema_migrations/20210428151144
Normal file
1
db/schema_migrations/20210428151144
Normal file
|
@ -0,0 +1 @@
|
|||
468373a97f7bd66197c81f01bebd27256cf96ec8fc226c5d73e579a7ecc3930d
|
1
db/schema_migrations/20210428151238
Normal file
1
db/schema_migrations/20210428151238
Normal file
|
@ -0,0 +1 @@
|
|||
3244023441c2afa450ad76345a494975b4a7154892298daf1ec4223d27fb7ca3
|
1
db/schema_migrations/20210429131525
Normal file
1
db/schema_migrations/20210429131525
Normal file
|
@ -0,0 +1 @@
|
|||
68ac54fa7b4e4ef99e58c31d8f960b6f986fd679c11ead235704c7a75b4617ac
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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
|
||||
|
|
9
spec/factories/users/credit_card_validations.rb
Normal file
9
spec/factories/users/credit_card_validations.rb
Normal file
|
@ -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
|
68
spec/fixtures/security_reports/master/gl-sast-report-minimal.json
vendored
Normal file
68
spec/fixtures/security_reports/master/gl-sast-report-minimal.json
vendored
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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",
|
||||
|
|
|
@ -40,7 +40,7 @@ describe('AddContextCommitsModal', () => {
|
|||
store,
|
||||
propsData: {
|
||||
contextCommitsPath: '',
|
||||
targetBranch: 'master',
|
||||
targetBranch: 'main',
|
||||
mergeRequestIid: 1,
|
||||
projectId: 1,
|
||||
...props,
|
||||
|
|
|
@ -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',
|
||||
};
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ function factory(initialState = {}) {
|
|||
state: {
|
||||
...createState(),
|
||||
...initialState,
|
||||
definitionPathPrefix: 'https://test.com/blob/master',
|
||||
definitionPathPrefix: 'https://test.com/blob/main',
|
||||
},
|
||||
actions: {
|
||||
fetchData,
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -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>',
|
||||
});
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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' },
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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)', () => {
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
{
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
|
|
@ -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',
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
33
spec/migrations/schedule_update_timelogs_project_id_spec.rb
Normal file
33
spec/migrations/schedule_update_timelogs_project_id_spec.rb
Normal file
|
@ -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
|
30
spec/migrations/update_invalid_web_hooks_spec.rb
Normal file
30
spec/migrations/update_invalid_web_hooks_spec.rb
Normal file
|
@ -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
|
|
@ -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) }
|
||||
|
|
7
spec/models/users/credit_card_validation_spec.rb
Normal file
7
spec/models/users/credit_card_validation_spec.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Users::CreditCardValidation do
|
||||
it { is_expected.to belong_to(:user) }
|
||||
end
|
Loading…
Reference in a new issue