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

Add latest changes from gitlab-org/gitlab@master

parent b3db4039
No related branches found
No related tags found
No related merge requests found
Showing
with 995 additions and 20 deletions
import { join as joinPaths } from 'path';
const PATH_SEPARATOR = '/';
const PATH_SEPARATOR_LEADING_REGEX = new RegExp(`^${PATH_SEPARATOR}+`);
const PATH_SEPARATOR_ENDING_REGEX = new RegExp(`${PATH_SEPARATOR}+$`);
 
// Returns a decoded url parameter value
// - Treats '+' as '%20'
Loading
Loading
@@ -6,6 +8,37 @@ function decodeUrlParameter(val) {
return decodeURIComponent(val.replace(/\+/g, '%20'));
}
 
function cleanLeadingSeparator(path) {
return path.replace(PATH_SEPARATOR_LEADING_REGEX, '');
}
function cleanEndingSeparator(path) {
return path.replace(PATH_SEPARATOR_ENDING_REGEX, '');
}
/**
* Safely joins the given paths which might both start and end with a `/`
*
* Example:
* - `joinPaths('abc/', '/def') === 'abc/def'`
* - `joinPaths(null, 'abc/def', 'zoo) === 'abc/def/zoo'`
*
* @param {...String} paths
* @returns {String}
*/
export function joinPaths(...paths) {
return paths.reduce((acc, path) => {
if (!path) {
return acc;
}
if (!acc) {
return path;
}
return [cleanEndingSeparator(acc), PATH_SEPARATOR, cleanLeadingSeparator(path)].join('');
}, '');
}
// Returns an array containing the value(s) of the
// of the key passed as an argument
export function getParameterValues(sParam, url = window.location) {
Loading
Loading
@@ -212,5 +245,3 @@ export function objectToQuery(obj) {
.map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`)
.join('&');
}
export { joinPaths };
Loading
Loading
@@ -12,7 +12,7 @@ class Projects::JobsController < Projects::ApplicationController
before_action :authorize_use_build_terminal!, only: [:terminal, :terminal_websocket_authorize]
before_action :verify_api_request!, only: :terminal_websocket_authorize
before_action only: [:show] do
push_frontend_feature_flag(:job_log_json, project)
push_frontend_feature_flag(:job_log_json, project, default_enabled: true)
end
 
layout 'project'
Loading
Loading
@@ -53,7 +53,7 @@ class Projects::JobsController < Projects::ApplicationController
format.json do
# TODO: when the feature flag is removed we should not pass
# content_format to serialize method.
content_format = Feature.enabled?(:job_log_json, @project) ? :json : :html
content_format = Feature.enabled?(:job_log_json, @project, default_enabled: true) ? :json : :html
 
build_trace = Ci::BuildTrace.new(
build: @build,
Loading
Loading
# frozen_string_literal: true
module Mutations
module Snippets
class Base < BaseMutation
field :snippet,
Types::SnippetType,
null: true,
description: 'The snippet after mutation'
private
def find_object(id:)
GitlabSchema.object_from_id(id)
end
def authorized_resource?(snippet)
Ability.allowed?(context[:current_user], ability_for(snippet), snippet)
end
def ability_for(snippet)
"#{ability_name}_#{snippet.to_ability_name}".to_sym
end
def ability_name
raise NotImplementedError
end
end
end
end
# frozen_string_literal: true
module Mutations
module Snippets
class Create < BaseMutation
include Mutations::ResolvesProject
graphql_name 'CreateSnippet'
field :snippet,
Types::SnippetType,
null: true,
description: 'The snippet after mutation'
argument :title, GraphQL::STRING_TYPE,
required: true,
description: 'Title of the snippet'
argument :file_name, GraphQL::STRING_TYPE,
required: false,
description: 'File name of the snippet'
argument :content, GraphQL::STRING_TYPE,
required: true,
description: 'Content of the snippet'
argument :description, GraphQL::STRING_TYPE,
required: false,
description: 'Description of the snippet'
argument :visibility_level, Types::VisibilityLevelsEnum,
description: 'The visibility level of the snippet',
required: true
argument :project_path, GraphQL::ID_TYPE,
required: false,
description: 'The project full path the snippet is associated with'
def resolve(args)
project_path = args.delete(:project_path)
if project_path.present?
project = find_project!(project_path: project_path)
elsif !can_create_personal_snippet?
raise_resource_not_avaiable_error!
end
snippet = CreateSnippetService.new(project,
context[:current_user],
args).execute
{
snippet: snippet.valid? ? snippet : nil,
errors: errors_on_object(snippet)
}
end
private
def find_project!(project_path:)
authorized_find!(full_path: project_path)
end
def find_object(full_path:)
resolve_project(full_path: full_path)
end
def authorized_resource?(project)
Ability.allowed?(context[:current_user], :create_project_snippet, project)
end
def can_create_personal_snippet?
Ability.allowed?(context[:current_user], :create_personal_snippet)
end
end
end
end
# frozen_string_literal: true
module Mutations
module Snippets
class Destroy < Base
graphql_name 'DestroySnippet'
ERROR_MSG = 'Error deleting the snippet'
argument :id,
GraphQL::ID_TYPE,
required: true,
description: 'The global id of the snippet to destroy'
def resolve(id:)
snippet = authorized_find!(id: id)
result = snippet.destroy
errors = result ? [] : [ERROR_MSG]
{
errors: errors
}
end
private
def ability_name
"admin"
end
end
end
end
# frozen_string_literal: true
module Mutations
module Snippets
class Update < Base
graphql_name 'UpdateSnippet'
argument :id,
GraphQL::ID_TYPE,
required: true,
description: 'The global id of the snippet to update'
argument :title, GraphQL::STRING_TYPE,
required: false,
description: 'Title of the snippet'
argument :file_name, GraphQL::STRING_TYPE,
required: false,
description: 'File name of the snippet'
argument :content, GraphQL::STRING_TYPE,
required: false,
description: 'Content of the snippet'
argument :description, GraphQL::STRING_TYPE,
required: false,
description: 'Description of the snippet'
argument :visibility_level, Types::VisibilityLevelsEnum,
description: 'The visibility level of the snippet',
required: false
def resolve(args)
snippet = authorized_find!(id: args.delete(:id))
result = UpdateSnippetService.new(snippet.project,
context[:current_user],
snippet,
args).execute
{
snippet: result ? snippet : snippet.reset,
errors: errors_on_object(snippet)
}
end
private
def ability_name
"update"
end
end
end
end
Loading
Loading
@@ -2,6 +2,8 @@
 
module Resolvers
class BaseResolver < GraphQL::Schema::Resolver
extend ::Gitlab::Utils::Override
def self.single
@single ||= Class.new(self) do
def resolve(**args)
Loading
Loading
@@ -36,5 +38,13 @@ module Resolvers
# complexity difference is minimal in this case.
[args[:iid], args[:iids]].any? ? 0 : 0.01
end
override :object
def object
super.tap do |obj|
# If the field this resolver is used in is wrapped in a presenter, go back to it's subject
break obj.subject if obj.is_a?(Gitlab::View::Presenter::Base)
end
end
end
end
Loading
Loading
@@ -25,6 +25,9 @@ module Types
mount_mutation Mutations::Todos::MarkDone
mount_mutation Mutations::Todos::Restore
mount_mutation Mutations::Todos::MarkAllDone
mount_mutation Mutations::Snippets::Destroy
mount_mutation Mutations::Snippets::Update
mount_mutation Mutations::Snippets::Create
end
end
 
Loading
Loading
Loading
Loading
@@ -44,8 +44,8 @@ module Types
description: 'Description of the snippet',
null: true
 
field :visibility, GraphQL::STRING_TYPE,
description: 'Visibility of the snippet',
field :visibility_level, Types::VisibilityLevelsEnum,
description: 'Visibility Level of the snippet',
null: false
 
field :created_at, Types::TimeType,
Loading
Loading
# frozen_string_literal: true
module Types
class VisibilityLevelsEnum < BaseEnum
Gitlab::VisibilityLevel.string_options.each do |name, int_value|
value name.downcase, value: int_value
end
end
end
Loading
Loading
@@ -30,6 +30,6 @@ class SnippetPresenter < Gitlab::View::Presenter::Delegated
end
 
def ability_name(ability_prefix)
"#{ability_prefix}_#{snippet.class.underscore}".to_sym
"#{ability_prefix}_#{snippet.to_ability_name}".to_sym
end
end
Loading
Loading
@@ -10,7 +10,7 @@
%br
 
%div
%span= _('Each Runner can be in one of the following states:')
%span= _('Each Runner can be in one of the following states and/or belong to one of the following types:')
%ul
%li
%span.badge.badge-success shared
Loading
Loading
@@ -120,7 +120,7 @@
.runners-content.content-list
.table-holder
.gl-responsive-table-row.table-row-header{ role: 'row' }
.table-section.section-10{ role: 'rowheader' }= _('Type')
.table-section.section-10{ role: 'rowheader' }= _('Type/State')
.table-section.section-10{ role: 'rowheader' }= _('Runner token')
.table-section.section-20{ role: 'rowheader' }= _('Description')
.table-section.section-10{ role: 'rowheader' }= _('Version')
Loading
Loading
---
title: Fixes wording on runner admin
merge_request:
author:
type: changed
---
title: Added Snippets GraphQL mutations
merge_request: 20956
author:
type: added
---
title: Enable new job log by default
merge_request: 21543
author:
type: added
Loading
Loading
@@ -442,6 +442,66 @@ type CreateNotePayload {
note: Note
}
 
"""
Autogenerated input type of CreateSnippet
"""
input CreateSnippetInput {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
Content of the snippet
"""
content: String!
"""
Description of the snippet
"""
description: String
"""
File name of the snippet
"""
fileName: String
"""
The project full path the snippet is associated with
"""
projectPath: ID
"""
Title of the snippet
"""
title: String!
"""
The visibility level of the snippet
"""
visibilityLevel: VisibilityLevelsEnum!
}
"""
Autogenerated return type of CreateSnippet
"""
type CreateSnippetPayload {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
Reasons why the mutation failed.
"""
errors: [String!]!
"""
The snippet after mutation
"""
snippet: Snippet
}
type Design implements Noteable {
diffRefs: DiffRefs!
 
Loading
Loading
@@ -861,6 +921,41 @@ type DestroyNotePayload {
note: Note
}
 
"""
Autogenerated input type of DestroySnippet
"""
input DestroySnippetInput {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
The global id of the snippet to destroy
"""
id: ID!
}
"""
Autogenerated return type of DestroySnippet
"""
type DestroySnippetPayload {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
Reasons why the mutation failed.
"""
errors: [String!]!
"""
The snippet after mutation
"""
snippet: Snippet
}
type DetailedStatus {
detailsPath: String!
favicon: String!
Loading
Loading
@@ -3737,9 +3832,11 @@ type Mutation {
createEpic(input: CreateEpicInput!): CreateEpicPayload
createImageDiffNote(input: CreateImageDiffNoteInput!): CreateImageDiffNotePayload
createNote(input: CreateNoteInput!): CreateNotePayload
createSnippet(input: CreateSnippetInput!): CreateSnippetPayload
designManagementDelete(input: DesignManagementDeleteInput!): DesignManagementDeletePayload
designManagementUpload(input: DesignManagementUploadInput!): DesignManagementUploadPayload
destroyNote(input: DestroyNoteInput!): DestroyNotePayload
destroySnippet(input: DestroySnippetInput!): DestroySnippetPayload
epicSetSubscription(input: EpicSetSubscriptionInput!): EpicSetSubscriptionPayload
epicTreeReorder(input: EpicTreeReorderInput!): EpicTreeReorderPayload
issueSetConfidential(input: IssueSetConfidentialInput!): IssueSetConfidentialPayload
Loading
Loading
@@ -3757,6 +3854,7 @@ type Mutation {
toggleAwardEmoji(input: ToggleAwardEmojiInput!): ToggleAwardEmojiPayload
updateEpic(input: UpdateEpicInput!): UpdateEpicPayload
updateNote(input: UpdateNoteInput!): UpdateNotePayload
updateSnippet(input: UpdateSnippetInput!): UpdateSnippetPayload
}
 
"""
Loading
Loading
@@ -5396,9 +5494,9 @@ type Snippet implements Noteable {
userPermissions: SnippetPermissions!
 
"""
Visibility of the snippet
Visibility Level of the snippet
"""
visibility: String!
visibilityLevel: VisibilityLevelsEnum!
 
"""
Web URL of the snippet
Loading
Loading
@@ -6120,6 +6218,66 @@ type UpdateNotePayload {
note: Note
}
 
"""
Autogenerated input type of UpdateSnippet
"""
input UpdateSnippetInput {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
Content of the snippet
"""
content: String
"""
Description of the snippet
"""
description: String
"""
File name of the snippet
"""
fileName: String
"""
The global id of the snippet to update
"""
id: ID!
"""
Title of the snippet
"""
title: String
"""
The visibility level of the snippet
"""
visibilityLevel: VisibilityLevelsEnum
}
"""
Autogenerated return type of UpdateSnippet
"""
type UpdateSnippetPayload {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
Reasons why the mutation failed.
"""
errors: [String!]!
"""
The snippet after mutation
"""
snippet: Snippet
}
scalar Upload
 
type User {
Loading
Loading
@@ -6286,6 +6444,12 @@ type UserPermissions {
createSnippet: Boolean!
}
 
enum VisibilityLevelsEnum {
internal
private
public
}
enum VisibilityScopesEnum {
internal
private
Loading
Loading
Loading
Loading
@@ -6442,8 +6442,8 @@
"deprecationReason": null
},
{
"name": "visibility",
"description": "Visibility of the snippet",
"name": "visibilityLevel",
"description": "Visibility Level of the snippet",
"args": [
 
],
Loading
Loading
@@ -6451,8 +6451,8 @@
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"kind": "ENUM",
"name": "VisibilityLevelsEnum",
"ofType": null
}
},
Loading
Loading
@@ -6828,6 +6828,35 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "ENUM",
"name": "VisibilityLevelsEnum",
"description": null,
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": [
{
"name": "private",
"description": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "internal",
"description": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "public",
"description": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"possibleTypes": null
},
{
"kind": "ENUM",
"name": "VisibilityScopesEnum",
Loading
Loading
@@ -15804,6 +15833,33 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "createSnippet",
"description": null,
"args": [
{
"name": "input",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "CreateSnippetInput",
"ofType": null
}
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "CreateSnippetPayload",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "designManagementDelete",
"description": null,
Loading
Loading
@@ -15885,6 +15941,33 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "destroySnippet",
"description": null,
"args": [
{
"name": "input",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "DestroySnippetInput",
"ofType": null
}
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "DestroySnippetPayload",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "epicSetSubscription",
"description": null,
Loading
Loading
@@ -16343,6 +16426,33 @@
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "updateSnippet",
"description": null,
"args": [
{
"name": "input",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "UpdateSnippetInput",
"ofType": null
}
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "UpdateSnippetPayload",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
Loading
Loading
@@ -19093,6 +19203,420 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "DestroySnippetPayload",
"description": "Autogenerated return type of DestroySnippet",
"fields": [
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "errors",
"description": "Reasons why the mutation failed.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
}
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "snippet",
"description": "The snippet after mutation",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "Snippet",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "DestroySnippetInput",
"description": "Autogenerated input type of DestroySnippet",
"fields": null,
"inputFields": [
{
"name": "id",
"description": "The global id of the snippet to destroy",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "UpdateSnippetPayload",
"description": "Autogenerated return type of UpdateSnippet",
"fields": [
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "errors",
"description": "Reasons why the mutation failed.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
}
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "snippet",
"description": "The snippet after mutation",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "Snippet",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "UpdateSnippetInput",
"description": "Autogenerated input type of UpdateSnippet",
"fields": null,
"inputFields": [
{
"name": "id",
"description": "The global id of the snippet to update",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "title",
"description": "Title of the snippet",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "fileName",
"description": "File name of the snippet",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "content",
"description": "Content of the snippet",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "description",
"description": "Description of the snippet",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "visibilityLevel",
"description": "The visibility level of the snippet",
"type": {
"kind": "ENUM",
"name": "VisibilityLevelsEnum",
"ofType": null
},
"defaultValue": null
},
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "CreateSnippetPayload",
"description": "Autogenerated return type of CreateSnippet",
"fields": [
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "errors",
"description": "Reasons why the mutation failed.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
}
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "snippet",
"description": "The snippet after mutation",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "Snippet",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "CreateSnippetInput",
"description": "Autogenerated input type of CreateSnippet",
"fields": null,
"inputFields": [
{
"name": "title",
"description": "Title of the snippet",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "fileName",
"description": "File name of the snippet",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "content",
"description": "Content of the snippet",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "description",
"description": "Description of the snippet",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "visibilityLevel",
"description": "The visibility level of the snippet",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "ENUM",
"name": "VisibilityLevelsEnum",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "projectPath",
"description": "The project full path the snippet is associated with",
"type": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
},
"defaultValue": null
},
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "DesignManagementUploadPayload",
Loading
Loading
Loading
Loading
@@ -92,6 +92,14 @@ The API can be explored interactively using the [GraphiQL IDE](../index.md#graph
| `errors` | String! => Array | Reasons why the mutation failed. |
| `note` | Note | The note after mutation |
 
### CreateSnippetPayload
| Name | Type | Description |
| --- | ---- | ---------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Reasons why the mutation failed. |
| `snippet` | Snippet | The snippet after mutation |
### Design
 
| Name | Type | Description |
Loading
Loading
@@ -145,6 +153,14 @@ The API can be explored interactively using the [GraphiQL IDE](../index.md#graph
| `errors` | String! => Array | Reasons why the mutation failed. |
| `note` | Note | The note after mutation |
 
### DestroySnippetPayload
| Name | Type | Description |
| --- | ---- | ---------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Reasons why the mutation failed. |
| `snippet` | Snippet | The snippet after mutation |
### DetailedStatus
 
| Name | Type | Description |
Loading
Loading
@@ -802,7 +818,7 @@ The API can be explored interactively using the [GraphiQL IDE](../index.md#graph
| `fileName` | String | File Name of the snippet |
| `content` | String! | Content of the snippet |
| `description` | String | Description of the snippet |
| `visibility` | String! | Visibility of the snippet |
| `visibilityLevel` | VisibilityLevelsEnum! | Visibility Level of the snippet |
| `createdAt` | Time! | Timestamp this snippet was created |
| `updatedAt` | Time! | Timestamp this snippet was updated |
| `webUrl` | String! | Web URL of the snippet |
Loading
Loading
@@ -929,6 +945,14 @@ The API can be explored interactively using the [GraphiQL IDE](../index.md#graph
| `errors` | String! => Array | Reasons why the mutation failed. |
| `note` | Note | The note after mutation |
 
### UpdateSnippetPayload
| Name | Type | Description |
| --- | ---- | ---------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Reasons why the mutation failed. |
| `snippet` | Snippet | The snippet after mutation |
### User
 
| Name | Type | Description |
Loading
Loading
doc/ci/img/collapsible_log.png

59.3 KiB | W: 1496px | H: 752px

doc/ci/img/collapsible_log.png

272 KiB | W: 1771px | H: 933px

doc/ci/img/collapsible_log.png
doc/ci/img/collapsible_log.png
doc/ci/img/collapsible_log.png
doc/ci/img/collapsible_log.png
  • 2-up
  • Swipe
  • Onion skin
Loading
Loading
@@ -149,12 +149,13 @@ The union of A, B, and C is (1, 4) and (6, 7). Therefore, the total running time
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/14664) in GitLab
> 12.0.
 
Job logs are divided into sections that can be collapsed or expanded.
Job logs are divided into sections that can be collapsed or expanded. Each section will display
the duration.
 
In the following example:
 
- Two sections are expanded and can be collapsed.
- One section is collapsed and can be expanded.
- Two sections are collapsed and can be expanded.
- Three sections are expanded and can be collapsed.
 
![Collapsible sections](img/collapsible_log.png)
 
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment