Skip to content
Snippets Groups Projects
Commit fca89bb7 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 76e9fc7b
No related branches found
No related tags found
No related merge requests found
Showing
with 222 additions and 43 deletions
Loading
Loading
@@ -18,7 +18,7 @@ a database schema.
 
Adding a `:migration` tag to a test signature enables some custom RSpec
`before` and `after` hooks in our
[`spec_helper.rb`](https://gitlab.com/gitlab-org/gitlab/blob/3b29908a64ff729c0cf6d93452fe00ab23079c75/spec%2Fspec_helper.rb#L259)
[`spec/support/migration.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/f81fa6ab1dd788b70ef44b85aaba1f31ffafae7d/spec/support/migration.rb)
to run.
 
A `before` hook will revert all migrations to the point that a migration
Loading
Loading
@@ -112,7 +112,7 @@ migration. You can find the complete spec in
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170526185842_migrate_pipeline_stages.rb')
 
describe MigratePipelineStages, :migration do
describe MigratePipelineStages do
# Create test data - pipeline and CI/CD jobs.
let(:jobs) { table(:ci_builds) }
let(:stages) { table(:ci_stages) }
Loading
Loading
@@ -163,7 +163,7 @@ schema tag to a context that you want to switch the database schema within.
Example:
 
```ruby
describe SomeClass, :migration, schema: 20170608152748 do
describe SomeClass, schema: 20170608152748 do
# ...
end
```
Loading
Loading
@@ -178,7 +178,7 @@ background migration. You can find the complete spec on
```ruby
require 'spec_helper'
 
describe Gitlab::BackgroundMigration::ArchiveLegacyTraces, :migration, schema: 20180529152628 do
describe Gitlab::BackgroundMigration::ArchiveLegacyTraces, schema: 20180529152628 do
include TraceHelpers
 
let(:namespaces) { table(:namespaces) }
Loading
Loading
Loading
Loading
@@ -183,7 +183,7 @@ NOTE: **Note:** GitLab is unable to provide support for IdPs that are not listed
| JumpCloud | [Single Sign On (SSO) with GitLab](https://support.jumpcloud.com/support/s/article/single-sign-on-sso-with-gitlab-2019-08-21-10-36-47) |
| Okta | [Setting up a SAML application in Okta](https://developer.okta.com/docs/guides/saml-application-setup/overview/) |
| OneLogin | [Use the OneLogin SAML Test Connector](https://onelogin.service-now.com/support?id=kb_article&sys_id=93f95543db109700d5505eea4b96198f) |
| Ping Identity | [Add and configure a new SAML application](https://support.pingidentity.com/s/document-item?bundleId=pingone&topicId=xsh1564020480660-1.html) |
| Ping One for Enterprise | [Add and configure a new SAML application](https://support.pingidentity.com/s/document-item?bundleId=pingone&topicId=xsh1564020480660-1.html) |
 
When [configuring your identify provider](#configuring-your-identity-provider), please consider the notes below for specific providers to help avoid common issues and as a guide for terminology used.
 
Loading
Loading
Loading
Loading
@@ -31,7 +31,7 @@ module API
end
 
params do
requires :id, type: Integer, desc: 'The ID of a project'
requires :id, type: String, desc: 'The ID of a project'
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before do
Loading
Loading
@@ -74,7 +74,7 @@ module API
end
 
params do
requires :id, type: Integer, desc: 'The ID of a group'
requires :id, type: String, desc: 'The ID of a group'
end
resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before do
Loading
Loading
@@ -94,6 +94,27 @@ module API
present paginate(user_group.deploy_tokens), with: Entities::DeployToken
end
 
params do
requires :name, type: String, desc: 'The name of the deploy token'
requires :expires_at, type: DateTime, desc: 'Expiration date for the deploy token. Does not expire if no value is provided.'
requires :username, type: String, desc: 'Username for deploy token. Default is `gitlab+deploy-token-{n}`'
requires :scopes, type: Array[String], values: ::DeployToken::AVAILABLE_SCOPES.map(&:to_s),
desc: 'Indicates the deploy token scopes. Must be at least one of "read_repository" or "read_registry".'
end
desc 'Create a group deploy token' do
detail 'This feature was introduced in GitLab 12.9'
success Entities::DeployTokenWithToken
end
post ':id/deploy_tokens' do
authorize!(:create_deploy_token, user_group)
deploy_token = ::Groups::DeployTokens::CreateService.new(
user_group, current_user, scope_params.merge(declared(params, include_missing: false, include_parent_namespaces: false))
).execute
present deploy_token, with: Entities::DeployTokenWithToken
end
desc 'Delete a group deploy token' do
detail 'This feature was introduced in GitLab 12.9'
end
Loading
Loading
Loading
Loading
@@ -6,7 +6,6 @@ module Banzai
# a given link format. To transform references to DB
# resources in place, prefer to inherit from AbstractReferenceFilter.
class InlineEmbedsFilter < HTML::Pipeline::Filter
include Gitlab::Utils::StrongMemoize
# Find every relevant link, create a new node based on
# the link, and insert this node after any html content
# surrounding the link.
Loading
Loading
@@ -74,9 +73,7 @@ module Banzai
# Ex) 'https://<root>/<project>/<environment>/metrics?title=Title&group=Group'
# --> { title: 'Title', group: 'Group' }
def query_params(url)
strong_memoize(:query_params) do
Gitlab::Metrics::Dashboard::Url.parse_query(url)
end
Gitlab::Metrics::Dashboard::Url.parse_query(url)
end
 
# Implement in child class.
Loading
Loading
Loading
Loading
@@ -5,7 +5,8 @@
# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables
 
variables:
DS_ANALYZER_IMAGE_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
SECURITY_SCANNER_IMAGE_PREFIX: "registry.gitlab.com/gitlab-org/security-products"
DS_ANALYZER_IMAGE_PREFIX: "$SECURITY_SCANNER_IMAGE_PREFIX/analyzers"
DS_DEFAULT_ANALYZERS: "bundler-audit, retire.js, gemnasium, gemnasium-maven, gemnasium-python"
DS_MAJOR_VERSION: 2
DS_DISABLE_DIND: "false"
Loading
Loading
@@ -64,7 +65,7 @@ dependency_scanning:
) \
--volume "$PWD:/code" \
--volume /var/run/docker.sock:/var/run/docker.sock \
"registry.gitlab.com/gitlab-org/security-products/dependency-scanning:$DS_VERSION" /code
"$SECURITY_SCANNER_IMAGE_PREFIX/dependency-scanning:$DS_VERSION" /code
artifacts:
reports:
dependency_scanning: gl-dependency-scanning-report.json
Loading
Loading
Loading
Loading
@@ -183,10 +183,8 @@ module Gitlab
 
# rubocop: disable CodeReuse/ActiveRecord
def services_usage
service_counts = count(Service.active.where(template: false).where.not(type: 'JiraService').group(:type), fallback: Hash.new(-1), batch: false)
results = Service.available_services_names.each_with_object({}) do |service_name, response|
response["projects_#{service_name}_active".to_sym] = service_counts["#{service_name}_service".camelize] || 0
results = Service.available_services_names.without('jira').each_with_object({}) do |service_name, response|
response["projects_#{service_name}_active".to_sym] = count(Service.active.where(template: false, type: "#{service_name}_service".camelize))
end
 
# Keep old Slack keys for backward compatibility, https://gitlab.com/gitlab-data/analytics/issues/3241
Loading
Loading
Loading
Loading
@@ -12507,7 +12507,9 @@ msgid "Metrics|Duplicating..."
msgstr ""
 
msgid "Metrics|Edit metric"
msgstr ""
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
msgstr[1] ""
 
msgid "Metrics|Environment"
msgstr ""
Loading
Loading
Loading
Loading
@@ -62,6 +62,29 @@ describe 'Metrics rendering', :js, :use_clean_rails_memory_store_caching, :sidek
expect(page).to have_text(chart_params[:title])
expect(page).to have_text(chart_params[:y_label])
end
context 'when two dashboard urls are included' do
let(:chart_params_2) do
{
group: 'System metrics (Kubernetes)',
title: 'Core Usage (Total)',
y_label: 'Total Cores'
}
end
let(:metrics_url_2) { urls.metrics_project_environment_url(project, environment, **chart_params_2) }
let(:description) { "See [metrics dashboard](#{metrics_url}) for info. \n See [metrics dashboard](#{metrics_url_2}) for info." }
let(:issue) { create(:issue, project: project, description: description) }
it 'shows embedded metrics for both urls' do
visit project_issue_path(project, issue)
expect(page).to have_css('div.prometheus-graph')
expect(page).to have_text(chart_params[:title])
expect(page).to have_text(chart_params[:y_label])
expect(page).to have_text(chart_params_2[:title])
expect(page).to have_text(chart_params_2[:y_label])
end
end
end
end
 
Loading
Loading
Loading
Loading
@@ -155,18 +155,17 @@ describe('Issue card component', () => {
 
describe('assignee default avatar', () => {
beforeEach(done => {
global.gon.default_avatar_url = 'default_avatar';
wrapper.setProps({
issue: {
...wrapper.props('issue'),
assignees: [
new ListAssignee(
{
id: 1,
name: 'testing 123',
username: 'test',
},
'default_avatar',
),
new ListAssignee({
id: 1,
name: 'testing 123',
username: 'test',
}),
],
},
});
Loading
Loading
@@ -174,6 +173,10 @@ describe('Issue card component', () => {
wrapper.vm.$nextTick(done);
});
 
afterEach(() => {
global.gon.default_avatar_url = null;
});
it('displays defaults avatar if users avatar is null', () => {
expect(wrapper.find('.board-card-assignee img').exists()).toBe(true);
expect(wrapper.find('.board-card-assignee img').attributes('src')).toBe(
Loading
Loading
import { commitItemIconMap } from '~/ide/constants';
import { getCommitIconMap } from '~/ide/utils';
import { getCommitIconMap, isTextFile } from '~/ide/utils';
import { decorateData } from '~/ide/stores/utils';
 
describe('WebIDE utils', () => {
describe('isTextFile', () => {
it('returns false for known binary types', () => {
expect(isTextFile('file content', 'image/png', 'my.png')).toBeFalsy();
// mime types are case insensitive
expect(isTextFile('file content', 'IMAGE/PNG', 'my.png')).toBeFalsy();
});
it('returns true for known text types', () => {
expect(isTextFile('file content', 'text/plain', 'my.txt')).toBeTruthy();
// mime types are case insensitive
expect(isTextFile('file content', 'TEXT/PLAIN', 'my.txt')).toBeTruthy();
});
it('returns true for file extensions that Monaco supports syntax highlighting for', () => {
// test based on both MIME and extension
expect(isTextFile('{"éêė":"value"}', 'application/json', 'my.json')).toBeTruthy();
expect(isTextFile('{"éêė":"value"}', 'application/json', '.tsconfig')).toBeTruthy();
expect(isTextFile('SELECT "éêė" from tablename', 'application/sql', 'my.sql')).toBeTruthy();
});
it('returns true even irrespective of whether the mimes, extensions or file names are lowercase or upper case', () => {
expect(isTextFile('{"éêė":"value"}', 'application/json', 'MY.JSON')).toBeTruthy();
expect(isTextFile('SELECT "éêė" from tablename', 'application/sql', 'MY.SQL')).toBeTruthy();
expect(
isTextFile('var code = "something"', 'application/javascript', 'Gruntfile'),
).toBeTruthy();
expect(
isTextFile(
'MAINTAINER Александр "alexander11354322283@me.com"',
'application/octet-stream',
'dockerfile',
),
).toBeTruthy();
});
it('returns false if filename is same as the expected extension', () => {
expect(isTextFile('SELECT "éêė" from tablename', 'application/sql', 'sql')).toBeFalsy();
});
it('returns true for ASCII only content for unknown types', () => {
expect(isTextFile('plain text', 'application/x-new-type', 'hello.mytype')).toBeTruthy();
});
it('returns true for relevant filenames', () => {
expect(
isTextFile(
'MAINTAINER Александр "alexander11354322283@me.com"',
'application/octet-stream',
'Dockerfile',
),
).toBeTruthy();
});
it('returns false for non-ASCII content for unknown types', () => {
expect(isTextFile('{"éêė":"value"}', 'application/octet-stream', 'my.random')).toBeFalsy();
});
});
const createFile = (name = 'name', id = name, type = '', parent = null) =>
decorateData({
id,
Loading
Loading
Loading
Loading
@@ -148,6 +148,82 @@ describe('Panel Type component', () => {
});
});
 
describe('Edit custom metric dropdown item', () => {
const findEditCustomMetricLink = () => wrapper.find({ ref: 'editMetricLink' });
beforeEach(() => {
createWrapper({
graphData: {
...graphDataPrometheusQueryRange,
},
});
return wrapper.vm.$nextTick();
});
it('is not present if the panel is not a custom metric', () => {
expect(findEditCustomMetricLink().exists()).toBe(false);
});
it('is present when the panel contains an edit_path property', () => {
wrapper.setProps({
graphData: {
...graphDataPrometheusQueryRange,
metrics: [
{
...graphDataPrometheusQueryRange.metrics[0],
edit_path: '/root/kubernetes-gke-project/prometheus/metrics/23/edit',
},
],
},
});
return wrapper.vm.$nextTick(() => {
expect(findEditCustomMetricLink().exists()).toBe(true);
});
});
it('shows an "Edit metric" link for a panel with a single metric', () => {
wrapper.setProps({
graphData: {
...graphDataPrometheusQueryRange,
metrics: [
{
...graphDataPrometheusQueryRange.metrics[0],
edit_path: '/root/kubernetes-gke-project/prometheus/metrics/23/edit',
},
],
},
});
return wrapper.vm.$nextTick(() => {
expect(findEditCustomMetricLink().text()).toBe('Edit metric');
});
});
it('shows an "Edit metrics" link for a panel with multiple metrics', () => {
wrapper.setProps({
graphData: {
...graphDataPrometheusQueryRange,
metrics: [
{
...graphDataPrometheusQueryRange.metrics[0],
edit_path: '/root/kubernetes-gke-project/prometheus/metrics/23/edit',
},
{
...graphDataPrometheusQueryRange.metrics[0],
edit_path: '/root/kubernetes-gke-project/prometheus/metrics/23/edit',
},
],
},
});
return wrapper.vm.$nextTick(() => {
expect(findEditCustomMetricLink().text()).toBe('Edit metrics');
});
});
});
describe('View Logs dropdown item', () => {
const mockLogsPath = '/path/to/logs';
const mockTimeRange = { duration: { seconds: 120 } };
Loading
Loading
/* eslint-disable no-new */
import _ from 'underscore';
import { clone } from 'lodash';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import Sidebar from '~/right_sidebar';
Loading
Loading
@@ -24,13 +24,13 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
mock = new MockAdapter(axios);
 
mock.onPost(`${gl.TEST_HOST}/frontend-fixtures/issues-project/todos`).reply(() => {
const response = _.clone(todoData);
const response = clone(todoData);
 
return [200, response];
});
 
mock.onDelete(/(.*)\/dashboard\/todos\/\d+$/).reply(() => {
const response = _.clone(todoData);
const response = clone(todoData);
delete response.delete_path;
 
return [200, response];
Loading
Loading
import _ from 'underscore';
import { range as rge } from 'lodash';
import DirtySubmitForm from '~/dirty_submit/dirty_submit_form';
import { getInputValue, setInputValue, createForm } from './helper';
 
Loading
Loading
@@ -82,7 +82,7 @@ describe('DirtySubmitForm', () => {
const { form, input } = createForm();
const updateDirtyInputSpy = spyOn(new DirtySubmitForm(form), 'updateDirtyInput');
 
_.range(10).forEach(i => {
rge(10).forEach(i => {
setInputValue(input, `change ${i}`, false);
});
 
Loading
Loading
@@ -93,7 +93,7 @@ describe('DirtySubmitForm', () => {
 
it('does not throttle updates when rapid changes are made to different form elements', () => {
const form = document.createElement('form');
const range = _.range(10);
const range = rge(10);
range.forEach(i => {
form.innerHTML += `<input type="text" name="input-${i}" class="js-input-${i}"/>`;
});
Loading
Loading
Loading
Loading
@@ -2,7 +2,7 @@
 
import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
import _ from 'underscore';
import { shuffle } from 'lodash';
import axios from '~/lib/utils/axios_utils';
import IssuableContext from '~/issuable_context';
import LabelsSelect from '~/labels_select';
Loading
Loading
@@ -27,7 +27,7 @@ function testLabelClicks(labelOrder, done) {
expect(labelsInDropdown.length).toBe(10);
 
const arrayOfLabels = labelsInDropdown.get();
const randomArrayOfLabels = _.shuffle(arrayOfLabels);
const randomArrayOfLabels = shuffle(arrayOfLabels);
randomArrayOfLabels.forEach((label, i) => {
if (i < saveLabelCount) {
$(label).click();
Loading
Loading
import _ from 'underscore';
import { range as rge } from 'lodash';
import Vue from 'vue';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import app from '~/releases/components/app_index.vue';
Loading
Loading
@@ -28,7 +28,7 @@ describe('Releases App ', () => {
 
beforeEach(() => {
store = createStore({ modules: { list: listModule } });
releasesPagination = _.range(21).map(index => ({
releasesPagination = rge(21).map(index => ({
...convertObjectPropsToCamelCase(release, { deep: true }),
tagName: `${index}.00`,
}));
Loading
Loading
import $ from 'jquery';
import _ from 'underscore';
import { assignIn } from 'lodash';
import waitForPromises from 'spec/helpers/wait_for_promises';
import SmartInterval from '~/smart_interval';
 
Loading
Loading
@@ -21,7 +21,7 @@ describe('SmartInterval', function() {
};
 
if (config) {
_.extend(defaultParams, config);
assignIn(defaultParams, config);
}
 
return new SmartInterval(defaultParams);
Loading
Loading
Loading
Loading
@@ -2,7 +2,7 @@
 
require 'spec_helper'
 
describe Gitlab::BackgroundMigration::AddMergeRequestDiffCommitsCount, :migration, schema: 20180105212544 do
describe Gitlab::BackgroundMigration::AddMergeRequestDiffCommitsCount, schema: 20180105212544 do
let(:projects_table) { table(:projects) }
let(:merge_requests_table) { table(:merge_requests) }
let(:merge_request_diffs_table) { table(:merge_request_diffs) }
Loading
Loading
Loading
Loading
@@ -2,7 +2,7 @@
 
require 'spec_helper'
 
describe Gitlab::BackgroundMigration::ArchiveLegacyTraces, :migration, schema: 20180529152628 do
describe Gitlab::BackgroundMigration::ArchiveLegacyTraces, schema: 20180529152628 do
include TraceHelpers
 
let(:namespaces) { table(:namespaces) }
Loading
Loading
Loading
Loading
@@ -2,6 +2,6 @@
 
require 'spec_helper'
 
describe Gitlab::BackgroundMigration::BackfillHashedProjectRepositories, :migration, schema: 20181130102132 do
describe Gitlab::BackgroundMigration::BackfillHashedProjectRepositories, schema: 20181130102132 do
it_behaves_like 'backfill migration for project repositories', :hashed
end
Loading
Loading
@@ -2,6 +2,6 @@
 
require 'spec_helper'
 
describe Gitlab::BackgroundMigration::BackfillLegacyProjectRepositories, :migration, schema: 20181212171634 do
describe Gitlab::BackgroundMigration::BackfillLegacyProjectRepositories, schema: 20181212171634 do
it_behaves_like 'backfill migration for project repositories', :legacy
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment