Commit 9ce66d4d authored by 🤖 GitLab Bot 🤖's avatar 🤖 GitLab Bot 🤖

Add latest changes from gitlab-org/[email protected]

parent 7bc73460
......@@ -1004,11 +1004,11 @@ GEM
shellany (0.0.1)
shoulda-matchers (4.0.1)
activesupport (>= 4.2.0)
sidekiq (5.2.7)
sidekiq (5.2.9)
connection_pool (~> 2.2, >= 2.2.2)
rack (>= 1.5.0)
rack (~> 2.0)
rack-protection (>= 1.5.0)
redis (>= 3.3.5, < 5)
redis (>= 3.3.5, < 4.2)
sidekiq-cron (1.0.4)
fugit (~> 1.1)
sidekiq (>= 4.2.1)
......
......@@ -6,7 +6,9 @@ import ReportSection from './report_section.vue';
import SummaryRow from './summary_row.vue';
import IssuesList from './issues_list.vue';
import Modal from './modal.vue';
import { GlButton } from '@gitlab/ui';
import createStore from '../store';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { summaryTextBuilder, reportTextBuilder, statusIcon } from '../store/utils';
export default {
......@@ -17,12 +19,19 @@ export default {
SummaryRow,
IssuesList,
Modal,
GlButton,
},
mixins: [glFeatureFlagsMixin()],
props: {
endpoint: {
type: String,
required: true,
},
pipelinePath: {
type: String,
required: false,
default: '',
},
},
componentNames,
computed: {
......@@ -43,6 +52,12 @@ export default {
return summaryTextBuilder(s__('Reports|Test summary'), this.summary);
},
testTabURL() {
return `${this.pipelinePath}/test_report`;
},
showViewFullReport() {
return Boolean(this.glFeatures.junitPipelineView) && this.pipelinePath.length;
},
},
created() {
this.setEndpoint(this.endpoint);
......@@ -98,6 +113,11 @@ export default {
:has-issues="reports.length > 0"
class="mr-widget-section grouped-security-reports mr-report"
>
<template v-if="showViewFullReport" #actionButtons>
<gl-button :href="testTabURL" icon="external-link" data-testid="group-test-reports-full-link">
{{ s__('ciReport|View full report') }}
</gl-button>
</template>
<template #body>
<div class="mr-widget-grouped-section report-block">
<template v-for="(report, i) in reports">
......
......@@ -384,6 +384,7 @@ export default {
v-if="mr.testResultsPath"
class="js-reports-container"
:endpoint="mr.testResultsPath"
:pipeline-path="mr.mergeRequestAddCiConfigPath"
/>
<terraform-plan v-if="mr.terraformReportsPath" :endpoint="mr.terraformReportsPath" />
......
......@@ -59,10 +59,6 @@ $item-remove-button-space: 42px;
flex-basis: 100%;
font-size: $gl-font-size-small;
&.mr-title {
font-weight: $gl-font-weight-bold;
}
.sortable-link {
color: $gray-900;
}
......@@ -77,10 +73,6 @@ $item-remove-button-space: 42px;
overflow: hidden;
white-space: nowrap;
}
.health-label-short {
display: none;
}
}
.item-body,
......@@ -89,10 +81,6 @@ $item-remove-button-space: 42px;
max-width: 0;
}
.health-label-long {
display: none;
}
.status {
&-at-risk {
color: $red-500;
......@@ -158,19 +146,16 @@ $item-remove-button-space: 42px;
max-width: $item-milestone-max-width;
.ic-clock {
color: $gl-text-color-secondary;
margin-right: $gl-padding-4;
}
}
.item-weight {
max-width: $item-weight-max-width;
.ic-weight {
color: $gl-text-color-secondary;
}
}
.item-milestone .ic-clock,
.item-weight .ic-weight,
.item-due-date .ic-calendar {
color: $gl-text-color-secondary;
}
......@@ -314,10 +299,6 @@ $item-remove-button-space: 42px;
max-width: 100px;
}
}
.health-label-long {
display: none;
}
}
/* Large devices (large desktops, 1200px and up) */
......@@ -331,10 +312,6 @@ $item-remove-button-space: 42px;
}
}
.health-label-long {
display: none;
}
.item-contents {
overflow: hidden;
}
......@@ -371,12 +348,8 @@ $item-remove-button-space: 42px;
@media only screen and (min-width: 1500px) {
.card-header {
.health-label-short {
display: none;
}
.health-label-long {
display: initial;
display: block;
}
}
}
......@@ -40,6 +40,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action do
push_frontend_feature_flag(:vue_issuable_sidebar, @project.group)
push_frontend_feature_flag(:junit_pipeline_view, @project.group)
end
around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions]
......
......@@ -21,5 +21,7 @@ module Types
description: 'Packages size of the project'
field :wiki_size, GraphQL::FLOAT_TYPE, null: true,
description: 'Wiki size of the project'
field :snippets_size, GraphQL::FLOAT_TYPE, null: true,
description: 'Snippets size of the project'
end
end
......@@ -167,7 +167,6 @@ class Project < ApplicationRecord
has_one :youtrack_service
has_one :custom_issue_tracker_service
has_one :bugzilla_service
has_one :gitlab_issue_tracker_service, inverse_of: :project
has_one :external_wiki_service
has_one :prometheus_service, inverse_of: :project
has_one :mock_ci_service
......
# frozen_string_literal: true
class GitlabIssueTrackerService < IssueTrackerService
include Gitlab::Routing
validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
default_value_for :default, true
def title
'GitLab'
end
def description
s_('IssueTracker|GitLab issue tracker')
end
def self.to_param
'gitlab'
end
def project_url
project_issues_url(project)
end
def new_issue_url
new_project_issue_url(project)
end
def issue_url(iid)
project_issue_url(project, id: iid)
end
def issue_tracker_path
project_issues_path(project)
end
def new_issue_path
new_project_issue_path(project)
end
def issue_path(iid)
project_issue_path(project, id: iid)
end
end
......@@ -55,11 +55,9 @@ class Service < ApplicationRecord
validates :instance, uniqueness: { scope: :type }, if: -> { instance? }
validate :validate_is_instance_or_template
scope :visible, -> { where.not(type: 'GitlabIssueTrackerService') }
scope :issue_trackers, -> { where(category: 'issue_tracker') }
scope :external_wikis, -> { where(type: 'ExternalWikiService').active }
scope :active, -> { where(active: true) }
scope :without_defaults, -> { where(default: false) }
scope :by_type, -> (type) { where(type: type) }
scope :by_active_flag, -> (flag) { where(active: flag) }
scope :templates, -> { where(template: true, type: available_services_types) }
......@@ -77,7 +75,7 @@ class Service < ApplicationRecord
scope :wiki_page_hooks, -> { where(wiki_page_events: true, active: true) }
scope :deployment_hooks, -> { where(deployment_events: true, active: true) }
scope :alert_hooks, -> { where(alert_events: true, active: true) }
scope :external_issue_trackers, -> { issue_trackers.active.without_defaults }
scope :external_issue_trackers, -> { issue_trackers.active }
scope :deployment, -> { where(category: 'deployment') }
default_value_for :category, 'common'
......
---
title: Link to test reports from MR Widget
merge_request: 29729
author:
type: added
---
title: Add snippets_size to ProjectStatistics GraphQL type
merge_request: 35319
author:
type: changed
---
title: Update Sidekiq to v5.2.9
merge_request: 35495
author:
type: other
......@@ -10134,6 +10134,11 @@ type ProjectStatistics {
"""
repositorySize: Float!
"""
Snippets size of the project
"""
snippetsSize: Float
"""
Storage size of the project
"""
......
......@@ -29952,6 +29952,20 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "snippetsSize",
"description": "Snippets size of the project",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "Float",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "storageSize",
"description": "Storage size of the project",
......@@ -1478,6 +1478,7 @@ Represents a Project Member
| `lfsObjectsSize` | Float! | Large File Storage (LFS) object size of the project |
| `packagesSize` | Float! | Packages size of the project |
| `repositorySize` | Float! | Repository size of the project |
| `snippetsSize` | Float | Snippets size of the project |
| `storageSize` | Float! | Storage size of the project |
| `wikiSize` | Float | Wiki size of the project |
......
......@@ -23,10 +23,6 @@ module Banzai
issue_url(issue, project)
end
def projects_relation_for_paths(paths)
super(paths).includes(:gitlab_issue_tracker_service)
end
def parent_records(parent, ids)
parent.issues.where(iid: ids.to_a)
end
......
......@@ -1313,6 +1313,9 @@ msgstr ""
msgid "Add LICENSE"
msgstr ""
msgid "Add New Node"
msgstr ""
msgid "Add README"
msgstr ""
......@@ -4420,15 +4423,9 @@ msgstr ""
msgid "Choose what content you want to see on a group’s overview page"
msgstr ""
msgid "Choose which groups you wish to synchronize to this secondary node"
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
msgstr ""
msgid "Choose which shards you wish to synchronize to this secondary node"
msgstr ""
msgid "Choose your framework"
msgstr ""
......@@ -6375,21 +6372,6 @@ msgstr ""
msgid "Control the display of third party offers."
msgstr ""
msgid "Control the maximum concurrency of LFS/attachment backfill for this secondary node"
msgstr ""
msgid "Control the maximum concurrency of container repository operations for this Geo node"
msgstr ""
msgid "Control the maximum concurrency of repository backfill for this secondary node"
msgstr ""
msgid "Control the maximum concurrency of verification operations for this Geo node"
msgstr ""
msgid "Control the minimum interval in days that a repository should be reverified for this primary node"
msgstr ""
msgid "Cookie domain"
msgstr ""
......@@ -11946,10 +11928,10 @@ msgstr ""
msgid "If enabled"
msgstr ""
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "If enabled, and if object storage is enabled, GitLab will handle Object Storage replication using Geo"
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
msgid "If there is no previous license or if the previous license has expired, some GitLab functionality will be blocked until a new, valid license is uploaded."
......@@ -12611,9 +12593,6 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
msgid "IssueTracker|GitLab issue tracker"
msgstr ""
msgid "IssueTracker|Redmine issue tracker"
msgstr ""
......@@ -14595,6 +14574,9 @@ msgstr ""
msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
msgstr ""
msgid "Minimum interval in days"
msgstr ""
msgid "Minimum length is %{minimum_password_length} characters"
msgstr ""
......@@ -14781,6 +14763,12 @@ msgstr ""
msgid "Multiple uploaders found: %{uploader_types}"
msgstr ""
msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
msgstr ""
msgid "Must match with the %{codeStart}geo_node_name%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "My Awesome Group"
msgstr ""
......@@ -14907,9 +14895,6 @@ msgstr ""
msgid "New File"
msgstr ""
msgid "New Geo Node"
msgstr ""
msgid "New Group"
msgstr ""
......@@ -16258,6 +16243,9 @@ msgstr ""
msgid "Perform common operations on GitLab project"
msgstr ""
msgid "Performance and resource management"
msgstr ""
msgid "Performance optimization"
msgstr ""
......@@ -20640,6 +20628,12 @@ msgstr ""
msgid "Set the milestone to %{milestone_reference}."
msgstr ""
msgid "Set the number of concurrent requests this secondary node will make to the primary node while backfilling."
msgstr ""
msgid "Set the synchronization and verification capacity for the secondary node."
msgstr ""
msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
msgstr ""
......@@ -20682,6 +20676,9 @@ msgstr ""
msgid "Set weight to %{weight}."
msgstr ""
msgid "Set what should be replicated by choosing specific projects or groups by the secondary node."
msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
......@@ -22469,7 +22466,7 @@ msgstr ""
msgid "The Terraform report %{name} was generated in your pipelines."
msgstr ""
msgid "The URL defined on the primary node that secondary nodes should use to contact it. Defaults to URL"
msgid "The URL defined on the primary node that secondary nodes should use to contact it."
msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
......@@ -22780,9 +22777,6 @@ msgstr ""
msgid "The total stage shows the time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
msgstr ""
msgid "The unique identifier for the Geo node. Must match %{geoNodeName} if it is set in gitlab.rb, otherwise it must match %{externalUrl} with a trailing slash"
msgstr ""
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
......@@ -22807,9 +22801,6 @@ msgstr ""
msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
msgstr ""
msgid "The user-facing URL of the Geo node"
msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
......@@ -22954,6 +22945,9 @@ msgstr ""
msgid "There was an error fetching the %{replicableType}"
msgstr ""
msgid "There was an error fetching the Geo Settings"
msgstr ""
msgid "There was an error fetching the Node's Groups"
msgstr ""
......@@ -27091,9 +27085,6 @@ msgstr ""
msgid "expires on %{timebox_due_date}"
msgstr ""
msgid "external_url"
msgstr ""
msgid "failed"
msgstr ""
......@@ -27129,9 +27120,6 @@ msgstr ""
msgid "from"
msgstr ""
msgid "geo_node_name"
msgstr ""
msgid "group"
msgstr ""
......
......@@ -165,6 +165,8 @@ module QA
terms.accept_terms if terms.visible?
end
skip_onboarding if respond_to?(:skip_onboarding)
Page::Main::Menu.validate_elements_present! unless skip_page_validation
end
......@@ -179,3 +181,5 @@ module QA
end
end
end
QA::Page::Main::Login.prepend_if_ee('QA::EE::Page::Main::Login')
......@@ -107,12 +107,6 @@ FactoryBot.define do
issue_tracker
end
factory :gitlab_issue_tracker_service do
project
active { true }
issue_tracker
end
trait :issue_tracker do
transient do
create_data { true }
......
......@@ -15,20 +15,29 @@ localVue.use(Vuex);
describe('Grouped test reports app', () => {
const endpoint = 'endpoint.json';
const pipelinePath = '/path/to/pipeline';
const Component = localVue.extend(GroupedTestReportsApp);
let wrapper;
let mockStore;
const mountComponent = () => {
const mountComponent = ({
glFeatures = { junitPipelineView: false },
props = { pipelinePath },
} = {}) => {
wrapper = mount(Component, {
store: mockStore,
localVue,
propsData: {
endpoint,
pipelinePath,
...props,
},
methods: {
fetchReports: () => {},
},
provide: {
glFeatures,
},
});
};
......@@ -39,6 +48,7 @@ describe('Grouped test reports app', () => {
};
const findHeader = () => wrapper.find('[data-testid="report-section-code-text"]');
const findFullTestReportLink = () => wrapper.find('[data-testid="group-test-reports-full-link"]');
const findSummaryDescription = () => wrapper.find('[data-testid="test-summary-row-description"]');
const findIssueDescription = () => wrapper.find('[data-testid="test-issue-body-description"]');
const findAllIssueDescriptions = () =>
......@@ -67,6 +77,38 @@ describe('Grouped test reports app', () => {
});
});
describe('`View full report` button', () => {
it('should not render the full test report link', () => {
expect(findFullTestReportLink().exists()).toBe(false);
});
describe('With junitPipelineView feature flag enabled', () => {
beforeEach(() => {
mountComponent({ glFeatures: { junitPipelineView: true } });
});
it('should render the full test report link', () => {
const fullTestReportLink = findFullTestReportLink();
expect(fullTestReportLink.exists()).toBe(true);
expect(fullTestReportLink.attributes('href')).toBe(`${pipelinePath}/test_report`);
});
});
describe('Without a pipelinePath', () => {
beforeEach(() => {
mountComponent({
glFeatures: { junitPipelineView: true },
props: { pipelinePath: '' },
});
});
it('should not render the full test report link', () => {
expect(findFullTestReportLink().exists()).toBe(false);
});
});
});
describe('with new failed result', () => {
beforeEach(() => {
setReports(newFailedTestReports);
......
......@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe GitlabSchema.types['ProjectStatistics'] do
it "has all the required fields" do
it 'has all the required fields' do
expect(described_class).to have_graphql_fields(:storage_size, :repository_size, :lfs_objects_size,
:build_artifacts_size, :packages_size, :commit_count,
:wiki_size)
:wiki_size, :snippets_size)
end
end
......@@ -349,7 +349,6 @@ project:
- youtrack_service
- custom_issue_tracker_service
- bugzilla_service
- gitlab_issue_tracker_service
- external_wiki_service
- mock_ci_service
- mock_deployment_service
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabIssueTrackerService do
describe "Associations" do
it { is_expected.to belong_to :project }
it { is_expected.to have_one :service_hook }
end
describe 'Validations' do
context 'when service is active' do
subject { described_class.new(project: create(:project), active: true) }
it { is_expected.to validate_presence_of(:issues_url) }
it_behaves_like 'issue tracker service URL attribute', :issues_url
end
context 'when service is inactive' do
subject { described_class.new(project: create(:project), active: false) }
it { is_expected.not_to validate_presence_of(:issues_url) }
end