Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
a1eee0f284
commit
3351b23ded
|
|
@ -300,7 +300,10 @@ export default {
|
|||
/>
|
||||
<div v-else class="gl-pr-3"><gl-loading-icon size="sm" inline /></div>
|
||||
<div class="gl-flex gl-min-w-0 gl-flex-1 gl-flex-col">
|
||||
<span class="gl-whitespace-normal" data-testid="downstream-title-content">
|
||||
<span
|
||||
class="gl-whitespace-normal gl-wrap-anywhere"
|
||||
data-testid="downstream-title-content"
|
||||
>
|
||||
{{ downstreamTitle }}
|
||||
</span>
|
||||
<div class="gl-truncate">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { GlTabs, GlTab, GlBadge, GlFilteredSearchToken } from '@gitlab/ui';
|
||||
import { isEqual, pick } from 'lodash';
|
||||
import { isEqual, pick, get } from 'lodash';
|
||||
import { __ } from '~/locale';
|
||||
import { QUERY_PARAM_END_CURSOR, QUERY_PARAM_START_CURSOR } from '~/graphql_shared/constants';
|
||||
import { numberToMetricPrefix } from '~/lib/utils/number_utils';
|
||||
|
|
@ -9,7 +9,6 @@ import FilteredSearchAndSort from '~/groups_projects/components/filtered_search_
|
|||
import { calculateGraphQLPaginationQueryParams } from '~/graphql_shared/utils';
|
||||
import { OPERATORS_IS } from '~/vue_shared/components/filtered_search_bar/constants';
|
||||
import { ACCESS_LEVEL_OWNER_INTEGER } from '~/access_level/constants';
|
||||
import projectCountsQuery from '~/projects/your_work/graphql/queries/project_counts.query.graphql';
|
||||
import * as Sentry from '~/sentry/sentry_browser_wrapper';
|
||||
import { InternalEvents } from '~/tracking';
|
||||
import {
|
||||
|
|
@ -26,9 +25,6 @@ const trackingMixin = InternalEvents.mixin();
|
|||
// Will be made more generic to work with groups and projects in future commits
|
||||
export default {
|
||||
name: 'TabsWithList',
|
||||
i18n: {
|
||||
projectCountError: __('An error occurred loading the project counts.'),
|
||||
},
|
||||
components: {
|
||||
GlTabs,
|
||||
GlTab,
|
||||
|
|
@ -98,11 +94,23 @@ export default {
|
|||
return {};
|
||||
},
|
||||
},
|
||||
tabCountsQuery: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default() {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
tabCountsQueryErrorMessage: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: __('An error occurred loading the tab counts.'),
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeTabIndex: this.initActiveTabIndex(),
|
||||
counts: this.tabs.reduce((accumulator, tab) => {
|
||||
tabCounts: this.tabs.reduce((accumulator, tab) => {
|
||||
return {
|
||||
...accumulator,
|
||||
[tab.value]: undefined,
|
||||
|
|
@ -110,32 +118,6 @@ export default {
|
|||
}, {}),
|
||||
};
|
||||
},
|
||||
apollo: {
|
||||
counts() {
|
||||
return {
|
||||
query: projectCountsQuery,
|
||||
update(response) {
|
||||
const {
|
||||
currentUser: { contributed, starred },
|
||||
personal,
|
||||
member,
|
||||
inactive,
|
||||
} = response;
|
||||
|
||||
return {
|
||||
contributed: contributed.count,
|
||||
starred: starred.count,
|
||||
personal: personal.count,
|
||||
member: member.count,
|
||||
inactive: inactive.count,
|
||||
};
|
||||
},
|
||||
error(error) {
|
||||
createAlert({ message: this.$options.i18n.projectCountError, error, captureError: true });
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
activeTab() {
|
||||
return this.tabs[this.activeTabIndex];
|
||||
|
|
@ -233,6 +215,30 @@ export default {
|
|||
return this.timestampTypeMap[this.activeSortOption.value];
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
if (!Object.keys(this.tabCountsQuery).length) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { data } = await this.$apollo.query({ query: this.tabCountsQuery });
|
||||
|
||||
this.tabCounts = this.tabs.reduce((accumulator, tab) => {
|
||||
const { count } = get(data, tab.countsQueryPath);
|
||||
|
||||
return {
|
||||
...accumulator,
|
||||
[tab.value]: count,
|
||||
};
|
||||
}, {});
|
||||
} catch (error) {
|
||||
createAlert({
|
||||
message: this.tabCountsQueryErrorMessage,
|
||||
error,
|
||||
captureError: true,
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
numberToMetricPrefix,
|
||||
createSortQuery({ sortBy, isAscending }) {
|
||||
|
|
@ -267,7 +273,7 @@ export default {
|
|||
this.trackEvent(this.eventTracking.tabs, { label: tab.text });
|
||||
},
|
||||
tabCount(tab) {
|
||||
return this.counts[tab.value];
|
||||
return this.tabCounts[tab.value];
|
||||
},
|
||||
shouldShowCountBadge(tab) {
|
||||
return this.tabCount(tab) !== undefined;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import {
|
|||
TIMESTAMP_TYPE_CREATED_AT,
|
||||
TIMESTAMP_TYPE_LAST_ACTIVITY_AT,
|
||||
} from '~/vue_shared/components/resource_lists/constants';
|
||||
import projectCountsQuery from '../graphql/queries/project_counts.query.graphql';
|
||||
import { PROJECT_DASHBOARD_TABS, FIRST_TAB_ROUTE_NAMES } from '../constants';
|
||||
|
||||
export default {
|
||||
|
|
@ -44,6 +45,7 @@ export default {
|
|||
tabs: 'click_tab_on_your_work_projects',
|
||||
sort: 'click_sort_on_your_work_projects',
|
||||
},
|
||||
tabCountsQuery: projectCountsQuery,
|
||||
name: 'YourWorkProjectsApp',
|
||||
components: {
|
||||
TabsWithList,
|
||||
|
|
@ -75,5 +77,7 @@ export default {
|
|||
:initial-sort="initialSort"
|
||||
:programming-languages="programmingLanguages"
|
||||
:event-tracking="$options.eventTracking"
|
||||
:tab-counts-query="$options.tabCountsQuery"
|
||||
:tab-counts-query-error-message="__('An error occurred loading the project counts.')"
|
||||
/>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ export const CONTRIBUTED_TAB = {
|
|||
query: userProjectsQuery,
|
||||
variables: { contributed: true },
|
||||
queryPath: 'currentUser.contributedProjects',
|
||||
countsQueryPath: 'currentUser.contributed',
|
||||
emptyStateComponentProps: {
|
||||
title: s__("Projects|You haven't contributed to any projects yet."),
|
||||
description: s__(
|
||||
|
|
@ -43,6 +44,7 @@ export const STARRED_TAB = {
|
|||
query: userProjectsQuery,
|
||||
variables: { starred: true },
|
||||
queryPath: 'currentUser.starredProjects',
|
||||
countsQueryPath: 'currentUser.starred',
|
||||
emptyStateComponentProps: {
|
||||
title: s__("Projects|You haven't starred any projects yet."),
|
||||
description: s__(
|
||||
|
|
@ -59,6 +61,7 @@ export const PERSONAL_TAB = {
|
|||
query: projectsQuery,
|
||||
variables: { personal: true },
|
||||
queryPath: 'projects',
|
||||
countsQueryPath: 'personal',
|
||||
emptyStateComponentProps: {
|
||||
title: s__("Projects|You don't have any personal projects yet."),
|
||||
},
|
||||
|
|
@ -71,6 +74,7 @@ export const MEMBER_TAB = {
|
|||
query: projectsQuery,
|
||||
variables: { membership: true },
|
||||
queryPath: 'projects',
|
||||
countsQueryPath: 'member',
|
||||
emptyStateComponentProps: {
|
||||
title: s__("Projects|You aren't a member of any projects yet."),
|
||||
},
|
||||
|
|
@ -83,6 +87,7 @@ export const INACTIVE_TAB = {
|
|||
query: projectsQuery,
|
||||
variables: { archived: 'ONLY', membership: true },
|
||||
queryPath: 'projects',
|
||||
countsQueryPath: 'inactive',
|
||||
emptyStateComponentProps: {
|
||||
title: s__("Projects|You don't have any inactive projects."),
|
||||
description: s__('Projects|Projects that are archived or pending deletion will appear here.'),
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
s_("CICD|Use separate caches for protected branches"),
|
||||
help_text: (s_('CICD|Unprotected branches will not have access to the cache from protected branches.') + ' ' + help_link_separated_caches).html_safe
|
||||
|
||||
= render_if_exists 'projects/settings/ci_cd/composite_identities_pipelines', form: f
|
||||
= render_if_exists 'projects/settings/ci_cd/pipeline_cancelation', form: f
|
||||
|
||||
.form-group
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../../tooling/danger/remote_development/desired_config_generator'
|
||||
require_relative '../../tooling/danger/remote_development/desired_config_generator_suggestor'
|
||||
|
||||
module Danger
|
||||
class RemoteDevelopment < ::Danger::Plugin
|
||||
include Tooling::Danger::RemoteDevelopment::DesiredConfigGenerator
|
||||
include Tooling::Danger::RemoteDevelopment::DesiredConfigGeneratorSuggestor
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateAiTroubleshootJobEventsTable < ClickHouse::Migration
|
||||
def up
|
||||
execute <<-SQL
|
||||
CREATE TABLE IF NOT EXISTS troubleshoot_job_events
|
||||
(
|
||||
user_id UInt64 NOT NULL DEFAULT 0,
|
||||
timestamp DateTime64(6, 'UTC') NOT NULL DEFAULT now64(),
|
||||
job_id UInt64 NOT NULL DEFAULT 0,
|
||||
project_id UInt64 NOT NULL DEFAULT 0,
|
||||
event UInt8 NOT NULL DEFAULT 0,
|
||||
namespace_path String DEFAULT '',
|
||||
pipeline_id UInt64 DEFAULT 0,
|
||||
merge_request_id UInt64 DEFAULT 0
|
||||
)
|
||||
ENGINE = ReplacingMergeTree
|
||||
PARTITION BY toYear(timestamp)
|
||||
ORDER BY (user_id, event, timestamp)
|
||||
SQL
|
||||
end
|
||||
|
||||
def down
|
||||
execute <<-SQL
|
||||
DROP TABLE IF EXISTS troubleshoot_job_events
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
|
@ -44,7 +44,6 @@ This is a partial list of the [RSpec metadata](https://rspec.info/features/3-12/
|
|||
| `:requires_admin` | The test requires an administrator account. Tests with the tag are excluded when run against Canary and Production environments. |
|
||||
| `:requires_git_protocol_v2` | The test requires that Git protocol version 2 is enabled on the server. It's assumed to be enabled by default but if not the test can be skipped by setting `QA_CAN_TEST_GIT_PROTOCOL_V2` to `false`. |
|
||||
| `:requires_praefect` | The test requires that the GitLab instance uses [Gitaly Cluster](../../../../administration/gitaly/praefect.md) (a.k.a. Praefect) as the repository storage. It's assumed to be used by default but if not the test can be skipped by setting `QA_CAN_TEST_PRAEFECT` to `false`. |
|
||||
| `:runner` | The test depends on and sets up a GitLab Runner instance, typically to run a pipeline. |
|
||||
| `:skip_live_env` | The test is excluded when run against live deployed environments such as Staging, Canary, and Production. |
|
||||
| `:skip_fips_env` | The test is excluded when run against an environment in FIPS mode. |
|
||||
| `:skip_signup_disabled` | The test uses UI to sign up a new user and is skipped in any environment that does not allow new user registration via the UI. |
|
||||
|
|
|
|||
|
|
@ -52,13 +52,24 @@ Although this is not mandatory for populating the dependency list, the SBOM docu
|
|||
|
||||
- In GitLab 17.2, the `location` field no longer links to the commit where the dependency was last detected when the feature flag `skip_sbom_occurrences_update_on_pipeline_id_change` is enabled. The flag is disabled by default.
|
||||
- In GitLab 17.3 the `location` field always links to the commit where the dependency was first detected. Feature flag `skip_sbom_occurrences_update_on_pipeline_id_change` removed.
|
||||
- View dependency paths option [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/519965) in GitLab 17.11 [with a flag](../../../administration/feature_flags.md) named `dependency_paths`. Disabled by default.
|
||||
|
||||
{{< /history >}}
|
||||
|
||||
{{< alert type="flag" >}}
|
||||
|
||||
The availability of this feature is controlled by a feature flag.
|
||||
For more information, see the history.
|
||||
|
||||
{{< /alert >}}
|
||||
|
||||
To view the dependencies of a project or all projects in a group:
|
||||
|
||||
1. On the left sidebar, select **Search or go to** and find your project or group.
|
||||
1. Select **Secure > Dependency list**.
|
||||
1. Optional. If there are transitive dependencies, you can also view all of the dependency paths:
|
||||
- For a project, in the **Location** column, select **View dependency paths**.
|
||||
- For a group, in the **Location** column, select the location, then select **View dependency paths**.
|
||||
|
||||
Details of each dependency are listed, sorted by decreasing severity of vulnerabilities (if any). You can sort the list instead by component name, packager, or license.
|
||||
|
||||
|
|
@ -66,7 +77,7 @@ Details of each dependency are listed, sorted by decreasing severity of vulnerab
|
|||
|:----------|:-----------|
|
||||
| Component | The dependency's name and version. |
|
||||
| Packager | The packager used to install the dependency. |
|
||||
| Location | For system dependencies, this lists the image that was scanned. For application dependencies, this shows a link to the packager-specific lock file in your project that declared the dependency. It also shows the [direct dependents](#dependency-paths) of the dependency, if any, and if supported. |
|
||||
| Location | For system dependencies, this field lists the image that was scanned. For application dependencies, this field shows a link to the packager-specific lock file in your project that declared the dependency. It also shows the direct [dependents](#dependency-paths), if any. If there are transitive dependencies, selecting **View dependency paths** shows the full path of all dependents. Transitive dependencies are indirect dependents that have a direct dependent as an ancestor. |
|
||||
| License (for projects only) | Links to dependency's software licenses. A warning badge that includes the number of vulnerabilities detected in the dependency. |
|
||||
| Projects (for groups only) | Links to the project with the dependency. If multiple projects have the same dependency, the total number of these projects is shown. To go to a project with this dependency, select the **Projects** number, then search for and select its name. The project search feature is supported only on groups that have up to 600 occurrences in their group hierarchy. |
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ including:
|
|||
- Available actions
|
||||
- Linked issues
|
||||
- Actions log
|
||||
- Filename and line number of the vulnerability (if available)
|
||||
- Location
|
||||
- Severity
|
||||
|
||||
For vulnerabilities in the [Common Vulnerabilities and Exposures (CVE)](https://www.cve.org/)
|
||||
|
|
@ -571,3 +571,29 @@ To view the security training for a vulnerability:
|
|||
1. Select **Secure > Vulnerability report**.
|
||||
1. Select the vulnerability for which you want to view security training.
|
||||
1. Select **View training**.
|
||||
|
||||
## View the location of a vulnerability in transitive dependencies
|
||||
|
||||
{{< history >}}
|
||||
|
||||
- View dependency paths option [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/519965) in GitLab 17.11 [with a flag](../../../administration/feature_flags.md) named `dependency_paths`. Disabled by default.
|
||||
|
||||
{{< /history >}}
|
||||
|
||||
{{< alert type="flag" >}}
|
||||
|
||||
The availability of this feature is controlled by a feature flag.
|
||||
For more information, see the history.
|
||||
|
||||
{{< /alert >}}
|
||||
|
||||
When managing vulnerabilities found in dependencies in the vulnerability details, under **Location**, you can view:
|
||||
|
||||
- The location of the direct dependency where the vulnerability was found.
|
||||
- If available, the specific line number where the vulnerability occurs.
|
||||
|
||||
If the vulnerability occurs in one or more transitive dependencies, knowing only the direct dependency may not be enough. Transitive dependencies are indirect dependencies that have a direct dependent as an ancestor.
|
||||
|
||||
If any transitive dependencies exist, you can view the paths to all dependencies, including the transitive dependencies that contain the vulnerability.
|
||||
|
||||
- On the vulnerability details page, under **Location**, select **View dependency paths**. If **View dependency paths** doesn't appear, then there are no transitive dependencies.
|
||||
|
|
|
|||
|
|
@ -6742,6 +6742,9 @@ msgstr ""
|
|||
msgid "An error occurred loading the projects. Please refresh the page to try again."
|
||||
msgstr ""
|
||||
|
||||
msgid "An error occurred loading the tab counts."
|
||||
msgstr ""
|
||||
|
||||
msgid "An error occurred previewing the blob"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -11552,6 +11555,9 @@ msgstr ""
|
|||
msgid "CICD|Allow Git push requests to the repository"
|
||||
msgstr ""
|
||||
|
||||
msgid "CICD|Allow composite identities to run pipelines"
|
||||
msgstr ""
|
||||
|
||||
msgid "CICD|An error occurred while adding the authentication log entries. Please try again."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -11609,6 +11615,9 @@ msgstr ""
|
|||
msgid "CICD|Continuous deployment to production using timed incremental rollout"
|
||||
msgstr ""
|
||||
|
||||
msgid "CICD|Controls whether AI agents can automatically run pipelines. When disabled, pipelines triggered by AI agents will require manual review and execution by a human user."
|
||||
msgstr ""
|
||||
|
||||
msgid "CICD|Default (user membership and role)"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -29623,6 +29632,9 @@ msgstr ""
|
|||
msgid "GroupSAML|An error occurred resetting your SCIM token. Please try again."
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupSAML|Any Provider (Default)"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -29677,6 +29689,9 @@ msgstr ""
|
|||
msgid "GroupSAML|Identifier"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupSAML|Identity Provider"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupSAML|Identity provider single sign-on URL"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -29770,6 +29785,9 @@ msgstr ""
|
|||
msgid "GroupSAML|Valid SAML Response"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupSAML|When selected, group sync will only occur when both the SAML group name and provider match."
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupSAML|as %{access_level}"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -71413,6 +71431,9 @@ msgstr ""
|
|||
msgid "does not match dast_site_validation.project"
|
||||
msgstr ""
|
||||
|
||||
msgid "does not match the name of the predefined control."
|
||||
msgstr ""
|
||||
|
||||
msgid "does not support select options."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -71753,6 +71774,9 @@ msgstr ""
|
|||
msgid "is not part of the given organization"
|
||||
msgstr ""
|
||||
|
||||
msgid "is not valid."
|
||||
msgstr ""
|
||||
|
||||
msgid "is not valid. The iteration group has to match the iteration cadence group."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
|
||||
RSpec.describe 'Verify', product_group: :pipeline_authoring do
|
||||
describe 'Pipeline API defined variable inheritance' do
|
||||
include_context 'variable inheritance test prep'
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring,
|
||||
RSpec.describe 'Verify', product_group: :pipeline_authoring,
|
||||
only: { subdomain: 'staging-canary' } do
|
||||
# Runs this test only in staging-canary to debug flakiness https://gitlab.com/gitlab-org/gitlab/-/issues/424903
|
||||
# We need to collect failure data, please don't quarantine for the time being
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
|
||||
RSpec.describe 'Verify', product_group: :pipeline_authoring do
|
||||
describe 'Pipeline with project file variables' do
|
||||
let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
|
||||
let(:project) { create(:project, name: 'project-with-file-variables') }
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ module QA
|
|||
end
|
||||
end
|
||||
|
||||
RSpec.describe 'Manage', :orchestrated, :runner, :requires_admin, :smtp, product_group: :import_and_integrate do
|
||||
RSpec.describe 'Manage', :orchestrated, :requires_admin, :smtp, product_group: :import_and_integrate do
|
||||
describe 'Pipeline status emails' do
|
||||
let(:executor) { "qa-runner-#{SecureRandom.hex(6)}" }
|
||||
let(:emails) { %w[foo@bar.com baz@buzz.com] }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Create', :runner, product_group: :code_review do
|
||||
RSpec.describe 'Create', product_group: :code_review do
|
||||
describe 'Merge request set to auto-merge' do
|
||||
let(:runner_name) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
|
||||
let(:project) { create(:project, name: 'set-to-auto-merge') }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
|
||||
RSpec.describe 'Verify', product_group: :pipeline_authoring do
|
||||
describe 'CI component', :skip_live_env do
|
||||
let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
|
||||
let(:tag) { '1.0.0' }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_execution do
|
||||
RSpec.describe 'Verify', product_group: :pipeline_execution do
|
||||
describe 'Job artifacts' do
|
||||
context 'when exposed' do
|
||||
let(:total_jobs_count) { 3 }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, :requires_admin, product_group: :pipeline_execution do
|
||||
RSpec.describe 'Verify', :requires_admin, product_group: :pipeline_execution do
|
||||
describe 'Pipeline configuration access keyword' do
|
||||
let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
|
||||
let(:project) { create(:project, name: 'project-with-artifacts', initialize_with_readme: true) }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_execution,
|
||||
RSpec.describe 'Verify', product_group: :pipeline_execution,
|
||||
quarantine: {
|
||||
issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/422863',
|
||||
type: :flaky
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_execution do
|
||||
RSpec.describe 'Verify', product_group: :pipeline_execution do
|
||||
describe "Unlocking job artifacts across pipelines" do
|
||||
let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
|
||||
let(:project) { create(:project, name: 'unlock-job-artifacts-project') }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_execution do
|
||||
RSpec.describe 'Verify', product_group: :pipeline_execution do
|
||||
describe 'Project artifacts' do
|
||||
context 'when user tries bulk deletion' do
|
||||
let(:total_jobs_count) { 20 }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring,
|
||||
RSpec.describe 'Verify', product_group: :pipeline_authoring,
|
||||
quarantine: {
|
||||
issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/523094',
|
||||
type: :investigating
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, :requires_admin, product_group: :pipeline_authoring do
|
||||
RSpec.describe 'Verify', :requires_admin, product_group: :pipeline_authoring do
|
||||
describe 'Pipeline with protected variable' do
|
||||
let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
|
||||
let(:protected_value) { Faker::Alphanumeric.alphanumeric(number: 8) }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner do
|
||||
RSpec.describe 'Verify' do
|
||||
describe 'Pipeline with raw variables in YAML', product_group: :pipeline_authoring do
|
||||
let(:executor) { "qa-runner-#{SecureRandom.hex(6)}" }
|
||||
let(:pipeline_job_name) { 'rspec' }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
|
||||
RSpec.describe 'Verify', product_group: :pipeline_authoring do
|
||||
describe 'UI defined variable' do
|
||||
include_context 'variable inheritance test prep'
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
|
||||
RSpec.describe 'Verify', product_group: :pipeline_authoring do
|
||||
describe 'UI defined variable' do
|
||||
include_context 'variable inheritance test prep'
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
|
||||
RSpec.describe 'Verify', product_group: :pipeline_authoring do
|
||||
describe 'Include multiple files from a project' do
|
||||
let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
|
||||
let(:expected_text) { Faker::Lorem.sentence }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
|
||||
RSpec.describe 'Verify', product_group: :pipeline_authoring do
|
||||
describe 'Include multiple files from multiple projects' do
|
||||
let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
|
||||
let(:main_project) { create(:project, name: 'project-with-pipeline') }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_execution,
|
||||
RSpec.describe 'Verify', product_group: :pipeline_execution,
|
||||
quarantine: {
|
||||
issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/411510',
|
||||
type: :flaky
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_execution do
|
||||
RSpec.describe 'Verify', product_group: :pipeline_execution do
|
||||
describe 'Parent-child pipelines independent relationship' do
|
||||
let!(:project) { create(:project, name: 'pipeline-independent-relationship') }
|
||||
let!(:runner) { create(:project_runner, project: project, name: project.name, tags: [project.name]) }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
|
||||
RSpec.describe 'Verify', product_group: :pipeline_authoring do
|
||||
describe 'Pass dotenv variables to downstream via bridge' do
|
||||
let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
|
||||
let(:upstream_var) { Faker::Alphanumeric.alphanumeric(number: 8) }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
|
||||
RSpec.describe 'Verify', product_group: :pipeline_authoring do
|
||||
describe 'Pipeline with image:pull_policy' do
|
||||
let(:runner_name) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
|
||||
let(:job_name) { "test-job-#{pull_policies.join('-')}" }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_execution do
|
||||
RSpec.describe 'Verify', product_group: :pipeline_execution do
|
||||
describe 'Run pipeline with manual jobs' do
|
||||
let(:executor) { "qa-runner-#{SecureRandom.hex(4)}" }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_execution do
|
||||
RSpec.describe 'Verify', product_group: :pipeline_execution do
|
||||
describe "Trigger child pipeline with 'when:manual'" do
|
||||
let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
|
||||
let(:project) { create(:project, name: 'project-with-pipeline') }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
|
||||
RSpec.describe 'Verify', product_group: :pipeline_authoring do
|
||||
describe 'Trigger matrix' do
|
||||
let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(number: 8)}" }
|
||||
let(:project) { create(:project, name: 'project-with-pipeline') }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :runner do
|
||||
RSpec.describe 'Verify', product_group: :runner do
|
||||
describe 'Group runner with deprecated registration token' do
|
||||
let(:executor) { "qa-runner-#{SecureRandom.hex(6)}" }
|
||||
let!(:runner) do
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :runner do
|
||||
RSpec.describe 'Verify', product_group: :runner do
|
||||
describe 'Group runner registration' do
|
||||
let(:executor) { "qa-runner-#{SecureRandom.hex(6)}" }
|
||||
let!(:runner) { create(:group_runner, name: executor) }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, product_group: :runner,
|
||||
RSpec.describe 'Verify', product_group: :runner,
|
||||
feature_flag: { name: 'vue_project_runners_settings', scope: :project } do
|
||||
describe 'Runner registration' do
|
||||
let(:executor) { "qa-runner-#{SecureRandom.hex(6)}" }
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ module QA
|
|||
# pipeline created (Sidekiq read/write) ->
|
||||
# runner picks up pipeline (API read/write) ->
|
||||
# User views pipeline succeeds (Web read)
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
|
||||
RSpec.describe 'Verify', product_group: :pipeline_authoring do
|
||||
context 'Endpoint Coverage' do
|
||||
let!(:project) { create(:project, name: 'endpoint-coverage') }
|
||||
let!(:runner) { create(:project_runner, project: project, name: project.name, tags: [project.name]) }
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
require 'digest/sha1'
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Release', :runner, product_group: :environments do
|
||||
RSpec.describe 'Release', product_group: :environments do
|
||||
describe 'Git clone using a deploy key' do
|
||||
let(:runner_name) { "qa-runner-#{SecureRandom.hex(4)}" }
|
||||
let(:repository_location) { project.repository_ssh_location }
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
"name": "minimum_approvals_required_2",
|
||||
"control_type": "internal",
|
||||
"expression": {
|
||||
"operator": "=",
|
||||
"operator": ">=",
|
||||
"field": "minimum_approvals_required",
|
||||
"value": 2
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
"name": "minimum_approvals_required_2",
|
||||
"control_type": "internal",
|
||||
"expression": {
|
||||
"operator": "=",
|
||||
"operator": ">=",
|
||||
"field": "minimum_approvals_required",
|
||||
"value": 2
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ describe('YourWorkGroupsApp', () => {
|
|||
initialSort: defaultPropsData.initialSort,
|
||||
programmingLanguages: [],
|
||||
eventTracking: {},
|
||||
tabCountsQuery: {},
|
||||
tabCountsQueryErrorMessage: 'An error occurred loading the tab counts.',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -88,6 +88,8 @@ const defaultPropsData = {
|
|||
tabs: 'click_tab_on_your_work_projects',
|
||||
sort: 'click_sort_on_your_work_projects',
|
||||
},
|
||||
tabCountsQuery: projectCountsQuery,
|
||||
tabCountsQueryErrorMessage: 'An error occurred loading the project counts.',
|
||||
};
|
||||
|
||||
const { bindInternalEventDocument } = useMockInternalEventsTracking();
|
||||
|
|
@ -143,6 +145,7 @@ describe('TabsWithList', () => {
|
|||
extendedWrapper(findTabByName(tabName)).findByTestId('tab-counter-badge').text();
|
||||
const findFilteredSearchAndSort = () => wrapper.findComponent(FilteredSearchAndSort);
|
||||
const findTabView = () => wrapper.findComponent(TabView);
|
||||
const findBadge = () => wrapper.findComponent(GlBadge);
|
||||
|
||||
afterEach(() => {
|
||||
router = null;
|
||||
|
|
@ -150,14 +153,14 @@ describe('TabsWithList', () => {
|
|||
});
|
||||
|
||||
describe('template', () => {
|
||||
describe('when project counts are loading', () => {
|
||||
describe('when tab counts are loading', () => {
|
||||
it('does not show count badges', async () => {
|
||||
await createComponent();
|
||||
expect(wrapper.findComponent(GlBadge).exists()).toBe(false);
|
||||
expect(findBadge().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when project counts are successfully retrieved', () => {
|
||||
describe('when tab counts are successfully retrieved', () => {
|
||||
beforeEach(async () => {
|
||||
await createComponent();
|
||||
await waitForPromises();
|
||||
|
|
@ -172,24 +175,58 @@ describe('TabsWithList', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('when project counts are not successfully retrieved', () => {
|
||||
describe('when tab counts are not successfully retrieved', () => {
|
||||
const error = new Error();
|
||||
|
||||
beforeEach(async () => {
|
||||
await createComponent({ projectsCountHandler: jest.fn().mockRejectedValue(error) });
|
||||
await waitForPromises();
|
||||
});
|
||||
describe('when tabCountsQueryErrorMessage prop is passed', () => {
|
||||
beforeEach(async () => {
|
||||
await createComponent({ projectsCountHandler: jest.fn().mockRejectedValue(error) });
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('displays error alert', () => {
|
||||
expect(createAlert).toHaveBeenCalledWith({
|
||||
message: 'An error occurred loading the project counts.',
|
||||
error,
|
||||
captureError: true,
|
||||
it('displays error alert with message', () => {
|
||||
expect(createAlert).toHaveBeenCalledWith({
|
||||
message: defaultPropsData.tabCountsQueryErrorMessage,
|
||||
error,
|
||||
captureError: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('does not show count badges', () => {
|
||||
expect(wrapper.findComponent(GlBadge).exists()).toBe(false);
|
||||
describe('when tabCountsQueryErrorMessage prop is not passed', () => {
|
||||
beforeEach(async () => {
|
||||
await createComponent({
|
||||
projectsCountHandler: jest.fn().mockRejectedValue(error),
|
||||
propsData: { tabCountsQueryErrorMessage: undefined },
|
||||
});
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('displays error alert with default message', () => {
|
||||
expect(createAlert).toHaveBeenCalledWith({
|
||||
message: 'An error occurred loading the tab counts.',
|
||||
error,
|
||||
captureError: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('does not show tab count badges', async () => {
|
||||
await createComponent({ projectsCountHandler: jest.fn().mockRejectedValue(error) });
|
||||
await waitForPromises();
|
||||
|
||||
expect(findBadge().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when tabCountsQuery prop is not passed', () => {
|
||||
beforeEach(async () => {
|
||||
await createComponent({ propsData: { tabCountsQuery: {} } });
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('does not make GraphQL query or show tab count badges', () => {
|
||||
expect(findBadge().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import {
|
|||
FILTERED_SEARCH_TERM_KEY,
|
||||
FILTERED_SEARCH_NAMESPACE,
|
||||
} from '~/projects/filtered_search_and_sort/constants';
|
||||
import projectCountsQuery from '~/projects/your_work/graphql/queries/project_counts.query.graphql';
|
||||
import {
|
||||
TIMESTAMP_TYPE_CREATED_AT,
|
||||
TIMESTAMP_TYPE_LAST_ACTIVITY_AT,
|
||||
|
|
@ -65,6 +66,8 @@ describe('YourWorkProjectsApp', () => {
|
|||
tabs: 'click_tab_on_your_work_projects',
|
||||
sort: 'click_sort_on_your_work_projects',
|
||||
},
|
||||
tabCountsQuery: projectCountsQuery,
|
||||
tabCountsQueryErrorMessage: 'An error occurred loading the project counts.',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
require 'fast_spec_helper'
|
||||
require 'gitlab/dangerfiles/spec_helper'
|
||||
|
||||
require_relative '../../../../tooling/danger/remote_development/desired_config_generator'
|
||||
require_relative '../../../../tooling/danger/remote_development/desired_config_generator_suggestor'
|
||||
require_relative '../../../../tooling/danger/project_helper'
|
||||
|
||||
RSpec.describe Tooling::Danger::RemoteDevelopment::DesiredConfigGenerator, feature_category: :tooling do
|
||||
RSpec.describe Tooling::Danger::RemoteDevelopment::DesiredConfigGeneratorSuggestor, feature_category: :workspaces do
|
||||
subject(:remote_development) { fake_danger.new(helper: fake_helper) }
|
||||
|
||||
let(:fake_danger) { DangerSpecHelper.fake_danger.include(described_class) }
|
||||
|
|
@ -5,7 +5,7 @@ require_relative '../suggestor'
|
|||
module Tooling
|
||||
module Danger
|
||||
module RemoteDevelopment
|
||||
module DesiredConfigGenerator
|
||||
module DesiredConfigGeneratorSuggestor
|
||||
include ::Tooling::Danger::Suggestor
|
||||
|
||||
WORKSPACE_LIB = 'ee/lib/remote_development/workspace_operations'
|
||||
Loading…
Reference in New Issue