Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-09-18 09:09:32 +00:00
parent 0115b63f64
commit a8b87b4fe0
39 changed files with 419 additions and 87 deletions

View file

@ -1 +1 @@
b670554eae8643f2072d3b4f6f7c5cd2b9ec8776
b5937b10d1a386c392adb1ebced2d0c8cb038696

View file

@ -25,31 +25,16 @@ export default {
GlLink,
GlButton,
},
props: {
projectId: {
type: String,
required: true,
},
projectPath: {
type: String,
required: true,
},
documentationPath: {
type: String,
required: true,
},
illustrationPath: {
type: String,
required: true,
},
newReleasePath: {
type: String,
required: false,
default: '',
},
},
computed: {
...mapState('list', ['isLoading', 'releases', 'hasError', 'pageInfo']),
...mapState('list', [
'documentationPath',
'illustrationPath',
'newReleasePath',
'isLoading',
'releases',
'hasError',
'pageInfo',
]),
shouldRenderEmptyState() {
return !this.releases.length && !this.hasError && !this.isLoading;
},
@ -65,15 +50,13 @@ export default {
created() {
this.fetchReleases({
page: getParameterByName('page'),
projectId: this.projectId,
projectPath: this.projectPath,
});
},
methods: {
...mapActions('list', ['fetchReleases']),
onChangePage(page) {
historyPushState(buildUrlWithCurrentLocation(`?page=${page}`));
this.fetchReleases({ page, projectId: this.projectId });
this.fetchReleases({ page });
},
},
};

View file

@ -7,7 +7,7 @@ export default {
name: 'ReleasesPaginationGraphql',
components: { GlKeysetPagination },
computed: {
...mapState('list', ['projectPath', 'graphQlPageInfo']),
...mapState('list', ['graphQlPageInfo']),
showPagination() {
return this.graphQlPageInfo.hasPreviousPage || this.graphQlPageInfo.hasNextPage;
},
@ -16,11 +16,11 @@ export default {
...mapActions('list', ['fetchReleasesGraphQl']),
onPrev(before) {
historyPushState(buildUrlWithCurrentLocation(`?before=${before}`));
this.fetchReleasesGraphQl({ projectPath: this.projectPath, before });
this.fetchReleasesGraphQl({ before });
},
onNext(after) {
historyPushState(buildUrlWithCurrentLocation(`?after=${after}`));
this.fetchReleasesGraphQl({ projectPath: this.projectPath, after });
this.fetchReleasesGraphQl({ after });
},
},
};

View file

@ -7,13 +7,13 @@ export default {
name: 'ReleasesPaginationRest',
components: { TablePagination },
computed: {
...mapState('list', ['projectId', 'pageInfo']),
...mapState('list', ['pageInfo']),
},
methods: {
...mapActions('list', ['fetchReleasesRest']),
onChangePage(page) {
historyPushState(buildUrlWithCurrentLocation(`?page=${page}`));
this.fetchReleasesRest({ page, projectId: this.projectId });
this.fetchReleasesRest({ page });
},
},
};

View file

@ -21,9 +21,6 @@ export default () => {
graphqlMilestoneStats: Boolean(gon.features?.graphqlMilestoneStats),
},
}),
render: h =>
h(ReleaseListApp, {
props: el.dataset,
}),
render: h => h(ReleaseListApp),
});
};

View file

