提交 b42bf2a6 编写于 作者: G GitLab Bot

Add latest changes from gitlab-org/gitlab@master

上级 1d799ea9
import white from './white';
import dark from './dark';
import monokai from './monokai';
import solarizedLight from './solarized_light';
import solarizedDark from './solarized_dark';
export const themes = [
......@@ -12,6 +13,10 @@ export const themes = [
name: 'dark',
data: dark,
},
{
name: 'solarized-light',
data: solarizedLight,
},
{
name: 'solarized-dark',
data: solarizedDark,
......
......@@ -5,7 +5,6 @@ import axios from '~/lib/utils/axios_utils';
import CiIcon from '../../vue_shared/components/ci_icon.vue';
import flash from '~/flash';
import Poll from '~/lib/utils/poll';
import Visibility from 'visibilityjs';
export default {
name: 'MRWidgetTerraformPlan',
......@@ -68,7 +67,11 @@ export default {
method: 'fetchPlans',
successCallback: ({ data }) => {
this.plans = data;
this.loading = false;
if (Object.keys(this.plan).length) {
this.loading = false;
poll.stop();
}
},
errorCallback: () => {
this.plans = {};
......@@ -77,17 +80,7 @@ export default {
},
});
if (!Visibility.hidden()) {
poll.makeRequest();
}
Visibility.change(() => {
if (!Visibility.hidden()) {
poll.restart();
} else {
poll.stop();
}
});
poll.makeRequest();
},
},
};
......
......@@ -69,8 +69,16 @@
display: none !important;
}
}
}
.multi-file-editor-holder {
height: 100%;
min-height: 0; // firefox fix
}
.monaco-diff-editor.vs {
// Apply theme related overrides only to the white theme
.theme-white .blob-editor-container {
.monaco-diff-editor {
.editor.modified {
box-shadow: none;
}
......@@ -131,12 +139,9 @@
}
}
.multi-file-editor-holder {
height: 100%;
min-height: 0; // firefox fix
&.is-readonly .vs,
.vs .editor.original {
.theme-white .multi-file-editor-holder {
&.is-readonly,
.editor.original {
.monaco-editor,
.monaco-editor-background,
.monaco-editor .inputarea.ime-input {
......
# frozen_string_literal: true
module Mutations
module Branches
class Create < BaseMutation
include Mutations::ResolvesProject
graphql_name 'CreateBranch'
argument :project_path, GraphQL::ID_TYPE,
required: true,
description: 'Project full path the branch is associated with'
argument :name, GraphQL::STRING_TYPE,
required: true,
description: 'Name of the branch'
argument :ref,
GraphQL::STRING_TYPE,
required: true,
description: 'Branch name or commit SHA to create branch from'
field :branch,
Types::BranchType,
null: true,
description: 'Branch after mutation'
authorize :push_code
def resolve(project_path:, name:, ref:)
project = authorized_find!(full_path: project_path)
context.scoped_set!(:branch_project, project)
result = ::Branches::CreateService.new(project, current_user)
.execute(name, ref)
{
branch: (result[:branch] 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 Resolvers
class BranchCommitResolver < BaseResolver
type Types::CommitType, null: true
alias_method :branch, :object
def resolve(**args)
return unless branch
commit = branch.dereferenced_target
::Commit.new(commit, context[:branch_project]) if commit
end
end
end
# frozen_string_literal: true
module Types
# rubocop: disable Graphql/AuthorizeTypes
class BranchType < BaseObject
graphql_name 'Branch'
field :name,
GraphQL::STRING_TYPE,
null: false,
description: 'Name of the branch'
field :commit, Types::CommitType,
null: true, resolver: Resolvers::BranchCommitResolver,
description: 'Commit for the branch'
end
# rubocop: enable Graphql/AuthorizeTypes
end
......@@ -10,6 +10,7 @@ module Types
mount_mutation Mutations::AwardEmojis::Add
mount_mutation Mutations::AwardEmojis::Remove
mount_mutation Mutations::AwardEmojis::Toggle
mount_mutation Mutations::Branches::Create, calls_gitaly: true
mount_mutation Mutations::Issues::SetConfidential
mount_mutation Mutations::Issues::SetDueDate
mount_mutation Mutations::Issues::Update
......
---
title: Add `name` and `search` parameters to project environments API
merge_request: 29385
author: Lee Tickett
type: added
---
title: Solarized light syntax highlighting theme for the Web IDE
merge_request: 30989
author:
type: added
---
title: Add mutation to create a new branch in GraphQL
merge_request: 30388
author:
type: added
---
title: Remove Visibility from terraform widget
merge_request: 30737
author:
type: fixed
---
title: Fix missing RSS feed events
merge_request: 19524
author:
type: fixed
---
title: Fix missing RSS feed events
merge_request: 28054
author:
type: fixed
---
title: 'Productivity Analytics: Remove separator and cleanup title margins'
merge_request: 30839
author:
type: changed
......@@ -651,6 +651,18 @@ type BoardListUpdateLimitMetricsPayload {
list: BoardList
}
type Branch {
"""
Commit for the branch
"""
commit: Commit
"""
Name of the branch
"""
name: String!
}
type Commit {
"""
Author of the commit
......@@ -768,6 +780,51 @@ type Commit {
webUrl: String!
}
"""
Autogenerated input type of CreateBranch
"""
input CreateBranchInput {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
Name of the branch
"""
name: String!
"""
Project full path the branch is associated with
"""
projectPath: ID!
"""
Branch name or commit SHA to create branch from
"""
ref: String!
}
"""
Autogenerated return type of CreateBranch
"""
type CreateBranchPayload {
"""
Branch after mutation
"""
branch: Branch
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
"""
Reasons why the mutation failed.
"""
errors: [String!]!
}
"""
Autogenerated input type of CreateDiffNote
"""
......@@ -5985,6 +6042,7 @@ type Mutation {
addProjectsToSecurityDashboard(input: AddProjectsToSecurityDashboardInput!): AddProjectsToSecurityDashboardPayload
adminSidekiqQueuesDeleteJobs(input: AdminSidekiqQueuesDeleteJobsInput!): AdminSidekiqQueuesDeleteJobsPayload
boardListUpdateLimitMetrics(input: BoardListUpdateLimitMetricsInput!): BoardListUpdateLimitMetricsPayload
createBranch(input: CreateBranchInput!): CreateBranchPayload
createDiffNote(input: CreateDiffNoteInput!): CreateDiffNotePayload
createEpic(input: CreateEpicInput!): CreateEpicPayload
createImageDiffNote(input: CreateImageDiffNoteInput!): CreateImageDiffNotePayload
......
......@@ -1903,6 +1903,51 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "Branch",
"description": null,
"fields": [
{
"name": "commit",
"description": "Commit for the branch",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "Commit",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"description": "Name of the branch",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "Commit",
......@@ -2208,6 +2253,136 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "CreateBranchInput",
"description": "Autogenerated input type of CreateBranch",
"fields": null,
"inputFields": [
{
"name": "projectPath",
"description": "Project full path the branch is associated with",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "name",
"description": "Name of the branch",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "ref",
"description": "Branch name or commit SHA to create branch from",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"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": "CreateBranchPayload",
"description": "Autogenerated return type of CreateBranch",
"fields": [
{
"name": "branch",
"description": "Branch after mutation",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "Branch",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"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
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "CreateDiffNoteInput",
......@@ -17138,6 +17313,33 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "createBranch",
"description": null,
"args": [
{
"name": "input",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "CreateBranchInput",
"ofType": null
}
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "CreateBranchPayload",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "createDiffNote",
"description": null,
......
......@@ -135,6 +135,13 @@ Autogenerated return type of BoardListUpdateLimitMetrics
| `errors` | String! => Array | Reasons why the mutation failed. |
| `list` | BoardList | The updated list |
## Branch
| Name | Type | Description |
| --- | ---- | ---------- |
| `commit` | Commit | Commit for the branch |
| `name` | String! | Name of the branch |
## Commit
| Name | Type | Description |
......@@ -152,6 +159,16 @@ Autogenerated return type of BoardListUpdateLimitMetrics
| `title` | String | Title of the commit message |
| `webUrl` | String! | Web URL of the commit |
## CreateBranchPayload
Autogenerated return type of CreateBranch
| Name | Type | Description |
| --- | ---- | ---------- |
| `branch` | Branch | Branch after mutation |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Reasons why the mutation failed. |
## CreateDiffNotePayload
Autogenerated return type of CreateDiffNote
......
......@@ -9778,13 +9778,16 @@ msgstr ""
msgid "Geo|All"
msgstr ""
msgid "Geo|All %{replicable_type}"
msgstr ""
msgid "Geo|All projects"
msgstr ""
msgid "Geo|All projects are being scheduled for re-sync"
msgid "Geo|All projects are being scheduled for resync"
msgstr ""
msgid "Geo|All projects are being scheduled for re-verify"
msgid "Geo|All projects are being scheduled for reverify"
msgstr ""
msgid "Geo|Could not remove tracking entry for an existing project."
......@@ -25609,6 +25612,9 @@ msgstr[1] ""
msgid "project avatar"
msgstr ""
msgid "projects"
msgstr ""
msgid "push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
msgstr ""
......
......@@ -35,7 +35,7 @@ describe 'Dashboard snippets' do
element = page.find('.row.empty-state')
expect(element).to have_content("Code snippets")
expect(element.find('.svg-content img')['src']).to have_content('illustrations/snippets_empty')
expect(element.find('.svg-content img.js-lazy-loaded')['src']).to have_content('illustrations/snippets_empty')
end
it 'shows new snippet button in main content area' do
......
......@@ -28,6 +28,7 @@ describe 'Merge request > User sees notes from forked project', :js do
page.within('.discussion-notes') do
find('.btn-text-field').click
scroll_to(page.find('#note_note', visible: false))
find('#note_note').send_keys('A reply comment')
find('.js-comment-button').click
end
......
......@@ -3,6 +3,7 @@ import { shallowMount } from '@vue/test-utils';
import axios from '~/lib/utils/axios_utils';
import MockAdapter from 'axios-mock-adapter';
import MrWidgetTerraformPlan from '~/vue_merge_request_widget/components/mr_widget_terraform_plan.vue';
import Poll from '~/lib/utils/poll';
const plan = {
create: 10,
......@@ -57,11 +58,23 @@ describe('MrWidgetTerraformPlan', () => {
});
describe('successful poll', () => {
let pollRequest;
let pollStop;
beforeEach(() => {
pollRequest = jest.spyOn(Poll.prototype, 'makeRequest');
pollStop = jest.spyOn(Poll.prototype, 'stop');
mockPollingApi(200, { 'tfplan.json': plan }, {});
return mountWrapper();
});
afterEach(() => {
pollRequest.mockRestore();
pollStop.mockRestore();
});
it('content change text', () => {
expect(wrapper.find(GlSprintf).exists()).toBe(true);
});
......@@ -69,6 +82,11 @@ describe('MrWidgetTerraformPlan', () => {
it('renders button when url is found', () => {
expect(wrapper.find('a').text()).toContain('View full log');
});
it('does not make additional requests after poll is successful', () => {
expect(pollRequest).toHaveBeenCalledTimes(1);
expect(pollStop).toHaveBeenCalledTimes(1);
});
});
describe('polling fails', () => {
......
# frozen_string_literal: true
require 'spec_helper'
describe Mutations::Branches::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_it_be(:context) do
GraphQL::Query::Context.new(
query: OpenStruct.new(schema: nil),
values: { current_user: user },
object: nil
)
end
describe '#resolve' do
subject { mutation.resolve(project_path: project.full_path, name: branch, ref: ref) }
let(:branch) { 'new_branch' }
let(:ref) { 'master' }
let(:mutated_branch) { subject[:branch] }
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 the user can create a branch' do
before do
project.add_developer(user)
allow_next_instance_of(::Branches::CreateService, project, user) do |create_service|
allow(create_service).to receive(:execute).with(branch, ref) { service_result }
end
end
context 'when service successfully creates a new branch' do
let(:service_result) { { status: :success, branch: double(name: branch) } }
it 'returns a new branch' do
expect(mutated_branch.name).to eq(branch)
expect(subject[:errors]).to be_empty
end
end
context 'when service fails to create a new branch' do
let(:service_result) { { status: :error, message: 'Branch already exists' } }
it { expect(mutated_branch).to be_nil }
it { expect(subject[:errors]).to eq(['Branch already exists']) }
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Resolvers::BranchCommitResolver do
include GraphqlHelpers
subject(:commit) { resolve(described_class, obj: branch) }
let_it_be(:repository) { create(:project, :repository).repository }
let(:branch) { repository.find_branch('master') }
describe '#resolve' do
it 'resolves commit' do
is_expected.to eq(repository.commits('master', limit: 1).last)
end
context 'when branch does not exist' do
let(:branch) { nil }
it 'returns nil' do
is_expected.to be_nil
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe GitlabSchema.types['Branch'] do
it { expect(described_class.graphql_name).to eq('Branch') }
it { expect(described_class).to have_graphql_fields(:name, :commit) }
end
# frozen_string_literal: true
require 'spec_helper'
describe 'Creation of a new branch' do
include GraphqlHelpers
let_it_be(:current_user) { create(:user) }
let(:project) { create(:project, :public, :repository) }
let(:input) { { project_path: project.full_path, name: new_branch, ref: ref } }
let(:new_branch) { 'new_branch' }
let(:ref) { 'master' }
let(:mutation) { graphql_mutation(:create_branch, input) }
let(:mutation_response) { graphql_mutation_response(:create_branch) }
context 'the user is not allowed to create a branch' 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 branch' do
before do
project.add_developer(current_user)
end
it 'creates a new branch' do
post_graphql_mutation(mutation, current_user: current_user)
expect(response).to have_gitlab_http_status(:success)
expect(mutation_response['branch']).to include(
'name' => new_branch,
'commit' => a_hash_including('id')
)
end
context 'when ref is not correct' do
let(:ref) { 'unknown' }
it_behaves_like 'a mutation that returns errors in the response',
errors: ['Invalid reference name: new_branch']
end
end
end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册