Commit 2307db06 authored by Philip Cunningham's avatar Philip Cunningham Committed by Etienne Baqué

Provide branch information from dastProfiles

- Add dast_branch_selection ff disabled by default
- Add new field and associated type
- Add new policy
- Add new model
parent 54aadc79
...@@ -1244,6 +1244,7 @@ Represents a DAST Profile. ...@@ -1244,6 +1244,7 @@ Represents a DAST Profile.
| Field | Type | Description | | Field | Type | Description |
| ----- | ---- | ----------- | | ----- | ---- | ----------- |
| `branch` | DastProfileBranch | The associated branch. Will always return `null` if `dast_branch_selection` feature flag is disabled. |
| `dastScannerProfile` | DastScannerProfile | The associated scanner profile. | | `dastScannerProfile` | DastScannerProfile | The associated scanner profile. |
| `dastSiteProfile` | DastSiteProfile | The associated site profile. | | `dastSiteProfile` | DastSiteProfile | The associated site profile. |
| `description` | String | The description of the scan. | | `description` | String | The description of the scan. |
...@@ -1251,6 +1252,15 @@ Represents a DAST Profile. ...@@ -1251,6 +1252,15 @@ Represents a DAST Profile.
| `id` | DastProfileID! | ID of the profile. | | `id` | DastProfileID! | ID of the profile. |
| `name` | String | The name of the profile. | | `name` | String | The name of the profile. |
### DastProfileBranch
Represents a DAST Profile Branch.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `exists` | Boolean | Indicates whether or not the branch exists. |
| `name` | String | The name of the branch. |
### DastProfileCreatePayload ### DastProfileCreatePayload
Autogenerated return type of DastProfileCreate. Autogenerated return type of DastProfileCreate.
......
# frozen_string_literal: true
module Types
module Dast
class ProfileBranchType < BaseObject
graphql_name 'DastProfileBranch'
description 'Represents a DAST Profile Branch'
authorize :read_on_demand_scans
field :name, GraphQL::STRING_TYPE, null: true,
description: 'The name of the branch.',
calls_gitaly: true
field :exists, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Indicates whether or not the branch exists.',
calls_gitaly: true
end
end
end
...@@ -23,9 +23,20 @@ module Types ...@@ -23,9 +23,20 @@ module Types
field :dast_scanner_profile, DastScannerProfileType, null: true, field :dast_scanner_profile, DastScannerProfileType, null: true,
description: 'The associated scanner profile.' description: 'The associated scanner profile.'
field :branch, Dast::ProfileBranchType, null: true,
description: 'The associated branch. Will always return `null` ' \
'if `dast_branch_selection` feature flag is disabled.',
calls_gitaly: true
field :edit_path, GraphQL::STRING_TYPE, null: true, field :edit_path, GraphQL::STRING_TYPE, null: true,
description: 'Relative web path to the edit page of a profile.' description: 'Relative web path to the edit page of a profile.'
def branch
return unless Feature.enabled?(:dast_branch_selection, object.project, default_enabled: :yaml)
object.branch
end
def edit_path def edit_path
Gitlab::Routing.url_helpers.edit_project_on_demand_scan_path(object.project, object) Gitlab::Routing.url_helpers.edit_project_on_demand_scan_path(object.project, object)
end end
......
# frozen_string_literal: true
module Dast
Branch = Struct.new(:project) do
def name
project.default_branch
end
def exists
project.repository.branch_exists?(project.default_branch)
end
end
end
...@@ -20,6 +20,12 @@ module Dast ...@@ -20,6 +20,12 @@ module Dast
where(project_id: project_id) where(project_id: project_id)
end end
def branch
return unless project.repository.exists?
Dast::Branch.new(project)
end
private private
def project_ids_match def project_ids_match
......
# frozen_string_literal: true
module Dast
class BranchPolicy < BasePolicy
delegate { @subject.project }
end
end
---
name: dast_branch_selection
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55015
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/322672
milestone: '13.10'
type: development
group: group::dynamic analysis
default_enabled: false
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe GitlabSchema.types['DastProfileBranch'] do
include GraphqlHelpers
specify { expect(described_class.graphql_name).to eq('DastProfileBranch') }
specify { expect(described_class).to require_graphql_authorizations(:read_on_demand_scans) }
it { expect(described_class).to have_graphql_field(:name, calls_gitaly?: true) }
it { expect(described_class).to have_graphql_field(:exists, calls_gitaly?: true) }
end
...@@ -5,10 +5,10 @@ require 'spec_helper' ...@@ -5,10 +5,10 @@ require 'spec_helper'
RSpec.describe GitlabSchema.types['DastProfile'] do RSpec.describe GitlabSchema.types['DastProfile'] do
include GraphqlHelpers include GraphqlHelpers
let_it_be(:object) { create(:dast_profile) } let_it_be(:project) { create(:project, :repository) }
let_it_be(:project) { object.project } let_it_be(:object) { create(:dast_profile, project: project) }
let_it_be(:user) { create(:user, developer_projects: [project]) } let_it_be(:user) { create(:user, developer_projects: [project]) }
let_it_be(:fields) { %i[id name description dastSiteProfile dastScannerProfile editPath] } let_it_be(:fields) { %i[id name description dastSiteProfile dastScannerProfile branch editPath] }
specify { expect(described_class.graphql_name).to eq('DastProfile') } specify { expect(described_class.graphql_name).to eq('DastProfile') }
specify { expect(described_class).to require_graphql_authorizations(:read_on_demand_scans) } specify { expect(described_class).to require_graphql_authorizations(:read_on_demand_scans) }
...@@ -18,9 +18,28 @@ RSpec.describe GitlabSchema.types['DastProfile'] do ...@@ -18,9 +18,28 @@ RSpec.describe GitlabSchema.types['DastProfile'] do
end end
it { expect(described_class).to have_graphql_fields(fields) } it { expect(described_class).to have_graphql_fields(fields) }
it { expect(described_class).to have_graphql_field(:branch, calls_gitaly?: true) }
describe 'branch field' do
context 'when the feature flag is disabled' do
it 'resolves nil' do
stub_feature_flags(dast_branch_selection: false)
expect(resolve_field(:branch, object, current_user: user)).to eq(nil)
end
end
context 'when the feature flag is enabled' do
it 'correctly resolves the field' do
expected_result = Dast::Branch.new(project)
expect(resolve_field(:branch, object, current_user: user)).to eq(expected_result)
end
end
end
describe 'editPath field' do describe 'editPath field' do
it 'correctly renders the field' do it 'correctly resolves the field' do
expected_result = Gitlab::Routing.url_helpers.edit_project_on_demand_scan_path(project, object) expected_result = Gitlab::Routing.url_helpers.edit_project_on_demand_scan_path(project, object)
expect(resolve_field(:edit_path, object, current_user: user)).to eq(expected_result) expect(resolve_field(:edit_path, object, current_user: user)).to eq(expected_result)
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Dast::Branch do
let_it_be(:project) { create(:project) }
subject { described_class.new(project) }
describe 'instance methods' do
context 'when the associated project does not have a repository' do
describe '#name' do
it 'returns nil' do
expect(subject.name).to be_nil
end
end
describe '#exists' do
it 'returns false' do
expect(subject.exists).to eq(false)
end
end
end
context 'when the associated project has a repository' do
let_it_be(:project) { create(:project, :repository) }
describe '#name' do
it 'returns the default_branch' do
expect(subject.name).to eq(project.default_branch)
end
end
describe '#exists' do
it 'returns true' do
expect(subject.exists).to eq(true)
end
end
end
end
end
...@@ -76,4 +76,24 @@ RSpec.describe Dast::Profile, type: :model do ...@@ -76,4 +76,24 @@ RSpec.describe Dast::Profile, type: :model do
end end
end end
end end
describe 'instance methods' do
describe '#branch' do
context 'when the associated project does not have a repository' do
it 'returns nil' do
expect(subject.branch).to be_nil
end
end
context 'when the associated project has a repository' do
let_it_be(:project) { create(:project, :repository) }
subject { create(:dast_profile, project: project) }
it 'returns a Dast::Branch' do
expect(subject.branch).to be_a(Dast::Branch)
end
end
end
end
end end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Dast::BranchPolicy do
it_behaves_like 'a dast on-demand scan policy' do
let_it_be(:record) { Dast::Branch.new(project) }
end
end
...@@ -5,7 +5,7 @@ require 'spec_helper' ...@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'Query.project(fullPath).dastProfiles' do RSpec.describe 'Query.project(fullPath).dastProfiles' do
include GraphqlHelpers include GraphqlHelpers
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project, :repository) }
let_it_be(:current_user) { create(:user) } let_it_be(:current_user) { create(:user) }
let_it_be(:dast_profile1) { create(:dast_profile, project: project) } let_it_be(:dast_profile1) { create(:dast_profile, project: project) }
let_it_be(:dast_profile2) { create(:dast_profile, project: project) } let_it_be(:dast_profile2) { create(:dast_profile, project: project) }
...@@ -72,6 +72,12 @@ RSpec.describe 'Query.project(fullPath).dastProfiles' do ...@@ -72,6 +72,12 @@ RSpec.describe 'Query.project(fullPath).dastProfiles' do
end end
end end
it 'includes branch information' do
subject
expect(graphql_data_at(:project, :dast_profiles, :nodes, 0, 'branch')).to eq('name' => 'master', 'exists' => true)
end
context 'when the feature is disabled' do context 'when the feature is disabled' do
it 'returns no nodes' do it 'returns no nodes' do
stub_feature_flags(dast_saved_scans: false) stub_feature_flags(dast_saved_scans: false)
......
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