Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-06-01 09:09:17 +00:00
parent 369de19d79
commit 7c42073320
23 changed files with 235 additions and 59 deletions

View File

@ -1 +1 @@
a6c5964bb455f77a0c79898f0b99c4c7df3aee3a
e3aa6272e47af528b7599f93db2b02c76c55718e

View File

@ -121,9 +121,10 @@ export default {
},
created() {
const [tabQueryParam] = getParameterValues(TAB_QUERY_PARAM);
const tabName = Object.keys(TABS_INDEX)[tabQueryParam];
if (tabQueryParam && TABS_INDEX[tabQueryParam]) {
this.setDefaultTab(tabQueryParam);
if (tabName) {
this.setDefaultTab(tabName);
}
},
methods: {

View File

@ -62,6 +62,7 @@ export default {
return {
hasActionTooltip: false,
isActionLoading: false,
isExpandBtnFocus: false,
};
},
computed: {
@ -89,6 +90,9 @@ export default {
? ['gl-border-r-0!', ...this.$options.styles.flatRightBorder]
: ['gl-border-l-0!', ...this.$options.styles.flatLeftBorder];
},
buttonShadowClass() {
return this.isExpandBtnFocus ? '' : 'gl-shadow-none!';
},
buttonId() {
return `js-linked-pipeline-${this.pipeline.id}`;
},
@ -214,6 +218,9 @@ export default {
setActionTooltip(flag) {
this.hasActionTooltip = flag;
},
setExpandBtnActiveState(flag) {
this.isExpandBtnFocus = flag;
},
},
};
</script>
@ -277,12 +284,16 @@ export default {
<div class="gl-display-flex">
<gl-button
:id="buttonId"
class="gl-border! gl-shadow-none! gl-rounded-lg!"
:class="[`js-pipeline-expand-${pipeline.id}`, buttonBorderClasses]"
class="gl-border! gl-rounded-lg!"
:class="[`js-pipeline-expand-${pipeline.id}`, buttonBorderClasses, buttonShadowClass]"
:icon="expandedIcon"
:aria-label="__('Expand pipeline')"
data-testid="expand-pipeline-button"
data-qa-selector="expand_linked_pipeline_button"
@mouseover="setExpandBtnActiveState(true)"
@mouseout="setExpandBtnActiveState(false)"
@focus="setExpandBtnActiveState(true)"
@blur="setExpandBtnActiveState(false)"
@click="onClickLinkedPipeline"
/>
</div>

View File

@ -187,14 +187,12 @@ module Namespaces
superset_sql = <<~SQL
SELECT d1.traversal_ids
FROM #{base_name} d1
LEFT JOIN LATERAL (
SELECT d2.id as ancestor_id
WHERE NOT EXISTS (
SELECT 1
FROM #{base_name} d2
WHERE d2.id = ANY(d1.traversal_ids)
AND d2.id <> d1.id
LIMIT 1
) covered ON TRUE
WHERE covered.ancestor_id IS NULL
)
SQL
Gitlab::SQL::CTE.new(:superset, superset_sql, materialized: false)

View File

@ -2,6 +2,9 @@
module PagesDomains
class CreateAcmeOrderService
# elliptic curve algorithm to generate the private key
ECDSA_CURVE = "prime256v1"
attr_reader :pages_domain
def initialize(pages_domain)
@ -14,7 +17,12 @@ module PagesDomains
challenge = order.new_challenge
private_key = OpenSSL::PKey::RSA.new(4096)
private_key = if Feature.enabled?(:pages_lets_encrypt_ecdsa, pages_domain.project)
OpenSSL::PKey::EC.generate(ECDSA_CURVE)
else
OpenSSL::PKey::RSA.new(4096)
end
saved_order = pages_domain.acme_orders.create!(
url: order.url,
expires_at: order.expires,

View File

@ -0,0 +1,8 @@
---
name: pages_lets_encrypt_ecdsa
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/88125
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/363026
milestone: '15.1'
type: development
group: group::editor
default_enabled: false

View File

@ -1,20 +1,21 @@
---
data_category: optional
key_path: usage_activity_by_stage_monthly.manage.omniauth_providers
description: Number of unique user logins using an OmniAuth provider
description: List of unique OmniAuth providers
product_section: dev
product_stage: manage
product_group: group::access
product_category: authentication_and_authorization
value_type: number
value_type: object
status: active
time_frame: 28d
data_source: database
data_source: system
distribution:
- ce
tier:
- free
- premium
- ultimate
value_json_schema: 'config/metrics/objects_schemas/omniauth_providers_schema.json'
performance_indicator_type: []
milestone: "<13.9"

View File

@ -1,19 +1,20 @@
---
data_category: optional
key_path: usage_activity_by_stage.manage.omniauth_providers
description: Number of unique user logins using an OmniAuth provider
description: List of unique OmniAuth providers
product_section: dev
product_stage: manage
product_group: group::access
product_category: authentication_and_authorization
value_type: number
value_type: object
status: active
time_frame: all
data_source: database
data_source: system
distribution:
- ce
tier:
- free
- premium
- ultimate
value_json_schema: 'config/metrics/objects_schemas/omniauth_providers_schema.json'
milestone: "<13.9"

View File

@ -0,0 +1,6 @@
{
"type": "array",
"items": {
"type": ["string", "null"]
}
}

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
class AddIndexOnExpirableUnknownArtifactsForRemoval < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
TABLE_NAME = 'ci_job_artifacts'
INDEX_NAME = 'tmp_index_ci_job_artifacts_on_expire_at_where_locked_unknown'
CONDITIONS = 'locked = 2 AND expire_at IS NOT NULL'
def up
add_concurrent_index TABLE_NAME, [:expire_at, :job_id], name: INDEX_NAME, where: CONDITIONS
end
def down
remove_concurrent_index_by_name TABLE_NAME, INDEX_NAME
end
end

View File

@ -0,0 +1 @@
6f8ddb4ba8931d00caa05e193a238add12176e82e25692186595ab0d847c74ea

View File

@ -29963,6 +29963,8 @@ CREATE UNIQUE INDEX term_agreements_unique_index ON term_agreements USING btree
CREATE INDEX tmp_idx_container_repos_on_non_migrated ON container_repositories USING btree (project_id, id) WHERE ((migration_state <> 'import_done'::text) AND (created_at < '2022-01-23 00:00:00'::timestamp without time zone));
CREATE INDEX tmp_index_ci_job_artifacts_on_expire_at_where_locked_unknown ON ci_job_artifacts USING btree (expire_at, job_id) WHERE ((locked = 2) AND (expire_at IS NOT NULL));
CREATE INDEX tmp_index_ci_job_artifacts_on_id_where_trace_and_expire_at ON ci_job_artifacts USING btree (id) WHERE ((file_type = 3) AND (expire_at = ANY (ARRAY['2021-04-22 00:00:00+00'::timestamp with time zone, '2021-05-22 00:00:00+00'::timestamp with time zone, '2021-06-22 00:00:00+00'::timestamp with time zone, '2022-01-22 00:00:00+00'::timestamp with time zone, '2022-02-22 00:00:00+00'::timestamp with time zone, '2022-03-22 00:00:00+00'::timestamp with time zone, '2022-04-22 00:00:00+00'::timestamp with time zone])));
CREATE INDEX tmp_index_container_repositories_on_id_migration_state ON container_repositories USING btree (id, migration_state);

View File

@ -6,12 +6,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Compliance features **(FREE)**
These GitLab features can help ensure that your GitLab instance meets common
compliance standards. For more information about compliance management, see the
compliance management [solutions page](https://about.gitlab.com/solutions/compliance/).
GitLab compliance features ensure your GitLab instance meets common compliance standards, and are available at various pricing tiers. For more information about compliance management, see the compliance
management [solutions page](https://about.gitlab.com/solutions/compliance/).
The [security features](../security/index.md) in GitLab may also help you meet
relevant compliance standards.
The [security features](../security/index.md) in GitLab may also help you meet relevant compliance standards.
## Policy management

View File

@ -12,7 +12,7 @@ It is the properties of the GraphQL query tree that create opportunities for bat
## When should you use it?
We should try to batch DB requests as much as possible during GraphQL **query** execution. There is no need to batch loading during **mutations** because they are executed serially. If you need to make a database query, and it is possible to combine two similar (but not identical) queries, then consider using the batch-loader.
We should try to batch DB requests as much as possible during GraphQL **query** execution. There is no need to batch loading during **mutations** because they are executed serially. If you need to make a database query, and it is possible to combine two similar (but not necessarily identical) queries, then consider using the batch-loader.
When implementing a new endpoint we should aim to minimise the number of SQL queries. For stability and scalability we must also ensure that our queries do not suffer from N+1 performance issues.
@ -47,6 +47,26 @@ end
Here an [example MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46549) illustrating how to use our `BatchLoading` mechanism.
## The `BatchModelLoader`
For ID lookups, the advice is to use the `BatchModelLoader`:
```ruby
def project
::Gitlab::Graphql::Loaders::BatchModelLoader.new(::Project, object.project_id).find
end
```
To preload associations, you can pass an array of them:
```ruby
def issue(lookahead:)
preloads = [:author] if lookahead.selects?(:author)
::Gitlab::Graphql::Loaders::BatchModelLoader.new(::Issue, object.issue_id, preloads).find
end
```
## How does it work exactly?
Each lazy object knows which data it needs to load and how to batch the query. When we need to use the lazy objects (which we announce by calling `#sync`), they will be loaded along with all other similar objects in the current batch.
@ -61,9 +81,28 @@ BatchLoader::GraphQL.for(username).batch do |usernames, loader|
end
```
The batch-loader uses the source code location of the block to determine
which requests belong in the same queue, but only one instance of the block
is evaluated for each batch. You do not control which one.
For this reason, it is important that:
- The block must not refer to (close over) any instance state on objects. The best practice
is to pass all data the block needs through to it in the `for(data)` call.
- The block must be specific to a kind of batched data. Implementing generic
loaders (such as the `BatchModelLoader`) is possible, but it requires the use
of an injective `key` argument.
- Batches are not shared unless they refer to the same block - two identical blocks
with the same behavior, parameters, and keys do not get shared. For this reason,
never implement batched ID lookups on your own, instead use the `BatchModelLoader` for
maximum sharing. If you see two fields define the same batch-loading, consider
extracting that out to a new `Loader`, and enabling them to share.
### What does lazy mean?
It is important to avoid syncing batches too early. In the example below we can see how calling sync too early can eliminate opportunities for batching:
It is important to avoid syncing batches (forcing their evaluation) too early. The following example shows how calling sync too early can eliminate opportunities for batching.
This example calls sync on `x` too early:
```ruby
x = find_lazy(1)
@ -80,6 +119,8 @@ z.sync
# => will run 2 queries
```
However, this example waits until all requests are queued, and eliminates the extra query:
```ruby
x = find_lazy(1)
y = find_lazy(2)
@ -92,9 +133,38 @@ z.sync
# => will run 1 query
```
NOTE:
There is no dependency analysis in the use of batch-loading. There is simply
a pending queue of requests, and as soon as any one result is needed, all pending
requests are evaluated.
You should never call `batch.sync` or use `Lazy.force` in resolver code.
If you depend on a lazy value, use `Lazy.with_value` instead:
```ruby
def publisher
::Gitlab::Graphql::Loaders::BatchModelLoader.new(::Publisher, object.publisher_id).find
end
# Here we need the publisher in order to generate the catalog URL
def catalog_url
::Gitlab::Graphql::Lazy.with_value(publisher) do |p|
UrlHelpers.book_catalog_url(publisher, object.isbn)
end
end
```
## Testing
Any GraphQL field that supports `BatchLoading` should be tested using the `batch_sync` method available in [GraphQLHelpers](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/support/helpers/graphql_helpers.rb).
Ideally, do all your testing using request specs, and using `Schema.execute`. If
you do so, you do not need to manage the lifecycle of lazy values yourself, and
you are assured accurate results.
GraphQL fields that return lazy values may need these values forced in tests.
Forcing refers to explicit demands for evaluation, where this would normally
be arranged by the framework.
You can force a lazy value with the `GraphqlHelpers#batch_sync` method available in [GraphQLHelpers](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/support/helpers/graphql_helpers.rb), or by using `Gitlab::Graphql::Lazy.force`. For example:
```ruby
it 'returns data as a batch' do
@ -114,8 +184,8 @@ We can also use [QueryRecorder](../query_recorder.md) to make sure we are perfor
```ruby
it 'executes only 1 SQL query' do
query_count = ActiveRecord::QueryRecorder.new { subject }.count
query_count = ActiveRecord::QueryRecorder.new { subject }
expect(query_count).to eq(1)
expect(query_count).not_to exceed_query_limit(1)
end
```

View File

@ -430,6 +430,10 @@ before this occurs.
- To resume functionality, activate a new license.
- To fall back to Free features, delete the expired license.
## Activate a license file or key
If you have a license file or key, you can activate it [in the Admin Area](../../user/admin_area/license_file.md#activate-gitlab-ee-with-a-license-file-or-key).
## Contact Support
Learn more about:

View File

@ -209,7 +209,7 @@ module API
.select { |_role, role_access_level| role_access_level <= user_access_level }
.map(&:first)
environment = if environment_slug = current_authenticated_job.deployment&.environment&.slug
environment = if environment_slug = current_authenticated_job.persisted_environment&.slug
{ slug: environment_slug }
end

View File

@ -21423,9 +21423,6 @@ msgstr ""
msgid "Iterations"
msgstr ""
msgid "Iterations|Add a duration, and number of upcoming iterations in order to convert this cadence to automatic scheduling."
msgstr ""
msgid "Iterations|Add iteration"
msgstr ""
@ -21438,6 +21435,9 @@ msgstr ""
msgid "Iterations|Cadence name"
msgstr ""
msgid "Iterations|Can be converted"
msgstr ""
msgid "Iterations|Cancel"
msgstr ""
@ -21492,10 +21492,10 @@ msgstr ""
msgid "Iterations|Iterations are a way to track issues over a period of time, allowing teams to also track velocity and volatility metrics."
msgstr ""
msgid "Iterations|Iterations can no longer be scheduled manually. Convert all cadences to automatic scheduling to keep your iterations working as expected."
msgid "Iterations|Learn more about automatic scheduling"
msgstr ""
msgid "Iterations|Learn more about automatic scheduling"
msgid "Iterations|Manual management of iterations will be deprecated in GitLab 15.6. Convert your manual cadence to use automated scheduling when you are ready."
msgstr ""
msgid "Iterations|Move incomplete issues to the next iteration."
@ -21531,9 +21531,6 @@ msgstr ""
msgid "Iterations|Open"
msgstr ""
msgid "Iterations|Requires update"
msgstr ""
msgid "Iterations|Roll over issues"
msgstr ""
@ -21549,9 +21546,6 @@ msgstr ""
msgid "Iterations|Select start date"
msgstr ""
msgid "Iterations|Some of your cadences need to be updated"
msgstr ""
msgid "Iterations|Start date"
msgstr ""
@ -21564,7 +21558,7 @@ msgstr ""
msgid "Iterations|The start date of the first iteration determines when your cadence begins."
msgstr ""
msgid "Iterations|This cadence requires an update"
msgid "Iterations|This cadence can be converted to use automated scheduling"
msgstr ""
msgid "Iterations|This will delete the cadence as well as all of the iterations within it."
@ -21576,6 +21570,9 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
msgid "Iterations|To convert this cadence to automatic scheduling, add a duration and number of upcoming iterations. The upgrade is irreversible."
msgstr ""
msgid "Iterations|Unable to find iteration cadence."
msgstr ""
@ -21588,6 +21585,9 @@ msgstr ""
msgid "Iterations|Upcoming iterations"
msgstr ""
msgid "Iterations|Your manual cadence can be converted to use automated scheduling"
msgstr ""
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""

View File

@ -5,7 +5,7 @@ module QA
describe 'Project transfer between groups', :reliable do
let(:source_group) do
Resource::Group.fabricate_via_api! do |group|
group.path = 'source-group'
group.path = "source-group-#{SecureRandom.hex(8)}"
end
end

View File

@ -13,9 +13,7 @@ import {
EDITOR_APP_STATUS_LOADING,
EDITOR_APP_STATUS_INVALID,
EDITOR_APP_STATUS_VALID,
MERGED_TAB,
TAB_QUERY_PARAM,
TABS_INDEX,
} from '~/pipeline_editor/constants';
import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
import { mockLintResponse, mockLintResponseWithoutMerged, mockCiYml } from '../mock_data';
@ -221,18 +219,6 @@ describe('Pipeline editor tabs component', () => {
search: `?${TAB_QUERY_PARAM}=${queryValue}`,
});
});
it('is the tab specified in query param and transform it into an index value', async () => {
setWindowLocation(`${gitlabUrl}?${TAB_QUERY_PARAM}=${MERGED_TAB}`);
createComponent();
// If the query param has changed to an index, it means we have synced the
// query with.
expect(window.location).toMatchObject({
...matchObject,
search: `?${TAB_QUERY_PARAM}=${TABS_INDEX[MERGED_TAB]}`,
});
});
});
describe('glTabs', () => {

View File

@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { GlButton, GlDrawer, GlModal } from '@gitlab/ui';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import setWindowLocation from 'helpers/set_window_location_helper';
import CiEditorHeader from '~/pipeline_editor/components/editor/ci_editor_header.vue';
import CommitSection from '~/pipeline_editor/components/commit/commit_section.vue';
import PipelineEditorDrawer from '~/pipeline_editor/components/drawer/pipeline_editor_drawer.vue';
@ -11,11 +12,12 @@ import BranchSwitcher from '~/pipeline_editor/components/file_nav/branch_switche
import PipelineEditorHeader from '~/pipeline_editor/components/header/pipeline_editor_header.vue';
import PipelineEditorTabs from '~/pipeline_editor/components/pipeline_editor_tabs.vue';
import {
MERGED_TAB,
VISUALIZE_TAB,
CREATE_TAB,
LINT_TAB,
FILE_TREE_DISPLAY_KEY,
LINT_TAB,
MERGED_TAB,
TABS_INDEX,
VISUALIZE_TAB,
} from '~/pipeline_editor/constants';
import PipelineEditorHome from '~/pipeline_editor/pipeline_editor_home.vue';
@ -162,6 +164,24 @@ describe('Pipeline editor home wrapper', () => {
await nextTick();
expect(findCommitSection().exists()).toBe(true);
});
describe('rendering with tab params', () => {
it.each`
tab | shouldShow
${MERGED_TAB} | ${false}
${VISUALIZE_TAB} | ${false}
${LINT_TAB} | ${false}
${CREATE_TAB} | ${true}
`(
'when the tab query param is $tab the commit form is shown: $shouldShow',
async ({ tab, shouldShow }) => {
setWindowLocation(`https://gitlab.test/ci/editor/?tab=${TABS_INDEX[tab]}`);
await createComponent({ stubs: { PipelineEditorTabs } });
expect(findCommitSection().exists()).toBe(shouldShow);
},
);
});
});
describe('WalkthroughPopover events', () => {

View File

@ -378,6 +378,31 @@ describe('Linked pipeline', () => {
expect(findExpandButton().classes()).toContain(buttonBorderClasses);
},
);
describe('shadow border', () => {
beforeEach(() => {
createWrapper({ propsData: downstreamProps });
});
it.each`
activateEventName | deactivateEventName
${'mouseover'} | ${'mouseout'}
${'focus'} | ${'blur'}
`(
'applies the class on $activateEventName and removes it on $deactivateEventName ',
async ({ activateEventName, deactivateEventName }) => {
const shadowClass = 'gl-shadow-none!';
expect(findExpandButton().classes()).toContain(shadowClass);
await findExpandButton().vm.$emit(activateEventName);
expect(findExpandButton().classes()).not.toContain(shadowClass);
await findExpandButton().vm.$emit(deactivateEventName);
expect(findExpandButton().classes()).toContain(shadowClass);
},
);
});
});
describe('when isLoading is true', () => {

View File

@ -239,6 +239,17 @@ RSpec.describe API::Ci::Jobs do
end
end
context 'when non-deployment environment action' do
let(:job) do
create(:environment, name: 'review', project_id: project.id)
create(:ci_build, :artifacts, :stop_review_app, environment: 'review', pipeline: pipeline, user: api_user, status: job_status)
end
it 'includes environment slug' do
expect(json_response.dig('environment', 'slug')).to eq('review')
end
end
context 'when passing the token as params' do
let(:headers) { {} }
let(:params) { { job_token: job.token } }

View File

@ -38,13 +38,21 @@ RSpec.describe PagesDomains::CreateAcmeOrderService do
expect(challenge).to have_received(:request_validation).ordered
end
it 'generates and saves private key' do
it 'generates and saves private key: rsa' do
stub_feature_flags(pages_lets_encrypt_ecdsa: false)
service.execute
saved_order = PagesDomainAcmeOrder.last
expect { OpenSSL::PKey::RSA.new(saved_order.private_key) }.not_to raise_error
end
it 'generates and saves private key: ec' do
service.execute
saved_order = PagesDomainAcmeOrder.last
expect { OpenSSL::PKey::EC.new(saved_order.private_key) }.not_to raise_error
end
it 'properly saves order attributes' do
service.execute