Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
5e65d4f6c6
commit
ee52c3666e
|
@ -23,6 +23,7 @@ export function initIssueStatusSelect() {
|
|||
|
||||
return new Vue({
|
||||
el,
|
||||
name: 'StatusSelectRoot',
|
||||
render: (createElement) => createElement(StatusSelect),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ export function initCsvImportExportButtons() {
|
|||
|
||||
return new Vue({
|
||||
el,
|
||||
name: 'CsvImportExportButtonsRoot',
|
||||
provide: {
|
||||
showExportButton: parseBoolean(showExportButton),
|
||||
showImportButton: parseBoolean(showImportButton),
|
||||
|
@ -74,6 +75,7 @@ export function initIssuableByEmail() {
|
|||
|
||||
return new Vue({
|
||||
el,
|
||||
name: 'IssuableByEmailRoot',
|
||||
provide: {
|
||||
initialEmail,
|
||||
issuableType,
|
||||
|
|
|
@ -30,6 +30,7 @@ export function mountJiraIssuesListApp() {
|
|||
|
||||
return new Vue({
|
||||
el,
|
||||
name: 'JiraIssuesImportStatusRoot',
|
||||
apolloProvider,
|
||||
render(createComponent) {
|
||||
return createComponent(JiraIssuesImportStatusRoot, {
|
||||
|
@ -119,6 +120,7 @@ export function mountIssuesListApp() {
|
|||
|
||||
return new Vue({
|
||||
el,
|
||||
name: 'IssuesListRoot',
|
||||
apolloProvider,
|
||||
provide: {
|
||||
autocompleteAwardEmojisPath,
|
||||
|
|
|
@ -20,6 +20,7 @@ export function initTitleSuggestions() {
|
|||
|
||||
return new Vue({
|
||||
el,
|
||||
name: 'TitleSuggestionsRoot',
|
||||
apolloProvider,
|
||||
data() {
|
||||
return {
|
||||
|
@ -51,6 +52,7 @@ export function initTypePopover() {
|
|||
|
||||
return new Vue({
|
||||
el,
|
||||
name: 'TypePopoverRoot',
|
||||
render: (createElement) => createElement(TypePopover),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ export default {
|
|||
this.renderGFM();
|
||||
this.updateTaskStatusText();
|
||||
|
||||
if (this.workItemsEnabled && this.$el) {
|
||||
if (this.workItemsEnabled) {
|
||||
this.renderTaskActions();
|
||||
}
|
||||
},
|
||||
|
@ -157,7 +157,12 @@ export default {
|
|||
}
|
||||
},
|
||||
renderTaskActions() {
|
||||
if (!this.$el?.querySelectorAll) {
|
||||
return;
|
||||
}
|
||||
|
||||
const taskListFields = this.$el.querySelectorAll('.task-list-item');
|
||||
|
||||
taskListFields.forEach((item, index) => {
|
||||
const button = document.createElement('button');
|
||||
button.classList.add(
|
||||
|
|
|
@ -160,6 +160,7 @@ export function initSentryErrorStackTrace() {
|
|||
|
||||
return new Vue({
|
||||
el,
|
||||
name: 'SentryErrorStackTraceRoot',
|
||||
store: errorTrackingStore,
|
||||
render: (createElement) =>
|
||||
createElement(SentryErrorStackTrace, { props: { issueStackTracePath } }),
|
||||
|
|
|
@ -11,6 +11,7 @@ import ProjectLabelSubscription from './project_label_subscription';
|
|||
|
||||
export function initDeleteLabelModal(optionalProps = {}) {
|
||||
new Vue({
|
||||
name: 'DeleteLabelModalRoot',
|
||||
render(h) {
|
||||
return h(DeleteLabelModal, {
|
||||
props: {
|
||||
|
@ -65,6 +66,7 @@ export function initLabelIndex() {
|
|||
|
||||
return new Vue({
|
||||
el: '#js-promote-label-modal',
|
||||
name: 'PromoteLabelModal',
|
||||
data() {
|
||||
return {
|
||||
modalProps: {
|
||||
|
|
|
@ -46,6 +46,7 @@ export function initPromoteMilestoneModal() {
|
|||
|
||||
return new Vue({
|
||||
el: promoteMilestoneModal,
|
||||
name: 'PromoteMilestoneModalRoot',
|
||||
render(createElement) {
|
||||
return createElement(PromoteMilestoneModal);
|
||||
},
|
||||
|
@ -80,6 +81,7 @@ export function initDeleteMilestoneModal() {
|
|||
|
||||
return new Vue({
|
||||
el: '#js-delete-milestone-modal',
|
||||
name: 'DeleteMilestoneModalRoot',
|
||||
data() {
|
||||
return {
|
||||
modalProps: {
|
||||
|
|
|
@ -136,8 +136,8 @@ export default {
|
|||
return __('Branch');
|
||||
}
|
||||
},
|
||||
commitTitle() {
|
||||
return this.pipeline?.commit?.title;
|
||||
commitTitleText() {
|
||||
return this.pipeline?.commit?.title || __("Can't find HEAD commit for this branch");
|
||||
},
|
||||
hasAuthor() {
|
||||
return (
|
||||
|
@ -159,27 +159,22 @@ export default {
|
|||
<div class="pipeline-tags" data-testid="pipeline-url-table-cell">
|
||||
<template v-if="rearrangePipelinesTable">
|
||||
<div class="commit-title gl-mb-2" data-testid="commit-title-container">
|
||||
<span v-if="commitTitle" class="gl-display-flex">
|
||||
<tooltip-on-truncate :title="commitTitle" class="flex-truncate-child gl-flex-grow-1">
|
||||
<span class="gl-display-flex">
|
||||
<tooltip-on-truncate :title="commitTitleText" class="flex-truncate-child gl-flex-grow-1">
|
||||
<gl-link
|
||||
:href="commitUrl"
|
||||
class="commit-row-message gl-text-gray-900"
|
||||
:href="pipeline.path"
|
||||
class="commit-row-message gl-text-blue-600!"
|
||||
data-testid="commit-title"
|
||||
>{{ commitTitle }}</gl-link
|
||||
data-qa-selector="pipeline_url_link"
|
||||
>{{ commitTitleText }}</gl-link
|
||||
>
|
||||
</tooltip-on-truncate>
|
||||
</span>
|
||||
<span v-else>{{ __("Can't find HEAD commit for this branch") }}</span>
|
||||
</div>
|
||||
<div class="gl-mb-2">
|
||||
<gl-link
|
||||
:href="pipeline.path"
|
||||
class="gl-text-decoration-underline gl-text-blue-600!"
|
||||
data-testid="pipeline-url-link"
|
||||
data-qa-selector="pipeline_url_link"
|
||||
>
|
||||
<span class="gl-font-weight-bold gl-text-gray-500" data-testid="pipeline-identifier">
|
||||
#{{ pipeline[pipelineKey] }}
|
||||
</gl-link>
|
||||
</span>
|
||||
<!--Commit row-->
|
||||
<div class="icon-container gl-display-inline-block">
|
||||
<gl-icon
|
||||
|
|
|
@ -21,6 +21,7 @@ export default class SidebarMilestone {
|
|||
// eslint-disable-next-line no-new
|
||||
new Vue({
|
||||
el,
|
||||
name: 'SidebarMilestoneRoot',
|
||||
components: {
|
||||
timeTracker,
|
||||
},
|
||||
|
|
|
@ -70,6 +70,7 @@ export default (selector) => {
|
|||
// eslint-disable-next-line no-new
|
||||
new Vue({
|
||||
el: selector,
|
||||
name: 'AlertDetailsRoot',
|
||||
components: {
|
||||
AlertDetails,
|
||||
},
|
||||
|
|
|
@ -4,7 +4,7 @@ module Ci
|
|||
class RunnersFinder < UnionFinder
|
||||
include Gitlab::Allowable
|
||||
|
||||
ALLOWED_SORTS = %w[contacted_asc contacted_desc created_at_asc created_at_desc created_date].freeze
|
||||
ALLOWED_SORTS = %w[contacted_asc contacted_desc created_at_asc created_at_desc created_date token_expires_at_asc token_expires_at_desc].freeze
|
||||
DEFAULT_SORT = 'created_at_desc'
|
||||
|
||||
def initialize(current_user:, params:)
|
||||
|
|
|
@ -10,6 +10,8 @@ module Types
|
|||
value 'CONTACTED_DESC', 'Ordered by contacted_at in descending order.', value: :contacted_desc
|
||||
value 'CREATED_ASC', 'Ordered by created_at in ascending order.', value: :created_at_asc
|
||||
value 'CREATED_DESC', 'Ordered by created_at in descending order.', value: :created_at_desc
|
||||
value 'TOKEN_EXPIRES_AT_ASC', 'Ordered by token_expires_at in ascending order.', value: :token_expires_at_asc
|
||||
value 'TOKEN_EXPIRES_AT_DESC', 'Ordered by token_expires_at in descending order.', value: :token_expires_at_desc
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -25,6 +25,9 @@ module Types
|
|||
field :contacted_at, Types::TimeType, null: true,
|
||||
description: 'Timestamp of last contact from this runner.',
|
||||
method: :contacted_at
|
||||
field :token_expires_at, Types::TimeType, null: true,
|
||||
description: 'Runner token expiration time.',
|
||||
method: :token_expires_at
|
||||
field :maximum_timeout, GraphQL::Types::Int, null: true,
|
||||
description: 'Maximum timeout (in seconds) for jobs processed by the runner.'
|
||||
field :access_level, ::Types::Ci::RunnerAccessLevelEnum, null: false,
|
||||
|
|
|
@ -15,5 +15,6 @@ module Types
|
|||
field :snippets_size, GraphQL::Types::Float, null: false, description: 'Snippets size in bytes.'
|
||||
field :pipeline_artifacts_size, GraphQL::Types::Float, null: false, description: 'CI pipeline artifacts size in bytes.'
|
||||
field :uploads_size, GraphQL::Types::Float, null: false, description: 'Uploads size in bytes.'
|
||||
field :dependency_proxy_size, GraphQL::Types::Float, null: false, description: 'Dependency Proxy sizes in bytes.'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -223,13 +223,9 @@ To add methods of a module to an allowlist, use `delegator_override_with`. For e
|
|||
```ruby
|
||||
module Ci
|
||||
class PipelinePresenter < Gitlab::View::Presenter::Delegated
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
include ActionView::Helpers::UrlHelper
|
||||
include ActionView::Helpers::TagHelper
|
||||
|
||||
delegator_override_with Gitlab::Utils::StrongMemoize # TODO: Remove `Gitlab::Utils::StrongMemoize` inclusion as it's duplicate
|
||||
delegator_override_with ActionView::Helpers::TagHelper # TODO: Remove `ActionView::Helpers::UrlHelper` inclusion as it overrides `Ci::Pipeline#tag`
|
||||
delegator_override_with ActionView::Helpers::TagHelper # TODO: Remove `ActionView::Helpers::TagHelper` inclusion as it overrides `Ci::Pipeline#tag`
|
||||
```
|
||||
|
||||
Keep in mind that if you use `delegator_override_with`,
|
||||
there is a high chance that you're doing **something wrong**.
|
||||
Read the [Validate Accidental Overrides](#validate-accidental-overrides) for more information.
|
||||
|
|
|
@ -6,7 +6,7 @@ module AlertManagement
|
|||
include ActionView::Helpers::UrlHelper
|
||||
|
||||
presents ::AlertManagement::Alert
|
||||
delegator_override_with Gitlab::Utils::StrongMemoize # TODO: Remove `Gitlab::Utils::StrongMemoize` inclusion as it's duplicate
|
||||
delegator_override_with Gitlab::Utils::StrongMemoize # This module inclusion is expected. See https://gitlab.com/gitlab-org/gitlab/-/issues/352884.
|
||||
|
||||
MARKDOWN_LINE_BREAK = " \n"
|
||||
HORIZONTAL_LINE = "\n\n---\n\n"
|
||||
|
|
|
@ -4,7 +4,7 @@ module Ci
|
|||
class PipelinePresenter < Gitlab::View::Presenter::Delegated
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
|
||||
delegator_override_with Gitlab::Utils::StrongMemoize # TODO: Remove `Gitlab::Utils::StrongMemoize` inclusion as it's duplicate
|
||||
delegator_override_with Gitlab::Utils::StrongMemoize # This module inclusion is expected. See https://gitlab.com/gitlab-org/gitlab/-/issues/352884.
|
||||
delegator_override_with ActionView::Helpers::TagHelper # TODO: Remove `ActionView::Helpers::UrlHelper` inclusion as it overrides `Ci::Pipeline#tag`
|
||||
|
||||
# We use a class method here instead of a constant, allowing EE to redefine
|
||||
|
|
|
@ -13,7 +13,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
|
|||
include Gitlab::Experiment::Dsl
|
||||
|
||||
delegator_override_with GitlabRoutingHelper # TODO: Remove `GitlabRoutingHelper` inclusion as it's duplicate
|
||||
delegator_override_with Gitlab::Utils::StrongMemoize # TODO: Remove `Gitlab::Utils::StrongMemoize` inclusion as it's duplicate
|
||||
delegator_override_with Gitlab::Utils::StrongMemoize # This module inclusion is expected. See https://gitlab.com/gitlab-org/gitlab/-/issues/352884.
|
||||
|
||||
presents ::Project, as: :project
|
||||
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: grape_gitlab_json
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36472
|
||||
rollout_issue_url:
|
||||
milestone: '13.2'
|
||||
type: development
|
||||
group: group::source code
|
||||
default_enabled: true
|
|
@ -0,0 +1,16 @@
|
|||
- name: "Deprecate feature flag PUSH_RULES_SUPERSEDE_CODE_OWNERS" # The name of the feature to be deprecated
|
||||
announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
|
||||
announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
|
||||
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
|
||||
removal_date: "2022-05-22" # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
|
||||
breaking_change: true # If this deprecation is a breaking change, set this value to true
|
||||
reporter: sarahwaldner # GitLab username of the person reporting the deprecation
|
||||
body: | # Do not modify this line, instead modify the lines below.
|
||||
The feature flag `PUSH_RULES_SUPERSEDE_CODE_OWNERS` is being removed in GitLab 15.0. Upon its removal, push rules will supersede CODEOWNERS. The CODEOWNERS feature will no longer be available for access control.
|
||||
# The following items are not published on the docs page, but may be used in the future.
|
||||
stage: create # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
|
||||
tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
|
||||
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/262019 # (optional) This is a link to the deprecation issue in GitLab
|
||||
documentation_url: # (optional) This is a link to the current documentation page
|
||||
image_url: # (optional) This is a link to a thumbnail image depicting the feature
|
||||
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
|
|
@ -0,0 +1,32 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateJobArtifactStates < Gitlab::Database::Migration[1.0]
|
||||
VERIFICATION_STATE_INDEX_NAME = "index_job_artifact_states_on_verification_state"
|
||||
PENDING_VERIFICATION_INDEX_NAME = "index_job_artifact_states_pending_verification"
|
||||
FAILED_VERIFICATION_INDEX_NAME = "index_job_artifact_states_failed_verification"
|
||||
NEEDS_VERIFICATION_INDEX_NAME = "index_job_artifact_states_needs_verification"
|
||||
|
||||
enable_lock_retries!
|
||||
|
||||
def up
|
||||
create_table :ci_job_artifact_states, id: false do |t|
|
||||
t.datetime_with_timezone :verification_started_at
|
||||
t.datetime_with_timezone :verification_retry_at
|
||||
t.datetime_with_timezone :verified_at
|
||||
t.references :job_artifact, primary_key: true, null: false, foreign_key: { on_delete: :cascade, to_table: :ci_job_artifacts }
|
||||
t.integer :verification_state, default: 0, limit: 2, null: false
|
||||
t.integer :verification_retry_count, limit: 2
|
||||
t.binary :verification_checksum, using: 'verification_checksum::bytea'
|
||||
t.text :verification_failure, limit: 255
|
||||
|
||||
t.index :verification_state, name: VERIFICATION_STATE_INDEX_NAME
|
||||
t.index :verified_at, where: "(verification_state = 0)", order: { verified_at: 'ASC NULLS FIRST' }, name: PENDING_VERIFICATION_INDEX_NAME
|
||||
t.index :verification_retry_at, where: "(verification_state = 3)", order: { verification_retry_at: 'ASC NULLS FIRST' }, name: FAILED_VERIFICATION_INDEX_NAME
|
||||
t.index :verification_state, where: "(verification_state = 0 OR verification_state = 3)", name: NEEDS_VERIFICATION_INDEX_NAME
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
drop_table :ci_job_artifact_states
|
||||
end
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
d618c28360f7716807e9727566019e269963d85164cf2f306ec9692d3b037802
|
|
@ -11863,6 +11863,27 @@ CREATE SEQUENCE ci_instance_variables_id_seq
|
|||
|
||||
ALTER SEQUENCE ci_instance_variables_id_seq OWNED BY ci_instance_variables.id;
|
||||
|
||||
CREATE TABLE ci_job_artifact_states (
|
||||
verification_started_at timestamp with time zone,
|
||||
verification_retry_at timestamp with time zone,
|
||||
verified_at timestamp with time zone,
|
||||
job_artifact_id bigint NOT NULL,
|
||||
verification_state smallint DEFAULT 0 NOT NULL,
|
||||
verification_retry_count smallint,
|
||||
verification_checksum bytea,
|
||||
verification_failure text,
|
||||
CONSTRAINT check_df832b66ea CHECK ((char_length(verification_failure) <= 255))
|
||||
);
|
||||
|
||||
CREATE SEQUENCE ci_job_artifact_states_job_artifact_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
ALTER SEQUENCE ci_job_artifact_states_job_artifact_id_seq OWNED BY ci_job_artifact_states.job_artifact_id;
|
||||
|
||||
CREATE TABLE ci_job_artifacts (
|
||||
project_id integer NOT NULL,
|
||||
file_type integer NOT NULL,
|
||||
|
@ -21661,6 +21682,8 @@ ALTER TABLE ONLY ci_group_variables ALTER COLUMN id SET DEFAULT nextval('ci_grou
|
|||
|
||||
ALTER TABLE ONLY ci_instance_variables ALTER COLUMN id SET DEFAULT nextval('ci_instance_variables_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY ci_job_artifact_states ALTER COLUMN job_artifact_id SET DEFAULT nextval('ci_job_artifact_states_job_artifact_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY ci_job_artifacts ALTER COLUMN id SET DEFAULT nextval('ci_job_artifacts_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY ci_job_token_project_scope_links ALTER COLUMN id SET DEFAULT nextval('ci_job_token_project_scope_links_id_seq'::regclass);
|
||||
|
@ -23138,6 +23161,9 @@ ALTER TABLE ONLY ci_group_variables
|
|||
ALTER TABLE ONLY ci_instance_variables
|
||||
ADD CONSTRAINT ci_instance_variables_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY ci_job_artifact_states
|
||||
ADD CONSTRAINT ci_job_artifact_states_pkey PRIMARY KEY (job_artifact_id);
|
||||
|
||||
ALTER TABLE ONLY ci_job_artifacts
|
||||
ADD CONSTRAINT ci_job_artifacts_pkey PRIMARY KEY (id);
|
||||
|
||||
|
@ -25767,6 +25793,8 @@ CREATE UNIQUE INDEX index_ci_group_variables_on_group_id_and_key_and_environment
|
|||
|
||||
CREATE UNIQUE INDEX index_ci_instance_variables_on_key ON ci_instance_variables USING btree (key);
|
||||
|
||||
CREATE INDEX index_ci_job_artifact_states_on_job_artifact_id ON ci_job_artifact_states USING btree (job_artifact_id);
|
||||
|
||||
CREATE INDEX index_ci_job_artifacts_for_terraform_reports ON ci_job_artifacts USING btree (project_id, id) WHERE (file_type = 18);
|
||||
|
||||
CREATE INDEX index_ci_job_artifacts_id_for_terraform_reports ON ci_job_artifacts USING btree (id) WHERE (file_type = 18);
|
||||
|
@ -26755,6 +26783,14 @@ CREATE INDEX index_jira_imports_on_user_id ON jira_imports USING btree (user_id)
|
|||
|
||||
CREATE INDEX index_jira_tracker_data_on_service_id ON jira_tracker_data USING btree (service_id);
|
||||
|
||||
CREATE INDEX index_job_artifact_states_failed_verification ON ci_job_artifact_states USING btree (verification_retry_at NULLS FIRST) WHERE (verification_state = 3);
|
||||
|
||||
CREATE INDEX index_job_artifact_states_needs_verification ON ci_job_artifact_states USING btree (verification_state) WHERE ((verification_state = 0) OR (verification_state = 3));
|
||||
|
||||
CREATE INDEX index_job_artifact_states_on_verification_state ON ci_job_artifact_states USING btree (verification_state);
|
||||
|
||||
CREATE INDEX index_job_artifact_states_pending_verification ON ci_job_artifact_states USING btree (verified_at NULLS FIRST) WHERE (verification_state = 0);
|
||||
|
||||
CREATE INDEX index_keys_on_expires_at_and_id ON keys USING btree (date(timezone('UTC'::text, expires_at)), id) WHERE (expiry_notification_delivered_at IS NULL);
|
||||
|
||||
CREATE UNIQUE INDEX index_keys_on_fingerprint ON keys USING btree (fingerprint);
|
||||
|
@ -30968,6 +31004,9 @@ ALTER TABLE ONLY application_settings
|
|||
ALTER TABLE ONLY clusters_kubernetes_namespaces
|
||||
ADD CONSTRAINT fk_rails_7e7688ecaf FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY ci_job_artifact_states
|
||||
ADD CONSTRAINT fk_rails_80a9cba3b2 FOREIGN KEY (job_artifact_id) REFERENCES ci_job_artifacts(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY approval_merge_request_rules_users
|
||||
ADD CONSTRAINT fk_rails_80e6801803 FOREIGN KEY (approval_merge_request_rule_id) REFERENCES approval_merge_request_rules(id) ON DELETE CASCADE;
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ verification methods:
|
|||
| Blobs | User uploads _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
|
||||
| Blobs | LFS objects _(file system)_ | Geo with API | SHA256 checksum |
|
||||
| Blobs | LFS objects _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
|
||||
| Blobs | CI job artifacts _(file system)_ | Geo with API | _Not implemented_ |
|
||||
| Blobs | CI job artifacts _(file system)_ | Geo with API | SHA256 checksum |
|
||||
| Blobs | CI job artifacts _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
|
||||
| Blobs | Archived CI build traces _(file system)_ | Geo with API | _Not implemented_ |
|
||||
| Blobs | Archived CI build traces _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
|
||||
|
|
|
@ -270,6 +270,16 @@ configuration option in `gitlab.yml`. These metrics are served from the
|
|||
| `geo_pages_deployments_verification_total` | Gauge | 14.6 | Number of pages deployments verifications tried on secondary | `url` |
|
||||
| `geo_pages_deployments_verified` | Gauge | 14.6 | Number of pages deployments verified on secondary | `url` |
|
||||
| `geo_pages_deployments_verification_failed` | Gauge | 14.6 | Number of pages deployments verifications failed on secondary | `url` |
|
||||
| `geo_job_artifacts` | Gauge | 14.8 | Number of job artifacts on primary | `url` |
|
||||
| `geo_job_artifacts_checksum_total` | Gauge | 14.8 | Number of job artifacts tried to checksum on primary | `url` |
|
||||
| `geo_job_artifacts_checksummed` | Gauge | 14.8 | Number of job artifacts successfully checksummed on primary | `url` |
|
||||
| `geo_job_artifacts_checksum_failed` | Gauge | 14.8 | Number of job artifacts failed to calculate the checksum on primary | `url` |
|
||||
| `geo_job_artifacts_synced` | Gauge | 14.8 | Number of syncable job artifacts synced on secondary | `url` |
|
||||
| `geo_job_artifacts_failed` | Gauge | 14.8 | Number of syncable job artifacts failed to sync on secondary | `url` |
|
||||
| `geo_job_artifacts_registry` | Gauge | 14.8 | Number of job artifacts in the registry | `url` |
|
||||
| `geo_job_artifacts_verification_total` | Gauge | 14.8 | Number of job artifacts verifications tried on secondary | `url` |
|
||||
| `geo_job_artifacts_verified` | Gauge | 14.8 | Number of job artifacts verified on secondary | `url` |
|
||||
| `geo_job_artifacts_verification_failed` | Gauge | 14.8 | Number of job artifacts verifications failed on secondary | `url` |
|
||||
| `limited_capacity_worker_running_jobs` | Gauge | 13.5 | Number of running jobs | `worker` |
|
||||
| `limited_capacity_worker_max_running_jobs` | Gauge | 13.5 | Maximum number of running jobs | `worker` |
|
||||
| `limited_capacity_worker_remaining_work_count` | Gauge | 13.5 | Number of jobs waiting to be enqueued | `worker` |
|
||||
|
|
|
@ -433,9 +433,9 @@ To disable the monitoring of Kubernetes:
|
|||
1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to
|
||||
take effect.
|
||||
|
||||
### Troubleshooting
|
||||
## Troubleshooting
|
||||
|
||||
## `/var/opt/gitlab/prometheus` consumes too much disk space
|
||||
### `/var/opt/gitlab/prometheus` consumes too much disk space
|
||||
|
||||
If you are **not** using Prometheus monitoring:
|
||||
|
||||
|
|
|
@ -1115,8 +1115,6 @@ than GitLab to prevent XSS attacks.
|
|||
|
||||
### Rate limits
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/631) in GitLab 14.5.
|
||||
|
||||
You can enforce rate limits to help minimize the risk of a Denial of Service (DoS) attack. GitLab Pages
|
||||
uses a [token bucket algorithm](https://en.wikipedia.org/wiki/Token_bucket) to enforce rate limiting. By default,
|
||||
requests that exceed the specified limits are reported but not rejected.
|
||||
|
@ -1136,6 +1134,8 @@ Rate limits are enforced using the following:
|
|||
|
||||
#### Enable source-IP rate limits
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/631) in GitLab 14.5.
|
||||
|
||||
1. Set rate limits in `/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```ruby
|
||||
|
@ -1154,6 +1154,8 @@ Rate limits are enforced using the following:
|
|||
|
||||
#### Enable domain rate limits
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/630) in GitLab 14.7.
|
||||
|
||||
1. Set rate limits in `/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```ruby
|
||||
|
|
|
@ -467,6 +467,19 @@ Example response:
|
|||
"uploads_verified_count": null,
|
||||
"uploads_verification_failed_count": null,
|
||||
"uploads_verified_in_percentage": "0.00%",
|
||||
"job_artifacts_count": 5,
|
||||
"job_artifacts_checksum_total_count": 5,
|
||||
"job_artifacts_checksummed_count": 5,
|
||||
"job_artifacts_checksum_failed_count": 0,
|
||||
"job_artifacts_synced_count": 5,
|
||||
"job_artifacts_failed_count": 0,
|
||||
"job_artifacts_registry_count": 5,
|
||||
"job_artifacts_verification_total_count": 5,
|
||||
"job_artifacts_verified_count": 5,
|
||||
"job_artifacts_verification_failed_count": 0,
|
||||
"job_artifacts_synced_in_percentage": "100.00%",
|
||||
"job_artifacts_verified_in_percentage": "100.00%",
|
||||
"job_artifacts_synced_missing_on_primary_count": 0,
|
||||
},
|
||||
{
|
||||
"geo_node_id": 2,
|
||||
|
@ -623,6 +636,19 @@ Example response:
|
|||
"uploads_verified_count": null,
|
||||
"uploads_verification_failed_count": null,
|
||||
"uploads_verified_in_percentage": "0.00%",
|
||||
"job_artifacts_count": 5,
|
||||
"job_artifacts_checksum_total_count": 5,
|
||||
"job_artifacts_checksummed_count": 5,
|
||||
"job_artifacts_checksum_failed_count": 0,
|
||||
"job_artifacts_synced_count": 5,
|
||||
"job_artifacts_failed_count": 0,
|
||||
"job_artifacts_registry_count": 5,
|
||||
"job_artifacts_verification_total_count": 5,
|
||||
"job_artifacts_verified_count": 5,
|
||||
"job_artifacts_verification_failed_count": 0,
|
||||
"job_artifacts_synced_in_percentage": "100.00%",
|
||||
"job_artifacts_verified_in_percentage": "100.00%",
|
||||
"job_artifacts_synced_missing_on_primary_count": 0,
|
||||
}
|
||||
]
|
||||
```
|
||||
|
@ -776,6 +802,19 @@ Example response:
|
|||
"uploads_verified_count": null,
|
||||
"uploads_verification_failed_count": null,
|
||||
"uploads_verified_in_percentage": "0.00%",
|
||||
"job_artifacts_count": 5,
|
||||
"job_artifacts_checksum_total_count": 5,
|
||||
"job_artifacts_checksummed_count": 5,
|
||||
"job_artifacts_checksum_failed_count": 0,
|
||||
"job_artifacts_synced_count": 5,
|
||||
"job_artifacts_failed_count": 0,
|
||||
"job_artifacts_registry_count": 5,
|
||||
"job_artifacts_verification_total_count": 5,
|
||||
"job_artifacts_verified_count": 5,
|
||||
"job_artifacts_verification_failed_count": 0,
|
||||
"job_artifacts_synced_in_percentage": "100.00%",
|
||||
"job_artifacts_verified_in_percentage": "100.00%",
|
||||
"job_artifacts_synced_missing_on_primary_count": 0,
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -6803,6 +6803,29 @@ The edge type for [`JiraProject`](#jiraproject).
|
|||
| <a id="jiraprojectedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
|
||||
| <a id="jiraprojectedgenode"></a>`node` | [`JiraProject`](#jiraproject) | The item at the end of the edge. |
|
||||
|
||||
#### `JobArtifactRegistryConnection`
|
||||
|
||||
The connection type for [`JobArtifactRegistry`](#jobartifactregistry).
|
||||
|
||||
##### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="jobartifactregistryconnectionedges"></a>`edges` | [`[JobArtifactRegistryEdge]`](#jobartifactregistryedge) | A list of edges. |
|
||||
| <a id="jobartifactregistryconnectionnodes"></a>`nodes` | [`[JobArtifactRegistry]`](#jobartifactregistry) | A list of nodes. |
|
||||
| <a id="jobartifactregistryconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
|
||||
|
||||
#### `JobArtifactRegistryEdge`
|
||||
|
||||
The edge type for [`JobArtifactRegistry`](#jobartifactregistry).
|
||||
|
||||
##### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="jobartifactregistryedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
|
||||
| <a id="jobartifactregistryedgenode"></a>`node` | [`JobArtifactRegistry`](#jobartifactregistry) | The item at the end of the edge. |
|
||||
|
||||
#### `JobNeedUnionConnection`
|
||||
|
||||
The connection type for [`JobNeedUnion`](#jobneedunion).
|
||||
|
@ -9201,6 +9224,7 @@ Represents the total number of issues and their weights for a particular day.
|
|||
| <a id="cirunnerrunnertype"></a>`runnerType` | [`CiRunnerType!`](#cirunnertype) | Type of the runner. |
|
||||
| <a id="cirunnershortsha"></a>`shortSha` | [`String`](#string) | First eight characters of the runner's token used to authenticate new job requests. Used as the runner's unique ID. |
|
||||
| <a id="cirunnertaglist"></a>`tagList` | [`[String!]`](#string) | Tags associated with the runner. |
|
||||
| <a id="cirunnertokenexpiresat"></a>`tokenExpiresAt` | [`Time`](#time) | Runner token expiration time. |
|
||||
| <a id="cirunneruserpermissions"></a>`userPermissions` | [`RunnerPermissions!`](#runnerpermissions) | Permissions for the current user on the resource. |
|
||||
| <a id="cirunnerversion"></a>`version` | [`String`](#string) | Version of the runner. |
|
||||
|
||||
|
@ -10780,6 +10804,22 @@ four standard [pagination arguments](#connection-pagination-arguments):
|
|||
| ---- | ---- | ----------- |
|
||||
| <a id="geonodegroupwikirepositoryregistriesids"></a>`ids` | [`[ID!]`](#id) | Filters registries by their ID. |
|
||||
|
||||
##### `GeoNode.jobArtifactRegistries`
|
||||
|
||||
Find Job Artifact registries on this Geo node Available only when feature flag `geo_job_artifact_replication` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice.
|
||||
|
||||
Returns [`JobArtifactRegistryConnection`](#jobartifactregistryconnection).
|
||||
|
||||
This field returns a [connection](#connections). It accepts the
|
||||
four standard [pagination arguments](#connection-pagination-arguments):
|
||||
`before: String`, `after: String`, `first: Int`, `last: Int`.
|
||||
|
||||
###### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="geonodejobartifactregistriesids"></a>`ids` | [`[ID!]`](#id) | Filters registries by their ID. |
|
||||
|
||||
##### `GeoNode.lfsObjectRegistries`
|
||||
|
||||
Find LFS object registries on this Geo node.
|
||||
|
@ -11970,6 +12010,23 @@ four standard [pagination arguments](#connection-pagination-arguments):
|
|||
| <a id="jirauserjiradisplayname"></a>`jiraDisplayName` | [`String!`](#string) | Display name of the Jira user. |
|
||||
| <a id="jirauserjiraemail"></a>`jiraEmail` | [`String`](#string) | Email of the Jira user, returned only for users with public emails. |
|
||||
|
||||
### `JobArtifactRegistry`
|
||||
|
||||
Represents the Geo replication and verification state of a job_artifact.
|
||||
|
||||
#### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="jobartifactregistryartifactid"></a>`artifactId` | [`ID!`](#id) | ID of the Job Artifact. |
|
||||
| <a id="jobartifactregistrycreatedat"></a>`createdAt` | [`Time`](#time) | Timestamp when the JobArtifactRegistry was created. |
|
||||
| <a id="jobartifactregistryid"></a>`id` | [`ID!`](#id) | ID of the JobArtifactRegistry. |
|
||||
| <a id="jobartifactregistrylastsyncfailure"></a>`lastSyncFailure` | [`String`](#string) | Error message during sync of the JobArtifactRegistry. |
|
||||
| <a id="jobartifactregistrylastsyncedat"></a>`lastSyncedAt` | [`Time`](#time) | Timestamp of the most recent successful sync of the JobArtifactRegistry. |
|
||||
| <a id="jobartifactregistryretryat"></a>`retryAt` | [`Time`](#time) | Timestamp after which the JobArtifactRegistry should be resynced. |
|
||||
| <a id="jobartifactregistryretrycount"></a>`retryCount` | [`Int`](#int) | Number of consecutive failed sync attempts of the JobArtifactRegistry. |
|
||||
| <a id="jobartifactregistrystate"></a>`state` | [`RegistryState`](#registrystate) | Sync state of the JobArtifactRegistry. |
|
||||
|
||||
### `JobPermissions`
|
||||
|
||||
#### Fields
|
||||
|
@ -14940,6 +14997,7 @@ Counts of requirements by their state.
|
|||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="rootstoragestatisticsbuildartifactssize"></a>`buildArtifactsSize` | [`Float!`](#float) | CI artifacts size in bytes. |
|
||||
| <a id="rootstoragestatisticsdependencyproxysize"></a>`dependencyProxySize` | [`Float!`](#float) | Dependency Proxy sizes in bytes. |
|
||||
| <a id="rootstoragestatisticslfsobjectssize"></a>`lfsObjectsSize` | [`Float!`](#float) | LFS objects size in bytes. |
|
||||
| <a id="rootstoragestatisticspackagessize"></a>`packagesSize` | [`Float!`](#float) | Packages size in bytes. |
|
||||
| <a id="rootstoragestatisticspipelineartifactssize"></a>`pipelineArtifactsSize` | [`Float!`](#float) | CI pipeline artifacts size in bytes. |
|
||||
|
@ -16796,6 +16854,8 @@ Values for sorting runners.
|
|||
| <a id="cirunnersortcontacted_desc"></a>`CONTACTED_DESC` | Ordered by contacted_at in descending order. |
|
||||
| <a id="cirunnersortcreated_asc"></a>`CREATED_ASC` | Ordered by created_at in ascending order. |
|
||||
| <a id="cirunnersortcreated_desc"></a>`CREATED_DESC` | Ordered by created_at in descending order. |
|
||||
| <a id="cirunnersorttoken_expires_at_asc"></a>`TOKEN_EXPIRES_AT_ASC` | Ordered by token_expires_at in ascending order. |
|
||||
| <a id="cirunnersorttoken_expires_at_desc"></a>`TOKEN_EXPIRES_AT_DESC` | Ordered by token_expires_at in descending order. |
|
||||
|
||||
### `CiRunnerStatus`
|
||||
|
||||
|
|
|
@ -818,6 +818,18 @@ The following `geo:db:*` tasks will be replaced with their corresponding `db:*:g
|
|||
|
||||
**Planned removal milestone: 15.0 (2022-05-22)**
|
||||
|
||||
### Deprecate feature flag PUSH_RULES_SUPERSEDE_CODE_OWNERS
|
||||
|
||||
WARNING:
|
||||
This feature will be changed or removed in 15.0
|
||||
as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
|
||||
Before updating GitLab, review the details carefully to determine if you need to make any
|
||||
changes to your code, settings, or workflow.
|
||||
|
||||
The feature flag `PUSH_RULES_SUPERSEDE_CODE_OWNERS` is being removed in GitLab 15.0. Upon its removal, push rules will supersede CODEOWNERS. The CODEOWNERS feature will no longer be available for access control.
|
||||
|
||||
**Planned removal milestone: 15.0 (2022-05-22)**
|
||||
|
||||
### Deprecate legacy Gitaly configuration methods
|
||||
|
||||
WARNING:
|
||||
|
|
|
@ -456,28 +456,24 @@ GitLab provides two methods of accomplishing this, each with advantages and disa
|
|||
- [Compliance framework pipelines](../project/settings/#compliance-pipeline-configuration)
|
||||
are recommended when:
|
||||
|
||||
- Scan execution enforcement is required for SAST IaC, Container Scanning, Dependency Scanning,
|
||||
- Scan execution enforcement is required for SAST IaC, Dependency Scanning,
|
||||
License Compliance, API Fuzzing, or Coverage-guided Fuzzing.
|
||||
- Scan execution enforcement of SAST or Secret Detection when customization of the default scan
|
||||
variables is required.
|
||||
- Scan execution enforcement is required for scanners external to GitLab.
|
||||
- Enforced execution is required for custom jobs other than security scans.
|
||||
|
||||
- [Scan execution policies](policies/#scan-execution-policies)
|
||||
- [Scan execution policies](policies/scan-execution-policies.md)
|
||||
are recommended when:
|
||||
|
||||
- Scan execution enforcement is required for DAST.
|
||||
- Scan execution enforcement is required for SAST or Secret Detection with the default scan
|
||||
variables.
|
||||
- Scan execution enforcement is required for DAST, SAST, Secret Detection, or Container Scanning.
|
||||
- Scans are required to run on a regular, scheduled cadence.
|
||||
|
||||
Additional details about the differences between the two solutions are outlined below:
|
||||
|
||||
| | Compliance Framework Pipelines | Scan Execution Policies |
|
||||
| ------ | ------ | ------ |
|
||||
| **Flexibility** | Supports anything that can be done in a CI file. | Limited to only the items for which GitLab has explicitly added support. DAST, SAST, and Secret Detection scans are supported. |
|
||||
| **Flexibility** | Supports anything that can be done in a CI file. | Limited to only the items for which GitLab has explicitly added support. DAST, SAST, Secret Detection, and Container Scanning scans are supported. |
|
||||
| **Usability** | Requires knowledge of CI YAML. | Follows a `rules` and `actions`-based YAML structure. |
|
||||
| **Inclusion in CI pipeline** | The compliance pipeline is executed instead of the project's `gitlab-ci.yml` file. To include the project's `gitlab-ci.yml` file, use an `include` statement. Defined variables aren't allowed to be overwritten by the included project's YAML file. | Forced inclusion of a new job into the CI pipeline. DAST jobs that must be customized on a per-project basis can have project-level Site Profiles and Scan Profiles defined. To ensure separation of duties, these profiles are immutable when referenced in a scan execution policy. |
|
||||
| **Inclusion in CI pipeline** | The compliance pipeline is executed instead of the project's `gitlab-ci.yml` file. To include the project's `gitlab-ci.yml` file, use an `include` statement. Defined variables aren't allowed to be overwritten by the included project's YAML file. | Forced inclusion of a new job into the CI pipeline. DAST jobs that must be customized on a per-project basis can have project-level Site Profiles and Scan Profiles defined. To ensure separation of duties, these profiles are immutable when referenced in a scan execution policy. All jobs can be customized as part of the security policy itself with the same variables that are normally available to the CI job. |
|
||||
| **Schedulable** | Can be scheduled through a scheduled pipeline on the group. | Can be scheduled natively through the policy configuration itself. |
|
||||
| **Separation of Duties** | Only group owners can create compliance framework labels. Only project owners can apply compliance framework labels to projects. The ability to make or approve changes to the compliance pipeline definition is limited to individuals who are explicitly given access to the project that contains the compliance pipeline. | Only project owners can define a linked security policy project. The ability to make or approve changes to security policies is limited to individuals who are explicitly given access to the security policy project. |
|
||||
| **Ability to apply one standard to multiple projects** | The same compliance framework label can be applied to multiple projects inside a group. | The same security policy project can be used for multiple projects across GitLab with no requirement of being located in the same group. |
|
||||
|
|
|
@ -101,7 +101,7 @@ rule in the defined policy are met.
|
|||
| `scan` | `string` | `dast`, `secret_detection`, `sast`, `container_scanning`, `cluster_image_scanning` | The action's type. |
|
||||
| `site_profile` | `string` | Name of the selected [DAST site profile](../dast/index.md#site-profile). | The DAST site profile to execute the DAST scan. This field should only be set if `scan` type is `dast`. |
|
||||
| `scanner_profile` | `string` or `null` | Name of the selected [DAST scanner profile](../dast/index.md#scanner-profile). | The DAST scanner profile to execute the DAST scan. This field should only be set if `scan` type is `dast`.|
|
||||
| `variables` | `object` | | Set of variables applied and enforced for the selected scan. The object's key is the variable name with a value provided as a string. |
|
||||
| `variables` | `object` | | A set of CI variables, supplied as an array of `key: value` pairs, to apply and enforce for the selected scan. The `key` is the variable name, with its `value` provided as a string. This parameter supports any variable that the GitLab CI job supports for the specified scan. |
|
||||
|
||||
Note the following:
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ executed in place of the local project's `gitlab-ci.yml` file. As part of this p
|
|||
files are merged together any time the pipeline runs. Jobs and variables defined in the compliance
|
||||
pipeline can't be changed by variables in the local project's `gitlab-ci.yml` file.
|
||||
|
||||
When used to enforce scan execution, this feature has some overlap with [scan execution policies](../../application_security/policies/#scan-execution-policies),
|
||||
When used to enforce scan execution, this feature has some overlap with [scan execution policies](../../application_security/policies/scan-execution-policies.md),
|
||||
as we have not [unified the user experience for these two features](https://gitlab.com/groups/gitlab-org/-/epics/7312).
|
||||
For details on the similarities and differences between these features, see
|
||||
[Enforce scan execution](../../application_security/#enforce-scan-execution).
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module BackgroundMigration
|
||||
# rubocop: disable Style/Documentation
|
||||
class MigrateJobArtifactRegistryToSsf
|
||||
def perform(*job_artifact_ids)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Gitlab::BackgroundMigration::MigrateJobArtifactRegistryToSsf.prepend_mod_with('Gitlab::BackgroundMigration::MigrateJobArtifactRegistryToSsf')
|
|
@ -85,6 +85,7 @@ ci_instance_variables: :gitlab_ci
|
|||
ci_job_artifacts: :gitlab_ci
|
||||
ci_job_token_project_scope_links: :gitlab_ci
|
||||
ci_job_variables: :gitlab_ci
|
||||
ci_job_artifact_states: :gitlab_ci
|
||||
ci_minutes_additional_packs: :gitlab_ci
|
||||
ci_namespace_monthly_usages: :gitlab_ci
|
||||
ci_namespace_mirrors: :gitlab_ci
|
||||
|
|
|
@ -180,9 +180,6 @@ module Gitlab
|
|||
class GrapeFormatter
|
||||
# Convert an object to JSON.
|
||||
#
|
||||
# This will default to the built-in Grape formatter if either :oj_json or :grape_gitlab_json
|
||||
# flags are disabled.
|
||||
#
|
||||
# The `env` param is ignored because it's not needed in either our formatter or Grape's,
|
||||
# but it is passed through for consistency.
|
||||
#
|
||||
|
@ -194,11 +191,7 @@ module Gitlab
|
|||
def self.call(object, env = nil)
|
||||
return object.to_s if object.is_a?(PrecompiledJson)
|
||||
|
||||
if Feature.enabled?(:grape_gitlab_json, default_enabled: true)
|
||||
Gitlab::Json.dump(object)
|
||||
else
|
||||
Grape::Formatter::Json.call(object, env)
|
||||
end
|
||||
Gitlab::Json.dump(object)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@
|
|||
"codesandbox-api": "0.0.23",
|
||||
"compression-webpack-plugin": "^5.0.2",
|
||||
"copy-webpack-plugin": "^6.4.1",
|
||||
"core-js": "^3.21.0",
|
||||
"core-js": "^3.21.1",
|
||||
"cron-validator": "^1.1.1",
|
||||
"cronstrue": "^1.122.0",
|
||||
"cropper": "^2.3.0",
|
||||
|
|
|
@ -14,7 +14,7 @@ module QA
|
|||
|
||||
attribute :group do
|
||||
Group.fabricate_via_api! do |resource|
|
||||
resource.name = 'group-with-milestone'
|
||||
resource.name = "group-with-milestone-#{SecureRandom.hex(4)}"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ FactoryBot.define do
|
|||
transient do
|
||||
groups { [] }
|
||||
projects { [] }
|
||||
token_expires_at { nil }
|
||||
end
|
||||
|
||||
after(:build) do |runner, evaluator|
|
||||
|
@ -25,6 +26,10 @@ FactoryBot.define do
|
|||
end
|
||||
end
|
||||
|
||||
after(:create) do |runner, evaluator|
|
||||
runner.update!(token_expires_at: evaluator.token_expires_at) if evaluator.token_expires_at
|
||||
end
|
||||
|
||||
trait :online do
|
||||
contacted_at { Time.now }
|
||||
end
|
||||
|
|
|
@ -64,7 +64,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
|
|||
it 'sees branch pipelines and detached merge request pipelines in correct order' do
|
||||
page.within('.ci-table') do
|
||||
expect(page).to have_selector('.ci-created', count: 2)
|
||||
expect(first('[data-testid="pipeline-url-link"]')).to have_content("##{detached_merge_request_pipeline.id}")
|
||||
expect(first('[data-testid="pipeline-identifier"]')).to have_content("##{detached_merge_request_pipeline.id}")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -101,16 +101,16 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
|
|||
page.within('.ci-table') do
|
||||
expect(page).to have_selector('.ci-pending', count: 4)
|
||||
|
||||
expect(all('[data-testid="pipeline-url-link"]')[0])
|
||||
expect(all('[data-testid="pipeline-identifier"]')[0])
|
||||
.to have_content("##{detached_merge_request_pipeline_2.id}")
|
||||
|
||||
expect(all('[data-testid="pipeline-url-link"]')[1])
|
||||
expect(all('[data-testid="pipeline-identifier"]')[1])
|
||||
.to have_content("##{detached_merge_request_pipeline.id}")
|
||||
|
||||
expect(all('[data-testid="pipeline-url-link"]')[2])
|
||||
expect(all('[data-testid="pipeline-identifier"]')[2])
|
||||
.to have_content("##{push_pipeline_2.id}")
|
||||
|
||||
expect(all('[data-testid="pipeline-url-link"]')[3])
|
||||
expect(all('[data-testid="pipeline-identifier"]')[3])
|
||||
.to have_content("##{push_pipeline.id}")
|
||||
end
|
||||
end
|
||||
|
@ -201,7 +201,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
|
|||
it 'sees a branch pipeline in pipeline tab' do
|
||||
page.within('.ci-table') do
|
||||
expect(page).to have_selector('.ci-created', count: 1)
|
||||
expect(first('[data-testid="pipeline-url-link"]')).to have_content("##{push_pipeline.id}")
|
||||
expect(first('[data-testid="pipeline-identifier"]')).to have_content("##{push_pipeline.id}")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -252,7 +252,7 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
|
|||
it 'sees branch pipelines and detached merge request pipelines in correct order' do
|
||||
page.within('.ci-table') do
|
||||
expect(page).to have_selector('.ci-pending', count: 2)
|
||||
expect(first('[data-testid="pipeline-url-link"]')).to have_content("##{detached_merge_request_pipeline.id}")
|
||||
expect(first('[data-testid="pipeline-identifier"]')).to have_content("##{detached_merge_request_pipeline.id}")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -295,16 +295,16 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
|
|||
page.within('.ci-table') do
|
||||
expect(page).to have_selector('.ci-pending', count: 4)
|
||||
|
||||
expect(all('[data-testid="pipeline-url-link"]')[0])
|
||||
expect(all('[data-testid="pipeline-identifier"]')[0])
|
||||
.to have_content("##{detached_merge_request_pipeline_2.id}")
|
||||
|
||||
expect(all('[data-testid="pipeline-url-link"]')[1])
|
||||
expect(all('[data-testid="pipeline-identifier"]')[1])
|
||||
.to have_content("##{detached_merge_request_pipeline.id}")
|
||||
|
||||
expect(all('[data-testid="pipeline-url-link"]')[2])
|
||||
expect(all('[data-testid="pipeline-identifier"]')[2])
|
||||
.to have_content("##{push_pipeline_2.id}")
|
||||
|
||||
expect(all('[data-testid="pipeline-url-link"]')[3])
|
||||
expect(all('[data-testid="pipeline-identifier"]')[3])
|
||||
.to have_content("##{push_pipeline.id}")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -134,7 +134,7 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
|
|||
create_merge_request_pipeline
|
||||
act_on_security_warning(action: 'Run pipeline')
|
||||
|
||||
check_pipeline(expected_project: parent_project)
|
||||
check_pipeline(expected_project: parent_project, link_selector: 'pipeline-url-link')
|
||||
check_head_pipeline(expected_project: parent_project)
|
||||
end
|
||||
|
||||
|
@ -179,13 +179,13 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
|
|||
click_button('Run pipeline')
|
||||
end
|
||||
|
||||
def check_pipeline(expected_project:)
|
||||
def check_pipeline(expected_project:, link_selector: 'commit-title')
|
||||
page.within('.ci-table') do
|
||||
expect(page).to have_selector('.commit', count: 2)
|
||||
|
||||
page.within(first('.commit')) do
|
||||
page.within('.pipeline-tags') do
|
||||
expect(page.find('[data-testid="pipeline-url-link"]')[:href]).to include(expected_project.full_path)
|
||||
expect(page.find("[data-testid=#{link_selector}]")[:href]).to include(expected_project.full_path)
|
||||
expect(page).to have_content('detached')
|
||||
end
|
||||
page.within('.pipeline-triggerer') do
|
||||
|
|
|
@ -711,7 +711,7 @@ RSpec.describe 'Pipelines', :js do
|
|||
end
|
||||
|
||||
expect(page.find('[data-testid="pipeline-th"]')).to have_content 'Pipeline'
|
||||
expect(page.find('[data-testid="pipeline-url-link"]')).to have_content "##{pipeline.iid}"
|
||||
expect(page.find('[data-testid="pipeline-identifier"]')).to have_content "##{pipeline.iid}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -91,8 +91,8 @@ RSpec.describe Ci::RunnersFinder do
|
|||
end
|
||||
|
||||
context 'sorting' do
|
||||
let_it_be(:runner1) { create :ci_runner, created_at: '2018-07-12 07:00', contacted_at: 1.minute.ago }
|
||||
let_it_be(:runner2) { create :ci_runner, created_at: '2018-07-12 08:00', contacted_at: 3.minutes.ago }
|
||||
let_it_be(:runner1) { create :ci_runner, created_at: '2018-07-12 07:00', contacted_at: 1.minute.ago, token_expires_at: '2022-02-15 07:00' }
|
||||
let_it_be(:runner2) { create :ci_runner, created_at: '2018-07-12 08:00', contacted_at: 3.minutes.ago, token_expires_at: '2022-02-15 06:00' }
|
||||
let_it_be(:runner3) { create :ci_runner, created_at: '2018-07-12 09:00', contacted_at: 2.minutes.ago }
|
||||
|
||||
subject do
|
||||
|
@ -142,6 +142,22 @@ RSpec.describe Ci::RunnersFinder do
|
|||
is_expected.to eq [runner1, runner3, runner2]
|
||||
end
|
||||
end
|
||||
|
||||
context 'with sort param equal to token_expires_at_asc' do
|
||||
let(:params) { { sort: 'token_expires_at_asc' } }
|
||||
|
||||
it 'sorts by contacted_at ascending' do
|
||||
is_expected.to eq [runner2, runner1, runner3]
|
||||
end
|
||||
end
|
||||
|
||||
context 'with sort param equal to token_expires_at_desc' do
|
||||
let(:params) { { sort: 'token_expires_at_desc' } }
|
||||
|
||||
it 'sorts by contacted_at descending' do
|
||||
is_expected.to eq [runner3, runner1, runner2]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'by non admin user' do
|
||||
|
|
|
@ -209,57 +209,79 @@ describe('Description component', () => {
|
|||
});
|
||||
|
||||
describe('with work items feature flag is enabled', () => {
|
||||
beforeEach(async () => {
|
||||
createComponent({
|
||||
props: {
|
||||
descriptionHtml: descriptionHtmlWithCheckboxes,
|
||||
},
|
||||
provide: {
|
||||
glFeatures: {
|
||||
workItems: true,
|
||||
describe('empty description', () => {
|
||||
beforeEach(async () => {
|
||||
createComponent({
|
||||
props: {
|
||||
descriptionHtml: '',
|
||||
},
|
||||
},
|
||||
provide: {
|
||||
glFeatures: {
|
||||
workItems: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('renders without error', () => {
|
||||
expect(findTaskActionButtons()).toHaveLength(0);
|
||||
});
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('renders a list of hidden buttons corresponding to checkboxes in description HTML', () => {
|
||||
expect(findTaskActionButtons()).toHaveLength(3);
|
||||
});
|
||||
describe('description with checkboxes', () => {
|
||||
beforeEach(async () => {
|
||||
createComponent({
|
||||
props: {
|
||||
descriptionHtml: descriptionHtmlWithCheckboxes,
|
||||
},
|
||||
provide: {
|
||||
glFeatures: {
|
||||
workItems: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('renders a list of popovers corresponding to checkboxes in description HTML', () => {
|
||||
expect(findPopovers()).toHaveLength(3);
|
||||
expect(findPopovers().at(0).props('target')).toBe(
|
||||
findTaskActionButtons().at(0).attributes('id'),
|
||||
);
|
||||
});
|
||||
it('renders a list of hidden buttons corresponding to checkboxes in description HTML', () => {
|
||||
expect(findTaskActionButtons()).toHaveLength(3);
|
||||
});
|
||||
|
||||
it('does not show a modal by default', () => {
|
||||
expect(findModal().props('visible')).toBe(false);
|
||||
});
|
||||
it('renders a list of popovers corresponding to checkboxes in description HTML', () => {
|
||||
expect(findPopovers()).toHaveLength(3);
|
||||
expect(findPopovers().at(0).props('target')).toBe(
|
||||
findTaskActionButtons().at(0).attributes('id'),
|
||||
);
|
||||
});
|
||||
|
||||
it('opens a modal when a button on popover is clicked and displays correct title', async () => {
|
||||
findConvertToTaskButton().vm.$emit('click');
|
||||
expect(showModal).toHaveBeenCalled();
|
||||
await nextTick();
|
||||
expect(findCreateWorkItem().props('initialTitle').trim()).toBe('todo 1');
|
||||
});
|
||||
it('does not show a modal by default', () => {
|
||||
expect(findModal().props('visible')).toBe(false);
|
||||
});
|
||||
|
||||
it('closes the modal on `closeCreateTaskModal` event', () => {
|
||||
findConvertToTaskButton().vm.$emit('click');
|
||||
findCreateWorkItem().vm.$emit('closeModal');
|
||||
expect(hideModal).toHaveBeenCalled();
|
||||
});
|
||||
it('opens a modal when a button on popover is clicked and displays correct title', async () => {
|
||||
findConvertToTaskButton().vm.$emit('click');
|
||||
expect(showModal).toHaveBeenCalled();
|
||||
await nextTick();
|
||||
expect(findCreateWorkItem().props('initialTitle').trim()).toBe('todo 1');
|
||||
});
|
||||
|
||||
it('updates description HTML on `onCreate` event', async () => {
|
||||
const newTitle = 'New title';
|
||||
findConvertToTaskButton().vm.$emit('click');
|
||||
findCreateWorkItem().vm.$emit('onCreate', newTitle);
|
||||
expect(hideModal).toHaveBeenCalled();
|
||||
await nextTick();
|
||||
it('closes the modal on `closeCreateTaskModal` event', () => {
|
||||
findConvertToTaskButton().vm.$emit('click');
|
||||
findCreateWorkItem().vm.$emit('closeModal');
|
||||
expect(hideModal).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
expect(findTaskSvg().exists()).toBe(true);
|
||||
expect(wrapper.text()).toContain(newTitle);
|
||||
it('updates description HTML on `onCreate` event', async () => {
|
||||
const newTitle = 'New title';
|
||||
findConvertToTaskButton().vm.$emit('click');
|
||||
findCreateWorkItem().vm.$emit('onCreate', newTitle);
|
||||
expect(hideModal).toHaveBeenCalled();
|
||||
await nextTick();
|
||||
|
||||
expect(findTaskSvg().exists()).toBe(true);
|
||||
expect(wrapper.text()).toContain(newTitle);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -676,7 +676,7 @@ export const mockPipeline = (projectPath) => {
|
|||
short_id: 'fd6df5b3',
|
||||
created_at: '2021-10-19T21:17:12.000+00:00',
|
||||
parent_ids: ['7147906b84306e83cb3fec6582a25390b75713c6'],
|
||||
title: 'Commit',
|
||||
title: 'Commit Title',
|
||||
message: 'Commit',
|
||||
author_name: 'Administrator',
|
||||
author_email: 'admin@example.com',
|
||||
|
@ -1141,3 +1141,176 @@ export const mockPipelineBranch = () => {
|
|||
viewType: 'root',
|
||||
};
|
||||
};
|
||||
|
||||
export const mockPipelineNoCommit = () => {
|
||||
return {
|
||||
pipeline: {
|
||||
id: 268,
|
||||
iid: 34,
|
||||
user: {
|
||||
id: 1,
|
||||
username: 'root',
|
||||
name: 'Administrator',
|
||||
state: 'active',
|
||||
avatar_url:
|
||||
'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
|
||||
web_url: 'http://gdk.test:3000/root',
|
||||
show_status: false,
|
||||
path: '/root',
|
||||
},
|
||||
active: false,
|
||||
source: 'push',
|
||||
created_at: '2022-01-14T17:40:27.866Z',
|
||||
updated_at: '2022-01-14T18:02:35.850Z',
|
||||
path: '/root/mr-widgets/-/pipelines/268',
|
||||
flags: {
|
||||
stuck: false,
|
||||
auto_devops: false,
|
||||
merge_request: false,
|
||||
yaml_errors: false,
|
||||
retryable: true,
|
||||
cancelable: false,
|
||||
failure_reason: false,
|
||||
detached_merge_request_pipeline: false,
|
||||
merge_request_pipeline: false,
|
||||
merge_train_pipeline: false,
|
||||
latest: true,
|
||||
},
|
||||
details: {
|
||||
status: {
|
||||
icon: 'status_warning',
|
||||
text: 'passed',
|
||||
label: 'passed with warnings',
|
||||
group: 'success-with-warnings',
|
||||
tooltip: 'passed',
|
||||
has_details: true,
|
||||
details_path: '/root/mr-widgets/-/pipelines/268',
|
||||
illustration: null,
|
||||
favicon:
|
||||
'/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
|
||||
},
|
||||
stages: [
|
||||
{
|
||||
name: 'validate',
|
||||
title: 'validate: passed with warnings',
|
||||
status: {
|
||||
icon: 'status_warning',
|
||||
text: 'passed',
|
||||
label: 'passed with warnings',
|
||||
group: 'success-with-warnings',
|
||||
tooltip: 'passed',
|
||||
has_details: true,
|
||||
details_path: '/root/mr-widgets/-/pipelines/268#validate',
|
||||
illustration: null,
|
||||
favicon:
|
||||
'/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
|
||||
},
|
||||
path: '/root/mr-widgets/-/pipelines/268#validate',
|
||||
dropdown_path: '/root/mr-widgets/-/pipelines/268/stage.json?stage=validate',
|
||||
},
|
||||
{
|
||||
name: 'test',
|
||||
title: 'test: passed',
|
||||
status: {
|
||||
icon: 'status_success',
|
||||
text: 'passed',
|
||||
label: 'passed',
|
||||
group: 'success',
|
||||
tooltip: 'passed',
|
||||
has_details: true,
|
||||
details_path: '/root/mr-widgets/-/pipelines/268#test',
|
||||
illustration: null,
|
||||
favicon:
|
||||
'/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
|
||||
},
|
||||
path: '/root/mr-widgets/-/pipelines/268#test',
|
||||
dropdown_path: '/root/mr-widgets/-/pipelines/268/stage.json?stage=test',
|
||||
},
|
||||
{
|
||||
name: 'build',
|
||||
title: 'build: passed',
|
||||
status: {
|
||||
icon: 'status_success',
|
||||
text: 'passed',
|
||||
label: 'passed',
|
||||
group: 'success',
|
||||
tooltip: 'passed',
|
||||
has_details: true,
|
||||
details_path: '/root/mr-widgets/-/pipelines/268#build',
|
||||
illustration: null,
|
||||
favicon:
|
||||
'/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
|
||||
},
|
||||
path: '/root/mr-widgets/-/pipelines/268#build',
|
||||
dropdown_path: '/root/mr-widgets/-/pipelines/268/stage.json?stage=build',
|
||||
},
|
||||
],
|
||||
duration: 75,
|
||||
finished_at: '2022-01-14T18:02:35.842Z',
|
||||
name: 'Pipeline',
|
||||
manual_actions: [],
|
||||
scheduled_actions: [],
|
||||
},
|
||||
ref: {
|
||||
name: 'update-ci',
|
||||
path: '/root/mr-widgets/-/commits/update-ci',
|
||||
tag: false,
|
||||
branch: true,
|
||||
merge_request: false,
|
||||
},
|
||||
retry_path: '/root/mr-widgets/-/pipelines/268/retry',
|
||||
delete_path: '/root/mr-widgets/-/pipelines/268',
|
||||
failed_builds: [
|
||||
{
|
||||
id: 1260,
|
||||
name: 'fmt',
|
||||
started: '2022-01-14T17:40:36.435Z',
|
||||
complete: true,
|
||||
archived: false,
|
||||
build_path: '/root/mr-widgets/-/jobs/1260',
|
||||
retry_path: '/root/mr-widgets/-/jobs/1260/retry',
|
||||
playable: false,
|
||||
scheduled: false,
|
||||
created_at: '2022-01-14T17:40:27.879Z',
|
||||
updated_at: '2022-01-14T17:40:42.129Z',
|
||||
status: {
|
||||
icon: 'status_warning',
|
||||
text: 'failed',
|
||||
label: 'failed (allowed to fail)',
|
||||
group: 'failed-with-warnings',
|
||||
tooltip: 'failed - (script failure) (allowed to fail)',
|
||||
has_details: true,
|
||||
details_path: '/root/mr-widgets/-/jobs/1260',
|
||||
illustration: {
|
||||
image:
|
||||
'/assets/illustrations/skipped-job_empty-29a8a37d8a61d1b6f68cf3484f9024e53cd6eb95e28eae3554f8011a1146bf27.svg',
|
||||
size: 'svg-430',
|
||||
title: 'This job does not have a trace.',
|
||||
},
|
||||
favicon:
|
||||
'/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png',
|
||||
action: {
|
||||
icon: 'retry',
|
||||
title: 'Retry',
|
||||
path: '/root/mr-widgets/-/jobs/1260/retry',
|
||||
method: 'post',
|
||||
button_title: 'Retry this job',
|
||||
},
|
||||
},
|
||||
recoverable: false,
|
||||
},
|
||||
],
|
||||
project: {
|
||||
id: 23,
|
||||
name: 'mr-widgets',
|
||||
full_path: '/root/mr-widgets',
|
||||
full_name: 'Administrator / mr-widgets',
|
||||
},
|
||||
triggered_by: null,
|
||||
triggered: [],
|
||||
},
|
||||
pipelineScheduleUrl: 'foo',
|
||||
pipelineKey: 'id',
|
||||
viewType: 'root',
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import { trimText } from 'helpers/text_helper';
|
||||
import PipelineUrlComponent from '~/pipelines/components/pipelines_list/pipeline_url.vue';
|
||||
import { mockPipeline, mockPipelineBranch, mockPipelineTag } from './mock_data';
|
||||
import {
|
||||
mockPipeline,
|
||||
mockPipelineBranch,
|
||||
mockPipelineTag,
|
||||
mockPipelineNoCommit,
|
||||
} from './mock_data';
|
||||
|
||||
const projectPath = 'test/test';
|
||||
|
||||
|
@ -26,7 +31,7 @@ describe('Pipeline Url Component', () => {
|
|||
const findCommitIconType = () => wrapper.findByTestId('commit-icon-type');
|
||||
|
||||
const findCommitTitleContainer = () => wrapper.findByTestId('commit-title-container');
|
||||
const findCommitTitle = (commitWrapper) => commitWrapper.find('[data-testid="commit-title"]');
|
||||
const findCommitTitle = () => wrapper.findByTestId('commit-title');
|
||||
|
||||
const defaultProps = mockPipeline(projectPath);
|
||||
|
||||
|
@ -232,5 +237,33 @@ describe('Pipeline Url Component', () => {
|
|||
expect(findCommitIconType().attributes('title')).toBe(expectedTitle);
|
||||
},
|
||||
);
|
||||
|
||||
describe('with commit', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({}, true);
|
||||
});
|
||||
|
||||
it('displays commit title with link to pipeline', () => {
|
||||
expect(findCommitTitle().attributes('href')).toBe(defaultProps.pipeline.path);
|
||||
});
|
||||
|
||||
it('displays commit title text', () => {
|
||||
expect(findCommitTitle().text()).toBe(defaultProps.pipeline.commit.title);
|
||||
});
|
||||
});
|
||||
|
||||
describe('without commit', () => {
|
||||
beforeEach(() => {
|
||||
createComponent(mockPipelineNoCommit(), true);
|
||||
});
|
||||
|
||||
it('displays cant find head commit text', () => {
|
||||
expect(findCommitTitle().text()).toBe("Can't find HEAD commit for this branch");
|
||||
});
|
||||
|
||||
it('displays link to pipeline', () => {
|
||||
expect(findCommitTitle().attributes('href')).toBe(mockPipelineNoCommit().pipeline.path);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -12,7 +12,7 @@ RSpec.describe GitlabSchema.types['CiRunner'] do
|
|||
id description created_at contacted_at maximum_timeout access_level active paused status
|
||||
version short_sha revision locked run_untagged ip_address runner_type tag_list
|
||||
project_count job_count admin_url edit_admin_url user_permissions executor_name
|
||||
groups projects jobs
|
||||
groups projects jobs token_expires_at
|
||||
]
|
||||
|
||||
expect(described_class).to include_graphql_fields(*expected_fields)
|
||||
|
|
|
@ -8,7 +8,7 @@ RSpec.describe GitlabSchema.types['RootStorageStatistics'] 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, :wiki_size, :snippets_size,
|
||||
:pipeline_artifacts_size, :uploads_size)
|
||||
:pipeline_artifacts_size, :uploads_size, :dependency_proxy_size)
|
||||
end
|
||||
|
||||
specify { expect(described_class).to require_graphql_authorizations(:read_statistics) }
|
||||
|
|
|
@ -317,36 +317,14 @@ RSpec.describe Gitlab::Json do
|
|||
let(:env) { {} }
|
||||
let(:result) { "{\"test\":true}" }
|
||||
|
||||
context "grape_gitlab_json flag is enabled" do
|
||||
before do
|
||||
stub_feature_flags(grape_gitlab_json: true)
|
||||
end
|
||||
|
||||
it "generates JSON" do
|
||||
expect(subject).to eq(result)
|
||||
end
|
||||
|
||||
it "uses Gitlab::Json" do
|
||||
expect(Gitlab::Json).to receive(:dump).with(obj)
|
||||
|
||||
subject
|
||||
end
|
||||
it "generates JSON" do
|
||||
expect(subject).to eq(result)
|
||||
end
|
||||
|
||||
context "grape_gitlab_json flag is disabled" do
|
||||
before do
|
||||
stub_feature_flags(grape_gitlab_json: false)
|
||||
end
|
||||
it "uses Gitlab::Json" do
|
||||
expect(Gitlab::Json).to receive(:dump).with(obj)
|
||||
|
||||
it "generates JSON" do
|
||||
expect(subject).to eq(result)
|
||||
end
|
||||
|
||||
it "uses Grape::Formatter::Json" do
|
||||
expect(Grape::Formatter::Json).to receive(:call).with(obj, env)
|
||||
|
||||
subject
|
||||
end
|
||||
subject
|
||||
end
|
||||
|
||||
context "precompiled JSON" do
|
||||
|
|
|
@ -3831,10 +3831,10 @@ core-js-pure@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813"
|
||||
integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==
|
||||
|
||||
core-js@^3.21.0:
|
||||
version "3.21.0"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.21.0.tgz#f479dbfc3dffb035a0827602dd056839a774aa71"
|
||||
integrity sha512-YUdI3fFu4TF/2WykQ2xzSiTQdldLB4KVuL9WeAy5XONZYt5Cun/fpQvctoKbCgvPhmzADeesTk/j2Rdx77AcKQ==
|
||||
core-js@^3.21.1:
|
||||
version "3.21.1"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.21.1.tgz#f2e0ddc1fc43da6f904706e8e955bc19d06a0d94"
|
||||
integrity sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==
|
||||
|
||||
core-js@~2.3.0:
|
||||
version "2.3.0"
|
||||
|
|
Loading…
Reference in New Issue