Commit 81a584df authored by Imre Farkas's avatar Imre Farkas

Merge branch '263144-commit-to-new-branch' into 'master'

Extend GraphQL API to commit to a new branch in a single operation

See merge request gitlab-org/gitlab!47203
parents 11d0c7c0 5d446e57
...@@ -13,7 +13,11 @@ module Mutations ...@@ -13,7 +13,11 @@ module Mutations
argument :branch, GraphQL::STRING_TYPE, argument :branch, GraphQL::STRING_TYPE,
required: true, required: true,
description: 'Name of the branch' description: 'Name of the branch to commit into, it can be a new branch'
argument :start_branch, GraphQL::STRING_TYPE,
required: false,
description: 'If on a new branch, name of the original branch'
argument :message, argument :message,
GraphQL::STRING_TYPE, GraphQL::STRING_TYPE,
...@@ -32,13 +36,13 @@ module Mutations ...@@ -32,13 +36,13 @@ module Mutations
authorize :push_code authorize :push_code
def resolve(project_path:, branch:, message:, actions:) def resolve(project_path:, branch:, message:, actions:, **args)
project = authorized_find!(full_path: project_path) project = authorized_find!(full_path: project_path)
attributes = { attributes = {
commit_message: message, commit_message: message,
branch_name: branch, branch_name: branch,
start_branch: branch, start_branch: args[:start_branch] || branch,
actions: actions.map { |action| action.to_h } actions: actions.map { |action| action.to_h }
} }
......
---
title: Extend GraphQL API to commit to a new branch in a single operation
merge_request: 47203
author:
type: changed
...@@ -2996,7 +2996,7 @@ input CommitCreateInput { ...@@ -2996,7 +2996,7 @@ input CommitCreateInput {
actions: [CommitAction!]! actions: [CommitAction!]!
""" """
Name of the branch Name of the branch to commit into, it can be a new branch
""" """
branch: String! branch: String!
...@@ -3014,6 +3014,11 @@ input CommitCreateInput { ...@@ -3014,6 +3014,11 @@ input CommitCreateInput {
Project full path the branch is associated with Project full path the branch is associated with
""" """
projectPath: ID! projectPath: ID!
"""
If on a new branch, name of the original branch
"""
startBranch: String
} }
""" """
......
...@@ -8114,7 +8114,7 @@ ...@@ -8114,7 +8114,7 @@
}, },
{ {
"name": "branch", "name": "branch",
"description": "Name of the branch", "description": "Name of the branch to commit into, it can be a new branch",
"type": { "type": {
"kind": "NON_NULL", "kind": "NON_NULL",
"name": null, "name": null,
...@@ -8126,6 +8126,16 @@ ...@@ -8126,6 +8126,16 @@
}, },
"defaultValue": null "defaultValue": null
}, },
{
"name": "startBranch",
"description": "If on a new branch, name of the original branch",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{ {
"name": "message", "name": "message",
"description": "Raw commit message", "description": "Raw commit message",
...@@ -5,8 +5,9 @@ require 'spec_helper' ...@@ -5,8 +5,9 @@ require 'spec_helper'
RSpec.describe Mutations::Commits::Create do RSpec.describe Mutations::Commits::Create do
subject(:mutation) { described_class.new(object: nil, context: context, field: nil) } 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(:user) { create(:user) }
let_it_be(:project) { create(:project, :public, :repository) }
let(:context) do let(:context) do
GraphQL::Query::Context.new( GraphQL::Query::Context.new(
query: OpenStruct.new(schema: nil), query: OpenStruct.new(schema: nil),
...@@ -18,9 +19,10 @@ RSpec.describe Mutations::Commits::Create do ...@@ -18,9 +19,10 @@ RSpec.describe Mutations::Commits::Create do
specify { expect(described_class).to require_graphql_authorizations(:push_code) } specify { expect(described_class).to require_graphql_authorizations(:push_code) }
describe '#resolve' do describe '#resolve' do
subject { mutation.resolve(project_path: project.full_path, branch: branch, message: message, actions: actions) } subject { mutation.resolve(project_path: project.full_path, branch: branch, start_branch: start_branch, message: message, actions: actions) }
let(:branch) { 'master' } let(:branch) { 'master' }
let(:start_branch) { nil }
let(:message) { 'Commit message' } let(:message) { 'Commit message' }
let(:actions) do let(:actions) do
[ [
...@@ -142,6 +144,29 @@ RSpec.describe Mutations::Commits::Create do ...@@ -142,6 +144,29 @@ RSpec.describe Mutations::Commits::Create do
end end
end end
context 'when branch does not exist and a start branch is provided' do
let(:branch) { 'my-branch' }
let(:start_branch) { 'master' }
let(:actions) do
[
{
action: 'create',
file_path: 'ANOTHER_FILE.md',
content: 'Bye'
}
]
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_file: true, new_path: 'ANOTHER_FILE.md')
])
end
end
context 'when message is not set' do context 'when message is not set' do
let(:message) { nil } let(:message) { nil }
......
...@@ -23,6 +23,18 @@ RSpec.describe 'Creation of a new commit' do ...@@ -23,6 +23,18 @@ RSpec.describe 'Creation of a new commit' do
let(:mutation) { graphql_mutation(:commit_create, input) } let(:mutation) { graphql_mutation(:commit_create, input) }
let(:mutation_response) { graphql_mutation_response(:commit_create) } let(:mutation_response) { graphql_mutation_response(:commit_create) }
shared_examples 'a commit is successful' do
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
end
context 'the user is not allowed to create a commit' do context 'the user is not allowed to create a commit' do
it_behaves_like 'a mutation that returns a top-level access error' it_behaves_like 'a mutation that returns a top-level access error'
end end
...@@ -32,14 +44,7 @@ RSpec.describe 'Creation of a new commit' do ...@@ -32,14 +44,7 @@ RSpec.describe 'Creation of a new commit' do
project.add_developer(current_user) project.add_developer(current_user)
end end
it 'creates a new commit' do it_behaves_like 'a commit is successful'
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 context 'when branch is not correct' do
let(:branch) { 'unknown' } let(:branch) { 'unknown' }
...@@ -47,5 +52,22 @@ RSpec.describe 'Creation of a new commit' do ...@@ -47,5 +52,22 @@ RSpec.describe 'Creation of a new commit' do
it_behaves_like 'a mutation that returns errors in the response', 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'] errors: ['You can only create or edit files when you are on a branch']
end end
context 'when branch is new, and a start_branch is defined' do
let(:input) { { project_path: project.full_path, branch: branch, start_branch: start_branch, message: message, actions: actions } }
let(:branch) { 'new-branch' }
let(:start_branch) { 'master' }
let(:actions) do
[
{
action: 'CREATE',
filePath: 'ANOTHER_FILE.md',
content: 'Bye'
}
]
end
it_behaves_like 'a commit is successful'
end
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment