Commit 565fa11a authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 8c30d396

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

...@@ -316,6 +316,7 @@ export default { ...@@ -316,6 +316,7 @@ export default {
<gl-dropdown-item <gl-dropdown-item
v-if="showDelete" v-if="showDelete"
class="text-danger" class="text-danger"
data-qa-selector="delete_board_button"
@click.prevent="showPage('delete')" @click.prevent="showPage('delete')"
> >
{{ s__('IssueBoards|Delete board') }} {{ s__('IssueBoards|Delete board') }}
......
...@@ -7,8 +7,16 @@ export default { ...@@ -7,8 +7,16 @@ export default {
ServiceCredentialsForm, ServiceCredentialsForm,
EksClusterConfigurationForm, EksClusterConfigurationForm,
}, },
props: {
gitlabManagedClusterHelpPath: {
type: String,
required: true,
},
},
}; };
</script> </script>
<template> <template>
<eks-cluster-configuration-form /> <eks-cluster-configuration-form
:gitlab-managed-cluster-help-path="gitlabManagedClusterHelpPath"
/>
</template> </template>
<script> <script>
import { createNamespacedHelpers, mapState, mapActions } from 'vuex'; import { createNamespacedHelpers, mapState, mapActions } from 'vuex';
import { sprintf, s__ } from '~/locale'; import { sprintf, s__ } from '~/locale';
import _ from 'underscore';
import { GlFormInput, GlFormCheckbox } from '@gitlab/ui';
import ClusterFormDropdown from './cluster_form_dropdown.vue'; import ClusterFormDropdown from './cluster_form_dropdown.vue';
import RegionDropdown from './region_dropdown.vue'; import RegionDropdown from './region_dropdown.vue';
import SecurityGroupDropdown from './security_group_dropdown.vue'; import { KUBERNETES_VERSIONS } from '../constants';
const { mapState: mapRolesState, mapActions: mapRolesActions } = createNamespacedHelpers('roles'); const { mapState: mapRolesState, mapActions: mapRolesActions } = createNamespacedHelpers('roles');
const { mapState: mapRegionsState, mapActions: mapRegionsActions } = createNamespacedHelpers( const { mapState: mapRegionsState, mapActions: mapRegionsActions } = createNamespacedHelpers(
...@@ -16,20 +18,36 @@ const { mapState: mapVpcsState, mapActions: mapVpcActions } = createNamespacedHe ...@@ -16,20 +18,36 @@ const { mapState: mapVpcsState, mapActions: mapVpcActions } = createNamespacedHe
const { mapState: mapSubnetsState, mapActions: mapSubnetActions } = createNamespacedHelpers( const { mapState: mapSubnetsState, mapActions: mapSubnetActions } = createNamespacedHelpers(
'subnets', 'subnets',
); );
const {
mapState: mapSecurityGroupsState,
mapActions: mapSecurityGroupsActions,
} = createNamespacedHelpers('securityGroups');
export default { export default {
components: { components: {
ClusterFormDropdown, ClusterFormDropdown,
RegionDropdown, RegionDropdown,
SecurityGroupDropdown, GlFormInput,
GlFormCheckbox,
},
props: {
gitlabManagedClusterHelpPath: {
type: String,
required: true,
},
}, },
computed: { computed: {
...mapState([ ...mapState([
'clusterName',
'environmentScope',
'kubernetesVersion',
'selectedRegion', 'selectedRegion',
'selectedKeyPair', 'selectedKeyPair',
'selectedVpc', 'selectedVpc',
'selectedSubnet', 'selectedSubnet',
'selectedRole', 'selectedRole',
'selectedSecurityGroup',
'gitlabManagedCluster',
]), ]),
...mapRolesState({ ...mapRolesState({
roles: 'items', roles: 'items',
...@@ -56,6 +74,14 @@ export default { ...@@ -56,6 +74,14 @@ export default {
isLoadingSubnets: 'isLoadingItems', isLoadingSubnets: 'isLoadingItems',
loadingSubnetsError: 'loadingItemsError', loadingSubnetsError: 'loadingItemsError',
}), }),
...mapSecurityGroupsState({
securityGroups: 'items',
isLoadingSecurityGroups: 'isLoadingItems',
loadingSecurityGroupsError: 'loadingItemsError',
}),
kubernetesVersions() {
return KUBERNETES_VERSIONS;
},
vpcDropdownDisabled() { vpcDropdownDisabled() {
return !this.selectedRegion; return !this.selectedRegion;
}, },
...@@ -65,6 +91,9 @@ export default { ...@@ -65,6 +91,9 @@ export default {
subnetDropdownDisabled() { subnetDropdownDisabled() {
return !this.selectedVpc; return !this.selectedVpc;
}, },
securityGroupDropdownDisabled() {
return !this.selectedVpc;
},
roleDropdownHelpText() { roleDropdownHelpText() {
return sprintf( return sprintf(
s__( s__(
...@@ -117,18 +146,57 @@ export default { ...@@ -117,18 +146,57 @@ export default {
false, false,
); );
}, },
securityGroupDropdownHelpText() {
return sprintf(
s__(
'ClusterIntegration|Choose the %{startLink}security groups%{endLink} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets.',
),
{
startLink:
'<a href="https://console.aws.amazon.com/vpc/home?#securityGroups" target="_blank" rel="noopener noreferrer">',
endLink: '</a>',
},
false,
);
},
gitlabManagedHelpText() {
const escapedUrl = _.escape(this.gitlabManagedClusterHelpPath);
return sprintf(
s__(
'ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}',
),
{
startLink: `<a href="${escapedUrl}" target="_blank" rel="noopener noreferrer">`,
endLink: '</a>',
},
false,
);
},
}, },
mounted() { mounted() {
this.fetchRegions(); this.fetchRegions();
this.fetchRoles(); this.fetchRoles();
}, },
methods: { methods: {
...mapActions(['setRegion', 'setVpc', 'setSubnet', 'setRole', 'setKeyPair']), ...mapActions([
'setClusterName',
'setEnvironmentScope',
'setKubernetesVersion',
'setRegion',
'setVpc',
'setSubnet',
'setRole',
'setKeyPair',
'setSecurityGroup',
'setGitlabManagedCluster',
]),
...mapRegionsActions({ fetchRegions: 'fetchItems' }), ...mapRegionsActions({ fetchRegions: 'fetchItems' }),
...mapVpcActions({ fetchVpcs: 'fetchItems' }), ...mapVpcActions({ fetchVpcs: 'fetchItems' }),
...mapSubnetActions({ fetchSubnets: 'fetchItems' }), ...mapSubnetActions({ fetchSubnets: 'fetchItems' }),
...mapRolesActions({ fetchRoles: 'fetchItems' }), ...mapRolesActions({ fetchRoles: 'fetchItems' }),
...mapKeyPairsActions({ fetchKeyPairs: 'fetchItems' }), ...mapKeyPairsActions({ fetchKeyPairs: 'fetchItems' }),
...mapSecurityGroupsActions({ fetchSecurityGroups: 'fetchItems' }),
setRegionAndFetchVpcsAndKeyPairs(region) { setRegionAndFetchVpcsAndKeyPairs(region) {
this.setRegion({ region }); this.setRegion({ region });
this.fetchVpcs({ region }); this.fetchVpcs({ region });
...@@ -137,12 +205,47 @@ export default { ...@@ -137,12 +205,47 @@ export default {
setVpcAndFetchSubnets(vpc) { setVpcAndFetchSubnets(vpc) {
this.setVpc({ vpc }); this.setVpc({ vpc });
this.fetchSubnets({ vpc }); this.fetchSubnets({ vpc });
this.fetchSecurityGroups({ vpc });
}, },
}, },
}; };
</script> </script>
<template> <template>
<form name="eks-cluster-configuration-form"> <form name="eks-cluster-configuration-form">
<div class="form-group">
<label class="label-bold" for="eks-cluster-name">{{
s__('ClusterIntegration|Kubernetes cluster name')
}}</label>
<gl-form-input
id="eks-cluster-name"
:value="clusterName"
@input="setClusterName({ clusterName: $event })"
/>
</div>
<div class="form-group">
<label class="label-bold" for="eks-environment-scope">{{
s__('ClusterIntegration|Environment scope')
}}</label>
<gl-form-input
id="eks-environment-scope"
:value="environmentScope"
@input="setEnvironmentScope({ environmentScope: $event })"
/>
</div>
<div class="form-group">
<label class="label-bold" for="eks-kubernetes-version">{{
s__('ClusterIntegration|Kubernetes version')
}}</label>
<cluster-form-dropdown
field-id="eks-kubernetes-version"
field-name="eks-kubernetes-version"
:value="kubernetesVersion"
:items="kubernetesVersions"
:empty-text="s__('ClusterIntegration|Kubernetes version not found')"
@input="setKubernetesVersion({ kubernetesVersion: $event })"
/>
<p class="form-text text-muted" v-html="roleDropdownHelpText"></p>
</div>
<div class="form-group"> <div class="form-group">
<label class="label-bold" for="eks-role">{{ s__('ClusterIntegration|Role name') }}</label> <label class="label-bold" for="eks-role">{{ s__('ClusterIntegration|Role name') }}</label>
<cluster-form-dropdown <cluster-form-dropdown
...@@ -233,5 +336,37 @@ export default { ...@@ -233,5 +336,37 @@ export default {
/> />
<p class="form-text text-muted" v-html="subnetDropdownHelpText"></p> <p class="form-text text-muted" v-html="subnetDropdownHelpText"></p>
</div> </div>
<div class="form-group">
<label class="label-bold" for="eks-security-group">{{
s__('ClusterIntegration|Security groups')
}}</label>
<cluster-form-dropdown
field-id="eks-security-group"
field-name="eks-security-group"
:input="selectedSecurityGroup"
:items="securityGroups"
:loading="isLoadingSecurityGroups"
:disabled="securityGroupDropdownDisabled"
:disabled-text="s__('ClusterIntegration|Select a VPC to choose a security group')"
:loading-text="s__('ClusterIntegration|Loading security groups')"
:placeholder="s__('ClusterIntergation|Select a security group')"
:search-field-placeholder="s__('ClusterIntegration|Search security groups')"
:empty-text="s__('ClusterIntegration|No security group found')"
:has-errors="Boolean(loadingSecurityGroupsError)"
:error-message="
s__('ClusterIntegration|Could not load security groups for the selected VPC')
"
@input="setSecurityGroup({ securityGroup: $event })"
/>
<p class="form-text text-muted" v-html="securityGroupDropdownHelpText"></p>
</div>
<div class="form-group">
<gl-form-checkbox
:checked="gitlabManagedCluster"
@input="setGitlabManagedCluster({ gitlabManagedCluster: $event })"
>{{ s__('ClusterIntegration|GitLab-managed cluster') }}</gl-form-checkbox
>
<p class="form-text text-muted" v-html="gitlabManagedHelpText"></p>
</div>
</form> </form>
</template> </template>
// eslint-disable-next-line import/prefer-default-export
export const KUBERNETES_VERSIONS = [
{ name: '1.14', value: '1.14' },
{ name: '1.13', value: '1.13' },
{ name: '1.12', value: '1.12' },
{ name: '1.11', value: '1.11' },
];
...@@ -12,7 +12,18 @@ export default () => ...@@ -12,7 +12,18 @@ export default () =>
components: { components: {
CreateEksCluster, CreateEksCluster,
}, },
data() {
const { gitlabManagedClusterHelpPath } = document.querySelector(this.$options.el).dataset;
return {
gitlabManagedClusterHelpPath,
};
},
render(createElement) { render(createElement) {
return createElement('create-eks-cluster'); return createElement('create-eks-cluster', {
props: {
gitlabManagedClusterHelpPath: this.gitlabManagedClusterHelpPath,
},
});
}, },
}); });
import EC2 from 'aws-sdk/clients/ec2'; import EC2 from 'aws-sdk/clients/ec2';
import IAM from 'aws-sdk/clients/iam'; import IAM from 'aws-sdk/clients/iam';
export const fetchRoles = () => export const fetchRoles = () => {
new Promise((resolve, reject) => {
const iam = new IAM(); const iam = new IAM();
iam return iam
.listRoles() .listRoles()
.on('success', ({ data: { Roles: roles } }) => { .promise()
const transformedRoles = roles.map(({ RoleName: name }) => ({ name })); .then(({ Roles: roles }) => roles.map(({ RoleName: name }) => ({ name })));
};
resolve(transformedRoles); export const fetchKeyPairs = () => {
})
.on('error', error => {
reject(error);
})
.send();
});
export const fetchKeyPairs = () =>
new Promise((resolve, reject) => {
const ec2 = new EC2(); const ec2 = new EC2();
ec2 return ec2
.describeKeyPairs() .describeKeyPairs()
.on('success', ({ data: { KeyPairs: keyPairs } }) => { .promise()
const transformedKeyPairs = keyPairs.map(({ RegionName: name }) => ({ name })); .then(({ KeyPairs: keyPairs }) => keyPairs.map(({ RegionName: name }) => ({ name })));
};
resolve(transformedKeyPairs);
})
.on('error', error => {
reject(error);
})
.send();
});
export const fetchRegions = () => export const fetchRegions = () => {
new Promise((resolve, reject) => {
const ec2 = new EC2(); const ec2 = new EC2();
ec2 return ec2
.describeRegions() .describeRegions()
.on('success', ({ data: { Regions: regions } }) => { .promise()
const transformedRegions = regions.map(({ RegionName: name }) => ({ name })); .then(({ Regions: regions }) =>
regions.map(({ RegionName: name }) => ({
resolve(transformedRegions); name,
}) value: name,
.on('error', error => { })),
reject(error); );
}) };
.send();
}); export const fetchVpcs = () => {
export const fetchVpcs = () =>
new Promise((resolve, reject) => {
const ec2 = new EC2(); const ec2 = new EC2();
ec2 return ec2
.describeVpcs() .describeVpcs()
.on('success', ({ data: { Vpcs: vpcs } }) => { .promise()
const transformedVpcs = vpcs.map(({ VpcId: id }) => ({ id, name: id })); .then(({ Vpcs: vpcs }) =>
vpcs.map(({ VpcId: id }) => ({
resolve(transformedVpcs); value: id,
}) name: id,
.on('error', error => { })),
reject(error); );
}) };
.send();
}); export const fetchSubnets = ({ vpc }) => {
export const fetchSubnets = ({ vpc }) =>
new Promise((resolve, reject) => {
const ec2 = new EC2(); const ec2 = new EC2();
ec2 return ec2
.describeSubnets({ .describeSubnets({
Filters: [ Filters: [
{ {
Name: 'vpc-id', Name: 'vpc-id',
Values: [vpc.id], Values: [vpc],
}, },
], ],
}) })
.on('success', ({ data: { Subnets: subnets } }) => { .promise()
const transformedSubnets = subnets.map(({ SubnetId: id }) => ({ id, name: id })); .then(({ Subnets: subnets }) => subnets.map(({ SubnetId: id }) => ({ id, name: id })));
};
resolve(transformedSubnets); export const fetchSecurityGroups = ({ vpc }) => {
}) const ec2 = new EC2();
.on('error', error => {
reject(error); return ec2
.describeSecurityGroups({
Filters: [
{
Name: 'vpc-id',
Values: [vpc],
},
],
}) })
.send(); .promise()
}); .then(({ SecurityGroups: securityGroups }) =>
securityGroups.map(({ GroupName: name, GroupId: value }) => ({ name, value })),
);
};
export default () => {}; export default () => {};
import * as types from './mutation_types'; import * as types from './mutation_types';
export const setClusterName = ({ commit }, payload) => {
commit(types.SET_CLUSTER_NAME, payload);
};
export const setEnvironmentScope = ({ commit }, payload) => {
commit(types.SET_ENVIRONMENT_SCOPE, payload);
};
export const setKubernetesVersion = ({ commit }, payload) => {
commit(types.SET_KUBERNETES_VERSION, payload);
};
export const setRegion = ({ commit }, payload) => { export const setRegion = ({ commit }, payload) => {
commit(types.SET_REGION, payload); commit(types.SET_REGION, payload);
}; };
...@@ -20,4 +32,12 @@ export const setRole = ({ commit }, payload) => { ...@@ -20,4 +32,12 @@ export const setRole = ({ commit }, payload) => {
commit(types.SET_ROLE, payload); commit(types.SET_ROLE, payload);
}; };
export const setSecurityGroup = ({ commit }, payload) => {
commit(types.SET_SECURITY_GROUP, payload);
};
export const setGitlabManagedCluster = ({ commit }, payload) => {
commit(types.SET_GITLAB_MANAGED_CLUSTER, payload);
};
export default () => {}; export default () => {};
...@@ -35,6 +35,10 @@ const createStore = () => ...@@ -35,6 +35,10 @@ const createStore = () =>
namespaced: true, namespaced: true,
...clusterDropdownStore(awsServices.fetchSubnets), ...clusterDropdownStore(awsServices.fetchSubnets),
}, },
securityGroups: {
namespaced: true,
...clusterDropdownStore(awsServices.fetchSecurityGroups),
},
}, },
}); });
......
export const SET_CLUSTER_NAME = 'SET_CLUSTER_NAME';
export const SET_ENVIRONMENT_SCOPE = 'SET_ENVIRONMENT_SCOPE';
export const SET_KUBERNETES_VERSION = 'SET_KUBERNETES_VERSION';
export const SET_REGION = 'SET_REGION'; export const SET_REGION = 'SET_REGION';
export const SET_VPC = 'SET_VPC'; export const SET_VPC = 'SET_VPC';
export const SET_KEY_PAIR = 'SET_KEY_PAIR'; export const SET_KEY_PAIR = 'SET_KEY_PAIR';
export const SET_SUBNET = 'SET_SUBNET'; export const SET_SUBNET = 'SET_SUBNET';
export const SET_ROLE = 'SET_ROLE'; export const SET_ROLE = 'SET_ROLE';
export const SET_SECURITY_GROUP = 'SET_SECURITY_GROUP';
export const SET_GITLAB_MANAGED_CLUSTER = 'SET_GITLAB_MANAGED_CLUSTER';
import * as types from './mutation_types'; import * as types from './mutation_types';
export default { export default {
[types.SET_CLUSTER_NAME](state, { clusterName }) {
state.clusterName = clusterName;
},
[types.SET_ENVIRONMENT_SCOPE](state, { environmentScope }) {
state.environmentScope = environmentScope;
},
[types.SET_KUBERNETES_VERSION](state, { kubernetesVersion }) {
state.kubernetesVersion = kubernetesVersion;
},
[types.SET_REGION](state, { region }) { [types.SET_REGION](state, { region }) {
state.selectedRegion = region; state.selectedRegion = region;
}, },
...@@ -16,4 +25,10 @@ export default { ...@@ -16,4 +25,10 @@ export default {
[types.SET_ROLE](state, { role }) { [types.SET_ROLE](state, { role }) {
state.selectedRole = role; state.selectedRole = role;
}, },
[types.SET_SECURITY_GROUP](state, { securityGroup }) {
state.selectedSecurityGroup = securityGroup;
},
[types.SET_GITLAB_MANAGED_CLUSTER](state, { gitlabManagedCluster }) {
state.gitlabManagedCluster = gitlabManagedCluster;
},
}; };
import { KUBERNETES_VERSIONS } from '../constants';
export default () => ({ export default () => ({
isValidatingCredentials: false, isValidatingCredentials: false,
validCredentials: false, validCredentials: false,
clusterName: '',
environmentScope: '*',
kubernetesVersion: [KUBERNETES_VERSIONS].value,
selectedRegion: '', selectedRegion: '',
selectedRole: '', selectedRole: '',
selectedKeyPair: '', selectedKeyPair: '',
selectedVpc: '', selectedVpc: '',
selectedSubnet: '', selectedSubnet: '',
selectedSecurityGroup: '', selectedSecurityGroup: '',
gitlabManagedCluster: true,
}); });
...@@ -48,7 +48,7 @@ export default { ...@@ -48,7 +48,7 @@ export default {
<template> <template>
<gl-link <gl-link
:id="lineNumberId" :id="lineNumberId"
class="d-inline-block text-right position-absolute line-number" class="d-inline-block text-right line-number"
:href="buildLineNumber" :href="buildLineNumber"
>{{ parsedLineNumber }}</gl-link >{{ parsedLineNumber }}</gl-link
> >
......
...@@ -169,6 +169,7 @@ export default class MergeRequestStore { ...@@ -169,6 +169,7 @@ export default class MergeRequestStore {
this.mergeRequestPipelinesHelpPath = data.merge_request_pipelines_docs_path; this.mergeRequestPipelinesHelpPath = data.merge_request_pipelines_docs_path;
this.conflictsDocsPath = data.conflicts_docs_path; this.conflictsDocsPath = data.conflicts_docs_path;
this.ciEnvironmentsStatusPath = data.ci_environments_status_path; this.ciEnvironmentsStatusPath = data.ci_environments_status_path;
this.securityApprovalsHelpPagePath = data.security_approvals_help_page_path;
} }
get isNothingToMergeState() { get isNothingToMergeState() {
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
border-radius: $border-radius-small; border-radius: $border-radius-small;
min-height: 42px; min-height: 42px;
background-color: $builds-trace-bg; background-color: $builds-trace-bg;
white-space: pre-wrap;
} }
.log-line { .log-line {
...@@ -17,7 +18,7 @@ ...@@ -17,7 +18,7 @@
} }
.line-number { .line-number {
color: $gl-text-color-inverted; color: $gl-gray-500;
padding: 0 $gl-padding-8; padding: 0 $gl-padding-8;
min-width: $job-line-number-width; min-width: $job-line-number-width;
margin-left: -$job-line-number-margin; margin-left: -$job-line-number-margin;
...@@ -27,7 +28,7 @@ ...@@ -27,7 +28,7 @@
&:active, &:active,
&:visited { &:visited {
text-decoration: underline; text-decoration: underline;
color: $gl-text-color-inverted; color: $gl-gray-500;
} }
} }
......
...@@ -12,27 +12,11 @@ module ReleasesHelper ...@@ -12,27 +12,11 @@ module ReleasesHelper
help_page_path(DOCUMENTATION_PATH) help_page_path(DOCUMENTATION_PATH)
end end
def url_for_merge_requests
project_merge_requests_url(@project, params_for_issue_and_mr_paths)
end
def url_for_issues
project_issues_url(@project, params_for_issue_and_mr_paths)
end
def data_for_releases_page def data_for_releases_page
{ {
project_id: @project.id, project_id: @project.id,
illustration_path: illustration, illustration_path: illustration,
documentation_path: help_page, documentation_path: help_page
merge_requests_url: url_for_merge_requests,
issues_url: url_for_issues
} }
end end
private
def params_for_issue_and_mr_paths
{ scope: 'all', state: 'opened' }
end
end end
.js-create-eks-cluster-form-container .js-create-eks-cluster-form-container{ data: { 'gitlab-managed-cluster-help-path' => help_page_path('user/project/clusters/index.md', anchor: 'gitlab-managed-clusters') } }
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
window.gl.mrWidgetData.squash_before_merge_help_path = '#{help_page_path("user/project/merge_requests/squash_and_merge")}'; window.gl.mrWidgetData.squash_before_merge_help_path = '#{help_page_path("user/project/merge_requests/squash_and_merge")}';
window.gl.mrWidgetData.troubleshooting_docs_path = '#{help_page_path('user/project/merge_requests/index.md', anchor: 'troubleshooting')}'; window.gl.mrWidgetData.troubleshooting_docs_path = '#{help_page_path('user/project/merge_requests/index.md', anchor: 'troubleshooting')}';
window.gl.mrWidgetData.security_approvals_help_page_path = '#{help_page_path('user/application_security/index.html', anchor: 'security-approvals-in-merge-requests-ultimate')}';
#js-vue-mr-widget.mr-widget #js-vue-mr-widget.mr-widget
......
---
title: Adds sorting of packages at the group level
merge_request: 18062
author:
type: added
---
title: Provide Merge requests and Issue links through the Release API
merge_request: 18311
author:
type: added
...@@ -244,17 +244,14 @@ adjusted prior to certification based on performance testing. ...@@ -244,17 +244,14 @@ adjusted prior to certification based on performance testing.
| 7 GitLab Rails <br> - Puma workers on each node set to 90% of available CPUs with 16 threads | 32 vCPU, 28.8GB Memory | n1-highcpu-32 | | 7 GitLab Rails <br> - Puma workers on each node set to 90% of available CPUs with 16 threads | 32 vCPU, 28.8GB Memory | n1-highcpu-32 |
| 3 PostgreSQL | 8 vCPU, 30GB Memory | n1-standard-8 | | 3 PostgreSQL | 8 vCPU, 30GB Memory | n1-standard-8 |
| 1 PgBouncer | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | | 1 PgBouncer | 2 vCPU, 1.8GB Memory | n1-highcpu-2 |
| 2 Gitaly <br> - Gitaly Ruby workers on each node set to 90% of available CPUs with 16 threads | 32 vCPU, 120GB Memory | n1-standard-32 | | X Gitaly[^1] <br> - Gitaly Ruby workers on each node set to 90% of available CPUs with 16 threads | 32 vCPU, 120GB Memory | n1-standard-32 |
| 3 Redis Cache + Sentinel <br> - Cache maxmemory set to 90% of available memory | 4 vCPU, 15GB Memory | n1-standard-4 | | 3 Redis Cache + Sentinel <br> - Cache maxmemory set to 90% of available memory | 4 vCPU, 15GB Memory | n1-standard-4 |
| 3 Redis Persistent + Sentinel | 4 vCPU, 15GB Memory | n1-standard-4 | | 3 Redis Persistent + Sentinel | 4 vCPU, 15GB Memory | n1-standard-4 |
| 4 Sidekiq | 4 vCPU, 15GB Memory | n1-standard-4 | | 4 Sidekiq | 4 vCPU, 15GB Memory | n1-standard-4 |
| 3 Consul | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | | 3 Consul | 2 vCPU, 1.8GB Memory | n1-highcpu-2 |
| 1 NFS Server | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | | 1 NFS Server | 2 vCPU, 1.8GB Memory | n1-highcpu-2 |
| 1 Monitoring node | 4 CPU, 3.6GB Memory | n1-highcpu-4 | | 1 Monitoring node | 4 CPU, 3.6GB Memory | n1-highcpu-4 |
| 1 Load Balancing node | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | | 1 Load Balancing node[^2] . | 2 vCPU, 1.8GB Memory | n1-highcpu-2 |
NOTE: **Note:** At this time, HAProxy is the only tested and recommended load
balancer. We may test and add additional options to this list in time.
### 50,000 User Configuration ### 50,000 User Configuration
...@@ -275,14 +272,20 @@ testing. ...@@ -275,14 +272,20 @@ testing.
| 15 GitLab Rails <br> - Puma workers on each node set to 90% of available CPUs with 16 threads | 32 vCPU, 28.8GB Memory | n1-highcpu-32 | | 15 GitLab Rails <br> - Puma workers on each node set to 90% of available CPUs with 16 threads | 32 vCPU, 28.8GB Memory | n1-highcpu-32 |
| 3 PostgreSQL | 8 vCPU, 30GB Memory | n1-standard-8 | | 3 PostgreSQL | 8 vCPU, 30GB Memory | n1-standard-8 |
| 1 PgBouncer | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | | 1 PgBouncer | 2 vCPU, 1.8GB Memory | n1-highcpu-2 |
| 2 Gitaly <br> - Gitaly Ruby workers on each node set to 90% of available CPUs with 16 threads | 64 vCPU, 240GB Memory | n1-standard-64 | | X Gitaly[^1] <br> - Gitaly Ruby workers on each node set to 90% of available CPUs with 16 threads | 64 vCPU, 240GB Memory | n1-standard-64 |
| 3 Redis Cache + Sentinel <br> - Cache maxmemory set to 90% of available memory | 4 vCPU, 15GB Memory | n1-standard-4 | | 3 Redis Cache + Sentinel <br> - Cache maxmemory set to 90% of available memory | 4 vCPU, 15GB Memory | n1-standard-4 |
| 3 Redis Persistent + Sentinel | 4 vCPU, 15GB Memory | n1-standard-4 | | 3 Redis Persistent + Sentinel | 4 vCPU, 15GB Memory | n1-standard-4 |
| 4 Sidekiq | 4 vCPU, 15GB Memory | n1-standard-4 | | 4 Sidekiq | 4 vCPU, 15GB Memory | n1-standard-4 |
| 3 Consul | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | | 3 Consul | 2 vCPU, 1.8GB Memory | n1-highcpu-2 |
| 1 NFS Server | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | | 1 NFS Server | 2 vCPU, 1.8GB Memory | n1-highcpu-2 |
| 1 Monitoring node | 4 CPU, 3.6GB Memory | n1-highcpu-4 | | 1 Monitoring node | 4 CPU, 3.6GB Memory | n1-highcpu-4 |
| 1 Load Balancing node | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | | 1 Load Balancing node[^2] . | 2 vCPU, 1.8GB Memory | n1-highcpu-2 |
[^1]: Gitaly node requirements are dependent on customer data. We recommend 2
nodes as an absolute minimum for performance at the 25,000 user scale and
4 nodes as an absolute minimum at the 50,000 user scale, but additional
nodes should be considered in conjunction with a review of project counts
and sizes.
NOTE: **Note:** At this time, HAProxy is the only tested and recommended load [^2]: HAProxy is the only tested and recommended load balancer. Additional
balancer. We may test and add additional options to this list in time. options may be supported in the future.
...@@ -276,5 +276,5 @@ Parameters: ...@@ -276,5 +276,5 @@ Parameters:
Example request: Example request:
```bash ```bash
curl --request DELETE --header 'Private-Token: <your_access_token>' https://gitlab.example.com/api/v4/groups/26/clusters/23' curl --request DELETE --header 'Private-Token: <your_access_token>' https://gitlab.example.com/api/v4/groups/26/clusters/23
``` ```
...@@ -121,6 +121,10 @@ Example response: ...@@ -121,6 +121,10 @@ Example response:
"external":true "external":true
} }
] ]
},
"_links":{
"merge_requests_url": "https://gitlab.example.com/root/awesome_app/merge_requests?release_tag=v0.2&scope=all&state=opened",
"issues_url": "https://gitlab.example.com/root/awesome_app/issues?release_tag=v0.2&scope=all&state=opened"
} }
}, },
{ {
...@@ -177,6 +181,10 @@ Example response: ...@@ -177,6 +181,10 @@ Example response:
"links":[ "links":[
] ]
},
"_links":{
"merge_requests_url": "https://gitlab.example.com/root/awesome_app/merge_requests?release_tag=v0.1&scope=all&state=opened",
"issues_url": "https://gitlab.example.com/root/awesome_app/issues?release_tag=v0.1&scope=all&state=opened"
} }
} }
] ]
...@@ -288,6 +296,10 @@ Example response: ...@@ -288,6 +296,10 @@ Example response:
"links":[ "links":[
] ]
},
"_links":{
"merge_requests_url": "https://gitlab.example.com/root/awesome_app/merge_requests?release_tag=v0.1&scope=all&state=opened",
"issues_url": "https://gitlab.example.com/root/awesome_app/issues?release_tag=v0.1&scope=all&state=opened"
} }
} }
``` ```
...@@ -413,6 +425,10 @@ Example response: ...@@ -413,6 +425,10 @@ Example response:
"external":true "external":true
} }
] ]
},
"_links":{
"merge_requests_url": "https://gitlab.example.com/root/awesome_app/merge_requests?release_tag=v0.3&scope=all&state=opened",
"issues_url": "https://gitlab.example.com/root/awesome_app/issues?release_tag=v0.3&scope=all&state=opened"
} }
} }
``` ```
...@@ -514,6 +530,10 @@ Example response: ...@@ -514,6 +530,10 @@ Example response:
"links":[ "links":[
] ]
},
"_links":{
"merge_requests_url": "https://gitlab.example.com/root/awesome_app/merge_requests?release_tag=v0.1&scope=all&state=opened",
"issues_url": "https://gitlab.example.com/root/awesome_app/issues?release_tag=v0.1&scope=all&state=opened"
} }
} }
``` ```
...@@ -596,6 +616,10 @@ Example response: ...@@ -596,6 +616,10 @@ Example response:
"links":[ "links":[
] ]
},
"_links":{
"merge_requests_url": "https://gitlab.example.com/root/awesome_app/merge_requests?release_tag=v0.1&scope=all&state=opened",
"issues_url": "https://gitlab.example.com/root/awesome_app/issues?release_tag=v0.1&scope=all&state=opened"
} }
} }
``` ```
......
...@@ -484,6 +484,9 @@ For other punctuation rules, please refer to the ...@@ -484,6 +484,9 @@ For other punctuation rules, please refer to the
- Leave exactly one blank line before and after a heading. - Leave exactly one blank line before and after a heading.
- Do not use links in headings. - Do not use links in headings.
- Add the corresponding [product badge](#product-badges) according to the tier the feature belongs. - Add the corresponding [product badge](#product-badges) according to the tier the feature belongs.
- Use sentence case in headings. Do not capitalize the words of the title, unless
it refers to a product feature. For example, capitalizing "issues" is acceptable in
`## What you can do with GitLab Issues`, but not in `## Closing multiple issues`.
## Links ## Links
......
...@@ -1314,6 +1314,10 @@ module API ...@@ -1314,6 +1314,10 @@ module API
release.links.sorted release.links.sorted
end end
end end
expose :_links do
expose :merge_requests_url
expose :issues_url
end
private private
...@@ -1324,11 +1328,27 @@ module API ...@@ -1324,11 +1328,27 @@ module API
def commit_path def commit_path
return unless object.commit return unless object.commit
Gitlab::Routing.url_helpers.project_commit_path(object.project, object.commit.id) Gitlab::Routing.url_helpers.project_commit_path(project, object.commit.id)
end end
def tag_path def tag_path
Gitlab::Routing.url_helpers.project_tag_path(object.project, object.tag) Gitlab::Routing.url_helpers.project_tag_path(project, object.tag)
end
def merge_requests_url
Gitlab::Routing.url_helpers.project_merge_requests_url(project, params_for_issues_and_mrs)
end
def issues_url
Gitlab::Routing.url_helpers.project_issues_url(project, params_for_issues_and_mrs)
end
def params_for_issues_and_mrs
{ scope: 'all', state: 'opened', release_tag: object.tag }
end
def project
@project ||= object.project
end end
end end
......
...@@ -653,6 +653,12 @@ msgstr "" ...@@ -653,6 +653,12 @@ msgstr ""
msgid "A member of the abuse team will review your report as soon as possible." msgid "A member of the abuse team will review your report as soon as possible."
msgstr "" msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started." msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr "" msgstr ""
...@@ -3402,6 +3408,9 @@ msgstr "" ...@@ -3402,6 +3408,9 @@ msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster." msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr "" msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
msgid "ClusterIntegration|Alternatively" msgid "ClusterIntegration|Alternatively"
msgstr "" msgstr ""
...@@ -3450,6 +3459,9 @@ msgstr "" ...@@ -3450,6 +3459,9 @@ msgstr ""
msgid "ClusterIntegration|Choose a prefix to be used for your namespaces. Defaults to your project path." msgid "ClusterIntegration|Choose a prefix to be used for your namespaces. Defaults to your project path."
msgstr "" msgstr ""
msgid "ClusterIntegration|Choose the %{startLink}security groups%{endLink} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
msgstr ""
msgid "ClusterIntegration|Choose the %{startLink}subnets%{endLink} in your VPC where your worker nodes will run." msgid "ClusterIntegration|Choose the %{startLink}subnets%{endLink} in your VPC where your worker nodes will run."
msgstr "" msgstr ""
...@@ -3504,6 +3516,9 @@ msgstr "" ...@@ -3504,6 +3516,9 @@ msgstr ""
msgid "ClusterIntegration|Could not load regions from your AWS account" msgid "ClusterIntegration|Could not load regions from your AWS account"
msgstr "" msgstr ""
msgid "ClusterIntegration|Could not load security groups for the selected VPC"
msgstr ""
msgid "ClusterIntegration|Could not load subnets for the selected VPC" msgid "ClusterIntegration|Could not load subnets for the selected VPC"
msgstr "" msgstr ""
...@@ -3669,6 +3684,12 @@ msgstr "" ...@@ -3669,6 +3684,12 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project" msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
msgstr "" msgstr ""
msgid "ClusterIntegration|Kubernetes version"
msgstr ""
msgid "ClusterIntegration|Kubernetes version not found"
msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}." msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr "" msgstr ""
...@@ -3702,6 +3723,9 @@ msgstr "" ...@@ -3702,6 +3723,9 @@ msgstr ""
msgid "ClusterIntegration|Loading VPCs" msgid "ClusterIntegration|Loading VPCs"
msgstr "" msgstr ""
msgid "ClusterIntegration|Loading security groups"
msgstr ""
msgid "ClusterIntegration|Loading subnets" msgid "ClusterIntegration|Loading subnets"
msgstr "" msgstr ""
...@@ -3735,6 +3759,9 @@ msgstr "" ...@@ -3735,6 +3759,9 @@ msgstr ""
msgid "ClusterIntegration|No region found" msgid "ClusterIntegration|No region found"
msgstr "" msgstr ""
msgid "ClusterIntegration|No security group found"
msgstr ""
msgid "ClusterIntegration|No subnet found" msgid "ClusterIntegration|No subnet found"
msgstr "" msgstr ""
...@@ -3822,15 +3849,24 @@ msgstr "" ...@@ -3822,15 +3849,24 @@ msgstr ""
msgid "ClusterIntegration|Search regions" msgid "ClusterIntegration|Search regions"
msgstr "" msgstr ""
msgid "ClusterIntegration|Search security groups"
msgstr ""
msgid "ClusterIntegration|Search subnets" msgid "ClusterIntegration|Search subnets"
msgstr "" msgstr ""
msgid "ClusterIntegration|Search zones" msgid "ClusterIntegration|Search zones"
msgstr "" msgstr ""
msgid "ClusterIntegration|Security groups"
msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster" msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "" msgstr ""
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr ""
msgid "ClusterIntegration|Select a VPC to choose a subnet" msgid "ClusterIntegration|Select a VPC to choose a subnet"
msgstr "" msgstr ""
...@@ -4002,6 +4038,9 @@ msgstr "" ...@@ -4002,6 +4038,9 @@ msgstr ""
msgid "ClusterIntergation|Select a region" msgid "ClusterIntergation|Select a region"
msgstr "" msgstr ""
msgid "ClusterIntergation|Select a security group"
msgstr ""
msgid "ClusterIntergation|Select a subnet" msgid "ClusterIntergation|Select a subnet"
msgstr "" msgstr ""
...@@ -9464,6 +9503,12 @@ msgstr "" ...@@ -9464,6 +9503,12 @@ msgstr ""
msgid "Learn more about Kubernetes" msgid "Learn more about Kubernetes"
msgstr "" msgstr ""
msgid "Learn more about License-Check"
msgstr ""
msgid "Learn more about Vulnerability-Check"
msgstr ""
msgid "Learn more about Web Terminal" msgid "Learn more about Web Terminal"
msgstr "" msgstr ""
...@@ -9488,9 +9533,6 @@ msgstr "" ...@@ -9488,9 +9533,6 @@ msgstr ""
msgid "Learn more about the dependency list" msgid "Learn more about the dependency list"
msgstr "" msgstr ""
msgid "Learn more about vulnerability check"
msgstr ""
msgid "Learn more in the" msgid "Learn more in the"
msgstr "" msgstr ""
...@@ -9527,6 +9569,9 @@ msgstr "" ...@@ -9527,6 +9569,9 @@ msgstr ""
msgid "License Compliance" msgid "License Compliance"
msgstr "" msgstr ""
msgid "License-Check"
msgstr ""
msgid "LicenseCompliance|Add a license" msgid "LicenseCompliance|Add a license"
msgstr "" msgstr ""
...@@ -15268,6 +15313,9 @@ msgstr "" ...@@ -15268,6 +15313,9 @@ msgstr ""
msgid "SortOptions|Priority" msgid "SortOptions|Priority"
msgstr "" msgstr ""
msgid "SortOptions|Project"
msgstr ""
msgid "SortOptions|Recent last activity" msgid "SortOptions|Recent last activity"
msgstr "" msgstr ""
...@@ -18213,7 +18261,7 @@ msgstr "" ...@@ -18213,7 +18261,7 @@ msgstr ""
msgid "Vulnerabilities over time" msgid "Vulnerabilities over time"
msgstr "" msgstr ""
msgid "Vulnerability-Check requires one or more merge request approvals only if high or critical security vulnerabilities are detected." msgid "Vulnerability-Check"
msgstr "" msgstr ""
msgid "VulnerabilityChart|%{formattedStartDate} to today" msgid "VulnerabilityChart|%{formattedStartDate} to today"
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment