Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
7de8ed230a
commit
8cfe3415e9
17 changed files with 68 additions and 165 deletions
|
@ -1,6 +1,5 @@
|
|||
<script>
|
||||
import { GlTooltipDirective } from '@gitlab/ui';
|
||||
import { visitUrl } from '~/lib/utils/url_utility';
|
||||
import { GlTooltipDirective, GlLink } from '@gitlab/ui';
|
||||
import CiIcon from './ci_icon.vue';
|
||||
/**
|
||||
* Renders CI Badge link with CI icon and status text based on
|
||||
|
@ -27,6 +26,7 @@ import CiIcon from './ci_icon.vue';
|
|||
|
||||
export default {
|
||||
components: {
|
||||
GlLink,
|
||||
CiIcon,
|
||||
},
|
||||
directives: {
|
||||
|
@ -61,29 +61,21 @@ export default {
|
|||
return className ? `ci-status ci-${className}` : 'ci-status';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
navigateToPipeline() {
|
||||
visitUrl(this.detailsPath);
|
||||
|
||||
// event used for tracking
|
||||
this.$emit('ciStatusBadgeClick');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<a
|
||||
<gl-link
|
||||
v-gl-tooltip
|
||||
:class="cssClass"
|
||||
class="gl-cursor-pointer"
|
||||
:title="title"
|
||||
data-qa-selector="status_badge_link"
|
||||
@click="navigateToPipeline"
|
||||
:href="detailsPath"
|
||||
@click="$emit('ciStatusBadgeClick')"
|
||||
>
|
||||
<ci-icon :status="status" :css-classes="iconClasses" />
|
||||
|
||||
<template v-if="showText">
|
||||
{{ status.text }}
|
||||
</template>
|
||||
</a>
|
||||
</gl-link>
|
||||
</template>
|
||||
|
|
|
@ -7,10 +7,6 @@ module Groups
|
|||
end
|
||||
|
||||
def execute
|
||||
if Feature.disabled?(:include_groups_from_group_shares_in_project_transfer_locations)
|
||||
return current_user.manageable_groups
|
||||
end
|
||||
|
||||
groups_accepting_project_transfers =
|
||||
[
|
||||
current_user.manageable_groups,
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: include_groups_from_group_shares_in_project_transfer_locations
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/90127
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366305
|
||||
milestone: '15.2'
|
||||
type: development
|
||||
group: group::workspace
|
||||
default_enabled: false
|
|
@ -26,6 +26,8 @@ to be emitted from the rails application:
|
|||
|
||||
1. [`rails_request_apdex`](rails_request_apdex.md)
|
||||
1. `global_search_apdex`
|
||||
1. `global_search_error_rate`
|
||||
1. `global_search_indexing_apdex`
|
||||
|
||||
## Defining a new SLI
|
||||
|
||||
|
|
|
@ -276,6 +276,10 @@ In the second (filtered) example, we know exactly 100 will be updated with each
|
|||
end
|
||||
```
|
||||
|
||||
NOTE:
|
||||
For EE migrations that define `scope_to`, ensure the module extends `ActiveSupport::Concern`.
|
||||
Otherwise, records are processed without taking the scope into consideration.
|
||||
|
||||
1. In the post-deployment migration, enqueue the batched background migration:
|
||||
|
||||
```ruby
|
||||
|
|
|
@ -181,9 +181,11 @@ Include in the MR description:
|
|||
- When providing query plans, make sure it hits enough data:
|
||||
- You can use a GitLab production replica to test your queries on a large scale,
|
||||
through the `#database-lab` Slack channel or through [ChatOps](database/understanding_explain_plans.md#chatops).
|
||||
- Usually, the `gitlab-org` namespace (`namespace_id = 9970`) and the
|
||||
`gitlab-org/gitlab-foss` (`project_id = 13083`) or the `gitlab-org/gitlab` (`project_id = 278964`)
|
||||
projects provide enough data to serve as a good example.
|
||||
- To produce a query plan with enough data, you can use the IDs of:
|
||||
- The `gitlab-org` namespace (`namespace_id = 9970`), for queries involving a group.
|
||||
- The `gitlab-org/gitlab-foss` (`project_id = 13083`) or the `gitlab-org/gitlab` (`project_id = 278964`) projects, for queries involving a project.
|
||||
- The `gitlab-qa` user (`user_id = 1614863`), for queries involving a user.
|
||||
- Optionally, you can also use your own `user_id`, or the `user_id` of a user with a long history within the project or group being used to generate the query plan.
|
||||
- That means that no query plan should return 0 records or less records than the provided limit (if a limit is included). If a query is used in batching, a proper example batch with adequate included results should be identified and provided.
|
||||
- If your queries belong to a new feature in GitLab.com and thus they don't return data in production:
|
||||
- You may analyze the query and to provide the plan from a local environment.
|
||||
|
|
|
@ -6,6 +6,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
# Troubleshooting Snowplow
|
||||
|
||||
## Monitoring
|
||||
|
||||
This page covers dashboards and alerts coming from a number of internal tools.
|
||||
|
||||
For a brief video overview of the tools used to monitor Snowplow usage, please check out [this internal video](https://www.youtube.com/watch?v=NxPS0aKa_oU) (you must be logged into GitLab Unfiltered to view).
|
||||
|
||||
## Good events drop
|
||||
|
||||
### Symptoms
|
||||
|
|
|
@ -58,7 +58,7 @@ gitops:
|
|||
|
||||
| Keyword | Description |
|
||||
|--|--|
|
||||
| `charts` | List of charts you want to be applied in your cluster. Charts are applied concurrently. All charts must be in the same directory. |
|
||||
| `charts` | List of charts you want to be applied in your cluster. Charts are applied concurrently. |
|
||||
| `release_name` | Required. Name of the release to use when applying the chart. |
|
||||
| `id` | Required. ID of the project where Helm chart is committed. No authentication mechanisms are currently supported. |
|
||||
| `path` | Optional. Path of the chart in the project repository. Root of the repository is used by default. This is the directory with the `Chart.yaml` file. |
|
||||
|
@ -69,7 +69,6 @@ gitops:
|
|||
|
||||
Drift happens when the current configuration of an infrastructure resource differs from its desired configuration.
|
||||
Typically, drift is caused by manually editing resources directly, rather than by editing the code that describes the desired state. Minimizing the risk of drift helps to ensure configuration consistency and successful operations.
|
||||
mechanism. Minimizing the risk of drift helps to ensure configuration consistency and successful operations.
|
||||
|
||||
In GitLab, the agent for Kubernetes regularly compares the desired state from the chart source with
|
||||
the actual state from the Kubernetes cluster. Deviations from the desired state are fixed at every check. These checks
|
||||
|
|
|
@ -1,33 +1,41 @@
|
|||
---
|
||||
type: reference, howto
|
||||
stage: Manage
|
||||
group: Optimize
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
# Insights **(ULTIMATE)**
|
||||
# Insights for groups **(ULTIMATE)**
|
||||
|
||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/725) in GitLab 12.0.
|
||||
|
||||
Configure the Insights that matter for your groups. Explore data such as
|
||||
triage hygiene, issues created or closed for a given period, average time for merge
|
||||
requests to be merged, and much more.
|
||||
|
||||
![Insights example stacked bar chart](img/insights_example_stacked_bar_chart_v13_11.png)
|
||||
Configure Insights to explore data about you group's activity, such as
|
||||
triage hygiene, issues created or closed in a given period, and average time for merge
|
||||
requests to be merged.
|
||||
|
||||
## View your group's Insights
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- You must have [permission](../../permissions.md#group-members-permissions) to view the group.
|
||||
- You must have access to a project to view information about its merge requests and issues,
|
||||
and permission to view them if they are confidential.
|
||||
|
||||
To access your group's Insights:
|
||||
|
||||
1. On the top bar, select **Main menu > Groups** and find your group.
|
||||
1. On the left sidebar, select **Analytics > Insights**.
|
||||
|
||||
![Insights example stacked bar chart](img/insights_example_stacked_bar_chart_v13_11.png)
|
||||
|
||||
## Configure your Insights
|
||||
|
||||
GitLab reads Insights from the [default configuration file](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/fixtures/insights/default.yml).
|
||||
If you want to customize it:
|
||||
GitLab reads Insights from the
|
||||
[default configuration file](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/fixtures/insights/default.yml).
|
||||
You can also create custom Insights charts that are more relevant for your group.
|
||||
|
||||
1. Create a new file [`.gitlab/insights.yml`](../../project/insights/index.md)
|
||||
To customize your Insights:
|
||||
|
||||
1. Create a new file [`.gitlab/insights.yml`](../../project/insights/index.md#writing-your-gitlabinsightsyml)
|
||||
in a project that belongs to your group.
|
||||
1. On the top bar, select **Main menu > Groups** and find your group.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
|
@ -35,17 +43,6 @@ in a project that belongs to your group.
|
|||
1. Select the project that contains your `.gitlab/insights.yml` configuration file.
|
||||
1. Select **Save changes**.
|
||||
|
||||
## Permissions
|
||||
|
||||
If you have access to view a group, then you have access to view its Insights.
|
||||
|
||||
NOTE:
|
||||
Issues or merge requests that you don't have access to (because you don't have
|
||||
access to the project they belong to, or because they are confidential) are
|
||||
filtered out of the Insights charts.
|
||||
|
||||
You may also consult the [group permissions table](../../permissions.md#group-members-permissions).
|
||||
|
||||
<!-- ## Troubleshooting
|
||||
|
||||
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 19 KiB |
Binary file not shown.
Before Width: | Height: | Size: 13 KiB |
|
@ -7,10 +7,6 @@ module Gitlab
|
|||
# see https://jira.atlassian.com/browse/JRACLOUD-67570
|
||||
# We set it to 1000 in case they change their mind.
|
||||
BATCH_SIZE = 1000
|
||||
JIRA_IMPORT_THRESHOLD = 100_000
|
||||
JIRA_IMPORT_PAUSE_LIMIT = 50_000
|
||||
|
||||
RetriesExceededError = Class.new(RuntimeError)
|
||||
|
||||
attr_reader :imported_items_cache_key, :start_at, :job_waiter
|
||||
|
||||
|
@ -71,9 +67,6 @@ module Gitlab
|
|||
{ iid: next_iid }
|
||||
).execute
|
||||
|
||||
# Pause the importer to allow the import to catch up and cache to drain
|
||||
pause_jira_issue_importer if jira_import_issue_worker.queue_size > JIRA_IMPORT_THRESHOLD
|
||||
|
||||
Gitlab::JiraImport::ImportIssueWorker.perform_async(project.id, jira_issue.id, issue_attrs, job_waiter.key)
|
||||
|
||||
job_waiter.jobs_remaining += 1
|
||||
|
@ -97,27 +90,6 @@ module Gitlab
|
|||
job_waiter
|
||||
end
|
||||
|
||||
def jira_import_issue_worker
|
||||
@_jira_import_issue_worker ||= Gitlab::JiraImport::ImportIssueWorker
|
||||
end
|
||||
|
||||
def pause_jira_issue_importer
|
||||
# Wait for import workers to drop below 50K in the iterations of the timeout
|
||||
# timeout - Set to 5 seconds.
|
||||
# Time to process 100K jobs is currently ~14 seconds.
|
||||
# Source: https://github.com/mperham/sidekiq#performance
|
||||
# retries - Set to 10 times to avoid indefinitely pause.
|
||||
# Raises an error if the queue does not reduce below the limit after 10 tries.
|
||||
|
||||
retries = 10
|
||||
while retries > 0 && jira_import_issue_worker.queue_size >= JIRA_IMPORT_PAUSE_LIMIT
|
||||
job_waiter.wait(5)
|
||||
retries -= 1
|
||||
end
|
||||
|
||||
raise RetriesExceededError, 'Retry failed after 10 attempts' if retries == 0
|
||||
end
|
||||
|
||||
def fetch_issues(start_at)
|
||||
client.Issue.jql("PROJECT='#{jira_project_key}' ORDER BY created ASC", { max_results: BATCH_SIZE, start_at: start_at })
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { GlLink } from '@gitlab/ui';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
|
||||
import CiIcon from '~/vue_shared/components/ci_icon.vue';
|
||||
import { visitUrl } from '~/lib/utils/url_utility';
|
||||
|
||||
jest.mock('~/lib/utils/url_utility', () => ({
|
||||
visitUrl: jest.fn(),
|
||||
|
@ -86,18 +86,14 @@ describe('CI Badge Link Component', () => {
|
|||
wrapper.destroy();
|
||||
});
|
||||
|
||||
it.each(Object.keys(statuses))('should render badge for status: %s', async (status) => {
|
||||
it.each(Object.keys(statuses))('should render badge for status: %s', (status) => {
|
||||
createComponent({ status: statuses[status] });
|
||||
|
||||
expect(wrapper.attributes('href')).toBe();
|
||||
expect(wrapper.attributes('href')).toBe(statuses[status].details_path);
|
||||
expect(wrapper.text()).toBe(statuses[status].text);
|
||||
expect(wrapper.classes()).toContain('ci-status');
|
||||
expect(wrapper.classes()).toContain(`ci-${statuses[status].group}`);
|
||||
expect(findIcon().exists()).toBe(true);
|
||||
|
||||
await wrapper.trigger('click');
|
||||
|
||||
expect(visitUrl).toHaveBeenCalledWith(statuses[status].details_path);
|
||||
});
|
||||
|
||||
it('should not render label', () => {
|
||||
|
@ -109,7 +105,7 @@ describe('CI Badge Link Component', () => {
|
|||
it('should emit ciStatusBadgeClick event', async () => {
|
||||
createComponent({ status: statuses.success });
|
||||
|
||||
await wrapper.trigger('click');
|
||||
await wrapper.find(GlLink).vm.$emit('click');
|
||||
|
||||
expect(wrapper.emitted('ciStatusBadgeClick')).toEqual([[]]);
|
||||
});
|
||||
|
|
|
@ -40,7 +40,7 @@ RSpec.describe Gitlab::JiraImport::IssuesImporter do
|
|||
|
||||
context 'with results returned' do
|
||||
jira_issue = Struct.new(:id)
|
||||
let_it_be(:jira_issues) { [jira_issue.new(1), jira_issue.new(2), jira_issue.new(3)] }
|
||||
let_it_be(:jira_issues) { [jira_issue.new(1), jira_issue.new(2)] }
|
||||
|
||||
def mock_issue_serializer(count, raise_exception_on_even_mocks: false)
|
||||
serializer = instance_double(Gitlab::JiraImport::IssueSerializer, execute: { key: 'data' })
|
||||
|
@ -125,47 +125,6 @@ RSpec.describe Gitlab::JiraImport::IssuesImporter do
|
|||
expect(Gitlab::JiraImport.get_issues_next_start_at(project.id)).to eq(2)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when number of issues is above the threshold' do
|
||||
before do
|
||||
stub_const("#{described_class.name}::JIRA_IMPORT_THRESHOLD", 2)
|
||||
stub_const("#{described_class.name}::JIRA_IMPORT_PAUSE_LIMIT", 1)
|
||||
allow(Gitlab::ErrorTracking).to receive(:track_exception)
|
||||
allow_next_instance_of(Gitlab::JobWaiter) do |job_waiter|
|
||||
allow(job_waiter).to receive(:wait).with(5).and_return(job_waiter.wait(0.1))
|
||||
end
|
||||
end
|
||||
|
||||
it 'schedules 2 import jobs with two pause points' do
|
||||
expect(subject).to receive(:fetch_issues).with(0).and_return([jira_issues[0], jira_issues[1], jira_issues[2]])
|
||||
expect(Gitlab::JiraImport::ImportIssueWorker).to receive(:perform_async).exactly(3).times
|
||||
expect(Gitlab::JiraImport::ImportIssueWorker)
|
||||
.to receive(:queue_size)
|
||||
.exactly(6).times
|
||||
.and_return(1, 2, 3, 2, 1, 0)
|
||||
|
||||
mock_issue_serializer(3)
|
||||
|
||||
expect(subject.execute).to have_received(:wait).with(5).twice
|
||||
end
|
||||
|
||||
it 'tracks the exception if the queue size does not reduce' do
|
||||
expect(subject).to receive(:fetch_issues).with(0).and_return([jira_issues[0]])
|
||||
expect(Gitlab::JiraImport::ImportIssueWorker).not_to receive(:perform_async)
|
||||
expect(Gitlab::JiraImport::ImportIssueWorker)
|
||||
.to receive(:queue_size)
|
||||
.exactly(11).times
|
||||
.and_return(3)
|
||||
|
||||
mock_issue_serializer(1)
|
||||
|
||||
expect(subject.execute).to have_received(:wait).with(5).exactly(10).times
|
||||
expect(Gitlab::ErrorTracking)
|
||||
.to have_received(:track_exception)
|
||||
.with(described_class::RetriesExceededError, { project_id: project.id })
|
||||
.once
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -465,15 +465,14 @@ RSpec.describe ProjectPolicy do
|
|||
end
|
||||
|
||||
context 'owner access' do
|
||||
let!(:owner_user) { create(:user) }
|
||||
let!(:owner_of_different_thing) { create(:user) }
|
||||
let(:stranger) { create(:user) }
|
||||
let_it_be(:owner_user) { owner }
|
||||
let_it_be(:owner_of_different_thing) { create(:user) }
|
||||
|
||||
context 'personal project' do
|
||||
let!(:project) { create(:project) }
|
||||
let!(:project2) { create(:project) }
|
||||
let_it_be(:project) { private_project }
|
||||
let_it_be(:project2) { create(:project) }
|
||||
|
||||
before do
|
||||
before_all do
|
||||
project.add_guest(guest)
|
||||
project.add_reporter(reporter)
|
||||
project.add_developer(developer)
|
||||
|
@ -483,7 +482,7 @@ RSpec.describe ProjectPolicy do
|
|||
|
||||
it 'allows owner access', :aggregate_failures do
|
||||
expect(described_class.new(owner_of_different_thing, project)).to be_disallowed(:owner_access)
|
||||
expect(described_class.new(stranger, project)).to be_disallowed(:owner_access)
|
||||
expect(described_class.new(non_member, project)).to be_disallowed(:owner_access)
|
||||
expect(described_class.new(guest, project)).to be_disallowed(:owner_access)
|
||||
expect(described_class.new(reporter, project)).to be_disallowed(:owner_access)
|
||||
expect(described_class.new(developer, project)).to be_disallowed(:owner_access)
|
||||
|
@ -493,12 +492,12 @@ RSpec.describe ProjectPolicy do
|
|||
end
|
||||
|
||||
context 'group project' do
|
||||
let(:group) { create(:group) }
|
||||
let!(:group2) { create(:group) }
|
||||
let!(:project) { create(:project, group: group) }
|
||||
let_it_be(:project) { private_project_in_group }
|
||||
let_it_be(:group2) { create(:group) }
|
||||
let_it_be(:group) { project.group }
|
||||
|
||||
context 'group members' do
|
||||
before do
|
||||
before_all do
|
||||
group.add_guest(guest)
|
||||
group.add_reporter(reporter)
|
||||
group.add_developer(developer)
|
||||
|
@ -509,7 +508,7 @@ RSpec.describe ProjectPolicy do
|
|||
|
||||
it 'allows owner access', :aggregate_failures do
|
||||
expect(described_class.new(owner_of_different_thing, project)).to be_disallowed(:owner_access)
|
||||
expect(described_class.new(stranger, project)).to be_disallowed(:owner_access)
|
||||
expect(described_class.new(non_member, project)).to be_disallowed(:owner_access)
|
||||
expect(described_class.new(guest, project)).to be_disallowed(:owner_access)
|
||||
expect(described_class.new(reporter, project)).to be_disallowed(:owner_access)
|
||||
expect(described_class.new(developer, project)).to be_disallowed(:owner_access)
|
||||
|
@ -1692,7 +1691,7 @@ RSpec.describe ProjectPolicy do
|
|||
let_it_be(:project_with_analytics_private) { create(:project, :analytics_private) }
|
||||
let_it_be(:project_with_analytics_enabled) { create(:project, :analytics_enabled) }
|
||||
|
||||
before do
|
||||
before_all do
|
||||
project_with_analytics_disabled.add_guest(guest)
|
||||
project_with_analytics_private.add_guest(guest)
|
||||
project_with_analytics_enabled.add_guest(guest)
|
||||
|
|
|
@ -4783,18 +4783,6 @@ RSpec.describe API::Projects do
|
|||
expect(project_ids_from_response).to include(shared_to_owner_group.id)
|
||||
expect(project_ids_from_response).not_to include(shared_to_guest_group.id)
|
||||
end
|
||||
|
||||
context 'when the feature flag `include_groups_from_group_shares_in_project_transfer_locations` is disabled' do
|
||||
before do
|
||||
stub_feature_flags(include_groups_from_group_shares_in_project_transfer_locations: false)
|
||||
end
|
||||
|
||||
it 'does not include any groups arising from group shares' do
|
||||
request
|
||||
|
||||
expect(project_ids_from_response).not_to include(shared_to_owner_group.id, shared_to_guest_group.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def project_ids_from_response
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package redis
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
|
@ -164,7 +163,15 @@ func sentinelDialer(dopts []redis.DialOption) redisDialerFunc {
|
|||
return nil, err
|
||||
}
|
||||
dopts = append(dopts, redis.DialNetDial(keepAliveDialer))
|
||||
return redisDial("tcp", address, dopts...)
|
||||
conn, err := redisDial("tcp", address, dopts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !sentinel.TestRole(conn, "master") {
|
||||
conn.Close()
|
||||
return nil, fmt.Errorf("%s is not redis master", address)
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,14 +254,6 @@ func Configure(cfg *config.RedisConfig, dialFunc func(*config.RedisConfig, bool)
|
|||
Dial: poolDialFunc,
|
||||
Wait: true,
|
||||
}
|
||||
if sntnl != nil {
|
||||
pool.TestOnBorrow = func(c redis.Conn, t time.Time) error {
|
||||
if !sentinel.TestRole(c, "master") {
|
||||
return errors.New("role check failed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get a connection for the Redis-pool
|
||||
|
|
Loading…
Reference in a new issue