提交 8b789570 编写于 作者: G GitLab Bot

Add latest changes from gitlab-org/gitlab@master

上级 29586358
......@@ -2,6 +2,7 @@
import * as Sentry from '@sentry/browser';
import {
GlAlert,
GlBadge,
GlIcon,
GlLoadingIcon,
GlSprintf,
......@@ -35,6 +36,7 @@ export default {
},
severityLabels: ALERTS_SEVERITY_LABELS,
components: {
GlBadge,
GlAlert,
GlIcon,
GlLoadingIcon,
......@@ -186,21 +188,18 @@ export default {
<div
class="gl-display-inline-flex gl-align-items-center gl-justify-content-space-between"
>
<gl-icon
class="gl-mr-3 align-middle"
:size="12"
:name="`severity-${alert.severity.toLowerCase()}`"
:class="`icon-${alert.severity.toLowerCase()}`"
/>
<strong>{{ $options.severityLabels[alert.severity] }}</strong>
<gl-badge class="gl-mr-3">
<strong>{{ s__('AlertManagement|Alert') }}</strong>
</gl-badge>
</div>
<span class="mx-2">&bull;</span>
<gl-sprintf :message="reportedAtMessage">
<template #when>
<time-ago-tooltip :time="alert.createdAt" class="gl-ml-3" />
</template>
<template #tool>{{ alert.monitoringTool }}</template>
</gl-sprintf>
<span>
<gl-sprintf :message="reportedAtMessage">
<template #when>
<time-ago-tooltip :time="alert.createdAt" />
</template>
<template #tool>{{ alert.monitoringTool }}</template>
</gl-sprintf>
</span>
</div>
<gl-button
v-if="alert.issueIid"
......@@ -242,24 +241,48 @@ export default {
</div>
<gl-tabs v-if="alert" data-testid="alertDetailsTabs">
<gl-tab data-testid="overviewTab" :title="$options.i18n.overviewTitle">
<ul class="pl-4 mb-n1">
<li v-if="alert.startedAt" class="my-2">
<strong class="bold">{{ s__('AlertManagement|Start time') }}:</strong>
<div v-if="alert.severity" class="gl-mt-3 gl-mb-5 gl-display-flex">
<div class="gl-font-weight-bold gl-w-13 gl-text-right gl-pr-3">
{{ s__('AlertManagement|Severity') }}:
</div>
<div class="gl-pl-2" data-testid="severity">
<span>
<gl-icon
class="gl-vertical-align-middle"
:size="12"
:name="`severity-${alert.severity.toLowerCase()}`"
:class="`icon-${alert.severity.toLowerCase()}`"
/>
</span>
{{ $options.severityLabels[alert.severity] }}
</div>
</div>
<div v-if="alert.startedAt" class="gl-my-5 gl-display-flex">
<div class="gl-font-weight-bold gl-w-13 gl-text-right gl-pr-3">
{{ s__('AlertManagement|Start time') }}:
</div>
<div class="gl-pl-2">
<time-ago-tooltip data-testid="startTimeItem" :time="alert.startedAt" />
</li>
<li v-if="alert.eventCount" class="my-2">
<strong class="bold">{{ s__('AlertManagement|Events') }}:</strong>
<span data-testid="eventCount">{{ alert.eventCount }}</span>
</li>
<li v-if="alert.monitoringTool" class="my-2">
<strong class="bold">{{ s__('AlertManagement|Tool') }}:</strong>
<span data-testid="monitoringTool">{{ alert.monitoringTool }}</span>
</li>
<li v-if="alert.service" class="my-2">
<strong class="bold">{{ s__('AlertManagement|Service') }}:</strong>
<span data-testid="service">{{ alert.service }}</span>
</li>
</ul>
</div>
</div>
<div v-if="alert.eventCount" class="gl-my-5 gl-display-flex">
<div class="gl-font-weight-bold gl-w-13 gl-text-right gl-pr-3">
{{ s__('AlertManagement|Events') }}:
</div>
<div class="gl-pl-2" data-testid="eventCount">{{ alert.eventCount }}</div>
</div>
<div v-if="alert.monitoringTool" class="gl-my-5 gl-display-flex">
<div class="gl-font-weight-bold gl-w-13 gl-text-right gl-pr-3">
{{ s__('AlertManagement|Tool') }}:
</div>
<div class="gl-pl-2" data-testid="monitoringTool">{{ alert.monitoringTool }}</div>
</div>
<div v-if="alert.service" class="gl-my-5 gl-display-flex">
<div class="bold gl-w-13 gl-text-right gl-pr-3">
{{ s__('AlertManagement|Service') }}:
</div>
<div class="gl-pl-2" data-testid="service">{{ alert.service }}</div>
</div>
</gl-tab>
<gl-tab data-testid="fullDetailsTab" :title="$options.i18n.fullAlertDetailsTitle">
<gl-table
......
......@@ -7,6 +7,7 @@ import BoardSidebar from 'ee_else_ce/boards/components/board_sidebar';
import initNewListDropdown from 'ee_else_ce/boards/components/new_list_dropdown';
import boardConfigToggle from 'ee_else_ce/boards/config_toggle';
import toggleLabels from 'ee_else_ce/boards/toggle_labels';
import toggleEpicsSwimlanes from 'ee_else_ce/boards/toggle_epics_swimlanes';
import {
setPromotionState,
setWeigthFetchingState,
......@@ -371,5 +372,6 @@ export default () => {
toggleFocusMode(ModalStore, boardsStore);
toggleLabels();
toggleEpicsSwimlanes();
mountMultipleBoardsSwitcher();
};
......@@ -2,7 +2,6 @@ import 'jquery';
// common jQuery plugins
import 'jquery-ujs';
import 'vendor/jquery.endless-scroll';
import 'jquery.caret'; // must be imported before at.js
import '@gitlab/at.js';
import 'vendor/jquery.scrollTo';
......
......@@ -98,20 +98,20 @@ export default {
<gl-sprintf
v-if="showDropdowns"
class="d-flex align-items-center compare-versions-container"
:message="s__('MergeRequest|Compare %{source} and %{target}')"
:message="s__('MergeRequest|Compare %{target} and %{source}')"
>
<template #source>
<compare-dropdown-layout
:versions="diffCompareDropdownSourceVersions"
class="mr-version-dropdown"
/>
</template>
<template #target>
<compare-dropdown-layout
:versions="diffCompareDropdownTargetVersions"
class="mr-version-compare-dropdown"
/>
</template>
<template #source>
<compare-dropdown-layout
:versions="diffCompareDropdownSourceVersions"
class="mr-version-dropdown"
/>
</template>
</gl-sprintf>
<div v-else-if="commit">
{{ __('Viewing commit') }}
......
import $ from 'jquery';
import 'vendor/jquery.endless-scroll';
import { getParameterByName } from '~/lib/utils/common_utils';
import axios from '~/lib/utils/axios_utils';
import { removeParams } from '~/lib/utils/url_utility';
......
......@@ -541,7 +541,8 @@
cursor: help;
}
.board-labels-toggle-wrapper {
.board-labels-toggle-wrapper,
.board-swimlanes-toggle-wrapper {
/**
* Make the wrapper the same height as a button so it aligns properly when the
* filtered-search-box input element increases in size on Linux smaller breakpoints
......
......@@ -446,7 +446,7 @@ table.code {
vertical-align: top;
span {
white-space: pre-wrap;
white-space: break-spaces;
&.context-cell {
display: inline-block;
......
# frozen_string_literal: true
module Mutations
module Commits
class Create < BaseMutation
include Mutations::ResolvesProject
graphql_name 'CommitCreate'
argument :project_path, GraphQL::ID_TYPE,
required: true,
description: 'Project full path the branch is associated with'
argument :branch, GraphQL::STRING_TYPE,
required: true,
description: 'Name of the branch'
argument :message,
GraphQL::STRING_TYPE,
required: true,
description: copy_field_description(Types::CommitType, :message)
argument :actions,
[Types::CommitActionType],
required: true,
description: 'Array of action hashes to commit as a batch'
field :commit,
Types::CommitType,
null: true,
description: 'The commit after mutation'
authorize :push_code
def resolve(project_path:, branch:, message:, actions:)
project = authorized_find!(full_path: project_path)
attributes = {
commit_message: message,
branch_name: branch,
start_branch: branch,
actions: actions.map { |action| action.to_h }
}
result = ::Files::MultiService.new(project, current_user, attributes).execute
{
commit: (project.repository.commit(result[:result]) if result[:status] == :success),
errors: Array.wrap(result[:message])
}
end
private
def find_object(full_path:)
resolve_project(full_path: full_path)
end
end
end
end
# frozen_string_literal: true
module Types
class CommitActionModeEnum < BaseEnum
graphql_name 'CommitActionMode'
description 'Mode of a commit action'
value 'CREATE', description: 'Create command', value: :create
value 'DELETE', description: 'Delete command', value: :delete
value 'MOVE', description: 'Move command', value: :move
value 'UPDATE', description: 'Update command', value: :update
value 'CHMOD', description: 'Chmod command', value: :chmod
end
end
# frozen_string_literal: true
module Types
# rubocop: disable Graphql/AuthorizeTypes
class CommitActionType < BaseInputObject
argument :action, type: Types::CommitActionModeEnum, required: true,
description: 'The action to perform, create, delete, move, update, chmod'
argument :file_path, type: GraphQL::STRING_TYPE, required: true,
description: 'Full path to the file'
argument :content, type: GraphQL::STRING_TYPE, required: false,
description: 'Content of the file'
argument :previous_path, type: GraphQL::STRING_TYPE, required: false,
description: 'Original full path to the file being moved'
argument :last_commit_id, type: GraphQL::STRING_TYPE, required: false,
description: 'Last known file commit ID'
argument :execute_filemode, type: GraphQL::BOOLEAN_TYPE, required: false,
description: 'Enables/disables the execute flag on the file'
argument :encoding, type: Types::CommitEncodingEnum, required: false,
description: 'Encoding of the file. Default is text'
end
# rubocop: enable Graphql/AuthorizeTypes
end
# frozen_string_literal: true
module Types
class CommitEncodingEnum < BaseEnum
graphql_name 'CommitEncoding'
value 'TEXT', description: 'Text encoding', value: :text
value 'BASE64', description: 'Base64 encoding', value: :base64
end
end
......@@ -13,6 +13,7 @@ module Types
mount_mutation Mutations::AwardEmojis::Remove
mount_mutation Mutations::AwardEmojis::Toggle
mount_mutation Mutations::Branches::Create, calls_gitaly: true
mount_mutation Mutations::Commits::Create, calls_gitaly: true
mount_mutation Mutations::Issues::SetConfidential
mount_mutation Mutations::Issues::SetDueDate
mount_mutation Mutations::Issues::Update
......
# frozen_string_literal: true
module NumbersHelper
# rubocop: disable CodeReuse/ActiveRecord
def limited_counter_with_delimiter(resource, **options)
limit = options.fetch(:limit, 1000).to_i
count = resource.limit(limit + 1).count(:all)
count = resource.page.total_count_with_limit(:all, limit: limit)
if count > limit
number_with_delimiter(count - 1, options) + '+'
else
number_with_delimiter(count, options)
end
end
# rubocop: enable CodeReuse/ActiveRecord
end
......@@ -41,10 +41,10 @@ module Spam
return unless Gitlab::CurrentSettings.spam_check_endpoint_enabled
return if endpoint_url.blank?
result = Gitlab::HTTP.try_get(endpoint_url, verdict_params)
return unless result
begin
result = Gitlab::HTTP.post(endpoint_url, body: verdict_params.to_json, headers: { 'Content-Type' => 'application/json' })
return unless result
json_result = Gitlab::Json.parse(result).with_indifferent_access
# @TODO metrics/logging
# Expecting:
......@@ -56,6 +56,10 @@ module Spam
# @TODO log if json_result[:error]
json_result[:verdict]
rescue *Gitlab::HTTP::HTTP_ERRORS => e
# @TODO: log error via try_post https://gitlab.com/gitlab-org/gitlab/-/issues/219223
Gitlab::ErrorTracking.log_exception(e)
return
rescue
# @TODO log
ALLOW
......
......@@ -173,6 +173,8 @@
= render 'shared/issuable/board_create_list_dropdown', board: board
- if @project
#js-add-issues-btn.prepend-left-10{ data: { can_admin_list: can?(current_user, :admin_list, @project) } }
- if Feature.enabled?(:boards_with_swimlanes)
#js-board-epics-swimlanes-toggle
#js-toggle-focus-btn
- elsif is_not_boards_modal_or_productivity_analytics && show_sorting_dropdown
= render 'shared/issuable/sort_dropdown'
---
title: Add mutation to create commits in GraphQL
merge_request: 31102
author:
type: added
---
title: Reorder diffs compare versions dropdowns.
merge_request: 31770
author: Gilang Gumilar
type: changed
---
title: Fix whitespace changes overgrowing the diff container
merge_request: 32774
author:
type: fixed
---
title: Upgrade to Gitaly v13.1.0-rc1
merge_request: 33302
author:
type: changed
---
title: Bump cluster-applications to 0.17.0, which updates Runner to 0.17.0 and Cilium
to 1.7.4
merge_request: 32931
author:
type: changed
......@@ -5,9 +5,10 @@ module Kaminari
# This is a modified version of
# https://github.com/kaminari/kaminari/blob/c5186f5d9b7f23299d115408e62047447fd3189d/kaminari-activerecord/lib/kaminari/activerecord/active_record_relation_methods.rb#L17-L41
# that limit the COUNT query to 10,000 to avoid query timeouts.
# that limit the COUNT query to a configurable value to avoid query timeouts.
# The default limit value is 10,000 records
# rubocop: disable Gitlab/ModuleWithInstanceVariables
def total_count_with_limit(column_name = :all, _options = nil) #:nodoc:
def total_count_with_limit(column_name = :all, options = {}) #:nodoc:
return @total_count if defined?(@total_count) && @total_count
# There are some cases that total count can be deduced from loaded records
......@@ -18,13 +19,14 @@ module Kaminari
return @total_count = (current_page - 1) * limit_value + @records.length if @records.any? && (@records.length < limit_value)
end
limit = options.fetch(:limit, MAX_COUNT_LIMIT).to_i
# #count overrides the #select which could include generated columns referenced in #order, so skip #order here, where it's irrelevant to the result anyway
c = except(:offset, :limit, :order)
# Remove includes only if they are irrelevant
c = c.except(:includes) unless references_eager_loaded_tables?
# .group returns an OrderedHash that responds to #count
# The following line was modified from `c = c.count(:all)`
c = c.limit(MAX_COUNT_LIMIT + 1).count(column_name)
c = c.limit(limit + 1).count(column_name)
@total_count =
if c.is_a?(Hash) || c.is_a?(ActiveSupport::OrderedHash)
c.count
......
......@@ -119,7 +119,7 @@ The connection settings match those provided by [Fog](https://github.com/fog), a
| `aws_signature_version` | AWS signature version to use. 2 or 4 are valid options. Digital Ocean Spaces and other providers may need 2. | 4 |
| `enable_signature_v4_streaming` | Set to true to enable HTTP chunked transfers with [AWS v4 signatures](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html). Oracle Cloud S3 needs this to be false | true |
| `region` | AWS region | us-east-1 |
| `host` | S3 compatible host for when not using AWS, e.g. `localhost` or `storage.example.com` | s3.amazonaws.com |
| `host` | S3 compatible host for when not using AWS, for example `localhost` or `storage.example.com` | s3.amazonaws.com |
| `endpoint` | Can be used when configuring an S3 compatible service such as [MinIO](https://min.io), by entering a URL such as `http://127.0.0.1:9000` | (optional) |
| `path_style` | Set to true to use `host/bucket_name/object` style paths instead of `bucket_name.host/object`. Leave as false for AWS S3 | false |
| `use_iam_profile` | Set to true to use IAM profile instead of access keys | false
......@@ -144,7 +144,7 @@ _The artifacts are stored by default in
}
```
NOTE: For GitLab 9.4+, if you are using AWS IAM profiles, be sure to omit the
NOTE: For GitLab 9.4+, if you're using AWS IAM profiles, be sure to omit the
AWS access key and secret access key/value pairs. For example:
```ruby
......@@ -209,8 +209,8 @@ The connection settings match those provided by [Fog](https://github.com/fog), a
| `provider` | Always `OpenStack` for compatible hosts | OpenStack |
| `openstack_username` | OpenStack username | |
| `openstack_api_key` | OpenStack API key | |
| `openstack_temp_url_key` | OpenStack key for generating temporary urls | |
| `openstack_auth_url` | OpenStack authentication endpont | |
| `openstack_temp_url_key` | OpenStack key for generating temporary URLs | |
| `openstack_auth_url` | OpenStack authentication endpoint | |
| `openstack_region` | OpenStack region | |
| `openstack_tenant_id` | OpenStack tenant ID |
......@@ -404,6 +404,8 @@ In these and other cases, you'll need to identify the projects most responsible
for disk space usage, figure out what types of artifacts are using the most
space, and in some cases, manually delete job artifacts to reclaim disk space.
One possible first step is to [clean up _orphaned_ artifact files](../raketasks/cleanup.md#remove-orphan-artifact-files).
#### List projects by total size of job artifacts stored
List the top 20 projects, sorted by the total size of job artifacts stored, by
......@@ -488,7 +490,7 @@ highly recommend running them only under the guidance of a Support Engineer, or
running them in a test environment with a backup of the instance ready to be
restored, just in case.
If you need to manually remove ALL job artifacts associated with multiple jobs,
If you need to manually remove **all** job artifacts associated with multiple jobs,
**including job logs**, this can be done from the Rails console (`sudo gitlab-rails console`):
1. Select jobs to be deleted:
......
......@@ -935,6 +935,135 @@ type Commit {
webUrl: String!
}
input CommitAction {
"""
The action to perform, create, delete, move, update, chmod
"""
action: CommitActionMode!
"""
Content of the file
"""
content: String
"""
Encoding of the file. Default is text
"""
encoding: CommitEncoding
"""
Enables/disables the execute flag on the file
"""
executeFilemode: Boolean
"""
Full path to the file
"""
filePath: String!
"""
Last known file commit ID
"""
lastCommitId: String
"""
Original full path to the file being moved
"""
previousPath: String
}
"""
Mode of a commit action
"""
enum CommitActionMode {
"""
Chmod command
"""
CHMOD
"""
Create command
"""
CREATE
"""
Delete command
"""
DELETE
"""
Move command
"""
MOVE
"""
Update command
"""
UPDATE
}
"""
Autogenerated input type of CommitCreate
"""
input CommitCreateInput {
"""
Array of action hashes to commit as a batch
"""
actions: [CommitAction!]!
"""
Name of the branch
"""
branch: String!
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
Raw commit message
"""
message: String!
"""
Project full path the branch is associated with
"""
projectPath: ID!
}
"""
Autogenerated return type of CommitCreate
"""
type CommitCreatePayload {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
The commit after mutation
"""
commit: Commit
"""
Errors encountered during execution of the mutation.
"""
errors: [String!]!
}
enum CommitEncoding {
"""
Base64 encoding
"""
BASE64
"""
Text encoding
"""
TEXT
}
"""
A tag expiration policy designed to keep only the images that matter most
"""
......@@ -6965,6 +7094,7 @@ type Mutation {
addProjectToSecurityDashboard(input: AddProjectToSecurityDashboardInput!): AddProjectToSecurityDashboardPayload
adminSidekiqQueuesDeleteJobs(input: AdminSidekiqQueuesDeleteJobsInput!): AdminSidekiqQueuesDeleteJobsPayload
boardListUpdateLimitMetrics(input: BoardListUpdateLimitMetricsInput!): BoardListUpdateLimitMetricsPayload
commitCreate(input: CommitCreateInput!): CommitCreatePayload
createAlertIssue(input: CreateAlertIssueInput!): CreateAlertIssuePayload
createAnnotation(input: CreateAnnotationInput!): CreateAnnotationPayload
createBranch(input: CreateBranchInput!): CreateBranchPayload
......@@ -9677,6 +9807,36 @@ type Requirement {
"""
state: RequirementState!
"""
Test reports of the requirement
"""
testReports(
"""
Returns the elements in the list that come after the specified cursor.
"""
after: String
"""
Returns the elements in the list that come before the specified cursor.
"""
before: String
"""
Returns the first _n_ elements from the list.
"""
first: Int
"""
Returns the last _n_ elements from the list.
"""
last: Int
"""
List test reports by sort order
"""
sort: Sort
): TestReportConnection
"""
Title of the requirement
"""
......@@ -10763,6 +10923,78 @@ type TaskCompletionStatus {
count: Int!
}
"""
Represents a requirement test report.
"""
type TestReport {
"""
Author of the test report
"""
author: User
"""
Timestamp of when the test report was created
"""
createdAt: Time!
"""
ID of the test report
"""
id: ID!
"""
Pipeline that created the test report
"""
pipeline: Pipeline
"""
State of the test report
"""
state: TestReportState!
}
"""
The connection type for TestReport.
"""
type TestReportConnection {
"""
A list of edges.
"""
edges: [TestReportEdge]
"""
A list of nodes.
"""
nodes: [TestReport]
"""
Information to aid in pagination.
"""
pageInfo: PageInfo!
}
"""
An edge in a connection.
"""
type TestReportEdge {
"""
A cursor for use in pagination.
"""
cursor: String!
"""
The item at the end of the edge.
"""
node: TestReport
}
"""
State of a test report
"""
enum TestReportState {
PASSED
}
"""
Time represented in ISO 8601
"""
......
......@@ -177,6 +177,16 @@ Autogenerated return type of BoardListUpdateLimitMetrics
| `titleHtml` | String | The GitLab Flavored Markdown rendering of `title` |
| `webUrl` | String! | Web URL of the commit |
## CommitCreatePayload
Autogenerated return type of CommitCreate
| Name | Type | Description |
| --- | ---- | ---------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `commit` | Commit | The commit after mutation |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
## ContainerExpirationPolicy
A tag expiration policy designed to keep only the images that matter most
......@@ -1606,6 +1616,18 @@ Completion status of tasks
| `completedCount` | Int! | Number of completed tasks |
| `count` | Int! | Number of total tasks |
## TestReport
Represents a requirement test report.
| Name | Type | Description |
| --- | ---- | ---------- |
| `author` | User | Author of the test report |
| `createdAt` | Time! | Timestamp of when the test report was created |
| `id` | ID! | ID of the test report |
| `pipeline` | Pipeline | Pipeline that created the test report |
| `state` | TestReportState! | State of the test report |
## Timelog
| Name | Type | Description |
......
apply:
stage: deploy
image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.16.0"
image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.17.0"
environment:
name: production
variables:
......@@ -26,6 +26,8 @@ apply:
refs:
- master
artifacts:
reports:
cluster_applications: gl-cluster-applications.json
when: on_failure
paths:
- tiller.log
......@@ -32,6 +32,7 @@ namespace :gemojione do
dir = Gemojione.images_path
resultant_emoji_map = {}
resultant_emoji_map_new = {}
Gitlab::Emoji.emojis.each do |name, emoji_hash|
# Ignore aliases
......@@ -53,6 +54,16 @@ namespace :gemojione do
}
resultant_emoji_map[name] = entry
# Our new map is only characters to make the json substantially smaller
new_entry = {
c: category,
e: emoji_hash['moji'],
d: emoji_hash['description'],
u: Gitlab::Emoji.emoji_unicode_version(name)
}
resultant_emoji_map_new[name] = new_entry
end
end
......@@ -60,6 +71,11 @@ namespace :gemojione do
File.open(out, 'w') do |handle|
handle.write(Gitlab::Json.pretty_generate(resultant_emoji_map))
end
out_new = File.join(Rails.root, 'public', '-', 'emojis', '1', 'emojis.json')
File.open(out_new, 'w') do |handle|
handle.write(Gitlab::Json.pretty_generate(resultant_emoji_map_new))
end
end
# This task will generate a standard and Retina sprite of all of the current
......
......@@ -2518,6 +2518,9 @@ msgstr ""
msgid "Apply a template"
msgstr ""
msgid "Apply changes"
msgstr ""
msgid "Apply suggestion"
msgstr ""
......@@ -10796,6 +10799,9 @@ msgstr ""
msgid "Group avatar"
msgstr ""
msgid "Group by:"
msgstr ""
msgid "Group could not be imported: %{errors}"
msgstr ""
......@@ -13622,7 +13628,7 @@ msgstr ""
msgid "MergeRequests|started a thread on commit %{linkStart}%{commitDisplay}%{linkEnd}"
msgstr ""
msgid "MergeRequest|Compare %{source} and %{target}"
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
msgid "MergeRequest|Error dismissing suggestion popover. Please try again."
......@@ -14223,6 +14229,9 @@ msgstr ""
msgid "Network"
msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
msgid "NetworkPolicies|Enabled"
msgstr ""
......@@ -14250,6 +14259,9 @@ msgstr ""
msgid "NetworkPolicies|Policy %{policyName} was successfully changed"
msgstr ""
msgid "NetworkPolicies|Policy definition"
msgstr ""
msgid "NetworkPolicies|Something went wrong, failed to update policy"
msgstr ""
......@@ -14531,6 +14543,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
msgid "No grouping"
msgstr ""
msgid "No job log"
msgstr ""
......
此差异已折叠。
......@@ -3,9 +3,11 @@ import { GlAlert, GlLoadingIcon, GlTable } from '@gitlab/ui';
import AlertDetails from '~/alert_management/components/alert_details.vue';
import createIssueQuery from '~/alert_management/graphql/mutations/create_issue_from_alert.graphql';
import { joinPaths } from '~/lib/utils/url_utility';
import { trackAlertsDetailsViewsOptions } from '~/alert_management/constants';
import {
trackAlertsDetailsViewsOptions,
ALERTS_SEVERITY_LABELS,
} from '~/alert_management/constants';
import Tracking from '~/tracking';
import mockAlerts from '../mocks/alerts.json';
const mockAlert = mockAlerts[0];
......@@ -77,6 +79,12 @@ describe('AlertDetails', () => {
expect(wrapper.find('[data-testid="fullDetailsTab"]').exists()).toBe(true);
});
it('renders severity', () => {
expect(wrapper.find('[data-testid="severity"]').text()).toBe(
ALERTS_SEVERITY_LABELS[mockAlert.severity],
);
});
it('renders a title', () => {
expect(wrapper.find('[data-testid="title"]').text()).toBe(mockAlert.title);
});
......@@ -204,15 +212,15 @@ describe('AlertDetails', () => {
describe('individual header fields', () => {
describe.each`
severity | createdAt | monitoringTool | result
${'MEDIUM'} | ${'2020-04-17T23:18:14.996Z'} | ${null} | ${'Medium • Reported now'}
${'INFO'} | ${'2020-04-17T23:18:14.996Z'} | ${'Datadog'} | ${'Info • Reported now by Datadog'}
createdAt | monitoringTool | result
${'2020-04-17T23:18:14.996Z'} | ${null} | ${'Alert Reported now'}
${'2020-04-17T23:18:14.996Z'} | ${'Datadog'} | ${'Alert Reported now by Datadog'}
`(
`When severity=$severity, createdAt=$createdAt, monitoringTool=$monitoringTool`,
({ severity, createdAt, monitoringTool, result }) => {
`When createdAt=$createdAt, monitoringTool=$monitoringTool`,
({ createdAt, monitoringTool, result }) => {
beforeEach(() => {
mountComponent({
data: { alert: { ...mockAlert, severity, createdAt, monitoringTool } },
data: { alert: { ...mockAlert, createdAt, monitoringTool } },
mountMethod: mount,
stubs,
});
......
# frozen_string_literal: true
require 'spec_helper'
describe Mutations::Commits::Create do
subject(:mutation) { described_class.new(object: nil, context: context, field: nil) }
let_it_be(:project) { create(:project, :public, :repository) }
let_it_be(:user) { create(:user) }
let(:context) do
GraphQL::Query::Context.new(
query: OpenStruct.new(schema: nil),
values: { current_user: user },
object: nil
)
end
specify { expect(described_class).to require_graphql_authorizations(:push_code) }
describe '#resolve' do
subject { mutation.resolve(project_path: project.full_path, branch: branch, message: message, actions: actions) }
let(:branch) { 'master' }
let(:message) { 'Commit message' }
let(:actions) do
[
{
action: 'create',
file_path: 'NEW_FILE.md',
content: 'Hello'
}
]
end
let(:mutated_commit) { subject[:commit] }
it 'raises an error if the resource is not accessible to the user' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
context 'when user does not have enough permissions' do
before do
project.add_guest(user)
end
it 'raises an error' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
context 'when user is a maintainer of a different project' do
before do
create(:project_empty_repo).add_maintainer(user)
end
it 'raises an error' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
context 'when the user can create a commit' do
let(:deltas) { mutated_commit.raw_deltas }
before_all do
project.add_developer(user)
end
context 'when service successfully creates a new commit' do
it 'returns a new commit' do
expect(mutated_commit).to have_attributes(message: message, project: project)
expect(subject[:errors]).to be_empty
expect_to_contain_deltas([
a_hash_including(a_mode: '0', b_mode: '100644', new_file: true, new_path: 'NEW_FILE.md')
])
end
end
context 'when request has multiple actions' do
let(:actions) do
[
{
action: 'create',
file_path: 'foo/foobar',
content: 'some content'
},
{
action: 'delete',
file_path: 'README.md'
},
{
action: 'move',
file_path: "LICENSE.md",
previous_path: "LICENSE",
content: "some content"
},
{
action: 'update',
file_path: 'VERSION',
content: 'new content'
},
{
action: 'chmod',
file_path: 'CHANGELOG',
execute_filemode: true
}
]
end
it 'returns a new commit' do
expect(mutated_commit).to have_attributes(message: message, project: project)
expect(subject[:errors]).to be_empty
expect_to_contain_deltas([
a_hash_including(a_mode: '0', b_mode: '100644', new_path: 'foo/foobar'),
a_hash_including(deleted_file: true, new_path: 'README.md'),
a_hash_including(deleted_file: true, new_path: 'LICENSE'),
a_hash_including(new_file: true, new_path: 'LICENSE.md'),
a_hash_including(new_file: false, new_path: 'VERSION'),
a_hash_including(a_mode: '100644', b_mode: '100755', new_path: 'CHANGELOG')
])
end
end
context 'when actions are not defined' do
let(:actions) { [] }
it 'returns a new commit' do
expect(mutated_commit).to have_attributes(message: message, project: project)
expect(subject[:errors]).to be_empty
expect_to_contain_deltas([])
end
end
context 'when branch does not exist' do
let(:branch) { 'unknown' }
it 'returns errors' do
expect(mutated_commit).to be_nil
expect(subject[:errors]).to eq(['You can only create or edit files when you are on a branch'])
end
end
context 'when message is not set' do
let(:message) { nil }
it 'returns errors' do
expect(mutated_commit).to be_nil
expect(subject[:errors]).to eq(['3:UserCommitFiles: empty CommitMessage'])
end
end
context 'when actions are incorrect' do
let(:actions) { [{ action: 'unknown', file_path: 'test.md', content: '' }] }
it 'returns errors' do
expect(mutated_commit).to be_nil
expect(subject[:errors]).to eq(['Unknown action \'unknown\''])
end
end
context 'when branch is protected' do
before do
create(:protected_branch, project: project, name: branch)
end
it 'returns errors' do
expect(mutated_commit).to be_nil
expect(subject[:errors]).to eq(['You are not allowed to push into this branch'])
end
end
end
end
def expect_to_contain_deltas(expected_deltas)
expect(deltas.count).to eq(expected_deltas.count)
expect(deltas).to include(*expected_deltas)
end
end
# frozen_string_literal: true
require 'spec_helper'
describe GitlabSchema.types['CommitActionMode'] do
it { expect(described_class.graphql_name).to eq('CommitActionMode') }
it 'exposes all the existing commit actions' do
expect(described_class.values.keys).to match_array(%w[CREATE UPDATE MOVE DELETE CHMOD])
end
end
# frozen_string_literal: true
require 'spec_helper'
describe GitlabSchema.types['CommitEncoding'] do
it { expect(described_class.graphql_name).to eq('CommitEncoding') }
it 'exposes all the existing encoding option' do
expect(described_class.values.keys).to match_array(%w[TEXT BASE64])
end
end
# frozen_string_literal: true
require 'spec_helper'
describe 'Creation of a new commit' do
include GraphqlHelpers
let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project, :public, :repository) }
let(:input) { { project_path: project.full_path, branch: branch, message: message, actions: actions } }
let(:branch) { 'master' }
let(:message) { 'Commit message' }
let(:actions) do
[
{
action: 'CREATE',
filePath: 'NEW_FILE.md',
content: 'Hello'
}
]
end
let(:mutation) { graphql_mutation(:commit_create, input) }
let(:mutation_response) { graphql_mutation_response(:commit_create) }
context 'the user is not allowed to create a commit' do
it_behaves_like 'a mutation that returns top-level errors',
errors: ['The resource that you are attempting to access does not exist or you don\'t have permission to perform this action']
end
context 'when user has permissions to create a commit' do
before do
project.add_developer(current_user)
end
it 'creates a new commit' do
post_graphql_mutation(mutation, current_user: current_user)
expect(response).to have_gitlab_http_status(:success)
expect(mutation_response['commit']).to include(
'title' => message
)
end
context 'when branch is not correct' do
let(:branch) { 'unknown' }
it_behaves_like 'a mutation that returns errors in the response',
errors: ['You can only create or edit files when you are on a branch']
end
end
end
......@@ -169,7 +169,7 @@ describe Spam::SpamVerdictService do
before do
stub_application_setting(spam_check_endpoint_enabled: true)
stub_application_setting(spam_check_endpoint_url: "http://www.spamcheckurl.com/spam_check")
stub_request(:any, /.*spamcheckurl.com.*/).to_return( body: spam_check_body.to_json, status: spam_check_http_status )
stub_request(:post, /.*spamcheckurl.com.*/).to_return( body: spam_check_body.to_json, status: spam_check_http_status )
end
context 'if the endpoint is accessible' do
......@@ -248,7 +248,7 @@ describe Spam::SpamVerdictService do
context 'if the endpoint times out' do
before do
stub_request(:any, /.*spamcheckurl.com.*/).to_timeout
stub_request(:post, /.*spamcheckurl.com.*/).to_timeout
end
it 'returns nil' do
......
......@@ -782,15 +782,15 @@
eslint-plugin-vue "^6.2.1"
vue-eslint-parser "^7.0.0"
"@gitlab/svgs@1.130.0":
version "1.130.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.130.0.tgz#0c2f3cdc0a4b0f54c47b2861c8fa31b2a58c570a"
integrity sha512-azJ1E9PBk6fGOaP6816BSr8oYrQu3m3BbYZwWOCUp8AfbZuf0ZOZVYmlR9i/eAOhoqqqmwF8hYCK2VjAklbpPA==
"@gitlab/svgs@1.131.0":
version "1.131.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.131.0.tgz#4fc3e15cea899e8941954197bfc600afd6d9e210"
integrity sha512-c/0FWIEz3fJjC0n2XdxQ/XdGzpJqPwiye6fG+imA0HRavlg+C0xENzUif8A+1t5/zNIkUCTRugNbknfpU7Y7DA==
"@gitlab/ui@16.0.0":
version "16.0.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-16.0.0.tgz#0e2d19b85c47f45a052caf6cd0367613cbab8e8e"
integrity sha512-xSWXtFWWQzGtL35dGexc5LGqAJXYjLMEFQyPLzCBX3yY9tkI9s9rVMX053tnKYb9kgEmL+R/xGiW7D9nb58VmQ==
"@gitlab/ui@16.1.0":
version "16.1.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-16.1.0.tgz#fe6bbb3a8fb8d1cb7a577f4bb7cb2f1b35b34c57"
integrity sha512-YPC0ntS7Wp3wQq/sSUu16Z62XgyY3Oe49vIvm0e3bt2ho2pVf9fuztrcsj7Kb9RrdHOUccUWfZLp+roDd9J0sQ==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"
......@@ -1040,10 +1040,10 @@
"@sentry/types" "5.10.0"
tslib "^1.9.3"
"@sourcegraph/code-host-integration@0.0.47":
version "0.0.47"
resolved "https://registry.yarnpkg.com/@sourcegraph/code-host-integration/-/code-host-integration-0.0.47.tgz#ad1b5aa70f90c9f46e8b7e4152602ab0ecc26c5a"
integrity sha512-2HtYcsch9PO/UUegA1p5fFjy0AMM35Hq8dsFJ9tkbqIQZcys2zW+giaXJVfforR6kxYPFo3otkqPD4Vpyi48pg==
"@sourcegraph/code-host-integration@0.0.48":
version "0.0.48"
resolved "https://registry.yarnpkg.com/@sourcegraph/code-host-integration/-/code-host-integration-0.0.48.tgz#327bd04182e8a9a8daabebc6f2b50c8186b19514"
integrity sha512-O4jQyfYmmZaZahLj2BbqjEh7MarQRhZHYdWhL4D3CdUGH4y3XOTGCmVHWEFb23UaV/izze1XoGDxbQeAnps7EA==
"@toast-ui/editor@^2.0.1":
version "2.0.1"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册