@ -23,7 +23,7 @@ export const requestReleases = ({ commit }) => commit(types.REQUEST_RELEASES);
*
* @param {String} projectId
*/
export const fetchReleases = ({ dispatch, rootState }, { page = '1', projectId, projectPath }) => {
export const fetchReleases = ({ dispatch, rootState, state }, { page = '1' }) => {
dispatch('requestReleases');
if (
@ -35,7 +35,7 @@ export const fetchReleases = ({ dispatch, rootState }, { page = '1', projectId,
.query({
query: allReleasesQuery,
variables: {
fullPath: projectPath,
fullPath: state.projectPath,
},
})
.then(response => {
@ -44,7 +44,7 @@ export const fetchReleases = ({ dispatch, rootState }, { page = '1', projectId,
.catch(() => dispatch('receiveReleasesError'));
} else {
api
.releases(projectId, { page })
.releases(state.projectId, { page })
.then(response => dispatch('receiveReleasesSuccess', response))
.catch(() => dispatch('receiveReleasesError'));
}

View file

@ -731,7 +731,6 @@
.issuable-info-container {
flex: 1;
display: flex;
padding-right: $gl-padding;
.issuable-main-info {
flex: 1 auto;

View file

@ -14,7 +14,7 @@
}
.issue {
padding: 10px 0 10px $gl-padding;
padding: 10px $gl-padding;
position: relative;
.title {

View file

@ -170,6 +170,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
def set_application_setting
@application_setting = ApplicationSetting.current_without_cache
@plans = Plan.all
end
def whitelist_query_limiting

View file

@ -0,0 +1,39 @@
# frozen_string_literal: true
class Admin::PlanLimitsController < Admin::ApplicationController
include InternalRedirect
before_action :set_plan_limits
def create
redirect_path = referer_path(request) || general_admin_application_settings_path
respond_to do |format|
if @plan_limits.update(plan_limits_params)
format.json { head :ok }
format.html { redirect_to redirect_path, notice: _('Application limits saved successfully') }
else
format.json { head :bad_request }
format.html { render_update_error }
end
end
end
private
def set_plan_limits
@plan_limits = Plan.find(plan_limits_params[:plan_id]).actual_limits
end
def plan_limits_params
params.require(:plan_limits).permit(%i[
plan_id
conan_max_file_size
maven_max_file_size
npm_max_file_size
nuget_max_file_size
pypi_max_file_size
generic_packages_max_file_size
])
end
end

View file

@ -0,0 +1,50 @@
- if Gitlab.config.packages.enabled
%section.settings.as-package.no-animate#js-package-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
%h4
= _('Package Registry')
%button.btn.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _("Settings related to the use and experience of using GitLab's Package Registry.")
= render_if_exists 'admin/application_settings/ee_package_registry'
.settings-content
%h4
= _('Package file size limits')
%p
= _('Set limit to 0 to allow any file size.')
.scrolling-tabs-container.inner-page-scroll-tabs
- if @plans.size > 1
%ul.nav-links.scrolling-tabs.mobile-separator.nav.nav-tabs.mb-3
- @plans.each_with_index do |plan, index|
%li
= link_to admin_plan_limits_path(anchor: 'js-package-settings'), data: { target: "div#plan#{index}", action: "plan#{index}", toggle: 'tab'}, class: index == 0 ? 'active': '' do
= plan.name.capitalize
.tab-content
- @plans.each_with_index do |plan, index|
.tab-pane{ :id => "plan#{index}", class: index == 0 ? 'active': '' }
= form_for plan.actual_limits, url: admin_plan_limits_path(anchor: 'js-package-settings'), html: { class: 'fieldset-form' }, method: :post do |f|
= form_errors(plan)
%fieldset
= f.hidden_field(:plan_id, value: plan.id)
.form-group
= f.label :conan_max_file_size, _('Maximum Conan package file size in bytes'), class: 'label-bold'
= f.number_field :conan_max_file_size, class: 'form-control'
.form-group
= f.label :maven_max_file_size, _('Maximum Maven package file size in bytes'), class: 'label-bold'
= f.number_field :maven_max_file_size, class: 'form-control'
.form-group
= f.label :npm_max_file_size, _('Maximum NPM package file size in bytes'), class: 'label-bold'
= f.number_field :npm_max_file_size, class: 'form-control'
.form-group
= f.label :nuget_max_file_size, _('Maximum NuGet package file size in bytes'), class: 'label-bold'
= f.number_field :nuget_max_file_size, class: 'form-control'
.form-group
= f.label :pypi_max_file_size, _('Maximum PyPI package file size in bytes'), class: 'label-bold'
= f.number_field :pypi_max_file_size, class: 'form-control'
.form-group
= f.label :generic_packages_max_file_size, _('Generic package file size in bytes'), class: 'label-bold'
= f.number_field :generic_packages_max_file_size, class: 'form-control'
= f.submit _('Save %{name} size limits').html_safe % { name: plan.name.capitalize }, class: 'btn gl-button btn-success'

View file

@ -21,6 +21,6 @@
.text-secondary
= s_('ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline.')
.form-check.mb-2
= form.check_box :only_allow_merge_if_all_discussions_are_resolved, class: 'form-check-input'
= form.check_box :only_allow_merge_if_all_discussions_are_resolved, class: 'form-check-input', data: { qa_selector: 'allow_merge_if_all_discussions_are_resolved_checkbox' }
= form.label :only_allow_merge_if_all_discussions_are_resolved, class: 'form-check-label' do
= s_('ProjectSettings|All discussions must be resolved')

View file

@ -0,0 +1,5 @@
---
title: Add admin UI for adjusting package file size limits
merge_request: 40423
author:
type: added

View file

@ -0,0 +1,5 @@
---
title: Remove an extra spacing from Dashboard Issues
merge_request: 42459
author: Takuya Noguchi
type: fixed

View file

@ -141,6 +141,8 @@ namespace :admin do
get :status_delete_self_monitoring_project
end
resources :plan_limits, only: :create
resources :labels
resources :runners, only: [:index, :show, :update, :destroy] do

View file

@ -167,6 +167,14 @@ added to GitLab to configure SSL certificates. See
[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
for details on managing SSL certificates and configuring NGINX.
### Readiness checks
Ensure the external load balancer only routes to working services with built
in monitoring endpoints. The [readiness checks](../../user/admin_area/monitoring/health_check.md)
all require [additional configuration](../monitoring/ip_whitelist.md)
on the nodes being checked, otherwise, the external load balancer will not be able to
connect.
### Ports
The basic ports to be used are shown in the table below.

View file

@ -167,6 +167,14 @@ added to GitLab to configure SSL certificates. See
[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
for details on managing SSL certificates and configuring NGINX.
### Readiness checks
Ensure the external load balancer only routes to working services with built
in monitoring endpoints. The [readiness checks](../../user/admin_area/monitoring/health_check.md)
all require [additional configuration](../monitoring/ip_whitelist.md)
on the nodes being checked, otherwise, the external load balancer will not be able to
connect.
### Ports
The basic ports to be used are shown in the table below.

View file

@ -42,7 +42,7 @@ doesn't require you to provision and maintain a node.
To set up GitLab and its components to accommodate up to 2,000 users:
1. [Configure the external load balancing node](#configure-the-load-balancer)
1. [Configure the external load balancing node](#configure-the-external-load-balancer)
to handle the load balancing of the two GitLab application services nodes.
1. [Configure PostgreSQL](#configure-postgresql), the database for GitLab.
1. [Configure Redis](#configure-redis).
@ -60,7 +60,7 @@ To set up GitLab and its components to accommodate up to 2,000 users:
storage. You can skip this step if you're not using GitLab Pages (which
requires NFS).
## Configure the load balancer
## Configure the external load balancer
NOTE: **Note:**
This architecture has been tested and validated with [HAProxy](https://www.haproxy.org/).
@ -115,6 +115,14 @@ need to add a configuration to GitLab to configure SSL certificates. For
details about managing SSL certificates and configuring NGINX, see the
[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https).
### Readiness checks
Ensure the external load balancer only routes to working services with built
in monitoring endpoints. The [readiness checks](../../user/admin_area/monitoring/health_check.md)
all require [additional configuration](../monitoring/ip_whitelist.md)
on the nodes being checked, otherwise, the external load balancer will not be able to
connect.
### Ports
The basic load balancer ports you should use are described in the following
@ -568,7 +576,7 @@ On each node perform the following:
1. Create/edit `/etc/gitlab/gitlab.rb` and use the following configuration.
To maintain uniformity of links across nodes, the `external_url`
on the application server should point to the external URL that users will use
to access GitLab. This would be the URL of the [load balancer](#configure-the-load-balancer)
to access GitLab. This would be the URL of the [load balancer](#configure-the-external-load-balancer)
which will route traffic to the GitLab application server:
```ruby

View file

@ -162,6 +162,14 @@ added to GitLab to configure SSL certificates. See
[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
for details on managing SSL certificates and configuring NGINX.
### Readiness checks
Ensure the external load balancer only routes to working services with built
in monitoring endpoints. The [readiness checks](../../user/admin_area/monitoring/health_check.md)
all require [additional configuration](../monitoring/ip_whitelist.md)
on the nodes being checked, otherwise, the external load balancer will not be able to
connect.
### Ports
The basic ports to be used are shown in the table below.

View file

@ -167,6 +167,14 @@ added to GitLab to configure SSL certificates. See
[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
for details on managing SSL certificates and configuring NGINX.
### Readiness checks
Ensure the external load balancer only routes to working services with built
in monitoring endpoints. The [readiness checks](../../user/admin_area/monitoring/health_check.md)
all require [additional configuration](../monitoring/ip_whitelist.md)
on the nodes being checked, otherwise, the external load balancer will not be able to
connect.
### Ports
The basic ports to be used are shown in the table below.

View file

@ -162,6 +162,14 @@ added to GitLab to configure SSL certificates. See
[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
for details on managing SSL certificates and configuring NGINX.
### Readiness checks
Ensure the external load balancer only routes to working services with built
in monitoring endpoints. The [readiness checks](../../user/admin_area/monitoring/health_check.md)
all require [additional configuration](../monitoring/ip_whitelist.md)
on the nodes being checked, otherwise, the external load balancer will not be able to
connect.
### Ports
The basic ports to be used are shown in the table below.

View file

@ -311,13 +311,20 @@ sudo adduser --disabled-login --gecos 'GitLab' git
## 6. Database
NOTE: **Note:**
Starting from GitLab 12.1, only PostgreSQL is supported. Since GitLab 13.0, we require PostgreSQL 11+.
Starting from GitLab 12.1, only PostgreSQL is supported. Since GitLab 13.0, we [require PostgreSQL 11+](requirements.md#postgresql-requirements).
1. Install the database packages:
```shell
sudo apt-get install -y postgresql postgresql-client libpq-dev postgresql-contrib
```
1. Verify the PostgreSQL version you have is supported by the version of GitLab you're
installing:
```shell
psql --version
```
1. Start the PostgreSQL service and confirm that the service is running:

View file

@ -140,7 +140,6 @@ We highly recommend users to use the minimum PostgreSQL versions specified below
GitLab version | Minimum PostgreSQL version
-|-
10.0 | 9.6
12.10 | 11
13.0 | 11
You must also ensure the `pg_trgm` and `btree_gist` extensions are [loaded into every

View file

@ -196,7 +196,9 @@ To set required pipeline configuration:
![Required pipeline](img/admin_required_pipeline.png)
## Package Registry configuration **(PREMIUM ONLY)**
## Package Registry configuration
### NPM Forwarding **(PREMIUM ONLY)**
GitLab administrators can disable the forwarding of NPM requests to [npmjs.com](https://www.npmjs.com/).
@ -208,3 +210,15 @@ To disable it:
1. Click **Save changes**.
![NPM package requests forwarding](img/admin_package_registry_npm_package_requests_forward.png)
### Package file size limits
GitLab administrators can adjust the maximum allowed file size for each package type.
To set the maximum file size:
1. Go to **Admin Area > Settings > CI/CD**.
1. Expand the **Package Registry** section.
1. Find the package type you would like to adjust.
1. Enter the maximum file size, in bytes.
1. Click **Save size limits**.

View file

@ -3101,6 +3101,9 @@ msgstr ""
msgid "Application ID"
msgstr ""
msgid "Application limits saved successfully"
msgstr ""
msgid "Application settings saved successfully"
msgstr ""
@ -11378,6 +11381,9 @@ msgstr ""
msgid "Generate new token"
msgstr ""
msgid "Generic package file size in bytes"
msgstr ""
msgid "Geo"
msgstr ""
@ -15403,6 +15409,21 @@ msgstr ""
msgid "Max size 15 MB"
msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
msgid "Maximum Maven package file size in bytes"
msgstr ""
msgid "Maximum NPM package file size in bytes"
msgstr ""
msgid "Maximum NuGet package file size in bytes"
msgstr ""
msgid "Maximum PyPI package file size in bytes"
msgstr ""
msgid "Maximum Users:"
msgstr ""
@ -17862,6 +17883,9 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
msgid "Package file size limits"
msgstr ""
msgid "Package recipe already exists"
msgstr ""
@ -21987,6 +22011,9 @@ msgstr ""
msgid "Save"
msgstr ""
msgid "Save %{name} size limits"
msgstr ""
msgid "Save Changes"
msgstr ""
@ -23048,6 +23075,9 @@ msgstr ""
msgid "Set iteration"
msgstr ""
msgid "Set limit to 0 to allow any file size."
msgstr ""
msgid "Set max session time for web terminal."
msgstr ""

View file

@ -15,6 +15,10 @@ module QA
element :radio_button_merge_ff
end
view 'app/views/projects/_merge_request_merge_checks_settings.html.haml' do
element :allow_merge_if_all_discussions_are_resolved_checkbox
end
def click_save_changes
click_element :save_merge_request_changes
end
@ -23,6 +27,11 @@ module QA
click_element :radio_button_merge_ff
click_save_changes
end
def enable_merge_if_all_disscussions_are_resolved
click_element :allow_merge_if_all_discussions_are_resolved_checkbox
click_save_changes
end
end
end
end

View file

@ -22,6 +22,7 @@ module RuboCop
def on_send(node)
distinct_count?(node) do |method_name, method_arguments|
next unless method_arguments && method_arguments.length >= 2
next if batch_set_to_false?(method_arguments[2])
next if allowed_foreign_key?(method_arguments[1])
add_offense(node, location: :selector, message: format(MSG, method_name))
@ -37,6 +38,21 @@ module RuboCop
def allowed_foreign_keys
(cop_config['AllowedForeignKeys'] || []).map(&:to_s)
end
def batch_set_to_false?(options)
return false unless options.is_a?(RuboCop::AST::HashNode)
batch_set_to_false = false
options.each_pair do |key, value|
next unless value.boolean_type? && value.falsey_literal?
next unless key.type == :sym && key.value == :batch
batch_set_to_false = true
break
end
batch_set_to_false
end
end
end
end

View file

@ -0,0 +1,45 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Admin::PlanLimitsController do
let_it_be(:plan) { create(:plan) }
let_it_be(:plan_limits) { create(:plan_limits, plan: plan) }
describe 'POST create' do
let(:params) do
{
plan_limits: {
plan_id: plan.id,
conan_max_file_size: file_size, id: plan_limits.id
}
}
end
context 'with an authenticated admin user' do
let(:file_size) { 10.megabytes }
it 'updates the plan limits', :aggregate_failures do
sign_in(create(:admin))
post :create, params: params
expect(response).to redirect_to(general_admin_application_settings_path)
expect(plan_limits.reload.conan_max_file_size).to eq(file_size)
end
end
context 'without admin access' do
let(:file_size) { 1.megabytes }
it 'returns `not_found`' do
sign_in(create(:user))
post :create, params: params
expect(response).to have_gitlab_http_status(:not_found)
expect(plan_limits.conan_max_file_size).not_to eq(file_size)
end
end
end
end

View file

@ -7,5 +7,14 @@ FactoryBot.define do
trait :default_plan do
plan factory: :default_plan
end
trait :with_package_file_sizes do
conan_max_file_size { 100 }
maven_max_file_size { 100 }
npm_max_file_size { 100 }
nuget_max_file_size { 100 }
pypi_max_file_size { 100 }
generic_packages_max_file_size { 100 }
end
end
end

View file

@ -7,11 +7,6 @@ RSpec.describe 'Expand and collapse diffs', :js do
let(:project) { create(:project, :repository) }
before do
# Set the limits to those when these specs were written, to avoid having to
# update the test repo every time we change them.
allow(Gitlab::Git::Diff).to receive(:size_limit).and_return(100.kilobytes)
allow(Gitlab::Git::Diff).to receive(:collapse_limit).and_return(10.kilobytes)
sign_in(create(:admin))
# Ensure that undiffable.md is in .gitattributes

View file

@ -7,9 +7,6 @@ RSpec.describe 'User expands diff', :js do
let(:merge_request) { create(:merge_request, source_branch: 'expand-collapse-files', source_project: project, target_project: project) }
before do
allow(Gitlab::Git::Diff).to receive(:size_limit).and_return(100.kilobytes)
allow(Gitlab::Git::Diff).to receive(:collapse_limit).and_return(10.kilobytes)
visit(diffs_project_merge_request_path(project, merge_request))
wait_for_requests

View file

@ -11,9 +11,6 @@ RSpec.describe 'User views diffs file-by-file', :js do
let(:user) { create(:user, view_diffs_file_by_file: true) }
before do
allow(Gitlab::Git::Diff).to receive(:size_limit).and_return(100.kilobytes)
allow(Gitlab::Git::Diff).to receive(:collapse_limit).and_return(10.kilobytes)
project.add_developer(user)
sign_in(user)

View file

@ -27,15 +27,18 @@ describe('Releases App ', () => {
tagName: `${index}.00`,
}));
const defaultProps = {
const defaultInitialState = {
projectId: 'gitlab-ce',
projectPath: 'gitlab-org/gitlab-ce',
documentationPath: 'help/releases',
illustrationPath: 'illustration/path',
};
const createComponent = (propsData = defaultProps) => {
const listModule = createListModule({});
const createComponent = (stateUpdates = {}) => {
const listModule = createListModule({
...defaultInitialState,
...stateUpdates,
});
fetchReleaseSpy = jest.spyOn(listModule.actions, 'fetchReleases');
@ -51,7 +54,6 @@ describe('Releases App ', () => {
wrapper = shallowMount(ReleasesApp, {
store,
localVue,
propsData,
});
};
@ -68,13 +70,9 @@ describe('Releases App ', () => {
createComponent();
});
it('calls fetchRelease with the page, project ID, and project path', () => {
it('calls fetchRelease with the page parameter', () => {
expect(fetchReleaseSpy).toHaveBeenCalledTimes(1);
expect(fetchReleaseSpy).toHaveBeenCalledWith(expect.anything(), {
page: null,
projectId: defaultProps.projectId,
projectPath: defaultProps.projectPath,
});
expect(fetchReleaseSpy).toHaveBeenCalledWith(expect.anything(), { page: null });
});
});
@ -156,7 +154,7 @@ describe('Releases App ', () => {
const newReleasePath = 'path/to/new/release';
beforeEach(() => {
createComponent({ ...defaultProps, newReleasePath });
createComponent({ ...defaultInitialState, newReleasePath });
});
it('renders the "New release" button', () => {

View file

@ -143,7 +143,7 @@ describe('~/releases/components/releases_pagination_graphql.vue', () => {
it('calls fetchReleasesGraphQl with the correct after cursor', () => {
expect(listModule.actions.fetchReleasesGraphQl.mock.calls).toEqual([
[expect.anything(), { projectPath, after: cursors.endCursor }],
[expect.anything(), { after: cursors.endCursor }],
]);
});
@ -161,7 +161,7 @@ describe('~/releases/components/releases_pagination_graphql.vue', () => {
it('calls fetchReleasesGraphQl with the correct before cursor', () => {
expect(listModule.actions.fetchReleasesGraphQl.mock.calls).toEqual([
[expect.anything(), { projectPath, before: cursors.startCursor }],
[expect.anything(), { before: cursors.startCursor }],
]);
});

View file

@ -59,7 +59,7 @@ describe('~/releases/components/releases_pagination_rest.vue', () => {
it('calls fetchReleasesRest with the correct page', () => {
expect(listModule.actions.fetchReleasesRest.mock.calls).toEqual([
[expect.anything(), { projectId, page: newPage }],
[expect.anything(), { page: newPage }],
]);
});

View file

@ -23,11 +23,16 @@ describe('Releases State actions', () => {
let pageInfo;
let releases;
let graphqlReleasesResponse;
let projectPath;
const projectPath = 'root/test-project';
const projectId = 19;
beforeEach(() => {
mockedState = {
...createState({}),
...createState({
projectId,
projectPath,
}),
featureFlags: {
graphqlReleaseData: true,
graphqlReleasesPage: true,
@ -38,7 +43,6 @@ describe('Releases State actions', () => {
pageInfo = parseIntPagination(pageInfoHeadersWithoutPagination);
releases = convertObjectPropsToCamelCase(originalReleases, { deep: true });
graphqlReleasesResponse = cloneDeep(originalGraphqlReleasesResponse);
projectPath = 'root/test-project';
});
describe('requestReleases', () => {
@ -51,7 +55,7 @@ describe('Releases State actions', () => {
describe('success', () => {
it('dispatches requestReleases and receiveReleasesSuccess', done => {
jest.spyOn(gqClient, 'query').mockImplementation(({ query, variables }) => {
expect(query).toEqual(allReleasesQuery);
expect(query).toBe(allReleasesQuery);
expect(variables).toEqual({
fullPath: projectPath,
});
@ -60,7 +64,7 @@ describe('Releases State actions', () => {
testAction(
fetchReleases,
{ projectPath },
{},
mockedState,
[],
[
@ -83,7 +87,7 @@ describe('Releases State actions', () => {
testAction(
fetchReleases,
{ projectPath },
{},
mockedState,
[],
[
@ -107,14 +111,14 @@ describe('Releases State actions', () => {
describe('success', () => {
it('dispatches requestReleases and receiveReleasesSuccess', done => {
jest.spyOn(api, 'releases').mockImplementation((id, options) => {
expect(id).toEqual(1);
expect(options.page).toEqual('1');
expect(id).toBe(projectId);
expect(options.page).toBe('1');
return Promise.resolve({ data: releases, headers: pageInfoHeadersWithoutPagination });
});
testAction(
fetchReleases,
{ projectId: 1 },
{},
mockedState,
[],
[
@ -132,13 +136,13 @@ describe('Releases State actions', () => {
it('dispatches requestReleases and receiveReleasesSuccess on page two', done => {
jest.spyOn(api, 'releases').mockImplementation((_, options) => {
expect(options.page).toEqual('2');
expect(options.page).toBe('2');
return Promise.resolve({ data: releases, headers: pageInfoHeadersWithoutPagination });
});
testAction(
fetchReleases,
{ page: '2', projectId: 1 },
{ page: '2' },
mockedState,
[],
[
@ -161,7 +165,7 @@ describe('Releases State actions', () => {
testAction(
fetchReleases,
{ projectId: null },
{},
mockedState,
[],
[

View file

@ -178,3 +178,9 @@ RSpec.describe Admin::SessionsController, "routing" do
expect(post("/admin/session/destroy")).to route_to('admin/sessions#destroy')
end
end
RSpec.describe Admin::PlanLimitsController, "routing" do
it "to #create" do
expect(post("/admin/plan_limits")).to route_to('admin/plan_limits#create')
end
end

View file

@ -21,11 +21,23 @@ RSpec.describe RuboCop::Cop::UsageData::DistinctCountByLargeForeignKey, type: :r
subject(:cop) { described_class.new(config) }
context 'when counting by disallowed key' do
it 'register an offence' do
it 'registers an offence' do
inspect_source('distinct_count(Issue, :creator_id)')
expect(cop.offenses.size).to eq(1)
end
it 'does not register an offence when batch is false' do
inspect_source('distinct_count(Issue, :creator_id, batch: false)')
expect(cop.offenses).to be_empty
end
it 'register an offence when batch is true' do
inspect_source('distinct_count(Issue, :creator_id, batch: true)')
expect(cop.offenses.size).to eq(1)
end
end
context 'when calling by allowed key' do

View file

@ -0,0 +1,65 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'admin/application_settings/_package_registry' do
let_it_be(:admin) { create(:admin) }
let_it_be(:default_plan_limits) { create(:plan_limits, :default_plan, :with_package_file_sizes) }
let_it_be(:application_setting) { build(:application_setting) }
let(:page) { Capybara::Node::Simple.new(rendered) }
before do
assign(:application_setting, application_setting)
allow(view).to receive(:current_user) { admin }
allow(view).to receive(:expanded) { true }
end
subject { render partial: 'admin/application_settings/package_registry' }
context 'package file size limits' do
before do
assign(:plans, [default_plan_limits.plan])
end
it 'has fields for max package file sizes' do
subject
expect(rendered).to have_field('Maximum Conan package file size in bytes', type: 'number')
expect(page.find_field('Maximum Conan package file size in bytes').value).to eq(default_plan_limits.conan_max_file_size.to_s)
expect(rendered).to have_field('Maximum Maven package file size in bytes', type: 'number')
expect(page.find_field('Maximum Maven package file size in bytes').value).to eq(default_plan_limits.maven_max_file_size.to_s)
expect(rendered).to have_field('Maximum NPM package file size in bytes', type: 'number')
expect(page.find_field('Maximum NPM package file size in bytes').value).to eq(default_plan_limits.npm_max_file_size.to_s)
expect(rendered).to have_field('Maximum NuGet package file size in bytes', type: 'number')
expect(page.find_field('Maximum NuGet package file size in bytes').value).to eq(default_plan_limits.nuget_max_file_size.to_s)
expect(rendered).to have_field('Maximum PyPI package file size in bytes', type: 'number')
expect(page.find_field('Maximum PyPI package file size in bytes').value).to eq(default_plan_limits.pypi_max_file_size.to_s)
end
it 'does not display the plan name when there is only one plan' do
subject
expect(page).not_to have_content('Default')
end
end
context 'with multiple plans' do
let_it_be(:plan) { create(:plan, name: 'Gold') }
let_it_be(:gold_plan_limits) { create(:plan_limits, :with_package_file_sizes, plan: plan) }
before do
assign(:plans, [default_plan_limits.plan, gold_plan_limits.plan])
end
it 'displays the plan name when there is more than one plan' do
subject
expect(page).to have_content('Default')
expect(page).to have_content('Gold')
end
end
end