Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-08-16 21:11:02 +00:00
parent e684f438e6
commit 587b778d3e
21 changed files with 251 additions and 38 deletions

View file

@ -16,6 +16,7 @@ export const i18n = {
downloadArtifact: __('Download %{name} artifact'),
artifactSectionHeader: __('Download artifacts'),
artifactsFetchErrorMessage: s__('Pipelines|Could not load artifacts.'),
emptyArtifactsMessage: __('No artifacts found'),
};
export default {
@ -99,6 +100,10 @@ export default {
<gl-loading-icon v-if="isLoading" size="sm" />
<gl-dropdown-item v-if="!artifacts.length" data-testid="artifacts-empty-message">
{{ $options.i18n.emptyArtifactsMessage }}
</gl-dropdown-item>
<gl-dropdown-item
v-for="(artifact, i) in artifacts"
:key="i"

View file

@ -87,22 +87,21 @@ export default {
@click="handleRetryClick"
/>
<gl-button
v-if="pipeline.flags.cancelable"
v-gl-tooltip.hover
v-gl-modal-directive="'confirmation-modal'"
:aria-label="$options.i18n.cancelTitle"
:title="$options.i18n.cancelTitle"
:loading="isCancelling"
:disabled="isCancelling"
icon="close"
variant="danger"
category="primary"
class="js-pipelines-cancel-button"
@click="handleCancelClick"
/>
<pipeline-multi-actions :pipeline-id="pipeline.id" />
</div>
<gl-button
v-if="pipeline.flags.cancelable"
v-gl-tooltip.hover
v-gl-modal-directive="'confirmation-modal'"
:aria-label="$options.i18n.cancelTitle"
:title="$options.i18n.cancelTitle"
:loading="isCancelling"
:disabled="isCancelling"
icon="cancel"
variant="danger"
category="primary"
class="js-pipelines-cancel-button gl-ml-1"
@click="handleCancelClick"
/>
</div>
</template>

View file

@ -168,7 +168,7 @@ class Member < ApplicationRecord
scope :on_project_and_ancestors, ->(project) { where(source: [project] + project.ancestors) }
before_validation :generate_invite_token, on: :create, if: -> (member) { member.invite_email.present? }
before_validation :generate_invite_token, on: :create, if: -> (member) { member.invite_email.present? && !member.invite_accepted_at? }
after_create :send_invite, if: :invite?, unless: :importing?
after_create :send_request, if: :request?, unless: :importing?

View file

@ -105,7 +105,7 @@
- if can?(current_user, :update_build, job)
- if job.active?
= link_to cancel_project_job_path(job.project, job, continue: { to: request.fullpath }), method: :post, title: _('Cancel'), class: 'gl-button btn btn-default btn-icon' do
= sprite_icon('close', css_class: 'gl-icon')
= sprite_icon('cancel', css_class: 'gl-icon')
- elsif job.scheduled?
.gl-button.btn.btn-default.btn-icon.disabled{ disabled: true }
= sprite_icon('planning', css_class: 'gl-icon')

View file

@ -1,8 +0,0 @@
---
name: vulnerability_finding_tracking_signatures
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54608
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/322044
milestone: '13.11'
type: development
group: group::vulnerability research
default_enabled: false

View file

@ -0,0 +1,18 @@
# frozen_string_literal: true
class CreateZentaoTrackerData < ActiveRecord::Migration[6.1]
def change
create_table :zentao_tracker_data do |t|
t.references :integration, foreign_key: { on_delete: :cascade }, type: :bigint, index: true, null: false
t.timestamps_with_timezone
t.binary :encrypted_url
t.binary :encrypted_url_iv
t.binary :encrypted_api_url
t.binary :encrypted_api_url_iv
t.binary :encrypted_zentao_product_xid
t.binary :encrypted_zentao_product_xid_iv
t.binary :encrypted_api_token
t.binary :encrypted_api_token_iv
end
end
end

View file

@ -0,0 +1,67 @@
# frozen_string_literal: true
class FinalizeCiSourcesPipelinesBigintConversion < ActiveRecord::Migration[6.1]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
TABLE_NAME = 'ci_sources_pipelines'
def up
ensure_batched_background_migration_is_finished(
job_class_name: 'CopyColumnUsingBackgroundMigrationJob',
table_name: TABLE_NAME,
column_name: 'id',
job_arguments: [['source_job_id'], ['source_job_id_convert_to_bigint']]
)
swap
end
def down
swap
end
private
def swap
# This is to replace the existing "index_ci_sources_pipelines_on_source_job_id" btree (source_job_id)
add_concurrent_index TABLE_NAME, :source_job_id_convert_to_bigint, name: 'index_ci_sources_pipelines_on_source_job_id_convert_to_bigint'
# Add a foreign key on `source_job_id_convert_to_bigint` before we swap the columns and drop the old FK (fk_be5624bf37)
add_concurrent_foreign_key TABLE_NAME, :ci_builds,
column: :source_job_id_convert_to_bigint, on_delete: :cascade,
name: 'fk_be5624bf37_tmp', reverse_lock_order: true
with_lock_retries(raise_on_exhaustion: true) do
# We'll need ACCESS EXCLUSIVE lock on the related tables,
# lets make sure it can be acquired from the start
execute "LOCK TABLE ci_builds, #{TABLE_NAME} IN ACCESS EXCLUSIVE MODE"
# Swap column names
temp_name = 'source_job_id_tmp'
execute "ALTER TABLE #{quote_table_name(TABLE_NAME)} RENAME COLUMN #{quote_column_name(:source_job_id)} TO #{quote_column_name(temp_name)}"
execute "ALTER TABLE #{quote_table_name(TABLE_NAME)} RENAME COLUMN #{quote_column_name(:source_job_id_convert_to_bigint)} TO #{quote_column_name(:source_job_id)}"
execute "ALTER TABLE #{quote_table_name(TABLE_NAME)} RENAME COLUMN #{quote_column_name(temp_name)} TO #{quote_column_name(:source_job_id_convert_to_bigint)}"
# We need to update the trigger function in order to make PostgreSQL to
# regenerate the execution plan for it. This is to avoid type mismatch errors like
# "type of parameter 15 (bigint) does not match that when preparing the plan (integer)"
function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME).name(:source_job_id, :source_job_id_convert_to_bigint)
execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
# No need to swap defaults, both columns have no default value
# Rename the index on the `bigint` column to match the new column name
# (we already hold an exclusive lock, so no need to use DROP INDEX CONCURRENTLY here)
execute 'DROP INDEX index_ci_sources_pipelines_on_source_job_id'
rename_index TABLE_NAME, 'index_ci_sources_pipelines_on_source_job_id_convert_to_bigint', 'index_ci_sources_pipelines_on_source_job_id'
# Drop original FK on the old int4 `source_job_id` (fk_be5624bf37)
remove_foreign_key TABLE_NAME, name: 'fk_be5624bf37'
# We swapped the columns but the FK is still using the temporary name
# So we have to also swap the FK name now that we dropped the other one
rename_constraint(TABLE_NAME, 'fk_be5624bf37_tmp', 'fk_be5624bf37')
end
end
end

View file

@ -0,0 +1,28 @@
# frozen_string_literal: true
class OrphanedInviteTokensCleanup < ActiveRecord::Migration[6.1]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
TMP_INDEX_NAME = 'tmp_idx_orphaned_invite_tokens'
QUERY_CONDITION = "invite_token IS NOT NULL and invite_accepted_at IS NOT NULL and invite_accepted_at < created_at"
def up
membership = define_batchable_model('members')
add_concurrent_index('members', :id, where: QUERY_CONDITION, name: TMP_INDEX_NAME)
membership.where(QUERY_CONDITION).pluck(:id).each_slice(10) do |group|
membership.where(id: group).where(QUERY_CONDITION).update_all(invite_token: nil)
end
remove_concurrent_index_by_name('members', TMP_INDEX_NAME)
end
def down
remove_concurrent_index_by_name('members', TMP_INDEX_NAME) if index_exists_by_name?('members', TMP_INDEX_NAME)
# This migration is irreversible
end
end

View file

@ -0,0 +1 @@
95aa786acfbd53f1e819e49c6c6ec703d609396f2cc04a5791d1ffc77800dc72

View file

@ -0,0 +1 @@
f4a1963c8f21b8c767766c3a18037bae223efce8452c87f570cf9789d6f666d6

View file

@ -0,0 +1 @@
4401423fc602a6d5df95857282bb84851fa99ddeb6c3d1ce4614f12c1dc4ec87

View file

@ -11269,9 +11269,9 @@ CREATE TABLE ci_sources_pipelines (
project_id integer,
pipeline_id integer,
source_project_id integer,
source_job_id integer,
source_job_id_convert_to_bigint integer,
source_pipeline_id integer,
source_job_id_convert_to_bigint bigint
source_job_id bigint
);
CREATE SEQUENCE ci_sources_pipelines_id_seq
@ -19948,6 +19948,30 @@ CREATE SEQUENCE x509_issuers_id_seq
ALTER SEQUENCE x509_issuers_id_seq OWNED BY x509_issuers.id;
CREATE TABLE zentao_tracker_data (
id bigint NOT NULL,
integration_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
encrypted_url bytea,
encrypted_url_iv bytea,
encrypted_api_url bytea,
encrypted_api_url_iv bytea,
encrypted_zentao_product_xid bytea,
encrypted_zentao_product_xid_iv bytea,
encrypted_api_token bytea,
encrypted_api_token_iv bytea
);
CREATE SEQUENCE zentao_tracker_data_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE zentao_tracker_data_id_seq OWNED BY zentao_tracker_data.id;
CREATE TABLE zoom_meetings (
id bigint NOT NULL,
project_id bigint NOT NULL,
@ -20885,6 +20909,8 @@ ALTER TABLE ONLY x509_commit_signatures ALTER COLUMN id SET DEFAULT nextval('x50
ALTER TABLE ONLY x509_issuers ALTER COLUMN id SET DEFAULT nextval('x509_issuers_id_seq'::regclass);
ALTER TABLE ONLY zentao_tracker_data ALTER COLUMN id SET DEFAULT nextval('zentao_tracker_data_id_seq'::regclass);
ALTER TABLE ONLY zoom_meetings ALTER COLUMN id SET DEFAULT nextval('zoom_meetings_id_seq'::regclass);
ALTER TABLE ONLY product_analytics_events_experimental
@ -22654,6 +22680,9 @@ ALTER TABLE ONLY x509_commit_signatures
ALTER TABLE ONLY x509_issuers
ADD CONSTRAINT x509_issuers_pkey PRIMARY KEY (id);
ALTER TABLE ONLY zentao_tracker_data
ADD CONSTRAINT zentao_tracker_data_pkey PRIMARY KEY (id);
ALTER TABLE ONLY zoom_meetings
ADD CONSTRAINT zoom_meetings_pkey PRIMARY KEY (id);
@ -25627,6 +25656,8 @@ CREATE INDEX index_x509_commit_signatures_on_x509_certificate_id ON x509_commit_
CREATE INDEX index_x509_issuers_on_subject_key_identifier ON x509_issuers USING btree (subject_key_identifier);
CREATE INDEX index_zentao_tracker_data_on_integration_id ON zentao_tracker_data USING btree (integration_id);
CREATE INDEX index_zoom_meetings_on_issue_id ON zoom_meetings USING btree (issue_id);
CREATE UNIQUE INDEX index_zoom_meetings_on_issue_id_and_issue_status ON zoom_meetings USING btree (issue_id, issue_status) WHERE (issue_status = 1);
@ -27673,6 +27704,9 @@ ALTER TABLE ONLY required_code_owners_sections
ALTER TABLE ONLY dast_site_profiles
ADD CONSTRAINT fk_rails_83e309d69e FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY zentao_tracker_data
ADD CONSTRAINT fk_rails_84efda7be0 FOREIGN KEY (integration_id) REFERENCES integrations(id) ON DELETE CASCADE;
ALTER TABLE ONLY boards_epic_user_preferences
ADD CONSTRAINT fk_rails_851fe1510a FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;

View file

@ -22,8 +22,8 @@ module API
end
def feature_enabled?
::Feature.enabled?(:integrated_error_tracking, project) &&
project.error_tracking_setting&.enabled?
project.error_tracking_setting&.enabled? &&
project.error_tracking_setting&.integrated_client?
end
def find_client_key(public_key)

View file

@ -15,10 +15,7 @@ module Gitlab
@base_report = base_report
@head_report = head_report
@signatures_enabled = (
::Feature.enabled?(:vulnerability_finding_tracking_signatures, project) &&
project.licensed_feature_available?(:vulnerability_finding_signatures)
)
@signatures_enabled = project.licensed_feature_available?(:vulnerability_finding_signatures)
if @signatures_enabled
@added_findings = []

View file

@ -22520,6 +22520,9 @@ msgstr ""
msgid "No approvers"
msgstr ""
msgid "No artifacts found"
msgstr ""
msgid "No assignee"
msgstr ""

View file

@ -12,5 +12,9 @@ FactoryBot.define do
trait :disabled do
enabled { false }
end
trait :integrated do
integrated { true }
end
end
end

View file

@ -53,6 +53,7 @@ describe('Pipeline Multi Actions Dropdown', () => {
const findDropdown = () => wrapper.findComponent(GlDropdown);
const findAllArtifactItems = () => wrapper.findAllByTestId(artifactItemTestId);
const findFirstArtifactItem = () => wrapper.findByTestId(artifactItemTestId);
const findEmptyMessage = () => wrapper.findByTestId('artifacts-empty-message');
beforeEach(() => {
mockAxios = new MockAdapter(axios);
@ -86,6 +87,7 @@ describe('Pipeline Multi Actions Dropdown', () => {
createComponent({ mockData: { artifacts } });
expect(findAllArtifactItems()).toHaveLength(artifacts.length);
expect(findEmptyMessage().exists()).toBe(false);
});
it('should render the correct artifact name and path', () => {
@ -95,6 +97,12 @@ describe('Pipeline Multi Actions Dropdown', () => {
expect(findFirstArtifactItem().text()).toBe(`Download ${artifacts[0].name} artifact`);
});
it('should render empty message when no artifacts are found', () => {
createComponent({ mockData: { artifacts: [] } });
expect(findEmptyMessage().exists()).toBe(true);
});
describe('with a failing request', () => {
it('should render an error message', async () => {
const endpoint = artifactsEndpoint.replace(artifactsEndpointPlaceholder, pipelineId);

View file

@ -24,12 +24,11 @@ RSpec.describe Gitlab::Ci::Reports::Security::VulnerabilityReportsComparer do
subject { described_class.new(project, base_report, head_report) }
where(vulnerability_finding_tracking_signatures_enabled: [true, false])
where(vulnerability_finding_signatures: [true, false])
with_them do
before do
stub_feature_flags(vulnerability_finding_tracking_signatures: vulnerability_finding_tracking_signatures_enabled)
stub_licensed_features(vulnerability_finding_signatures: vulnerability_finding_tracking_signatures_enabled)
stub_licensed_features(vulnerability_finding_signatures: vulnerability_finding_signatures)
end
describe '#base_report_out_of_date' do

View file

@ -0,0 +1,32 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration! 'orphaned_invite_tokens_cleanup'
RSpec.describe OrphanedInviteTokensCleanup, :migration do
def create_member(**extra_attributes)
defaults = {
access_level: 10,
source_id: 1,
source_type: "Project",
notification_level: 0,
type: 'ProjectMember'
}
table(:members).create!(defaults.merge(extra_attributes))
end
describe '#up', :aggregate_failures do
it 'removes invite tokens for accepted records with invite_accepted_at < created_at' do
record1 = create_member(invite_token: 'foo', invite_accepted_at: 1.day.ago, created_at: 1.hour.ago)
record2 = create_member(invite_token: 'foo2', invite_accepted_at: nil, created_at: 1.hour.ago)
record3 = create_member(invite_token: 'foo3', invite_accepted_at: 1.day.ago, created_at: 1.year.ago)
migrate!
expect(table(:members).find(record1.id).invite_token).to eq nil
expect(table(:members).find(record2.id).invite_token).to eq 'foo2'
expect(table(:members).find(record3.id).invite_token).to eq 'foo3'
end
end
end

View file

@ -667,7 +667,23 @@ RSpec.describe Member do
let!(:member) { create(:project_member, invite_email: "user@example.com", user: nil) }
it "sets the invite token" do
expect { member.generate_invite_token }.to change { member.invite_token}
expect { member.generate_invite_token }.to change { member.invite_token }
end
end
describe 'generate invite token on create' do
let!(:member) { build(:project_member, invite_email: "user@example.com") }
it "sets the invite token" do
expect { member.save! }.to change { member.invite_token }.to(kind_of(String))
end
context 'when invite was already accepted' do
it "does not set invite token" do
member.invite_accepted_at = 1.day.ago
expect { member.save! }.not_to change { member.invite_token }.from(nil)
end
end
end

View file

@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe API::ErrorTrackingCollector do
let_it_be(:project) { create(:project, :private) }
let_it_be(:setting) { create(:project_error_tracking_setting, project: project) }
let_it_be(:setting) { create(:project_error_tracking_setting, :integrated, project: project) }
let_it_be(:client_key) { create(:error_tracking_client_key, project: project) }
describe "POST /error_tracking/collector/api/:id/envelope" do
@ -40,6 +40,14 @@ RSpec.describe API::ErrorTrackingCollector do
it_behaves_like 'not found'
end
context 'integrated error tracking is disabled' do
before do
setting.update!(integrated: false)
end
it_behaves_like 'not found'
end
context 'feature flag is disabled' do
before do
stub_feature_flags(integrated_error_tracking: false)