Skip to content
Snippets Groups Projects
Commit fc4e77db authored by Patrick Cyiza's avatar Patrick Cyiza
Browse files

GraphQL project fields to get refs tipping at a commit

Changelog: added
parent 6aeef55f
No related branches found
No related tags found
2 merge requests!118700Remove refactor_vulnerability_filters feature flag,!116697GraphQL project fields for refs tipping at commit
# frozen_string_literal: true
module Resolvers
module Projects
class BranchesTippingAtCommitResolver < RefTippingAtCommitResolver
MAX_LIMIT = 100
calls_gitaly!
type ::Types::Projects::CommitParentNamesType, null: true
# the methode ref_prefix is implemented
# because this class is prepending Resolver::CommitParentNamesResolver module
# through it's parent ::Resolvers::RefTippingAtCommitResolver
def ref_prefix
Gitlab::Git::BRANCH_REF_PREFIX
end
end
end
end
# frozen_string_literal: true
module Resolvers
module Projects
module CommitParentNamesResolver
extend ActiveSupport::Concern
prepended do
argument :commit_sha, GraphQL::Types::String,
required: true,
description: 'Project commit SHA identifier. For example, `287774414568010855642518513f085491644061`.'
argument :limit, GraphQL::Types::Int,
required: false,
description: 'Number of branch names to return.'
alias_method :project, :object
end
def compute_limit(limit)
max = self.class::MAX_LIMIT
limit ? [limit, max].min : max
end
def get_tipping_refs(project, sha, limit: 0)
# the methode ref_prefix needs to be implemented in all classes prepending this module
refs = project.repository.refs_by_oid(oid: sha, ref_patterns: [ref_prefix], limit: limit)
refs.map { |n| n.delete_prefix(ref_prefix) }
end
end
end
end
# frozen_string_literal: true
module Resolvers
module Projects
class RefTippingAtCommitResolver < BaseResolver
include Gitlab::Graphql::Authorize::AuthorizeResource
prepend CommitParentNamesResolver
type ::Types::Projects::CommitParentNamesType, null: true
authorize :read_code
def resolve(commit_sha:, limit: nil)
final_limit = compute_limit(limit)
names = get_tipping_refs(project, commit_sha, limit: final_limit)
{
names: names,
total_count: nil
}
end
end
end
end
# frozen_string_literal: true
module Resolvers
module Projects
class TagsTippingAtCommitResolver < RefTippingAtCommitResolver
MAX_LIMIT = 100
calls_gitaly!
type ::Types::Projects::CommitParentNamesType, null: true
# the methode ref_prefix is implemented
# because this class is prepending Resolver::CommitParentNamesResolver module
# through it's parent ::Resolvers::RefTippingAtCommitResolver
def ref_prefix
Gitlab::Git::TAG_REF_PREFIX
end
end
end
end
......@@ -594,6 +594,16 @@ class ProjectType < BaseObject
authorize: :read_cycle_analytics,
alpha: { milestone: '15.10' }
field :tags_tipping_at_commit, ::Types::Projects::CommitParentNamesType,
null: true,
resolver: Resolvers::Projects::TagsTippingAtCommitResolver,
description: "Get tag names tipping at a given commit."
field :branches_tipping_at_commit, ::Types::Projects::CommitParentNamesType,
null: true,
resolver: Resolvers::Projects::BranchesTippingAtCommitResolver,
description: "Get branch names tipping at a given commit."
def timelog_categories
object.project_namespace.timelog_categories if Feature.enabled?(:timelog_categories)
end
......
# frozen_string_literal: true
module Types
module Projects
# rubocop: disable Graphql/AuthorizeTypes
class CommitParentNamesType < BaseObject
graphql_name 'CommitParentNames'
field :names, [GraphQL::Types::String], null: true, description: 'Names of the commit parent (branch or tag).'
field :total_count, GraphQL::Types::Int, null: true, description: 'Total of parent branches or tags.'
end
# rubocop: enable Graphql/AuthorizeTypes
end
end
......@@ -12439,6 +12439,15 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="commitpipelinesupdatedbefore"></a>`updatedBefore` | [`Time`](#time) | Pipelines updated before this date. |
| <a id="commitpipelinesusername"></a>`username` | [`String`](#string) | Filter pipelines by the user that triggered the pipeline. |
 
### `CommitParentNames`
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="commitparentnamesnames"></a>`names` | [`[String!]`](#string) | Names of the commit parent (branch or tag). |
| <a id="commitparentnamestotalcount"></a>`totalCount` | [`Int`](#int) | Total of parent branches or tags. |
### `ComplianceFramework`
 
Represents a ComplianceFramework associated with a Project.
......@@ -18692,6 +18701,19 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="projectboardsid"></a>`id` | [`BoardID`](#boardid) | Find a board by its ID. |
 
##### `Project.branchesTippingAtCommit`
Get branch names tipping at a given commit.
Returns [`CommitParentNames`](#commitparentnames).
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="projectbranchestippingatcommitcommitsha"></a>`commitSha` | [`String!`](#string) | Project commit SHA identifier. For example, `287774414568010855642518513f085491644061`. |
| <a id="projectbranchestippingatcommitlimit"></a>`limit` | [`Int`](#int) | Number of branch names to return. |
##### `Project.ciConfigVariables`
 
CI/CD config variable.
......@@ -19703,6 +19725,19 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="projectsnippetsids"></a>`ids` | [`[SnippetID!]`](#snippetid) | Array of global snippet IDs. For example, `gid://gitlab/ProjectSnippet/1`. |
| <a id="projectsnippetsvisibility"></a>`visibility` | [`VisibilityScopesEnum`](#visibilityscopesenum) | Visibility of the snippet. |
 
##### `Project.tagsTippingAtCommit`
Get tag names tipping at a given commit.
Returns [`CommitParentNames`](#commitparentnames).
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="projecttagstippingatcommitcommitsha"></a>`commitSha` | [`String!`](#string) | Project commit SHA identifier. For example, `287774414568010855642518513f085491644061`. |
| <a id="projecttagstippingatcommitlimit"></a>`limit` | [`Int`](#int) | Number of branch names to return. |
##### `Project.terraformState`
 
Find a single Terraform state by name.
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Query.project(fullPath).tagsTippingAtCommit(commitSha)', feature_category: :source_code_management do
include GraphqlHelpers
include Presentable
let_it_be(:project) { create(:project, :repository) }
let_it_be(:repository) { project.repository.raw }
let_it_be(:current_user) { project.first_owner }
let_it_be(:branches_names) { %w[master not-merged-branch v1.1.0] }
let(:post_query) { post_graphql(query, current_user: current_user) }
let(:path) { %w[project branchesTippingAtCommit names] }
let(:data) { graphql_data.dig(*path) }
let(:query) do
graphql_query_for(
:project,
{ fullPath: project.full_path },
query_graphql_field(:branchesTippingAtCommit, { commitSha: commit_sha }, :names)
)
end
context 'when commit exists and is tipping branches' do
let_it_be(:commit_sha) { repository.commit.id }
context 'with authorized user' do
it 'returns branches names tipping the commit' do
post_query
expect(data).to eq(branches_names)
end
end
context 'when user is not authorized' do
let(:current_user) { create(:user) }
it 'returns branches names tipping the commit' do
post_query
expect(data).to eq(nil)
end
end
end
context 'when commit does not exist' do
let(:commit_sha) { '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff4' }
it 'returns tags names tipping the commit' do
post_query
expect(data).to eq([])
end
end
context 'when commit exists but does not tip any branches' do
let(:commit_sha) { project.repository.commits(nil, { limit: 4 }).commits[2].id }
it 'returns tags names tipping the commit' do
post_query
expect(data).to eq([])
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Query.project(fullPath).tagsTippingAtCommit(commitSha)', feature_category: :source_code_management do
include GraphqlHelpers
include Presentable
let_it_be(:project) { create(:project, :repository) }
let_it_be(:repository) { project.repository.raw }
let_it_be(:current_user) { project.first_owner }
let_it_be(:tag_name) { 'v1.0.0' }
let(:post_query) { post_graphql(query, current_user: current_user) }
let(:path) { %w[project tagsTippingAtCommit names] }
let(:data) { graphql_data.dig(*path) }
let(:query) do
graphql_query_for(
:project,
{ fullPath: project.full_path },
query_graphql_field(:tagsTippingAtCommit, { commitSha: commit_sha }, :names)
)
end
context 'when commit exists and is tipping tags' do
let(:commit_sha) { repository.find_tag(tag_name).dereferenced_target.sha }
context 'with authorized user' do
it 'returns tags names tipping the commit' do
post_query
expect(data).to eq([tag_name])
end
end
context 'when user is not authorized' do
let(:current_user) { create(:user) }
it 'returns tags names tipping the commit' do
post_query
expect(data).to eq(nil)
end
end
end
context 'when commit does not exist' do
let(:commit_sha) { '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff4' }
it 'returns tags names tipping the commit' do
post_query
expect(data).to eq([])
end
end
context 'when commit exists but does not tip any tags' do
let(:commit_sha) { project.repository.commits(nil, { limit: 4 }).commits[2].id }
it 'returns tags names tipping the commit' do
post_query
expect(data).to eq([])
end
end
end
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