Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
011fd86e
Commit
011fd86e
authored
Aug 03, 2018
by
Lukas Eipert
Committed by
Dmitriy Zaporozhets
Aug 03, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Show License Management at pipeline level
parent
5678460d
Changes
20
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
395 additions
and
169 deletions
+395
-169
app/assets/javascripts/pipelines/pipeline_details_bundle.js
app/assets/javascripts/pipelines/pipeline_details_bundle.js
+0
-103
config/routes/project.rb
config/routes/project.rb
+1
-0
ee/app/assets/javascripts/pages/projects/pipelines/builds/index.js
...sets/javascripts/pages/projects/pipelines/builds/index.js
+2
-0
ee/app/assets/javascripts/pages/projects/pipelines/failures/index.js
...ts/javascripts/pages/projects/pipelines/failures/index.js
+2
-0
ee/app/assets/javascripts/pages/projects/pipelines/licenses/index.js
...ts/javascripts/pages/projects/pipelines/licenses/index.js
+2
-0
ee/app/assets/javascripts/pages/projects/pipelines/security/index.js
...ts/javascripts/pages/projects/pipelines/security/index.js
+2
-7
ee/app/assets/javascripts/pages/projects/pipelines/show/index.js
...assets/javascripts/pages/projects/pipelines/show/index.js
+11
-0
ee/app/assets/javascripts/pages/projects/pipelines/show/license_report.js
...vascripts/pages/projects/pipelines/show/license_report.js
+39
-0
ee/app/assets/javascripts/pages/projects/pipelines/show/security_report.js
...ascripts/pages/projects/pipelines/show/security_report.js
+87
-0
ee/app/assets/javascripts/pages/projects/pipelines/show/utils.js
...assets/javascripts/pages/projects/pipelines/show/utils.js
+24
-0
ee/app/assets/javascripts/vue_shared/license_management/mr_widget_license_report.vue
...ue_shared/license_management/mr_widget_license_report.vue
+21
-1
ee/app/assets/javascripts/vue_shared/security_reports/split_security_reports_app.vue
...ue_shared/security_reports/split_security_reports_app.vue
+22
-23
ee/app/controllers/ee/projects/pipelines_controller.rb
ee/app/controllers/ee/projects/pipelines_controller.rb
+9
-1
ee/app/helpers/ee/gitlab_routing_helper.rb
ee/app/helpers/ee/gitlab_routing_helper.rb
+5
-0
ee/app/views/projects/pipelines/_tabs_content.html.haml
ee/app/views/projects/pipelines/_tabs_content.html.haml
+22
-17
ee/app/views/projects/pipelines/_tabs_holder.html.haml
ee/app/views/projects/pipelines/_tabs_holder.html.haml
+10
-5
ee/changelogs/unreleased/5491-license-management-at-pipeline-ee.yml
...ogs/unreleased/5491-license-management-at-pipeline-ee.yml
+5
-0
ee/spec/controllers/projects/pipelines_controller_spec.rb
ee/spec/controllers/projects/pipelines_controller_spec.rb
+71
-6
ee/spec/features/projects/pipelines/pipeline_spec.rb
ee/spec/features/projects/pipelines/pipeline_spec.rb
+55
-4
locale/gitlab.pot
locale/gitlab.pot
+5
-2
No files found.
app/assets/javascripts/pipelines/pipeline_details_bundle.js
View file @
011fd86e
...
@@ -7,10 +7,6 @@ import pipelineGraph from './components/graph/graph_component.vue';
...
@@ -7,10 +7,6 @@ import pipelineGraph from './components/graph/graph_component.vue';
import
pipelineHeader
from
'
./components/header_component.vue
'
;
import
pipelineHeader
from
'
./components/header_component.vue
'
;
import
eventHub
from
'
./event_hub
'
;
import
eventHub
from
'
./event_hub
'
;
import
SecurityReportApp
from
'
ee/vue_shared/security_reports/split_security_reports_app.vue
'
;
// eslint-disable-line import/first
import
SastSummaryWidget
from
'
ee/pipelines/components/security_reports/report_summary_widget.vue
'
;
// eslint-disable-line import/first
import
createStore
from
'
ee/vue_shared/security_reports/store
'
;
// eslint-disable-line import/first
Vue
.
use
(
Translate
);
Vue
.
use
(
Translate
);
export
default
()
=>
{
export
default
()
=>
{
...
@@ -87,103 +83,4 @@ export default () => {
...
@@ -87,103 +83,4 @@ export default () => {
});
});
},
},
});
});
/**
* EE only
*/
const
securityTab
=
document
.
getElementById
(
'
js-security-report-app
'
);
const
sastSummary
=
document
.
querySelector
(
'
.js-sast-summary
'
);
const
updateBadgeCount
=
count
=>
{
const
badge
=
document
.
querySelector
(
'
.js-sast-counter
'
);
if
(
badge
.
textContent
!==
''
)
{
badge
.
textContent
=
parseInt
(
badge
.
textContent
,
10
)
+
count
;
}
else
{
badge
.
textContent
=
count
;
}
badge
.
classList
.
remove
(
'
hidden
'
);
};
// They are being rendered under the same condition
if
(
securityTab
&&
sastSummary
)
{
const
datasetOptions
=
securityTab
.
dataset
;
const
{
endpoint
,
blobPath
,
sastHelpPath
,
dependencyScanningEndpoint
,
dependencyScanningHelpPath
,
vulnerabilityFeedbackPath
,
vulnerabilityFeedbackHelpPath
,
dastEndpoint
,
sastContainerEndpoint
,
dastHelpPath
,
sastContainerHelpPath
,
}
=
datasetOptions
;
const
pipelineId
=
parseInt
(
datasetOptions
.
pipelineId
,
10
);
const
{
canCreateIssue
,
canCreateFeedback
}
=
datasetOptions
;
const
store
=
createStore
();
// Widget summary
// eslint-disable-next-line no-new
new
Vue
({
el
:
sastSummary
,
store
,
components
:
{
SastSummaryWidget
,
},
methods
:
{
updateBadge
(
count
)
{
updateBadgeCount
(
count
);
},
},
render
(
createElement
)
{
return
createElement
(
'
sast-summary-widget
'
,
{
on
:
{
updateBadgeCount
:
this
.
updateBadge
,
},
});
},
});
// Tab content
// eslint-disable-next-line no-new
new
Vue
({
el
:
securityTab
,
store
,
components
:
{
SecurityReportApp
,
},
methods
:
{
updateBadge
(
count
)
{
updateBadgeCount
(
count
);
},
},
render
(
createElement
)
{
return
createElement
(
'
security-report-app
'
,
{
props
:
{
headBlobPath
:
blobPath
,
sastHeadPath
:
endpoint
,
sastHelpPath
,
dependencyScanningHeadPath
:
dependencyScanningEndpoint
,
dependencyScanningHelpPath
,
vulnerabilityFeedbackPath
,
vulnerabilityFeedbackHelpPath
,
pipelineId
,
dastHeadPath
:
dastEndpoint
,
sastContainerHeadPath
:
sastContainerEndpoint
,
dastHelpPath
,
sastContainerHelpPath
,
canCreateFeedback
,
canCreateIssue
,
},
on
:
{
updateBadgeCount
:
this
.
updateBadge
,
},
});
},
});
}
};
};
config/routes/project.rb
View file @
011fd86e
...
@@ -232,6 +232,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
...
@@ -232,6 +232,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
get
:failures
get
:failures
get
:status
get
:status
get
:security
get
:security
get
:licenses
end
end
end
end
...
...
ee/app/assets/javascripts/pages/projects/pipelines/builds/index.js
0 → 100644
View file @
011fd86e
// /builds is an alias for show
import
'
../show/index
'
;
ee/app/assets/javascripts/pages/projects/pipelines/failures/index.js
0 → 100644
View file @
011fd86e
// /failures is an alias for show
import
'
../show/index
'
;
ee/app/assets/javascripts/pages/projects/pipelines/licenses/index.js
0 → 100644
View file @
011fd86e
// /licenses is an alias for show
import
'
../show/index
'
;
ee/app/assets/javascripts/pages/projects/pipelines/security/index.js
View file @
011fd86e
import
initPipelineDetails
from
'
~/pipelines/pipeline_details_bundle
'
;
// /security is an alias for show
import
initPipelines
from
'
~/pages/projects/pipelines/init_pipelines
'
;
import
'
../show/index
'
;
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
{
initPipelines
();
initPipelineDetails
();
});
ee/app/assets/javascripts/pages/projects/pipelines/show/index.js
0 → 100644
View file @
011fd86e
import
initPipelineDetails
from
'
~/pipelines/pipeline_details_bundle
'
;
import
initPipelines
from
'
~/pages/projects/pipelines/init_pipelines
'
;
import
initSecurityReport
from
'
./security_report
'
;
import
initLicenseReport
from
'
./license_report
'
;
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
{
initPipelines
();
initPipelineDetails
();
initSecurityReport
();
initLicenseReport
();
});
ee/app/assets/javascripts/pages/projects/pipelines/show/license_report.js
0 → 100644
View file @
011fd86e
import
Vue
from
'
vue
'
;
import
Translate
from
'
~/vue_shared/translate
'
;
import
LicenseReportApp
from
'
ee/vue_shared/license_management/mr_widget_license_report.vue
'
;
import
{
convertPermissionToBoolean
}
from
'
~/lib/utils/common_utils
'
;
import
{
updateBadgeCount
}
from
'
./utils
'
;
Vue
.
use
(
Translate
);
export
default
()
=>
{
const
licensesTab
=
document
.
getElementById
(
'
js-licenses-app
'
);
if
(
licensesTab
)
{
const
{
licenseHeadPath
,
canManageLicenses
,
apiUrl
}
=
licensesTab
.
dataset
;
// eslint-disable-next-line no-new
new
Vue
({
el
:
licensesTab
,
components
:
{
LicenseReportApp
,
},
render
(
createElement
)
{
return
createElement
(
'
license-report-app
'
,
{
props
:
{
apiUrl
,
headPath
:
licenseHeadPath
,
canManageLicenses
:
convertPermissionToBoolean
(
canManageLicenses
),
alwaysOpen
:
true
,
reportSectionClass
:
'
split-report-section
'
,
},
on
:
{
updateBadgeCount
:
(
count
)
=>
{
updateBadgeCount
(
'
.js-licenses-counter
'
,
count
);
},
},
});
},
});
}
};
ee/app/assets/javascripts/pages/projects/pipelines/show/security_report.js
0 → 100644
View file @
011fd86e
import
Vue
from
'
vue
'
;
import
Translate
from
'
~/vue_shared/translate
'
;
import
SecurityReportApp
from
'
ee/vue_shared/security_reports/split_security_reports_app.vue
'
;
import
SastSummaryWidget
from
'
ee/pipelines/components/security_reports/report_summary_widget.vue
'
;
import
createStore
from
'
ee/vue_shared/security_reports/store
'
;
import
{
convertPermissionToBoolean
}
from
'
~/lib/utils/common_utils
'
;
import
{
updateBadgeCount
}
from
'
./utils
'
;
Vue
.
use
(
Translate
);
export
default
()
=>
{
const
securityTab
=
document
.
getElementById
(
'
js-security-report-app
'
);
const
sastSummary
=
document
.
querySelector
(
'
.js-sast-summary
'
);
// They are being rendered under the same condition
if
(
securityTab
)
{
const
datasetOptions
=
securityTab
.
dataset
;
const
{
headBlobPath
,
sastHeadPath
,
sastHelpPath
,
dependencyScanningHeadPath
,
dependencyScanningHelpPath
,
vulnerabilityFeedbackPath
,
vulnerabilityFeedbackHelpPath
,
dastHeadPath
,
sastContainerHeadPath
,
dastHelpPath
,
sastContainerHelpPath
,
canCreateIssue
,
canCreateFeedback
,
}
=
datasetOptions
;
const
pipelineId
=
parseInt
(
datasetOptions
.
pipelineId
,
10
);
const
store
=
createStore
();
// Widget summary
if
(
sastSummary
)
{
// eslint-disable-next-line no-new
new
Vue
({
el
:
sastSummary
,
store
,
components
:
{
SastSummaryWidget
,
},
render
(
createElement
)
{
return
createElement
(
'
sast-summary-widget
'
);
},
});
}
// Tab content
// eslint-disable-next-line no-new
new
Vue
({
el
:
securityTab
,
store
,
components
:
{
SecurityReportApp
,
},
render
(
createElement
)
{
return
createElement
(
'
security-report-app
'
,
{
props
:
{
headBlobPath
,
sastHeadPath
,
sastHelpPath
,
dependencyScanningHeadPath
,
dependencyScanningHelpPath
,
vulnerabilityFeedbackPath
,
vulnerabilityFeedbackHelpPath
,
pipelineId
,
dastHeadPath
,
sastContainerHeadPath
,
dastHelpPath
,
sastContainerHelpPath
,
canCreateFeedback
:
convertPermissionToBoolean
(
canCreateFeedback
),
canCreateIssue
:
convertPermissionToBoolean
(
canCreateIssue
),
},
on
:
{
updateBadgeCount
:
(
count
)
=>
{
updateBadgeCount
(
'
.js-licenses-counter
'
,
count
);
},
},
});
},
});
}
};
ee/app/assets/javascripts/pages/projects/pipelines/show/utils.js
0 → 100644
View file @
011fd86e
/* eslint-disable import/prefer-default-export */
/**
*
* Sets the text content of a DOM element to a given value.
* If the given value is an integer,
* the text content will set to the value and will be shown.
* If the given value is not an integer,
* the text content will be emptied and the element will be hidden.
*
* The visibility of the element is based on the helper class `.hidden`
*
* @param selector {String} selector of the DOM element
* @param count {Number=} value for the DOM element
*/
export
const
updateBadgeCount
=
(
selector
,
count
)
=>
{
const
badge
=
document
.
querySelector
(
selector
);
if
(
Number
.
isInteger
(
count
))
{
badge
.
textContent
=
`
${
count
}
`
;
badge
.
classList
.
remove
(
'
hidden
'
);
}
else
{
badge
.
classList
.
add
(
'
hidden
'
);
badge
.
textContent
=
''
;
}
};
ee/app/assets/javascripts/vue_shared/license_management/mr_widget_license_report.vue
View file @
011fd86e
...
@@ -36,6 +36,16 @@ export default {
...
@@ -36,6 +36,16 @@ export default {
type
:
Boolean
,
type
:
Boolean
,
required
:
true
,
required
:
true
,
},
},
reportSectionClass
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
alwaysOpen
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
},
computed
:
{
computed
:
{
...
mapState
([
'
loadLicenseReportError
'
]),
...
mapState
([
'
loadLicenseReportError
'
]),
...
@@ -48,6 +58,14 @@ export default {
...
@@ -48,6 +58,14 @@ export default {
return
this
.
checkReportStatus
(
this
.
isLoading
,
this
.
loadLicenseReportError
);
return
this
.
checkReportStatus
(
this
.
isLoading
,
this
.
loadLicenseReportError
);
},
},
},
},
watch
:
{
licenseReport
()
{
this
.
$emit
(
'
updateBadgeCount
'
,
this
.
licenseReport
.
length
,
);
},
},
mounted
()
{
mounted
()
{
const
{
headPath
,
basePath
,
apiUrl
,
canManageLicenses
}
=
this
;
const
{
headPath
,
basePath
,
apiUrl
,
canManageLicenses
}
=
this
;
...
@@ -77,7 +95,9 @@ export default {
...
@@ -77,7 +95,9 @@ export default {
:neutral-issues=
"licenseReport"
:neutral-issues=
"licenseReport"
:has-issues=
"hasLicenseReportIssues"
:has-issues=
"hasLicenseReportIssues"
:component=
"$options.componentNames.LicenseIssueBody"
:component=
"$options.componentNames.LicenseIssueBody"
class=
"license-report-widget mr-widget-border-top"
:class=
"reportSectionClass"
:always-open=
"alwaysOpen"
class=
"license-report-widget"
/>
/>
</div>
</div>
</
template
>
</
template
>
ee/app/assets/javascripts/vue_shared/security_reports/split_security_reports_app.vue
View file @
011fd86e
...
@@ -110,6 +110,20 @@ export default {
...
@@ -110,6 +110,20 @@ export default {
dastText
()
{
dastText
()
{
return
this
.
summaryTextBuilder
(
'
DAST
'
,
this
.
dast
.
newIssues
.
length
);
return
this
.
summaryTextBuilder
(
'
DAST
'
,
this
.
dast
.
newIssues
.
length
);
},
},
issuesCount
()
{
return
(
this
.
dast
.
newIssues
.
length
+
this
.
dependencyScanning
.
newIssues
.
length
+
this
.
sastContainer
.
newIssues
.
length
+
this
.
sast
.
newIssues
.
length
);
},
},
watch
:
{
issuesCount
()
{
this
.
$emit
(
'
updateBadgeCount
'
,
this
.
issuesCount
);
},
},
},
created
()
{
created
()
{
// update the store with the received props
// update the store with the received props
...
@@ -123,33 +137,23 @@ export default {
...
@@ -123,33 +137,23 @@ export default {
if
(
this
.
sastHeadPath
)
{
if
(
this
.
sastHeadPath
)
{
this
.
setSastHeadPath
(
this
.
sastHeadPath
);
this
.
setSastHeadPath
(
this
.
sastHeadPath
);
this
.
fetchSastReports
()
this
.
fetchSastReports
().
catch
(()
=>
.
then
(()
=>
{
createFlash
(
s__
(
'
ciReport|There was an error loading SAST report
'
)),
this
.
$emit
(
'
updateBadgeCount
'
,
this
.
sast
.
newIssues
.
length
);
);
})
.
catch
(()
=>
createFlash
(
s__
(
'
ciReport|There was an error loading SAST report
'
)));
}
}
if
(
this
.
dependencyScanningHeadPath
)
{
if
(
this
.
dependencyScanningHeadPath
)
{
this
.
setDependencyScanningHeadPath
(
this
.
dependencyScanningHeadPath
);
this
.
setDependencyScanningHeadPath
(
this
.
dependencyScanningHeadPath
);
this
.
fetchDependencyScanningReports
()
this
.
fetchDependencyScanningReports
().
catch
(()
=>
.
then
(()
=>
{
createFlash
(
s__
(
'
ciReport|There was an error loading dependency scanning report
'
)),
this
.
$emit
(
'
updateBadgeCount
'
,
this
.
dependencyScanning
.
newIssues
.
length
);
);
})
.
catch
(()
=>
createFlash
(
s__
(
'
ciReport|There was an error loading dependency scanning report
'
)),
);
}
}
if
(
this
.
sastContainerHeadPath
)
{
if
(
this
.
sastContainerHeadPath
)
{
this
.
setSastContainerHeadPath
(
this
.
sastContainerHeadPath
);
this
.
setSastContainerHeadPath
(
this
.
sastContainerHeadPath
);
this
.
fetchSastContainerReports
()
this
.
fetchSastContainerReports
().
catch
(()
=>
.
then
(()
=>
{
this
.
$emit
(
'
updateBadgeCount
'
,
this
.
sastContainer
.
newIssues
.
length
);
})
.
catch
(()
=>
createFlash
(
s__
(
'
ciReport|There was an error loading container scanning report
'
)),
createFlash
(
s__
(
'
ciReport|There was an error loading container scanning report
'
)),
);
);
}
}
...
@@ -157,11 +161,7 @@ export default {
...
@@ -157,11 +161,7 @@ export default {
if
(
this
.
dastHeadPath
)
{
if
(
this
.
dastHeadPath
)
{
this
.
setDastHeadPath
(
this
.
dastHeadPath
);
this
.
setDastHeadPath
(
this
.
dastHeadPath
);
this
.
fetchDastReports
()
this
.
fetchDastReports
().
catch
(()
=>
.
then
(()
=>
{
this
.
$emit
(
'
updateBadgeCount
'
,
this
.
dast
.
newIssues
.
length
);
})
.
catch
(()
=>
createFlash
(
s__
(
'
ciReport|There was an error loading DAST report
'
)),
createFlash
(
s__
(
'
ciReport|There was an error loading DAST report
'
)),
);
);
}
}
...
@@ -184,7 +184,6 @@ export default {
...
@@ -184,7 +184,6 @@ export default {
'
setCanCreateIssuePermission
'
,
'
setCanCreateIssuePermission
'
,
'
setCanCreateFeedbackPermission
'
,
'
setCanCreateFeedbackPermission
'
,
]),
]),
summaryTextBuilder
(
type
,
issuesCount
=
0
)
{
summaryTextBuilder
(
type
,
issuesCount
=
0
)
{
if
(
issuesCount
===
0
)
{
if
(
issuesCount
===
0
)
{
return
sprintf
(
s__
(
'
ciReport|%{type} detected no vulnerabilities
'
),
{
return
sprintf
(
s__
(
'
ciReport|%{type} detected no vulnerabilities
'
),
{
...
...
ee/app/controllers/ee/projects/pipelines_controller.rb
View file @
011fd86e
...
@@ -4,7 +4,15 @@ module EE
...
@@ -4,7 +4,15 @@ module EE
extend
ActiveSupport
::
Concern
extend
ActiveSupport
::
Concern
def
security
def
security
if
pipeline
.
expose_sast_data?
if
pipeline
.
expose_security_dashboard?
render_show
else
redirect_to
pipeline_path
(
pipeline
)
end
end
def
licenses
if
pipeline
.
expose_license_management_data?
render_show
render_show
else
else
redirect_to
pipeline_path
(
pipeline
)
redirect_to
pipeline_path
(
pipeline
)
...
...
ee/app/helpers/ee/gitlab_routing_helper.rb
View file @
011fd86e
...
@@ -2,6 +2,7 @@ module EE
...
@@ -2,6 +2,7 @@ module EE
module
GitlabRoutingHelper
module
GitlabRoutingHelper
include
::
ProjectsHelper
include
::
ProjectsHelper
include
::
ApplicationSettingsHelper
include
::
ApplicationSettingsHelper
include
::
API
::
Helpers
::
RelatedResourcesHelpers
def
geo_primary_web_url
(
project_or_wiki
)
def
geo_primary_web_url
(
project_or_wiki
)
File
.
join
(
::
Gitlab
::
Geo
.
primary_node
.
url
,
project_or_wiki
.
full_path
)
File
.
join
(
::
Gitlab
::
Geo
.
primary_node
.
url
,
project_or_wiki
.
full_path
)
...
@@ -64,5 +65,9 @@ module EE
...
@@ -64,5 +65,9 @@ module EE
pipeline
.
license_management_artifact
,
pipeline
.
license_management_artifact
,
path:
Ci
::
Build
::
LICENSE_MANAGEMENT_FILE
)
path:
Ci
::
Build
::
LICENSE_MANAGEMENT_FILE
)
end
end
def
license_management_api_url
(
project
)
api_v4_projects_managed_licenses_path
(
id:
project
.
id
)
end
end
end
end
end
ee/app/views/projects/pipelines/_tabs_content.html.haml
View file @
011fd86e
-
pipeline
=
local_assigns
.
fetch
(
:pipeline
)
-
pipeline
=
local_assigns
.
fetch
(
:pipeline
)
-
project
=
local_assigns
.
fetch
(
:project
)
-
project
=
local_assigns
.
fetch
(
:project
)
-
return
unless
pipeline
.
expose_security_dashboard?
-
sast_endpoint
=
pipeline
.
expose_sast_data?
?
sast_artifact_url
(
pipeline
)
:
nil
-
sast_endpoint
=
pipeline
.
expose_sast_data?
?
sast_artifact_url
(
pipeline
)
:
nil
-
dependency_scanning_endpoint
=
pipeline
.
expose_dependency_scanning_data?
?
dependency_scanning_artifact_url
(
pipeline
)
:
nil
-
dependency_scanning_endpoint
=
pipeline
.
expose_dependency_scanning_data?
?
dependency_scanning_artifact_url
(
pipeline
)
:
nil
-
dast_endpoint
=
pipeline
.
expose_dast_data?
?
dast_artifact_url
(
pipeline
)
:
nil
-
dast_endpoint
=
pipeline
.
expose_dast_data?
?
dast_artifact_url
(
pipeline
)
:
nil
-
sast_container_endpoint
=
pipeline
.
expose_sast_container_data?
?
sast_container_artifact_url
(
pipeline
)
:
pipeline
.
expose_container_scanning_data?
?
container_scanning_artifact_url
(
pipeline
)
:
nil
-
sast_container_endpoint
=
pipeline
.
expose_sast_container_data?
?
sast_container_artifact_url
(
pipeline
)
:
pipeline
.
expose_container_scanning_data?
?
container_scanning_artifact_url
(
pipeline
)
:
nil
-
blob_path
=
project_blob_path
(
project
,
pipeline
.
sha
)
-
blob_path
=
project_blob_path
(
project
,
pipeline
.
sha
)
#js-tab-security
.build-security.tab-pane
-
if
pipeline
.
expose_security_dashboard?
#js-security-report-app
{
data:
{
endpoint:
sast_endpoint
,
#js-tab-security
.build-security.tab-pane
blob_path:
blob_path
,
#js-security-report-app
{
data:
{
head_blob_path:
blob_path
,
dependency_scanning_endpoint:
dependency_scanning_endpoint
,
sast_head_path:
sast_endpoint
,
dast_endpoint:
dast_endpoint
,
dependency_scanning_head_path:
dependency_scanning_endpoint
,
sast_container_endpoint:
sast_container_endpoint
,
dast_head_path:
dast_endpoint
,
pipeline_id:
pipeline
.
id
,
sast_container_head_path:
sast_container_endpoint
,
vulnerability_feedback_path:
project_vulnerability_feedback_index_path
(
project
),
pipeline_id:
pipeline
.
id
,
vulnerability_feedback_help_path:
help_page_path
(
"user/project/merge_requests/index"
,
anchor:
"interacting-with-security-reports-ultimate"
),
vulnerability_feedback_path:
project_vulnerability_feedback_index_path
(
project
),
sast_help_path:
help_page_path
(
'user/project/merge_requests/sast'
),
vulnerability_feedback_help_path:
help_page_path
(
"user/project/merge_requests/index"
,
anchor:
"interacting-with-security-reports-ultimate"
),
dependency_scanning_help_path:
help_page_path
(
'user/project/merge_requests/dependency_scanning'
),
sast_help_path:
help_page_path
(
'user/project/merge_requests/sast'
),
dast_help_path:
help_page_path
(
'user/project/merge_requests/dast'
),
dependency_scanning_help_path:
help_page_path
(
'user/project/merge_requests/dependency_scanning'
),
sast_container_help_path:
help_page_path
(
'user/project/merge_requests/sast_container'
),
dast_help_path:
help_page_path
(
'user/project/merge_requests/dast'
),
can_create_feedback:
can?
(
current_user
,
:admin_vulnerability_feedback
,
project
),
sast_container_help_path:
help_page_path
(
'user/project/merge_requests/sast_container'
),
can_create_issue:
show_new_issue_link?
(
project
)}
}
can_create_feedback:
can?
(
current_user
,
:admin_vulnerability_feedback
,
project
).
to_s
,
can_create_issue:
show_new_issue_link?
(
project
).
to_s
}
}
-
if
pipeline
.
expose_license_management_data?
#js-tab-licenses
.tab-pane
#js-licenses-app
{
data:
{
license_head_path:
pipeline
.
expose_license_management_data?
?
license_management_artifact_url
(
pipeline
)
:
nil
,
api_url:
license_management_api_url
(
project
),
can_manage_licenses:
can?
(
current_user
,
:admin_software_license_policy
,
project
).
to_s
}
}
ee/app/views/projects/pipelines/_tabs_holder.html.haml
View file @
011fd86e
-
pipeline
=
local_assigns
.
fetch
(
:pipeline
)
-
pipeline
=
local_assigns
.
fetch
(
:pipeline
)
-
project
=
local_assigns
.
fetch
(
:project
)
-
project
=
local_assigns
.
fetch
(
:project
)
-
return
unless
pipeline
.
expose_security_dashboard?
-
if
pipeline
.
expose_security_dashboard?
%li
.js-security-tab-link
=
link_to
security_project_pipeline_path
(
project
,
pipeline
),
data:
{
target:
'#js-tab-security'
,
action:
'security'
,
toggle:
'tab'
},
class:
'security-tab'
do
=
_
(
"Security"
)
%span
.badge.badge-pill.js-sast-counter.hidden
%li
.js-security-tab-link
-
if
pipeline
.
expose_license_management_data?
=
link_to
security_project_pipeline_path
(
project
,
pipeline
),
data:
{
target:
'#js-tab-security'
,
action:
'security'
,
toggle:
'tab'
},
class:
'security-tab'
do
%li
.js-licenses-tab-link
=
_
(
"Security report"
)
=
link_to
licenses_project_pipeline_path
(
project
,
pipeline
),
data:
{
target:
'#js-tab-licenses'
,
action:
'licenses'
,
toggle:
'tab'
},
class:
'licenses-tab'
do
%span
.badge.badge-pill.js-sast-counter.hidden
=
_
(
"Licenses"
)
%span
.badge.badge-pill.js-licenses-counter.hidden
ee/changelogs/unreleased/5491-license-management-at-pipeline-ee.yml
0 → 100644
View file @
011fd86e
---
title
:
Show License Management at pipeline level
merge_request
:
6688
author
:
type
:
added
ee/spec/controllers/projects/pipelines_controller_spec.rb
View file @
011fd86e
...
@@ -11,7 +11,7 @@ describe Projects::PipelinesController do
...
@@ -11,7 +11,7 @@ describe Projects::PipelinesController do
end
end
describe
'GET security'
do
describe
'GET security'
do
l
et
(
:pipeline
)
{
create
(
:ci_pipeline
,
project:
project
,
ref:
'master'
,
sha:
project
.
commit
.
id
)
}
s
et
(
:pipeline
)
{
create
(
:ci_pipeline
,
project:
project
,
ref:
'master'
,
sha:
project
.
commit
.
id
)
}
context
'with a sast artifact'
do
context
'with a sast artifact'
do
before
do
before
do
...
@@ -31,7 +31,7 @@ describe Projects::PipelinesController do
...
@@ -31,7 +31,7 @@ describe Projects::PipelinesController do
context
'with feature enabled'
do
context
'with feature enabled'
do
before
do
before
do
allow
(
License
).
to
receive
(
:feature_available?
).
and_return
(
true
)
stub_licensed_features
(
sast:
true
)
get
:security
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
pipeline
get
:security
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
pipeline
end
end
...
@@ -48,7 +48,6 @@ describe Projects::PipelinesController do
...
@@ -48,7 +48,6 @@ describe Projects::PipelinesController do
end
end
it
do
it
do
expect
(
response
).
to
have_gitlab_http_status
(
:redirect
)
expect
(
response
).
to
redirect_to
(
pipeline_path
(
pipeline
))
expect
(
response
).
to
redirect_to
(
pipeline_path
(
pipeline
))
end
end
end
end
...
@@ -57,13 +56,12 @@ describe Projects::PipelinesController do
...
@@ -57,13 +56,12 @@ describe Projects::PipelinesController do
context
'without sast artifact'
do
context
'without sast artifact'
do
context
'with feature enabled'
do
context
'with feature enabled'
do
before
do
before
do
allow
(
License
).
to
receive
(
:feature_available?
).
and_return
(
true
)
stub_licensed_features
(
sast:
true
)
get
:security
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
pipeline
get
:security
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
pipeline
end
end
it
do
it
do
expect
(
response
).
to
have_gitlab_http_status
(
:redirect
)
expect
(
response
).
to
redirect_to
(
pipeline_path
(
pipeline
))
expect
(
response
).
to
redirect_to
(
pipeline_path
(
pipeline
))
end
end
end
end
...
@@ -74,7 +72,74 @@ describe Projects::PipelinesController do
...
@@ -74,7 +72,74 @@ describe Projects::PipelinesController do
end
end
it
do
it
do
expect
(
response
).
to
have_gitlab_http_status
(
:redirect
)
expect
(
response
).
to
redirect_to
(
pipeline_path
(
pipeline
))
end
end
end
end
describe
'GET licenses'
do
set
(
:pipeline
)
{
create
(
:ci_pipeline
,
project:
project
,
ref:
'master'
,
sha:
project
.
commit
.
id
)
}
context
'with a license management artifact'
do
before
do
create
(
:ci_build
,
:success
,
:artifacts
,
name:
'license_management'
,
pipeline:
pipeline
,
options:
{
artifacts:
{
paths:
[
Ci
::
Build
::
LICENSE_MANAGEMENT_FILE
]
}
}
)
end
context
'with feature enabled'
do
before
do
stub_licensed_features
(
license_management:
true
)
get
:licenses
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
pipeline
end
it
do
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
response
).
to
render_template
:show
end
end
context
'with feature disabled'
do
before
do
get
:licenses
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
pipeline
end
it
do
expect
(
response
).
to
redirect_to
(
pipeline_path
(
pipeline
))
end
end
end
context
'without license management artifact'
do
context
'with feature enabled'
do
before
do
stub_licensed_features
(
license_management:
true
)
get
:licenses
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
pipeline
end
it
do
expect
(
response
).
to
redirect_to
(
pipeline_path
(
pipeline
))
end
end
context
'with feature disabled'
do
before
do
get
:licenses
,
namespace_id:
project
.
namespace
,
project_id:
project
,
id:
pipeline
end
it
do
expect
(
response
).
to
redirect_to
(
pipeline_path
(
pipeline
))
expect
(
response
).
to
redirect_to
(
pipeline_path
(
pipeline
))
end
end
end
end
...
...
ee/spec/features/projects/pipelines/pipeline_spec.rb
View file @
011fd86e
...
@@ -7,13 +7,15 @@ describe 'Pipeline', :js do
...
@@ -7,13 +7,15 @@ describe 'Pipeline', :js do
before
do
before
do
sign_in
(
user
)
sign_in
(
user
)
project
.
add_developer
(
user
)
project
.
add_developer
(
user
)
allow
(
License
).
to
receive
(
:feature_available?
).
and_return
(
true
)
end
end
describe
'GET /:project/pipelines/:id/security'
do
describe
'GET /:project/pipelines/:id/security'
do
let
(
:pipeline
)
{
create
(
:ci_pipeline
,
project:
project
,
ref:
'master'
,
sha:
project
.
commit
.
id
)
}
let
(
:pipeline
)
{
create
(
:ci_pipeline
,
project:
project
,
ref:
'master'
,
sha:
project
.
commit
.
id
)
}
before
do
stub_licensed_features
(
sast:
true
)
end
context
'with a sast artifact'
do
context
'with a sast artifact'
do
before
do
before
do
create
(
create
(
...
@@ -33,7 +35,7 @@ describe 'Pipeline', :js do
...
@@ -33,7 +35,7 @@ describe 'Pipeline', :js do
end
end
it
'shows jobs tab pane as active'
do
it
'shows jobs tab pane as active'
do
expect
(
page
).
to
have_content
(
'Security
report
'
)
expect
(
page
).
to
have_content
(
'Security'
)
expect
(
page
).
to
have_css
(
'#js-tab-security'
)
expect
(
page
).
to
have_css
(
'#js-tab-security'
)
end
end
...
@@ -49,7 +51,56 @@ describe 'Pipeline', :js do
...
@@ -49,7 +51,56 @@ describe 'Pipeline', :js do
it
'displays the pipeline graph'
do
it
'displays the pipeline graph'
do
expect
(
current_path
).
to
eq
(
pipeline_path
(
pipeline
))
expect
(
current_path
).
to
eq
(
pipeline_path
(
pipeline
))
expect
(
page
).
not_to
have_content
(
'Security report'
)
expect
(
page
).
not_to
have_content
(
'Security'
)
expect
(
page
).
to
have_selector
(
'.pipeline-visualization'
)
end
end
end
describe
'GET /:project/pipelines/:id/licenses'
do
let
(
:pipeline
)
{
create
(
:ci_pipeline
,
project:
project
,
ref:
'master'
,
sha:
project
.
commit
.
id
)
}
before
do
stub_licensed_features
(
license_management:
true
)
end
context
'with a license management artifact'
do
before
do
create
(
:ci_build
,
:success
,
:artifacts
,
name:
'license_management'
,
pipeline:
pipeline
,
options:
{
artifacts:
{
paths:
[
Ci
::
Build
::
LICENSE_MANAGEMENT_FILE
]
}
}
)
visit
licenses_project_pipeline_path
(
project
,
pipeline
)
end
it
'shows jobs tab pane as active'
do
expect
(
page
).
to
have_content
(
'Licenses'
)
expect
(
page
).
to
have_css
(
'#js-tab-licenses'
)
expect
(
find
(
'.js-licenses-counter'
)).
to
have_content
(
'0'
)
end
it
'shows security report section'
do
expect
(
page
).
to
have_content
(
'Loading license management report'
)
end
end
context
'without license management artifact'
do
before
do
visit
licenses_project_pipeline_path
(
project
,
pipeline
)
end
it
'displays the pipeline graph'
do
expect
(
current_path
).
to
eq
(
pipeline_path
(
pipeline
))
expect
(
page
).
not_to
have_content
(
'Licenses'
)
expect
(
page
).
to
have_selector
(
'.pipeline-visualization'
)
expect
(
page
).
to
have_selector
(
'.pipeline-visualization'
)
end
end
end
end
...
...
locale/gitlab.pot
View file @
011fd86e
...
@@ -3934,6 +3934,9 @@ msgstr ""
...
@@ -3934,6 +3934,9 @@ msgstr ""
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
msgstr ""
msgid "Licenses"
msgstr ""
msgid "LinkedIn"
msgid "LinkedIn"
msgstr ""
msgstr ""
...
@@ -5645,10 +5648,10 @@ msgstr ""
...
@@ -5645,10 +5648,10 @@ msgstr ""
msgid "Secret:"
msgid "Secret:"
msgstr ""
msgstr ""
msgid "Security
Dashboard
"
msgid "Security"
msgstr ""
msgstr ""
msgid "Security
report
"
msgid "Security
Dashboard
"
msgstr ""
msgstr ""
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment