Commit 9d2bf4fb authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2018-10-22

# Conflicts:
#	locale/gitlab.pot

[ci skip]
parents 88ea34ed 3def0b3e
...@@ -19,6 +19,7 @@ Closes ...@@ -19,6 +19,7 @@ Closes
- [ ] [Apply the correct labels and milestone](https://docs.gitlab.com/ee/development/documentation/workflow.html#2-developer-s-role-in-the-documentation-process) - [ ] [Apply the correct labels and milestone](https://docs.gitlab.com/ee/development/documentation/workflow.html#2-developer-s-role-in-the-documentation-process)
- [ ] Crosslink the document from the higher-level index - [ ] Crosslink the document from the higher-level index
- [ ] Crosslink the document from other subject-related docs - [ ] Crosslink the document from other subject-related docs
- [ ] Feature moving tiers? Make sure the change is also reflected in [`features.yml`](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/features.yml)
- [ ] Correctly apply the product [badges](https://docs.gitlab.com/ee/development/documentation/styleguide.html#product-badges) and [tiers](https://docs.gitlab.com/ee/development/documentation/styleguide.html#gitlab-versions-and-tiers) - [ ] Correctly apply the product [badges](https://docs.gitlab.com/ee/development/documentation/styleguide.html#product-badges) and [tiers](https://docs.gitlab.com/ee/development/documentation/styleguide.html#gitlab-versions-and-tiers)
- [ ] [Port the MR to EE (or backport from CE)](https://docs.gitlab.com/ee/development/documentation/index.html#cherry-picking-from-ce-to-ee): _always recommended, required when the `ee-compat-check` job fails_ - [ ] [Port the MR to EE (or backport from CE)](https://docs.gitlab.com/ee/development/documentation/index.html#cherry-picking-from-ce-to-ee): _always recommended, required when the `ee-compat-check` job fails_
......
...@@ -72,7 +72,7 @@ This [documentation](doc/development/contributing/index.md#security-vulnerabilit ...@@ -72,7 +72,7 @@ This [documentation](doc/development/contributing/index.md#security-vulnerabilit
## Code of Conduct ## Code of Conduct
This [documentation](doc/development/contributing/index.md#code-of-conduct) has been moved. This [documentation](https://about.gitlab.com/contributing/code-of-conduct/) has been moved.
## Closing policy for issues and merge requests ## Closing policy for issues and merge requests
......
...@@ -40,7 +40,7 @@ export default function initCompareAutocomplete(limitTo = null, clickHandler = ( ...@@ -40,7 +40,7 @@ export default function initCompareAutocomplete(limitTo = null, clickHandler = (
}, },
selectable: true, selectable: true,
filterable: true, filterable: true,
filterRemote: true, filterRemote: !!$dropdown.data('refsUrl'),
fieldName: $dropdown.data('fieldName'), fieldName: $dropdown.data('fieldName'),
filterInput: 'input[type="search"]', filterInput: 'input[type="search"]',
renderRow: function(ref) { renderRow: function(ref) {
......
...@@ -25,14 +25,32 @@ export default { ...@@ -25,14 +25,32 @@ export default {
}, },
}, },
methods: { methods: {
createFile(target, file, isText) { isText(content, fileType) {
const knownBinaryFileTypes = ['image/'];
const knownTextFileTypes = ['text/'];
const isKnownBinaryFileType = knownBinaryFileTypes.find(type => fileType.includes(type));
const isKnownTextFileType = knownTextFileTypes.find(type => fileType.includes(type));
const asciiRegex = /^[ -~\t\n\r]+$/; // tests whether a string contains ascii characters only (ranges from space to tilde, tabs and new lines)
if (isKnownBinaryFileType) {
return false;
}
if (isKnownTextFileType) {
return true;
}
// if it's not a known file type, determine the type by evaluating the file contents
return asciiRegex.test(content);
},
createFile(target, file) {
const { name } = file; const { name } = file;
let { result } = target; let { result } = target;
const encodedContent = result.split('base64,')[1];
const rawContent = encodedContent ? atob(encodedContent) : '';
const isText = this.isText(rawContent, file.type);
if (!isText) { result = isText ? rawContent : encodedContent;
// eslint-disable-next-line prefer-destructuring
result = result.split('base64,')[1];
}
this.$emit('create', { this.$emit('create', {
name: `${this.path ? `${this.path}/` : ''}${name}`, name: `${this.path ? `${this.path}/` : ''}${name}`,
...@@ -43,15 +61,9 @@ export default { ...@@ -43,15 +61,9 @@ export default {
}, },
readFile(file) { readFile(file) {
const reader = new FileReader(); const reader = new FileReader();
const isText = file.type.match(/text.*/) !== null;
reader.addEventListener('load', e => this.createFile(e.target, file, isText), { once: true }); reader.addEventListener('load', e => this.createFile(e.target, file), { once: true });
if (isText) {
reader.readAsText(file);
} else {
reader.readAsDataURL(file); reader.readAsDataURL(file);
}
}, },
openFile() { openFile() {
Array.from(this.$refs.fileUpload.files).forEach(file => this.readFile(file)); Array.from(this.$refs.fileUpload.files).forEach(file => this.readFile(file));
......
...@@ -6,11 +6,9 @@ class Admin::ApplicationsController < Admin::ApplicationController ...@@ -6,11 +6,9 @@ class Admin::ApplicationsController < Admin::ApplicationController
before_action :set_application, only: [:show, :edit, :update, :destroy] before_action :set_application, only: [:show, :edit, :update, :destroy]
before_action :load_scopes, only: [:new, :create, :edit, :update] before_action :load_scopes, only: [:new, :create, :edit, :update]
# rubocop: disable CodeReuse/ActiveRecord
def index def index
@applications = Doorkeeper::Application.where("owner_id IS NULL") @applications = ApplicationsFinder.new.execute
end end
# rubocop: enable CodeReuse/ActiveRecord
def show def show
end end
...@@ -49,11 +47,9 @@ class Admin::ApplicationsController < Admin::ApplicationController ...@@ -49,11 +47,9 @@ class Admin::ApplicationsController < Admin::ApplicationController
private private
# rubocop: disable CodeReuse/ActiveRecord
def set_application def set_application
@application = Doorkeeper::Application.where("owner_id IS NULL").find(params[:id]) @application = ApplicationsFinder.new(id: params[:id]).execute
end end
# rubocop: enable CodeReuse/ActiveRecord
# Only allow a trusted parameter "white list" through. # Only allow a trusted parameter "white list" through.
def application_params def application_params
......
...@@ -9,7 +9,7 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -9,7 +9,7 @@ class Projects::BlobController < Projects::ApplicationController
include ActionView::Helpers::SanitizeHelper include ActionView::Helpers::SanitizeHelper
prepend_before_action :authenticate_user!, only: [:edit] prepend_before_action :authenticate_user!, only: [:edit]
before_action :set_request_format, only: [:edit, :show, :update] before_action :set_request_format, only: [:edit, :show, :update, :destroy]
before_action :require_non_empty_project, except: [:new, :create] before_action :require_non_empty_project, except: [:new, :create]
before_action :authorize_download_code! before_action :authorize_download_code!
......
# frozen_string_literal: true
class ApplicationsFinder
attr_reader :params
def initialize(params = {})
@params = params
end
def execute
applications = Doorkeeper::Application.where(owner_id: nil) # rubocop: disable CodeReuse/ActiveRecord
by_id(applications)
end
private
def by_id(applications)
return applications unless params[:id]
Doorkeeper::Application.find_by(id: params[:id]) # rubocop: disable CodeReuse/ActiveRecord
end
end
...@@ -21,17 +21,15 @@ module TimeHelper ...@@ -21,17 +21,15 @@ module TimeHelper
"#{from.to_s(:short)} - #{to.to_s(:short)}" "#{from.to_s(:short)} - #{to.to_s(:short)}"
end end
def duration_in_numbers(duration_in_seconds, allow_overflow = false) def duration_in_numbers(duration_in_seconds)
if allow_overflow
seconds = duration_in_seconds % 1.minute seconds = duration_in_seconds % 1.minute
minutes = (duration_in_seconds / 1.minute) % (1.hour / 1.minute) minutes = (duration_in_seconds / 1.minute) % (1.hour / 1.minute)
hours = duration_in_seconds / 1.hour hours = duration_in_seconds / 1.hour
"%02d:%02d:%02d" % [hours, minutes, seconds] if hours == 0
"%02d:%02d" % [minutes, seconds]
else else
time_format = duration_in_seconds < 1.hour ? "%M:%S" : "%H:%M:%S" "%02d:%02d:%02d" % [hours, minutes, seconds]
Time.at(duration_in_seconds).utc.strftime(time_format)
end end
end end
end end
...@@ -29,11 +29,15 @@ module Ci ...@@ -29,11 +29,15 @@ module Ci
metadata: :gzip, metadata: :gzip,
trace: :raw, trace: :raw,
junit: :gzip, junit: :gzip,
codequality: :gzip,
sast: :gzip, # All these file formats use `raw` as we need to store them uncompressed
dependency_scanning: :gzip, # for Frontend to fetch the files and do analysis
container_scanning: :gzip, # When they will be only used by backend, they can be `gzipped`.
dast: :gzip codequality: :raw,
sast: :raw,
dependency_scanning: :raw,
container_scanning: :raw,
dast: :raw
}.freeze }.freeze
belongs_to :project belongs_to :project
...@@ -103,7 +107,8 @@ module Ci ...@@ -103,7 +107,8 @@ module Ci
} }
FILE_FORMAT_ADAPTERS = { FILE_FORMAT_ADAPTERS = {
gzip: Gitlab::Ci::Build::Artifacts::GzipFileAdapter gzip: Gitlab::Ci::Build::Artifacts::Adapters::GzipStream,
raw: Gitlab::Ci::Build::Artifacts::Adapters::RawStream
}.freeze }.freeze
def valid_file_format? def valid_file_format?
......
...@@ -17,7 +17,7 @@ class MicrosoftTeamsService < ChatNotificationService ...@@ -17,7 +17,7 @@ class MicrosoftTeamsService < ChatNotificationService
'This service sends notifications about projects events to Microsoft Teams channels.<br /> 'This service sends notifications about projects events to Microsoft Teams channels.<br />
To set up this service: To set up this service:
<ol> <ol>
<li><a href="https://msdn.microsoft.com/en-us/microsoft-teams/connectors">Getting started with 365 Office Connectors For Microsoft Teams</a>.</li> <li><a href="https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/connectors/connectors-using#setting-up-a-custom-incoming-webhook">Setup a custom Incoming Webhook using Office 365 Connectors For Microsoft Teams</a>.</li>
<li>Paste the <strong>Webhook URL</strong> into the field below.</li> <li>Paste the <strong>Webhook URL</strong> into the field below.</li>
<li>Select events below to enable notifications.</li> <li>Select events below to enable notifications.</li>
</ol>' </ol>'
......
...@@ -30,12 +30,12 @@ module Ci ...@@ -30,12 +30,12 @@ module Ci
def create_reports(reports, expire_in:) def create_reports(reports, expire_in:)
return unless reports&.any? return unless reports&.any?
reports.map do |k, v| reports.map do |report_type, report_paths|
{ {
artifact_type: k.to_sym, artifact_type: report_type.to_sym,
artifact_format: :gzip, artifact_format: ::Ci::JobArtifact::TYPE_AND_FORMAT_PAIRS.fetch(report_type.to_sym),
name: ::Ci::JobArtifact::DEFAULT_FILE_NAMES[k.to_sym], name: ::Ci::JobArtifact::DEFAULT_FILE_NAMES.fetch(report_type.to_sym),
paths: v, paths: report_paths,
when: 'always', when: 'always',
expire_in: expire_in expire_in: expire_in
} }
......
...@@ -108,7 +108,7 @@ ...@@ -108,7 +108,7 @@
.btn.btn-default.has-tooltip{ disabled: true, .btn.btn-default.has-tooltip{ disabled: true,
title: job.scheduled_at } title: job.scheduled_at }
= sprite_icon('planning') = sprite_icon('planning')
= duration_in_numbers(job.execute_in, true) = duration_in_numbers(job.execute_in)
- confirmation_message = s_("DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes.") % { job_name: job.name } - confirmation_message = s_("DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes.") % { job_name: job.name }
= link_to play_project_job_path(job.project, job, return_to: request.original_url), = link_to play_project_job_path(job.project, job, return_to: request.original_url),
method: :post, method: :post,
......
---
title: Add Applications API endpoints for listing and deleting entries.
merge_request: 22296
author: Jean-Baptiste Vasseur
type: added
---
title: Drop `allow_overflow` option in `TimeHelper.duration_in_numbers`
merge_request: 52284
author:
type: changed
---
title: Remove base64 encoding from files that contain plain text
merge_request: 22425
author:
type: fixed
---
title: Enable frozen string for lib/gitlab/*.rb
merge_request:
author: gfyoung
type: performance
---
title: Fixed source project not filtering in merge request creation compare form
merge_request:
author:
type: fixed
---
title: 'Rails5: fix delete blob'
merge_request: 22456
author: Jasper Maes
type: other
---
title: Make all legacy security reports to use raw format
merge_request:
author:
type: changed
...@@ -7,8 +7,8 @@ Sidekiq::Testing.inline! do ...@@ -7,8 +7,8 @@ Sidekiq::Testing.inline! do
'https://gitlab.com/gitlab-org/gitlab-shell.git', 'https://gitlab.com/gitlab-org/gitlab-shell.git',
'https://gitlab.com/gnuwget/wget2.git', 'https://gitlab.com/gnuwget/wget2.git',
'https://gitlab.com/Commit451/LabCoat.git', 'https://gitlab.com/Commit451/LabCoat.git',
'https://github.com/documentcloud/underscore.git', 'https://github.com/jashkenas/underscore.git',
'https://github.com/twitter/flight.git', 'https://github.com/flightjs/flight.git',
'https://github.com/twitter/typeahead.js.git', 'https://github.com/twitter/typeahead.js.git',
'https://github.com/h5bp/html5-boilerplate.git', 'https://github.com/h5bp/html5-boilerplate.git',
'https://github.com/google/material-design-lite.git', 'https://github.com/google/material-design-lite.git',
...@@ -20,18 +20,18 @@ Sidekiq::Testing.inline! do ...@@ -20,18 +20,18 @@ Sidekiq::Testing.inline! do
'https://github.com/airbnb/javascript.git', 'https://github.com/airbnb/javascript.git',
'https://github.com/tessalt/echo-chamber-js.git', 'https://github.com/tessalt/echo-chamber-js.git',
'https://github.com/atom/atom.git', 'https://github.com/atom/atom.git',
'https://github.com/mattermost/platform.git', 'https://github.com/mattermost/mattermost-server.git',
'https://github.com/purifycss/purifycss.git', 'https://github.com/purifycss/purifycss.git',
'https://github.com/facebook/nuclide.git', 'https://github.com/facebook/nuclide.git',
'https://github.com/wbkd/awesome-d3.git', 'https://github.com/wbkd/awesome-d3.git',
'https://github.com/kilimchoi/engineering-blogs.git', 'https://github.com/kilimchoi/engineering-blogs.git',
'https://github.com/gilbarbara/logos.git', 'https://github.com/gilbarbara/logos.git',
'https://github.com/gaearon/redux.git', 'https://github.com/reduxjs/redux.git',
'https://github.com/awslabs/s2n.git', 'https://github.com/awslabs/s2n.git',
'https://github.com/arkency/reactjs_koans.git', 'https://github.com/arkency/reactjs_koans.git',
'https://github.com/twbs/bootstrap.git', 'https://github.com/twbs/bootstrap.git',
'https://github.com/chjj/ttystudio.git', 'https://github.com/chjj/ttystudio.git',
'https://github.com/DrBoolean/mostly-adequate-guide.git', 'https://github.com/MostlyAdequate/mostly-adequate-guide.git',
'https://github.com/octocat/Spoon-Knife.git', 'https://github.com/octocat/Spoon-Knife.git',
'https://github.com/opencontainers/runc.git', 'https://github.com/opencontainers/runc.git',
'https://github.com/googlesamples/android-topeka.git' 'https://github.com/googlesamples/android-topeka.git'
......
require './spec/support/sidekiq' require './spec/support/sidekiq'
class Gitlab::Seeder::Pipelines class Gitlab::Seeder::Pipelines
STAGES = %w[build test deploy notify] STAGES = %w[build test security deploy notify]
BUILDS = [ BUILDS = [
# build stage # build stage
{ name: 'build:linux', stage: 'build', status: :success, { name: 'build:linux', stage: 'build', status: :success,
...@@ -31,6 +31,16 @@ class Gitlab::Seeder::Pipelines ...@@ -31,6 +31,16 @@ class Gitlab::Seeder::Pipelines
{ name: 'spinach:osx', stage: 'test', status: :failed, allow_failure: true, { name: 'spinach:osx', stage: 'test', status: :failed, allow_failure: true,
queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago }, queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago },
# security stage
{ name: 'dast', stage: 'security', status: :success,
queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago },
{ name: 'sast', stage: 'security', status: :success,
queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago },
{ name: 'dependency_scanning', stage: 'security', status: :success,
queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago },
{ name: 'container_scanning', stage: 'security', status: :success,
queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago },
# deploy stage # deploy stage
{ name: 'staging', stage: 'deploy', environment: 'staging', status_event: :success, { name: 'staging', stage: 'deploy', environment: 'staging', status_event: :success,
options: { environment: { action: 'start', on_stop: 'stop staging' } }, options: { environment: { action: 'start', on_stop: 'stop staging' } },
...@@ -115,6 +125,11 @@ class Gitlab::Seeder::Pipelines ...@@ -115,6 +125,11 @@ class Gitlab::Seeder::Pipelines
setup_artifacts(build) setup_artifacts(build)
setup_test_reports(build) setup_test_reports(build)
if build.ref == build.project.default_branch
setup_security_reports_file(build)
else
setup_security_reports_legacy_archive(build)
end
setup_build_log(build) setup_build_log(build)
build.project.environments. build.project.environments.
...@@ -150,6 +165,55 @@ class Gitlab::Seeder::Pipelines ...@@ -150,6 +165,55 @@ class Gitlab::Seeder::Pipelines
end end
end end
def setup_security_reports_file(build)
return unless build.stage == "security"
# we have two sources: master and feature-branch
branch_name = build.ref == build.project.default_branch ?
'master' : 'feature-branch'
artifacts_cache_file(security_reports_path(branch_name, build.name)) do |file|
build.job_artifacts.build(
project: build.project,
file_type: build.name,
file_format: :raw,
file: file)
end
end
def setup_security_reports_legacy_archive(build)
return unless build.stage == "security"
# we have two sources: master and feature-branch
branch_name = build.ref == build.project.default_branch ?
'master' : 'feature-branch'
artifacts_cache_file(security_reports_archive_path(branch_name)) do |file|
build.job_artifacts.build(
project: build.project,
file_type: :archive,
file_format: :zip,
file: file)
end
# assign dummy metadata
artifacts_cache_file(artifacts_metadata_path) do |file|
build.job_artifacts.build(
project: build.project,
file_type: :metadata,
file_format: :gzip,
file: file)
end
build.options = {
artifacts: {
paths: [
Ci::JobArtifact::DEFAULT_FILE_NAMES.fetch(build.name.to_sym)
]
}
}
end
def setup_build_log(build) def setup_build_log(build)
if %w(running success failed).include?(build.status) if %w(running success failed).include?(build.status)
build.trace.set(FFaker::Lorem.paragraphs(6).join("\n\n")) build.trace.set(FFaker::Lorem.paragraphs(6).join("\n\n"))
...@@ -201,6 +265,15 @@ class Gitlab::Seeder::Pipelines ...@@ -201,6 +265,15 @@ class Gitlab::Seeder::Pipelines
Rails.root + 'spec/fixtures/junit/junit.xml.gz' Rails.root + 'spec/fixtures/junit/junit.xml.gz'
end end
def security_reports_archive_path(branch)
Rails.root.join('spec', 'fixtures', 'security-reports', branch + '.zip')
end
def security_reports_path(branch, name)
file_name = Ci::JobArtifact::DEFAULT_FILE_NAMES.fetch(name.to_sym)
Rails.root.join('spec', 'fixtures', 'security-reports', branch, file_name)
end
def artifacts_cache_file(file_path) def artifacts_cache_file(file_path)
file = Tempfile.new("artifacts") file = Tempfile.new("artifacts")
file.close file.close
......
...@@ -4,12 +4,12 @@ ...@@ -4,12 +4,12 @@
[ce-8160]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8160 [ce-8160]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8160
Only admin user can use the Applications API.
## Create a application ## Create a application
Create a application by posting a JSON payload. Create a application by posting a JSON payload.
User must be admin to do that.
Returns `200` if the request succeeds. Returns `200` if the request succeeds.
``` ```
...@@ -30,8 +30,55 @@ Example response: ...@@ -30,8 +30,55 @@ Example response:
```json ```json
{ {
"id":1,
"application_id": "5832fc6e14300a0d962240a8144466eef4ee93ef0d218477e55f11cf12fc3737", "application_id": "5832fc6e14300a0d962240a8144466eef4ee93ef0d218477e55f11cf12fc3737",
"application_name": "MyApplication",
"secret": "ee1dd64b6adc89cf7e2c23099301ccc2c61b441064e9324d963c46902a85ec34", "secret": "ee1dd64b6adc89cf7e2c23099301ccc2c61b441064e9324d963c46902a85ec34",
"callback_url": "http://redirect.uri" "callback_url": "http://redirect.uri"
} }
``` ```
## List all applications
List all registered applications.
```
GET /applications
```
```bash
curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/applications
```
Example response:
```json
[
{
"id":1,
"application_id": "5832fc6e14300a0d962240a8144466eef4ee93ef0d218477e55f11cf12fc3737",
"application_name": "MyApplication",
"callback_url": "http://redirect.uri"
}
]
```
> Note: the `secret` value will not be exposed by this API.
## Delete an application
Delete a specific application.
Returns `204` if the request succeeds.
```
DELETE /applications/:id
```
Parameters:
- `id` (required) - The id of the application (not the application_id)
```bash
curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/applications/:id
```
...@@ -14,7 +14,7 @@ GET /projects/:id/repository/tree ...@@ -14,7 +14,7 @@ GET /projects/:id/repository/tree
Parameters: Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user - `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `path` (optional) - The path inside repository. Used to get contend of subdirectories - `path` (optional) - The path inside repository. Used to get content of subdirectories
- `ref` (optional) - The name of a repository branch or tag or if not given the default branch - `ref` (optional) - The name of a repository branch or tag or if not given the default branch
- `recursive` (optional) - Boolean value used to get a recursive tree (false by default) - `recursive` (optional) - Boolean value used to get a recursive tree (false by default)
......
...@@ -25,7 +25,7 @@ before_script: ...@@ -25,7 +25,7 @@ before_script:
- apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 642AC823 - apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 642AC823
- apt-get update -y - apt-get update -y
- apt-get install sbt -y - apt-get install sbt -y
- sbt sbt-version - sbt sbtVersion
test: test:
stage: test stage: test
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
Thank you for your interest in contributing to GitLab. This guide details how Thank you for your interest in contributing to GitLab. This guide details how
to contribute to GitLab in a way that is easy for everyone. to contribute to GitLab in a way that is easy for everyone.
We want to create a welcoming environment for everyone who is interested in contributing. Please visit our [Code of Conduct page](https://about.gitlab.com/contributing/code-of-conduct) to learn more about our committment to an open and welcoming environment.
For a first-time step-by-step guide to the contribution process, please see For a first-time step-by-step guide to the contribution process, please see
["Contributing to GitLab"](https://about.gitlab.com/contributing/). ["Contributing to GitLab"](https://about.gitlab.com/contributing/).
...@@ -28,80 +30,6 @@ Please report suspected security vulnerabilities in private to ...@@ -28,80 +30,6 @@ Please report suspected security vulnerabilities in private to
Please do **NOT** create publicly viewable issues for suspected security Please do **NOT** create publicly viewable issues for suspected security
vulnerabilities. vulnerabilities.
## Code of conduct
### Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
### Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
### Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
### Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
### Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at conduct@gitlab.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
### Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
## Closing policy for issues and merge requests ## Closing policy for issues and merge requests
GitLab is a popular open source project and the capacity to deal with issues GitLab is a popular open source project and the capacity to deal with issues
......
...@@ -472,6 +472,37 @@ GitLab uses [factory_bot] as a test fixture replacement. ...@@ -472,6 +472,37 @@ GitLab uses [factory_bot] as a test fixture replacement.
All fixtures should be be placed under `spec/fixtures/`. All fixtures should be be placed under `spec/fixtures/`.
### Repositories
Testing some functionality, e.g., merging a merge request, requires a git
repository with a certain state to be present in the test environment. GitLab
maintains the [gitlab-test](https://gitlab.com/gitlab-org/gitlab-test)
repository for certain common cases - you can ensure a copy of the repository is
used with the `:repository` trait for project factories:
```ruby
let(:project) { create(:project, :repository) }
```
Where you can, consider using the `:custom_repo` trait instead of `:repository`.
This allows you to specify exactly what files will appear in the `master` branch
of the project's repository. For example:
```ruby
let(:project) do
create(
:project, :custom_repo,
files: {
'README.md' => 'Content here',
'foo/bar/baz.txt' => 'More content here'
}
)
end
```
This will create a repository containing two files, with default permissions and
the specified content.
### Config ### Config
RSpec config files are files that change the RSpec config (i.e. RSpec config files are files that change the RSpec config (i.e.
......
...@@ -24,6 +24,22 @@ module API ...@@ -24,6 +24,22 @@ module API
render_validation_error! application render_validation_error! application
end end
end end
desc 'Get applications' do
success Entities::Application
end
get do
applications = ApplicationsFinder.new.execute
present applications, with: Entities::Application
end
desc 'Delete an application'
delete ':id' do
application = ApplicationsFinder.new(params).execute
application.destroy
status 204
end
end end
end end
end end
...@@ -1440,7 +1440,9 @@ module API ...@@ -1440,7 +1440,9 @@ module API
end end
class Application < Grape::Entity class Application < Grape::Entity
expose :id
expose :uid, as: :application_id expose :uid, as: :application_id
expose :name, as: :application_name
expose :redirect_uri, as: :callback_url expose :redirect_uri, as: :callback_url
end end
......
...@@ -164,7 +164,7 @@ module Backup ...@@ -164,7 +164,7 @@ module Backup
def tar_version def tar_version
tar_version, _ = Gitlab::Popen.popen(%w(tar --version)) tar_version, _ = Gitlab::Popen.popen(%w(tar --version))
tar_version.force_encoding('locale').split("\n").first tar_version.dup.force_encoding('locale').split("\n").first
end end
def skipped?(item) def skipped?(item)
......
# frozen_string_literal: true
# Gitlab::Access module # Gitlab::Access module
# #
# Define allowed roles that can be used # Define allowed roles that can be used
......
# frozen_string_literal: true
module Gitlab module Gitlab
# This class implements a simple rate limiter that can be used to throttle # This class implements a simple rate limiter that can be used to throttle
# certain actions. Unlike Rack Attack and Rack::Throttle, which operate at # certain actions. Unlike Rack Attack and Rack::Throttle, which operate at
......
# frozen_string_literal: true
module Gitlab module Gitlab
module Allowable module Allowable
def can?(*args) def can?(*args)
......
# frozen_string_literal: true
module Gitlab module Gitlab
class AppLogger < Gitlab::Logger class AppLogger < Gitlab::Logger
def self.file_name_noext def self.file_name_noext
......
# frozen_string_literal: true
require 'asciidoctor' require 'asciidoctor'
require 'asciidoctor/converter/html5' require 'asciidoctor/converter/html5'
require "asciidoctor-plantuml" require "asciidoctor-plantuml"
......
# frozen_string_literal: true
module Gitlab module Gitlab
module Auth module Auth
MissingPersonalAccessTokenError = Class.new(StandardError) MissingPersonalAccessTokenError = Class.new(StandardError)
......
# frozen_string_literal: true
module Gitlab module Gitlab
module BackgroundMigration module BackgroundMigration
def self.queue def self.queue
......
# frozen_string_literal: true
# This is a base controller for doorkeeper. # This is a base controller for doorkeeper.
# It adds the `can?` helper used in the views. # It adds the `can?` helper used in the views.
module Gitlab module Gitlab
......
# frozen_string_literal: true
module Gitlab module Gitlab
class Blame class Blame
attr_accessor :blob, :commit attr_accessor :blob, :commit
......
# frozen_string_literal: true
# This has been extracted from https://github.com/github/linguist/blob/master/lib/linguist/blob_helper.rb # This has been extracted from https://github.com/github/linguist/blob/master/lib/linguist/blob_helper.rb
module Gitlab module Gitlab
module BlobHelper module BlobHelper
......
# frozen_string_literal: true
module Gitlab module Gitlab
class BuildAccess < UserAccess class BuildAccess < UserAccess
attr_accessor :user, :project attr_accessor :user, :project
......
# frozen_string_literal: true
module Gitlab module Gitlab
class ChangesList class ChangesList
include Enumerable include Enumerable
......
# frozen_string_literal: true
require 'json' require 'json'
module Gitlab module Gitlab
......
module Gitlab
module Ci
module Build
module Artifacts
module Adapters
class GzipStream
attr_reader :stream
InvalidStreamError = Class.new(StandardError)
def initialize(stream)
raise InvalidStreamError, "Stream is required" unless stream
@stream = stream
end
def each_blob
stream.seek(0)
until stream.eof?
gzip(stream) do |gz|
yield gz.read, gz.orig_name
unused = gz.unused&.length.to_i
# pos has already reached to EOF at the moment
# We rewind the pos to the top of unused files
# to read next gzip stream, to support multistream archives
# https://golang.org/src/compress/gzip/gunzip.go#L117
stream.seek(-unused, IO::SEEK_CUR)
end
end
end
private
def gzip(stream, &block)
gz = Zlib::GzipReader.new(stream)
yield(gz)
rescue Zlib::Error => e
raise InvalidStreamError, e.message
ensure
gz&.finish
end
end
end
end
end
end
end
module Gitlab
module Ci
module Build
module Artifacts
module Adapters
class RawStream
attr_reader :stream
InvalidStreamError = Class.new(StandardError)
def initialize(stream)
raise InvalidStreamError, "Stream is required" unless stream
@stream = stream
end
def each_blob
stream.seek(0)
yield(stream.read, 'raw') unless stream.eof?
end
end
end
end
end
end
end
module Gitlab
module Ci
module Build
module Artifacts
class GzipFileAdapter
attr_reader :stream
InvalidStreamError = Class.new(StandardError)
def initialize(stream)
raise InvalidStreamError, "Stream is required" unless stream
@stream = stream
end
def each_blob
stream.seek(0)
until stream.eof?
gzip(stream) do |gz|
yield gz.read, gz.orig_name
unused = gz.unused&.length.to_i
# pos has already reached to EOF at the moment
# We rewind the pos to the top of unused files
# to read next gzip stream, to support multistream archives
# https://golang.org/src/compress/gzip/gunzip.go#L117
stream.seek(-unused, IO::SEEK_CUR)
end
end
end
private
def gzip(stream, &block)
gz = Zlib::GzipReader.new(stream)
yield(gz)
rescue Zlib::Error => e
raise InvalidStreamError, e.message
ensure
gz&.finish
end
end
end
end
end
end
...@@ -29,7 +29,7 @@ module Gitlab ...@@ -29,7 +29,7 @@ module Gitlab
def execute_in def execute_in
remaining_seconds = [0, subject.scheduled_at - Time.now].max remaining_seconds = [0, subject.scheduled_at - Time.now].max
duration_in_numbers(remaining_seconds, true) duration_in_numbers(remaining_seconds)
end end
end end
end end
......
# frozen_string_literal: true
module Gitlab module Gitlab
# For backwards compatibility, generic CI (which is a build without a user) is # For backwards compatibility, generic CI (which is a build without a user) is
# allowed to :build_download_code without any other checks. # allowed to :build_download_code without any other checks.
......
# frozen_string_literal: true
module Gitlab module Gitlab
class ClosingIssueExtractor class ClosingIssueExtractor
ISSUE_CLOSING_REGEX = begin ISSUE_CLOSING_REGEX = begin
......
# frozen_string_literal: true
module Gitlab module Gitlab
# Module containing GitLab's syntax color scheme definitions and helper # Module containing GitLab's syntax color scheme definitions and helper
# methods for accessing them. # methods for accessing them.
......
# frozen_string_literal: true
module Gitlab::ConfigHelper module Gitlab::ConfigHelper
def gitlab_config_features def gitlab_config_features
Gitlab.config.gitlab.default_projects_features Gitlab.config.gitlab.default_projects_features
......
# frozen_string_literal: true
module Gitlab module Gitlab
class ContributionsCalendar class ContributionsCalendar
attr_reader :contributor attr_reader :contributor
......
# frozen_string_literal: true
module Gitlab module Gitlab
class Contributor class Contributor
attr_accessor :email, :name, :commits, :additions, :deletions attr_accessor :email, :name, :commits, :additions, :deletions
......
# frozen_string_literal: true
module Gitlab module Gitlab
class CrossProjectAccess class CrossProjectAccess
class << self class << self
......
# frozen_string_literal: true
module Gitlab module Gitlab
module CurrentSettings module CurrentSettings
class << self class << self
......
# frozen_string_literal: true
module Gitlab module Gitlab
class Daemon class Daemon
def self.initialize_instance(*args) def self.initialize_instance(*args)
......
# frozen_string_literal: true
module Gitlab module Gitlab
module Database module Database
# The max value of INTEGER type is the same between MySQL and PostgreSQL: # The max value of INTEGER type is the same between MySQL and PostgreSQL:
...@@ -109,11 +111,11 @@ module Gitlab ...@@ -109,11 +111,11 @@ module Gitlab
order = "#{field} #{direction}" order = "#{field} #{direction}"
if postgresql? if postgresql?
order << ' NULLS LAST' order = "#{order} NULLS LAST"
else else
# `field IS NULL` will be `0` for non-NULL columns and `1` for NULL # `field IS NULL` will be `0` for non-NULL columns and `1` for NULL
# columns. In the (default) ascending order, `0` comes first. # columns. In the (default) ascending order, `0` comes first.
order.prepend("#{field} IS NULL, ") if direction == 'ASC' order = "#{field} IS NULL, #{order}" if direction == 'ASC'
end end
order order
...@@ -123,11 +125,11 @@ module Gitlab ...@@ -123,11 +125,11 @@ module Gitlab
order = "#{field} #{direction}" order = "#{field} #{direction}"
if postgresql? if postgresql?
order << ' NULLS FIRST' order = "#{order} NULLS FIRST"
else else
# `field IS NULL` will be `0` for non-NULL columns and `1` for NULL # `field IS NULL` will be `0` for non-NULL columns and `1` for NULL
# columns. In the (default) ascending order, `0` comes first. # columns. In the (default) ascending order, `0` comes first.
order.prepend("#{field} IS NULL, ") if direction == 'DESC' order = "#{field} IS NULL, #{order}" if direction == 'DESC'
end end
order order
...@@ -198,7 +200,7 @@ module Gitlab ...@@ -198,7 +200,7 @@ module Gitlab
EOF EOF
if return_ids if return_ids
sql << 'RETURNING id' sql = "#{sql}RETURNING id"
end end
result = connection.execute(sql) result = connection.execute(sql)
......
# frozen_string_literal: true
module Gitlab module Gitlab
module DependencyLinker module DependencyLinker
LINKERS = [ LINKERS = [
......
# frozen_string_literal: true
module Gitlab module Gitlab
# Checks if a set of migrations requires downtime or not. # Checks if a set of migrations requires downtime or not.
class DowntimeCheck class DowntimeCheck
......
# frozen_string_literal: true
# rubocop: disable Rails/Output # rubocop: disable Rails/Output
module Gitlab module Gitlab
# Checks if a set of migrations requires downtime or not. # Checks if a set of migrations requires downtime or not.
......
# frozen_string_literal: true
module Gitlab module Gitlab
module Emoji module Emoji
extend self extend self
......
# frozen_string_literal: true
module Gitlab module Gitlab
module EncodingHelper module EncodingHelper
extend self extend self
......
# frozen_string_literal: true
module Gitlab module Gitlab
module Environment module Environment
def self.hostname def self.hostname
......
# frozen_string_literal: true
module Gitlab module Gitlab
class EnvironmentLogger < Gitlab::Logger class EnvironmentLogger < Gitlab::Logger
def self.file_name_noext def self.file_name_noext
......
# frozen_string_literal: true
require 'securerandom' require 'securerandom'
module Gitlab module Gitlab
......
# frozen_string_literal: true
module Gitlab module Gitlab
# This module provides helper methods which are intregrated with GitLab::ExclusiveLease # This module provides helper methods which are intregrated with GitLab::ExclusiveLease
module ExclusiveLeaseHelpers module ExclusiveLeaseHelpers
......
# frozen_string_literal: true
# This class extends an OpenStruct object by adding predicate methods to mimic # This class extends an OpenStruct object by adding predicate methods to mimic
# ActiveRecord access. We rely on the initial values being true or false to # ActiveRecord access. We rely on the initial values being true or false to
# determine whether to define a predicate method because for a newly-added # determine whether to define a predicate method because for a newly-added
......
# frozen_string_literal: true
module Gitlab module Gitlab
class Favicon class Favicon
class << self class << self
......
# frozen_string_literal: true
require 'set' require 'set'
module Gitlab module Gitlab
......
# frozen_string_literal: true
# This class finds files in a repository by name and content # This class finds files in a repository by name and content
# the result is joined and sorted by file name # the result is joined and sorted by file name
module Gitlab module Gitlab
......
# frozen_string_literal: true
# Builds the markdown link of a file # Builds the markdown link of a file
# It needs the methods filename and secure_url (final destination url) to be defined. # It needs the methods filename and secure_url (final destination url) to be defined.
module Gitlab module Gitlab
...@@ -8,7 +10,7 @@ module Gitlab ...@@ -8,7 +10,7 @@ module Gitlab
return unless name = markdown_name return unless name = markdown_name
markdown = "[#{name.gsub(']', '\\]')}](#{secure_url})" markdown = "[#{name.gsub(']', '\\]')}](#{secure_url})"
markdown.prepend("!") if image_or_video? || dangerous? markdown = "!#{markdown}" if image_or_video? || dangerous?
markdown markdown
end end
......
# frozen_string_literal: true
require_dependency 'gitlab/encoding_helper' require_dependency 'gitlab/encoding_helper'
module Gitlab module Gitlab
......
# frozen_string_literal: true
# Check a user's access to perform a git action. All public methods in this # Check a user's access to perform a git action. All public methods in this
# class return an instance of `GitlabAccessStatus` # class return an instance of `GitlabAccessStatus`
module Gitlab module Gitlab
......
# frozen_string_literal: true
module Gitlab module Gitlab
class GitAccessWiki < GitAccess class GitAccessWiki < GitAccess
prepend EE::Gitlab::GitAccessWiki prepend EE::Gitlab::GitAccessWiki
......
# frozen_string_literal: true
module Gitlab module Gitlab
class GitLogger < Gitlab::Logger class GitLogger < Gitlab::Logger
def self.file_name_noext def self.file_name_noext
......
# frozen_string_literal: true
# Gitaly note: JV: does not need to be migrated, works without a repo. # Gitaly note: JV: does not need to be migrated, works without a repo.
module Gitlab module Gitlab
......
# frozen_string_literal: true
require 'base64' require 'base64'
require 'gitaly' require 'gitaly'
...@@ -23,7 +25,7 @@ module Gitlab ...@@ -23,7 +25,7 @@ module Gitlab
stacks = most_invoked_stack.join('\n') if most_invoked_stack stacks = most_invoked_stack.join('\n') if most_invoked_stack
msg = "GitalyClient##{call_site} called #{invocation_count} times from single request. Potential n+1?" msg = "GitalyClient##{call_site} called #{invocation_count} times from single request. Potential n+1?"
msg << "\nThe following call site called into Gitaly #{max_call_stack} times:\n#{stacks}\n" if stacks msg = "#{msg}\nThe following call site called into Gitaly #{max_call_stack} times:\n#{stacks}\n" if stacks
super(msg) super(msg)
end end
......
# frozen_string_literal: true
module Gitlab module Gitlab
module GithubImport module GithubImport
def self.refmap def self.refmap
......
# frozen_string_literal: true
module Gitlab module Gitlab
module GlId module GlId
def self.gl_id(user) def self.gl_id(user)
......
# frozen_string_literal: true
module Gitlab module Gitlab
module GlRepository module GlRepository
def self.gl_repository(project, is_wiki) def self.gl_repository(project, is_wiki)
......
# frozen_string_literal: true
# rubocop:disable Metrics/AbcSize # rubocop:disable Metrics/AbcSize
module Gitlab module Gitlab
......
# frozen_string_literal: true
module Gitlab module Gitlab
module Gpg module Gpg
extend self extend self
......
# frozen_string_literal: true
module Gitlab module Gitlab
module Graphql module Graphql
StandardGraphqlError = Class.new(StandardError) StandardGraphqlError = Class.new(StandardError)
......
# frozen_string_literal: true
module Gitlab module Gitlab
# Retrieving of parent or child groups based on a base ActiveRecord relation. # Retrieving of parent or child groups based on a base ActiveRecord relation.
# #
......
# frozen_string_literal: true
module Gitlab module Gitlab
class Highlight class Highlight
TIMEOUT_BACKGROUND = 30.seconds TIMEOUT_BACKGROUND = 30.seconds
......
# frozen_string_literal: true
# This class is used as a proxy for all outbounding http connection # This class is used as a proxy for all outbounding http connection
# coming from callbacks, services and hooks. The direct use of the HTTParty # coming from callbacks, services and hooks. The direct use of the HTTParty
# is discouraged because it can lead to several security problems, like SSRF # is discouraged because it can lead to several security problems, like SSRF
......
# frozen_string_literal: true
## ##
# This class is compatible with IO class (https://ruby-doc.org/core-2.3.1/IO.html) # This class is compatible with IO class (https://ruby-doc.org/core-2.3.1/IO.html)
# source: https://gitlab.com/snippets/1685610 # source: https://gitlab.com/snippets/1685610
...@@ -73,8 +75,8 @@ module Gitlab ...@@ -73,8 +75,8 @@ module Gitlab
end end
end end
def read(length = nil, outbuf = "") def read(length = nil, outbuf = nil)
out = "" out = []
length ||= size - tell length ||= size - tell
...@@ -90,17 +92,18 @@ module Gitlab ...@@ -90,17 +92,18 @@ module Gitlab
length -= chunk_data.bytesize length -= chunk_data.bytesize
end end
out = out.join
# If outbuf is passed, we put the output into the buffer. This supports IO.copy_stream functionality # If outbuf is passed, we put the output into the buffer. This supports IO.copy_stream functionality
if outbuf if outbuf
outbuf.slice!(0, outbuf.bytesize) outbuf.replace(out)
outbuf << out
end end
out out
end end
def readline def readline
out = "" out = []
until eof? until eof?
data = get_chunk data = get_chunk
...@@ -116,7 +119,7 @@ module Gitlab ...@@ -116,7 +119,7 @@ module Gitlab
end end
end end
out out.join
end end
def write(data) def write(data)
......
# frozen_string_literal: true
module Gitlab module Gitlab
module I18n module I18n
extend self extend self
......
# frozen_string_literal: true
# Detect user based on identifier like # Detect user based on identifier like
# key-13 or user-36 or last commit # key-13 or user-36 or last commit
module Gitlab module Gitlab
......
# frozen_string_literal: true
module Gitlab module Gitlab
module ImportExport module ImportExport
extend self extend self
......
# frozen_string_literal: true
module Gitlab module Gitlab
class ImportFormatter class ImportFormatter
def comment(author, date, body) def comment(author, date, body)
......
# frozen_string_literal: true
# Gitlab::ImportSources module # Gitlab::ImportSources module
# #
# Define import sources that can be used # Define import sources that can be used
......
# frozen_string_literal: true
module Gitlab module Gitlab
module IncomingEmail module IncomingEmail
UNSUBSCRIBE_SUFFIX = '+unsubscribe'.freeze UNSUBSCRIBE_SUFFIX = '+unsubscribe'.freeze
......
# frozen_string_literal: true
module Gitlab module Gitlab
# #
# Calculates the fingerprint of a given key without using # Calculates the fingerprint of a given key without using
......
# frozen_string_literal: true
module Gitlab module Gitlab
module IssuableMetadata module IssuableMetadata
def issuable_meta_data(issuable_collection, collection_type) def issuable_meta_data(issuable_collection, collection_type)
......
# frozen_string_literal: true
module Gitlab module Gitlab
module IssuableSorter module IssuableSorter
class << self class << self
......
# frozen_string_literal: true
module Gitlab module Gitlab
# Class for counting and caching the number of issuables per state. # Class for counting and caching the number of issuables per state.
class IssuablesCountForState class IssuablesCountForState
......
# frozen_string_literal: true
module Gitlab module Gitlab
class IssuesLabels class IssuesLabels
class << self class << self
......
# frozen_string_literal: true
module Gitlab module Gitlab
# JobWaiter can be used to wait for a number of Sidekiq jobs to complete. # JobWaiter can be used to wait for a number of Sidekiq jobs to complete.
# #
......
# frozen_string_literal: true
module Gitlab module Gitlab
class JsonLogger < ::Gitlab::Logger class JsonLogger < ::Gitlab::Logger
def self.file_name_noext def self.file_name_noext
......
# frozen_string_literal: true
module Gitlab module Gitlab
# Helper methods to do with Kubernetes network services & resources # Helper methods to do with Kubernetes network services & resources
module Kubernetes module Kubernetes
......
# frozen_string_literal: true
module Gitlab module Gitlab
class LanguageDetection class LanguageDetection
MAX_LANGUAGES = 5 MAX_LANGUAGES = 5
......
# frozen_string_literal: true
module Gitlab module Gitlab
# A class that can be wrapped around an expensive method call so it's only # A class that can be wrapped around an expensive method call so it's only
# executed when actually needed. # executed when actually needed.
......
# frozen_string_literal: true
module Gitlab module Gitlab
class LfsToken class LfsToken
attr_accessor :actor attr_accessor :actor
......
# frozen_string_literal: true
module Gitlab module Gitlab
class Logger < ::Logger class Logger < ::Logger
def self.file_name def self.file_name
......
# frozen_string_literal: true
require 'yaml' require 'yaml'
require 'json' require 'json'
require_relative 'redis/queues' unless defined?(Gitlab::Redis::Queues) require_relative 'redis/queues' unless defined?(Gitlab::Redis::Queues)
......
# frozen_string_literal: true
module Gitlab module Gitlab
module MarkupHelper module MarkupHelper
extend self extend self
......
# frozen_string_literal: true
module Gitlab module Gitlab
module Metrics module Metrics
include Gitlab::Metrics::InfluxDb include Gitlab::Metrics::InfluxDb
......
# frozen_string_literal: true
module Gitlab module Gitlab
class MultiCollectionPaginator class MultiCollectionPaginator
attr_reader :first_collection, :second_collection, :per_page attr_reader :first_collection, :second_collection, :per_page
......
# frozen_string_literal: true
module Gitlab module Gitlab
class OmniauthInitializer class OmniauthInitializer
prepend ::EE::Gitlab::OmniauthInitializer prepend ::EE::Gitlab::OmniauthInitializer
......
# frozen_string_literal: true
module Gitlab module Gitlab
module OptimisticLocking module OptimisticLocking
module_function module_function
......
# frozen_string_literal: true
module Gitlab module Gitlab
# Parser/renderer for markups without other special support code. # Parser/renderer for markups without other special support code.
module OtherMarkup module OtherMarkup
......
# frozen_string_literal: true
module Gitlab module Gitlab
# The +otp_key_base+ param is used to encrypt the User#otp_secret attribute. # The +otp_key_base+ param is used to encrypt the User#otp_secret attribute.
# #
......
# frozen_string_literal: true
module Gitlab module Gitlab
module Pages module Pages
VERSION = File.read(Rails.root.join("GITLAB_PAGES_VERSION")).strip.freeze VERSION = File.read(Rails.root.join("GITLAB_PAGES_VERSION")).strip.freeze
......
# frozen_string_literal: true
module Gitlab module Gitlab
class PagesClient class PagesClient
class << self class << self
......
# frozen_string_literal: true
module Gitlab module Gitlab
class PagesTransfer < ProjectTransfer class PagesTransfer < ProjectTransfer
def root_dir def root_dir
......
# frozen_string_literal: true
module Gitlab module Gitlab
module PathRegex module PathRegex
extend self extend self
......
# frozen_string_literal: true
module Gitlab module Gitlab
module PerformanceBar module PerformanceBar
ALLOWED_USER_IDS_KEY = 'performance_bar_allowed_user_ids:v2'.freeze ALLOWED_USER_IDS_KEY = 'performance_bar_allowed_user_ids:v2'.freeze
......
# frozen_string_literal: true
module Gitlab module Gitlab
module Plugin module Plugin
def self.files def self.files
......
# frozen_string_literal: true
module Gitlab module Gitlab
class PluginLogger < Gitlab::Logger class PluginLogger < Gitlab::Logger
def self.file_name_noext def self.file_name_noext
......
# frozen_string_literal: true
module Gitlab module Gitlab
class PollingInterval class PollingInterval
HEADER_NAME = 'Poll-Interval'.freeze HEADER_NAME = 'Poll-Interval'.freeze
......
# frozen_string_literal: true
require 'fileutils' require 'fileutils'
require 'open3' require 'open3'
...@@ -11,7 +13,7 @@ module Gitlab ...@@ -11,7 +13,7 @@ module Gitlab
def popen(cmd, path = nil, vars = {}, &block) def popen(cmd, path = nil, vars = {}, &block)
result = popen_with_detail(cmd, path, vars, &block) result = popen_with_detail(cmd, path, vars, &block)
[result.stdout << result.stderr, result.status&.exitstatus] ["#{result.stdout}#{result.stderr}", result.status&.exitstatus]
end end
# Returns Result # Returns Result
......
# coding: utf-8 # coding: utf-8
# frozen_string_literal: true
module Gitlab module Gitlab
module Profiler module Profiler
FILTERED_STRING = '[FILTERED]'.freeze FILTERED_STRING = '[FILTERED]'.freeze
......
# frozen_string_literal: true
module Gitlab module Gitlab
class ProjectSearchResults < SearchResults class ProjectSearchResults < SearchResults
attr_reader :project, :repository_ref attr_reader :project, :repository_ref
...@@ -57,7 +59,8 @@ module Gitlab ...@@ -57,7 +59,8 @@ module Gitlab
ref = nil ref = nil
filename = nil filename = nil
basename = nil basename = nil
data = ""
data = []
startline = 0 startline = 0
result.each_line.each_with_index do |line, index| result.each_line.each_with_index do |line, index|
...@@ -78,7 +81,7 @@ module Gitlab ...@@ -78,7 +81,7 @@ module Gitlab
basename: basename, basename: basename,
ref: ref, ref: ref,
startline: startline, startline: startline,
data: data, data: data.join,
project_id: project ? project.id : nil project_id: project ? project.id : nil
) )
end end
......
# frozen_string_literal: true
module Gitlab module Gitlab
class ProjectServiceLogger < Gitlab::JsonLogger class ProjectServiceLogger < Gitlab::JsonLogger
def self.file_name_noext def self.file_name_noext
......
# frozen_string_literal: true
module Gitlab module Gitlab
class ProjectTemplate class ProjectTemplate
attr_reader :title, :name, :description, :preview attr_reader :title, :name, :description, :preview
......
# frozen_string_literal: true
module Gitlab module Gitlab
# This class is used to move local, unhashed files owned by projects to their new location # This class is used to move local, unhashed files owned by projects to their new location
class ProjectTransfer class ProjectTransfer
......
# frozen_string_literal: true
module Gitlab module Gitlab
# Helper methods to interact with Prometheus network services & resources # Helper methods to interact with Prometheus network services & resources
class PrometheusClient class PrometheusClient
......
# frozen_string_literal: true
module Gitlab module Gitlab
module ProtocolAccess module ProtocolAccess
def self.allowed?(protocol) def self.allowed?(protocol)
......
# frozen_string_literal: true
# This class is part of the Gitlab::HTTP wrapper. Depending on the value # This class is part of the Gitlab::HTTP wrapper. Depending on the value
# of the global setting allow_local_requests_from_hooks_and_services this adapter # of the global setting allow_local_requests_from_hooks_and_services this adapter
# will allow/block connection to internal IPs and/or urls. # will allow/block connection to internal IPs and/or urls.
......
# frozen_string_literal: true
module Gitlab module Gitlab
module QueryLimiting module QueryLimiting
# Returns true if we should enable tracking of query counts. # Returns true if we should enable tracking of query counts.
......
# frozen_string_literal: true
module Gitlab module Gitlab
module Recaptcha module Recaptcha
def self.load_configurations! def self.load_configurations!
......
# frozen_string_literal: true
module Gitlab module Gitlab
class ReferenceCounter class ReferenceCounter
REFERENCE_EXPIRE_TIME = 600 REFERENCE_EXPIRE_TIME = 600
......
# frozen_string_literal: true
module Gitlab module Gitlab
# Extract possible GFM references from an arbitrary String for further processing. # Extract possible GFM references from an arbitrary String for further processing.
class ReferenceExtractor < Banzai::ReferenceExtractor class ReferenceExtractor < Banzai::ReferenceExtractor
......
# frozen_string_literal: true
module Gitlab module Gitlab
module Regex module Regex
extend self extend self
......
# frozen_string_literal: true
module Gitlab module Gitlab
module RepoPath module RepoPath
NotFoundError = Class.new(StandardError) NotFoundError = Class.new(StandardError)
......
# frozen_string_literal: true
# Interface to the Redis-backed cache store # Interface to the Redis-backed cache store
module Gitlab module Gitlab
class RepositoryCache class RepositoryCache
...@@ -6,7 +8,7 @@ module Gitlab ...@@ -6,7 +8,7 @@ module Gitlab
def initialize(repository, extra_namespace: nil, backend: Rails.cache) def initialize(repository, extra_namespace: nil, backend: Rails.cache)
@repository = repository @repository = repository
@namespace = "#{repository.full_path}:#{repository.project.id}" @namespace = "#{repository.full_path}:#{repository.project.id}"
@namespace += ":#{extra_namespace}" if extra_namespace @namespace = "#{@namespace}:#{extra_namespace}" if extra_namespace
@backend = backend @backend = backend
end end
......
# frozen_string_literal: true
module Gitlab module Gitlab
module RepositoryCacheAdapter module RepositoryCacheAdapter
extend ActiveSupport::Concern extend ActiveSupport::Concern
......
# frozen_string_literal: true
module Gitlab module Gitlab
class RepositoryCheckLogger < Gitlab::Logger class RepositoryCheckLogger < Gitlab::Logger
def self.file_name_noext def self.file_name_noext
......
# frozen_string_literal: true
module Gitlab module Gitlab
class RequestContext class RequestContext
class << self class << self
......
# frozen_string_literal: true
# A module to check CSRF tokens in requests. # A module to check CSRF tokens in requests.
# It's used in API helpers and OmniAuth. # It's used in API helpers and OmniAuth.
# Usage: GitLab::RequestForgeryProtection.call(env) # Usage: GitLab::RequestForgeryProtection.call(env)
......
# frozen_string_literal: true
require 'fileutils' require 'fileutils'
module Gitlab module Gitlab
......
# frozen_string_literal: true
module Gitlab module Gitlab
class RouteMap class RouteMap
FormatError = Class.new(StandardError) FormatError = Class.new(StandardError)
......
# frozen_string_literal: true
module Gitlab module Gitlab
module Routing module Routing
extend ActiveSupport::Concern extend ActiveSupport::Concern
...@@ -47,7 +49,7 @@ module Gitlab ...@@ -47,7 +49,7 @@ module Gitlab
# #
# `request.fullpath` includes the querystring # `request.fullpath` includes the querystring
new_path = request.path.sub(%r{/#{path}(/*)(?!.*#{path})}, "/-/#{path}\\1") new_path = request.path.sub(%r{/#{path}(/*)(?!.*#{path})}, "/-/#{path}\\1")
new_path << "?#{request.query_string}" if request.query_string.present? new_path = "#{new_path}?#{request.query_string}" if request.query_string.present?
new_path new_path
end end
......
# frozen_string_literal: true
module Gitlab module Gitlab
class SearchResults class SearchResults
class FoundBlob class FoundBlob
......
# frozen_string_literal: true
# :nocov: # :nocov:
module DeliverNever module DeliverNever
def deliver_later def deliver_later
......
# frozen_string_literal: true
module Gitlab module Gitlab
module Sentry module Sentry
def self.enabled? def self.enabled?
......
# frozen_string_literal: true
require 'toml-rb' require 'toml-rb'
module Gitlab module Gitlab
......
# frozen_string_literal: true
module Gitlab module Gitlab
class ShardHealthCache class ShardHealthCache
HEALTHY_SHARDS_KEY = 'gitlab-healthy-shards'.freeze HEALTHY_SHARDS_KEY = 'gitlab-healthy-shards'.freeze
......
# frozen_string_literal: true
# Gitaly note: SSH key operations are not part of Gitaly so will never be migrated. # Gitaly note: SSH key operations are not part of Gitaly so will never be migrated.
require 'securerandom' require 'securerandom'
......
# frozen_string_literal: true
# == GitLab Shell mixin # == GitLab Shell mixin
# #
# Provide a shortcut to Gitlab::Shell instance by gitlab_shell # Provide a shortcut to Gitlab::Shell instance by gitlab_shell
......
# frozen_string_literal: true
require 'securerandom' require 'securerandom'
module Gitlab module Gitlab
......
# frozen_string_literal: true
require 'yaml' require 'yaml'
require 'set' require 'set'
......
# frozen_string_literal: true
module Gitlab module Gitlab
class SidekiqLogger < Gitlab::Logger class SidekiqLogger < Gitlab::Logger
def self.file_name_noext def self.file_name_noext
......
# frozen_string_literal: true
module Gitlab module Gitlab
# The SidekiqStatus module and its child classes can be used for checking if a # The SidekiqStatus module and its child classes can be used for checking if a
# Sidekiq job has been processed or not. # Sidekiq job has been processed or not.
......
# frozen_string_literal: true
module Gitlab module Gitlab
module SidekiqVersioning module SidekiqVersioning
def self.install! def self.install!
......
# frozen_string_literal: true
module Gitlab module Gitlab
class SnippetSearchResults < SearchResults class SnippetSearchResults < SearchResults
include SnippetsHelper include SnippetsHelper
......
# frozen_string_literal: true
module Gitlab module Gitlab
class SSHPublicKey class SSHPublicKey
Technology = Struct.new(:name, :key_class, :supported_sizes) Technology = Struct.new(:name, :key_class, :supported_sizes)
...@@ -26,7 +28,7 @@ module Gitlab ...@@ -26,7 +28,7 @@ module Gitlab
return key_content if parts.empty? return key_content if parts.empty?
parts.each_with_object("#{ssh_type} ").with_index do |(part, content), index| parts.each_with_object(+"#{ssh_type} ").with_index do |(part, content), index|
content << part content << part
if Gitlab::SSHPublicKey.new(content).valid? if Gitlab::SSHPublicKey.new(content).valid?
......
# frozen_string_literal: true
module Gitlab module Gitlab
class StringPlaceholderReplacer class StringPlaceholderReplacer
# This method accepts the following paras # This method accepts the following paras
......
# frozen_string_literal: true
module Gitlab module Gitlab
class StringRangeMarker class StringRangeMarker
attr_accessor :raw_line, :rich_line, :html_escaped attr_accessor :raw_line, :rich_line, :html_escaped
......
# frozen_string_literal: true
module Gitlab module Gitlab
class StringRegexMarker < StringRangeMarker class StringRegexMarker < StringRangeMarker
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
......
# frozen_string_literal: true
require 'rainbow/ext/string' require 'rainbow/ext/string'
require 'gitlab/utils/strong_memoize' require 'gitlab/utils/strong_memoize'
...@@ -39,7 +41,7 @@ module Gitlab ...@@ -39,7 +41,7 @@ module Gitlab
File.read('/etc/os-release').match(/PRETTY_NAME=\"(.+)\"/)[1] File.read('/etc/os-release').match(/PRETTY_NAME=\"(.+)\"/)[1]
end end
os_name.try(:squish!) os_name.try(:squish)
end end
# Prompt the user to input something # Prompt the user to input something
......
# frozen_string_literal: true
module Gitlab module Gitlab
class TcpChecker class TcpChecker
attr_reader :remote_host, :remote_port, :local_host, :local_port, :error attr_reader :remote_host, :remote_port, :local_host, :local_port, :error
......
# frozen_string_literal: true
module Gitlab module Gitlab
module TemplateHelper module TemplateHelper
def prepare_template_environment(file) def prepare_template_environment(file)
......
# frozen_string_literal: true
module Gitlab module Gitlab
module TemporarilyAllow module TemporarilyAllow
TEMPORARILY_ALLOW_MUTEX = Mutex.new TEMPORARILY_ALLOW_MUTEX = Mutex.new
......
# frozen_string_literal: true
module Gitlab module Gitlab
# Module containing GitLab's application theme definitions and helper methods # Module containing GitLab's application theme definitions and helper methods
# for accessing them. # for accessing them.
......
# frozen_string_literal: true
module Gitlab module Gitlab
module TimeTrackingFormatter module TimeTrackingFormatter
extend self extend self
......
# frozen_string_literal: true
module Gitlab module Gitlab
module Timeless module Timeless
def self.timeless(model, &block) def self.timeless(model, &block)
......
# frozen_string_literal: true
module Gitlab module Gitlab
class TreeSummary class TreeSummary
prepend ::EE::Gitlab::TreeSummary prepend ::EE::Gitlab::TreeSummary
......
# frozen_string_literal: true
module Gitlab module Gitlab
# An untrusted regular expression is any regexp containing patterns sourced # An untrusted regular expression is any regexp containing patterns sourced
# from user input. # from user input.
......
# frozen_string_literal: true
module Gitlab module Gitlab
UpdatePathError = Class.new(StandardError) UpdatePathError = Class.new(StandardError)
end end
# frozen_string_literal: true
module Gitlab module Gitlab
class Upgrader class Upgrader
def execute def execute
......
# frozen_string_literal: true
module Gitlab module Gitlab
class UploadsTransfer < ProjectTransfer class UploadsTransfer < ProjectTransfer
def root_dir def root_dir
......
# frozen_string_literal: true
require 'resolv' require 'resolv'
module Gitlab module Gitlab
......
# frozen_string_literal: true
module Gitlab module Gitlab
class UrlBuilder class UrlBuilder
include Gitlab::Routing include Gitlab::Routing
......
# frozen_string_literal: true
module Gitlab module Gitlab
class UrlSanitizer class UrlSanitizer
ALLOWED_SCHEMES = %w[http https ssh git].freeze ALLOWED_SCHEMES = %w[http https ssh git].freeze
......
# frozen_string_literal: true
module Gitlab module Gitlab
class UsageData class UsageData
class << self class << self
......
# frozen_string_literal: true
module Gitlab module Gitlab
class UserAccess class UserAccess
extend Gitlab::Cache::RequestCache extend Gitlab::Cache::RequestCache
......
# frozen_string_literal: true
module Gitlab module Gitlab
module Utils module Utils
extend self extend self
......
# frozen_string_literal: true
module Gitlab module Gitlab
class VersionInfo class VersionInfo
include Comparable include Comparable
......
# frozen_string_literal: true
# Gitlab::VisibilityLevel module # Gitlab::VisibilityLevel module
# #
# Define allowed public modes that can be used for # Define allowed public modes that can be used for
......
# frozen_string_literal: true
module Gitlab module Gitlab
class WikiFileFinder < FileFinder class WikiFileFinder < FileFinder
attr_reader :repository attr_reader :repository
......
# frozen_string_literal: true
require 'base64' require 'base64'
require 'json' require 'json'
require 'securerandom' require 'securerandom'
...@@ -63,7 +65,7 @@ module Gitlab ...@@ -63,7 +65,7 @@ module Gitlab
def send_git_archive(repository, ref:, format:, append_sha:) def send_git_archive(repository, ref:, format:, append_sha:)
format ||= 'tar.gz' format ||= 'tar.gz'
format.downcase! format = format.downcase
params = repository.archive_metadata(ref, Gitlab.config.gitlab.repository_downloads_path, format, append_sha: append_sha) params = repository.archive_metadata(ref, Gitlab.config.gitlab.repository_downloads_path, format, append_sha: append_sha)
raise "Repository or ref not found" if params.empty? raise "Repository or ref not found" if params.empty?
......
...@@ -8526,9 +8526,12 @@ msgstr "" ...@@ -8526,9 +8526,12 @@ msgstr ""
msgid "View app" msgid "View app"
msgstr "" msgstr ""
<<<<<<< HEAD
msgid "View epics list" msgid "View epics list"
msgstr "" msgstr ""
=======
>>>>>>> upstream/master
msgid "View file @ " msgid "View file @ "
msgstr "" msgstr ""
......
...@@ -119,11 +119,11 @@ FactoryBot.define do ...@@ -119,11 +119,11 @@ FactoryBot.define do
trait :codequality do trait :codequality do
file_type :codequality file_type :codequality
file_format :gzip file_format :raw
after(:build) do |artifact, evaluator| after(:build) do |artifact, evaluator|
artifact.file = fixture_file_upload( artifact.file = fixture_file_upload(
Rails.root.join('spec/fixtures/codequality/codequality.json.gz'), 'application/x-gzip') Rails.root.join('spec/fixtures/codequality/codequality.json'), 'application/json')
end end
end end
......
...@@ -28,4 +28,29 @@ describe 'Merge request > User creates MR' do ...@@ -28,4 +28,29 @@ describe 'Merge request > User creates MR' do
it_behaves_like 'a creatable merge request' it_behaves_like 'a creatable merge request'
end end
end end
context 'source project', :js do
let(:user) { create(:user) }
let(:target_project) { create(:project, :public, :repository) }
let(:source_project) { target_project }
before do
source_project.add_maintainer(user)
sign_in(user)
visit project_new_merge_request_path(
target_project,
merge_request: {
source_project_id: source_project.id,
target_project_id: target_project.id
})
end
it 'filters source project' do
find('.js-source-project').click
find('.dropdown-source-project input').set('source')
expect(find('.dropdown-source-project .dropdown-content')).not_to have_content(source_project.name)
end
end
end end
...@@ -373,17 +373,15 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do ...@@ -373,17 +373,15 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
context 'when job starts environment', :js do context 'when job starts environment', :js do
let(:environment) { create(:environment, name: 'production', project: project) } let(:environment) { create(:environment, name: 'production', project: project) }
context 'job is successful and has deployment' do
let(:build) { create(:ci_build, :success, :trace_live, environment: environment.name, pipeline: pipeline) }
let!(:deployment) { create(:deployment, environment: environment, project: environment.project, deployable: build) }
before do before do
visit project_job_path(project, build) visit project_job_path(project, build)
wait_for_requests wait_for_requests
# scroll to the top of the page first
execute_script "window.scrollTo(0,0)"
end end
context 'job is successful and has deployment' do
let(:build) { create(:ci_build, :success, :trace_live, environment: environment.name, pipeline: pipeline) }
let!(:deployment) { create(:deployment, environment: environment, project: environment.project, deployable: build) }
it 'shows a link for the job' do it 'shows a link for the job' do
expect(page).to have_link environment.name expect(page).to have_link environment.name
end end
...@@ -398,11 +396,6 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do ...@@ -398,11 +396,6 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
let(:build) { create(:ci_build, :failed, :trace_artifact, environment: environment.name, pipeline: pipeline) } let(:build) { create(:ci_build, :failed, :trace_artifact, environment: environment.name, pipeline: pipeline) }
it 'shows a link for the job' do it 'shows a link for the job' do
visit project_job_path(project, build)
wait_for_requests
# scroll to the top of the page first
execute_script "window.scrollTo(0,0)"
expect(page).to have_link environment.name expect(page).to have_link environment.name
expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}") expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}")
end end
...@@ -412,11 +405,6 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do ...@@ -412,11 +405,6 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
let(:build) { create(:ci_build, :success, environment: environment.name, pipeline: pipeline) } let(:build) { create(:ci_build, :success, environment: environment.name, pipeline: pipeline) }
it 'shows a link to latest deployment' do it 'shows a link to latest deployment' do
visit project_job_path(project, build)
wait_for_all_requests
# scroll to the top of the page first
execute_script "window.scrollTo(0,0)"
expect(page).to have_link environment.name expect(page).to have_link environment.name
expect(page).to have_content 'This job is creating a deployment' expect(page).to have_content 'This job is creating a deployment'
expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}") expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}")
...@@ -453,8 +441,6 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do ...@@ -453,8 +441,6 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
before do before do
visit project_job_path(project, job) visit project_job_path(project, job)
wait_for_requests wait_for_requests
# scroll to the top of the page first
execute_script "window.scrollTo(0,0)"
end end
context 'job with outdated deployment' do context 'job with outdated deployment' do
...@@ -484,8 +470,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do ...@@ -484,8 +470,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
it 'shows deployment message' do it 'shows deployment message' do
expected_text = 'The deployment of this job to staging did not succeed.' expected_text = 'The deployment of this job to staging did not succeed.'
expect(page).to have_css( expect(page).to have_css('.environment-information', text: expected_text)
'.environment-information', text: expected_text)
end end
end end
...@@ -498,8 +483,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do ...@@ -498,8 +483,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
it 'shows deployment message' do it 'shows deployment message' do
expected_text = 'This job is creating a deployment to staging' expected_text = 'This job is creating a deployment to staging'
expect(page).to have_css( expect(page).to have_css('.environment-information', text: expected_text)
'.environment-information', text: expected_text)
expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}") expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}")
end end
...@@ -509,10 +493,8 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do ...@@ -509,10 +493,8 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
it 'shows that deployment will be overwritten' do it 'shows that deployment will be overwritten' do
expected_text = 'This job is creating a deployment to staging' expected_text = 'This job is creating a deployment to staging'
expect(page).to have_css( expect(page).to have_css('.environment-information', text: expected_text)
'.environment-information', text: expected_text) expect(page).to have_css('.environment-information', text: 'latest deployment')
expect(page).to have_css(
'.environment-information', text: 'latest deployment')
expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}") expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}")
end end
end end
......
# frozen_string_literal: true
require 'spec_helper'
describe ApplicationsFinder do
let(:application1) { create(:application, name: 'some_application', owner: nil, redirect_uri: 'http://some_application.url', scopes: '') }
let(:application2) { create(:application, name: 'another_application', owner: nil, redirect_uri: 'http://other_application.url', scopes: '') }
describe '#execute' do
it 'returns an array of applications' do
found = described_class.new.execute
expect(found).to match_array([application1, application2])
end
it 'returns the application by id' do
params = { id: application1.id }
found = described_class.new(params).execute
expect(found).to match(application1)
end
end
end
{
"image": "registry.gitlab.com/bikebilly/auto-devops-10-6/feature-branch:e7315ba964febb11bac8f5cd6ec433db8a3a1583",
"unapproved": [
"CVE-2017-15650"
],
"vulnerabilities": [
{
"featurename": "musl",
"featureversion": "1.1.14-r15",
"vulnerability": "CVE-2017-15650",
"namespace": "alpine:v3.4",
"description": "",
"link": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-15650",
"severity": "Medium",
"fixedby": "1.1.14-r16"
}
]
}
{
"site": {
"alerts": [
{
"sourceid": "3",
"wascid": "15",
"cweid": "16",
"reference": "<p>http://msdn.microsoft.com/en-us/library/ie/gg622941%28v=vs.85%29.aspx</p><p>https://www.owasp.org/index.php/List_of_useful_HTTP_headers</p>",
"otherinfo": "<p>This issue still applies to error type pages (401, 403, 500, etc) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.</p><p>At \"High\" threshold this scanner will not alert on client or server error responses.</p>",
"solution": "<p>Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.</p><p>If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.</p>",
"count": "2",
"pluginid": "10021",
"alert": "X-Content-Type-Options Header Missing",
"name": "X-Content-Type-Options Header Missing",
"riskcode": "1",
"confidence": "2",
"riskdesc": "Low (Medium)",
"desc": "<p>The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.</p>",
"instances": [
{
"param": "X-Content-Type-Options",
"method": "GET",
"uri": "http://bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io"
},
{
"param": "X-Content-Type-Options",
"method": "GET",
"uri": "http://bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io/"
}
]
}
],
"@ssl": "false",
"@port": "80",
"@host": "bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io",
"@name": "http://bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io"
},
"@generated": "Fri, 13 Apr 2018 09:22:01",
"@version": "2.7.0"
}
[
{
"priority": "Unknown",
"file": "pom.xml",
"cve": "CVE-2012-4387",
"url": "http://struts.apache.org/docs/s2-011.html",
"message": "Long parameter name DoS for org.apache.struts/struts2-core",
"tools": [
"gemnasium"
],
"tool": "gemnasium"
},
{
"priority": "Unknown",
"file": "pom.xml",
"cve": "CVE-2013-1966",
"url": "http://struts.apache.org/docs/s2-014.html",
"message": "Remote command execution due to flaw in the includeParams attribute of URL and Anchor tags for org.apache.struts/struts2-core",
"tools": [
"gemnasium"
],
"tool": "gemnasium"
},
{
"priority": "Unknown",
"file": "pom.xml",
"cve": "CVE-2013-2115",
"url": "http://struts.apache.org/docs/s2-014.html",
"message": "Remote command execution due to flaw in the includeParams attribute of URL and Anchor tags for org.apache.struts/struts2-core",
"tools": [
"gemnasium"
],
"tool": "gemnasium"
},
{
"priority": "Unknown",
"file": "pom.xml",
"cve": "CVE-2013-2134",
"url": "http://struts.apache.org/docs/s2-015.html",
"message": "Arbitrary OGNL code execution via unsanitized wildcard matching for org.apache.struts/struts2-core",
"tools": [
"gemnasium"
],
"tool": "gemnasium"
}
]
{
"licenses": [
{
"count": 13,
"name": "MIT"
},
{
"count": 2,
"name": "New BSD"
},
{
"count": 1,
"name": "LGPL"
}
],
"dependencies": [
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "bundler",
"url": "http://bundler.io",
"description": "The best way to manage your application's dependencies",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "concurrent-ruby",
"url": "http://www.concurrent-ruby.com",
"description": "Modern concurrency tools for Ruby. Inspired by Erlang, Clojure, Scala, Haskell, F#, C#, Java, and classic concurrency patterns.",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "connection_pool",
"url": "https://github.com/mperham/connection_pool",
"description": "Generic connection pool for Ruby",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "mini_portile2",
"url": "http://github.com/flavorjones/mini_portile",
"description": "Simplistic port-like solution for developers",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "mustermann",
"url": "https://github.com/sinatra/mustermann",
"description": "Your personal string matching expert.",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "nokogiri",
"url": "http://nokogiri.org",
"description": "Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser",
"pathes": [
"."
]
}
},
{
"license": {
"name": "New BSD",
"url": "http://opensource.org/licenses/BSD-3-Clause"
},
"dependency": {
"name": "pg",
"url": "https://bitbucket.org/ged/ruby-pg",
"description": "Pg is the Ruby interface to the {PostgreSQL RDBMS}[http://www.postgresql.org/]",
"pathes": [
"."
]
}
},
{
"license": {
"name": "New BSD",
"url": "http://opensource.org/licenses/BSD-3-Clause"
},
"dependency": {
"name": "puma",
"url": "http://puma.io",
"description": "Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "rack",
"url": "https://rack.github.io/",
"description": "a modular Ruby webserver interface",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "rack-protection",
"url": "http://github.com/sinatra/sinatra/tree/master/rack-protection",
"description": "Protect against typical web attacks, works with all Rack apps, including Rails.",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "redis",
"url": "https://github.com/redis/redis-rb",
"description": "A Ruby client library for Redis",
"pathes": [
"."
]
}
},
{
"license": {
"name": "LGPL",
"url": "http://www.gnu.org/licenses/lgpl.txt"
},
"dependency": {
"name": "sidekiq",
"url": "http://sidekiq.org",
"description": "Simple, efficient background processing for Ruby",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "sinatra",
"url": "http://www.sinatrarb.com/",
"description": "Classy web-development dressed in a DSL",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "slim",
"url": "http://slim-lang.com/",
"description": "Slim is a template language.",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "temple",
"url": "https://github.com/judofyr/temple",
"description": "Template compilation framework in Ruby",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "tilt",
"url": "http://github.com/rtomayko/tilt/",
"description": "Generic interface to multiple Ruby template engines",
"pathes": [
"."
]
}
}
]
}
[
{
"category": "sast",
"message": "Probable insecure usage of temp file/directory.",
"cve": "python/hardcoded/hardcoded-tmp.py:52865813c884a507be1f152d654245af34aba8a391626d01f1ab6d3f52ec8779:B108",
"severity": "Medium",
"confidence": "Medium",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/hardcoded/hardcoded-tmp.py",
"start_line": 1,
"end_line": 1
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B108",
"value": "B108",
"url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
}
],
"priority": "Medium",
"file": "python/hardcoded/hardcoded-tmp.py",
"line": 1,
"url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
"tool": "bandit"
},
{
"category": "sast",
"name": "Predictable pseudorandom number generator",
"message": "Predictable pseudorandom number generator",
"cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:47:PREDICTABLE_RANDOM",
"severity": "Medium",
"confidence": "Medium",
"scanner": {
"id": "find_sec_bugs",
"name": "Find Security Bugs"
},
"location": {
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
"start_line": 47,
"end_line": 47,
"class": "com.gitlab.security_products.tests.App",
"method": "generateSecretToken2"
},
"identifiers": [
{
"type": "find_sec_bugs_type",
"name": "Find Security Bugs-PREDICTABLE_RANDOM",
"value": "PREDICTABLE_RANDOM",
"url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
}
],
"priority": "Medium",
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
"line": 47,
"url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
"tool": "find_sec_bugs"
},
{
"category": "sast",
"name": "Predictable pseudorandom number generator",
"message": "Predictable pseudorandom number generator",
"cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:41:PREDICTABLE_RANDOM",
"severity": "Medium",
"confidence": "Medium",
"scanner": {
"id": "find_sec_bugs",
"name": "Find Security Bugs"
},
"location": {
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
"start_line": 41,
"end_line": 41,
"class": "com.gitlab.security_products.tests.App",
"method": "generateSecretToken1"
},
"identifiers": [
{
"type": "find_sec_bugs_type",
"name": "Find Security Bugs-PREDICTABLE_RANDOM",
"value": "PREDICTABLE_RANDOM",
"url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
}
],
"priority": "Medium",
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
"line": 41,
"url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
"tool": "find_sec_bugs"
},
{
"category": "sast",
"message": "Use of insecure MD2, MD4, or MD5 hash function.",
"cve": "python/imports/imports-aliases.py:cb203b465dffb0cb3a8e8bd8910b84b93b0a5995a938e4b903dbb0cd6ffa1254:B303",
"severity": "Medium",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-aliases.py",
"start_line": 11,
"end_line": 11
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B303",
"value": "B303"
}
],
"priority": "Medium",
"file": "python/imports/imports-aliases.py",
"line": 11,
"tool": "bandit"
},
{
"category": "sast",
"message": "Use of insecure MD2, MD4, or MD5 hash function.",
"cve": "python/imports/imports-aliases.py:a7173c43ae66bd07466632d819d450e0071e02dbf782763640d1092981f9631b:B303",
"severity": "Medium",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-aliases.py",
"start_line": 12,
"end_line": 12
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B303",
"value": "B303"
}
],
"priority": "Medium",
"file": "python/imports/imports-aliases.py",
"line": 12,
"tool": "bandit"
},
{
"category": "sast",
"message": "Use of insecure MD2, MD4, or MD5 hash function.",
"cve": "python/imports/imports-aliases.py:017017b77deb0b8369b6065947833eeea752a92ec8a700db590fece3e934cf0d:B303",
"severity": "Medium",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-aliases.py",
"start_line": 13,
"end_line": 13
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B303",
"value": "B303"
}
],
"priority": "Medium",
"file": "python/imports/imports-aliases.py",
"line": 13,
"tool": "bandit"
},
{
"category": "sast",
"message": "Use of insecure MD2, MD4, or MD5 hash function.",
"cve": "python/imports/imports-aliases.py:45fc8c53aea7b84f06bc4e590cc667678d6073c4c8a1d471177ca2146fb22db2:B303",
"severity": "Medium",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-aliases.py",
"start_line": 14,
"end_line": 14
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B303",
"value": "B303"
}
],
"priority": "Medium",
"file": "python/imports/imports-aliases.py",
"line": 14,
"tool": "bandit"
},
{
"category": "sast",
"message": "Pickle library appears to be in use, possible security issue.",
"cve": "python/imports/imports-aliases.py:5f200d47291e7bbd8352db23019b85453ca048dd98ea0c291260fa7d009963a4:B301",
"severity": "Medium",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-aliases.py",
"start_line": 15,
"end_line": 15
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B301",
"value": "B301"
}
],
"priority": "Medium",
"file": "python/imports/imports-aliases.py",
"line": 15,
"tool": "bandit"
},
{
"category": "sast",
"name": "ECB mode is insecure",
"message": "ECB mode is insecure",
"cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:ECB_MODE",
"severity": "Medium",
"confidence": "High",
"scanner": {
"id": "find_sec_bugs",
"name": "Find Security Bugs"
},
"location": {
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
"start_line": 29,
"end_line": 29,
"class": "com.gitlab.security_products.tests.App",
"method": "insecureCypher"
},
"identifiers": [
{
"type": "find_sec_bugs_type",
"name": "Find Security Bugs-ECB_MODE",
"value": "ECB_MODE",
"url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE"
}
],
"priority": "Medium",
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
"line": 29,
"url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE",
"tool": "find_sec_bugs"
},
{
"category": "sast",
"name": "Cipher with no integrity",
"message": "Cipher with no integrity",
"cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:CIPHER_INTEGRITY",
"severity": "Medium",
"confidence": "High",
"scanner": {
"id": "find_sec_bugs",
"name": "Find Security Bugs"
},
"location": {
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
"start_line": 29,
"end_line": 29,
"class": "com.gitlab.security_products.tests.App",
"method": "insecureCypher"
},
"identifiers": [
{
"type": "find_sec_bugs_type",
"name": "Find Security Bugs-CIPHER_INTEGRITY",
"value": "CIPHER_INTEGRITY",
"url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY"
}
],
"priority": "Medium",
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
"line": 29,
"url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY",
"tool": "find_sec_bugs"
},
{
"category": "sast",
"message": "Probable insecure usage of temp file/directory.",
"cve": "python/hardcoded/hardcoded-tmp.py:63dd4d626855555b816985d82c4614a790462a0a3ada89dc58eb97f9c50f3077:B108",
"severity": "Medium",
"confidence": "Medium",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/hardcoded/hardcoded-tmp.py",
"start_line": 14,
"end_line": 14
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B108",
"value": "B108",
"url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
}
],
"priority": "Medium",
"file": "python/hardcoded/hardcoded-tmp.py",
"line": 14,
"url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
"tool": "bandit"
},
{
"category": "sast",
"message": "Probable insecure usage of temp file/directory.",
"cve": "python/hardcoded/hardcoded-tmp.py:4ad6d4c40a8c263fc265f3384724014e0a4f8dd6200af83e51ff120420038031:B108",
"severity": "Medium",
"confidence": "Medium",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/hardcoded/hardcoded-tmp.py",
"start_line": 10,
"end_line": 10
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B108",
"value": "B108",
"url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
}
],
"priority": "Medium",
"file": "python/hardcoded/hardcoded-tmp.py",
"line": 10,
"url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
"tool": "bandit"
},
{
"category": "sast",
"message": "Consider possible security implications associated with Popen module.",
"cve": "python/imports/imports-aliases.py:2c3e1fa1e54c3c6646e8bcfaee2518153c6799b77587ff8d9a7b0631f6d34785:B404",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-aliases.py",
"start_line": 1,
"end_line": 1
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B404",
"value": "B404"
}
],
"priority": "Low",
"file": "python/imports/imports-aliases.py",
"line": 1,
"tool": "bandit"
},
{
"category": "sast",
"message": "Consider possible security implications associated with pickle module.",
"cve": "python/imports/imports.py:af58d07f6ad519ef5287fcae65bf1a6999448a1a3a8bc1ac2a11daa80d0b96bf:B403",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports.py",
"start_line": 2,
"end_line": 2
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B403",
"value": "B403"
}
],
"priority": "Low",
"file": "python/imports/imports.py",
"line": 2,
"tool": "bandit"
},
{
"category": "sast",
"message": "Consider possible security implications associated with subprocess module.",
"cve": "python/imports/imports.py:8de9bc98029d212db530785a5f6780cfa663548746ff228ab8fa96c5bb82f089:B404",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports.py",
"start_line": 4,
"end_line": 4
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B404",
"value": "B404"
}
],
"priority": "Low",
"file": "python/imports/imports.py",
"line": 4,
"tool": "bandit"
},
{
"category": "sast",
"message": "Possible hardcoded password: 'blerg'",
"cve": "python/hardcoded/hardcoded-passwords.py:97c30f1d76d2a88913e3ce9ae74087874d740f87de8af697a9c455f01119f633:B106",
"severity": "Low",
"confidence": "Medium",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/hardcoded/hardcoded-passwords.py",
"start_line": 22,
"end_line": 22
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B106",
"value": "B106",
"url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html"
}
],
"priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
"line": 22,
"url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html",
"tool": "bandit"
},
{
"category": "sast",
"message": "Possible hardcoded password: 'root'",
"cve": "python/hardcoded/hardcoded-passwords.py:7431c73a0bc16d94ece2a2e75ef38f302574d42c37ac0c3c38ad0b3bf8a59f10:B105",
"severity": "Low",
"confidence": "Medium",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/hardcoded/hardcoded-passwords.py",
"start_line": 5,
"end_line": 5
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B105",
"value": "B105",
"url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
}
],
"priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
"line": 5,
"url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
"tool": "bandit"
},
{
"category": "sast",
"message": "Possible hardcoded password: ''",
"cve": "python/hardcoded/hardcoded-passwords.py:d2d1857c27caedd49c57bfbcdc23afcc92bd66a22701fcdc632869aab4ca73ee:B105",
"severity": "Low",
"confidence": "Medium",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/hardcoded/hardcoded-passwords.py",
"start_line": 9,
"end_line": 9
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B105",
"value": "B105",
"url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
}
],
"priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
"line": 9,
"url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
"tool": "bandit"
},
{
"category": "sast",
"message": "Possible hardcoded password: 'ajklawejrkl42348swfgkg'",
"cve": "python/hardcoded/hardcoded-passwords.py:fb3866215a61393a5c9c32a3b60e2058171a23219c353f722cbd3567acab21d2:B105",
"severity": "Low",
"confidence": "Medium",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/hardcoded/hardcoded-passwords.py",
"start_line": 13,
"end_line": 13
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B105",
"value": "B105",
"url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
}
],
"priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
"line": 13,
"url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
"tool": "bandit"
},
{
"category": "sast",
"message": "Possible hardcoded password: 'blerg'",
"cve": "python/hardcoded/hardcoded-passwords.py:63c62a8b7e1e5224439bd26b28030585ac48741e28ca64561a6071080c560a5f:B105",
"severity": "Low",
"confidence": "Medium",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/hardcoded/hardcoded-passwords.py",
"start_line": 23,
"end_line": 23
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B105",
"value": "B105",
"url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
}
],
"priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
"line": 23,
"url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
"tool": "bandit"
},
{
"category": "sast",
"message": "Possible hardcoded password: 'blerg'",
"cve": "python/hardcoded/hardcoded-passwords.py:4311b06d08df8fa58229b341c531da8e1a31ec4520597bdff920cd5c098d86f9:B105",
"severity": "Low",
"confidence": "Medium",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/hardcoded/hardcoded-passwords.py",
"start_line": 24,
"end_line": 24
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B105",
"value": "B105",
"url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
}
],
"priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
"line": 24,
"url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
"tool": "bandit"
},
{
"category": "sast",
"message": "Consider possible security implications associated with subprocess module.",
"cve": "python/imports/imports-function.py:5858400c2f39047787702de44d03361ef8d954c9d14bd54ee1c2bef9e6a7df93:B404",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-function.py",
"start_line": 4,
"end_line": 4
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B404",
"value": "B404"
}
],
"priority": "Low",
"file": "python/imports/imports-function.py",
"line": 4,
"tool": "bandit"
},
{
"category": "sast",
"message": "Consider possible security implications associated with pickle module.",
"cve": "python/imports/imports-function.py:dbda3cf4190279d30e0aad7dd137eca11272b0b225e8af4e8bf39682da67d956:B403",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-function.py",
"start_line": 2,
"end_line": 2
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B403",
"value": "B403"
}
],
"priority": "Low",
"file": "python/imports/imports-function.py",
"line": 2,
"tool": "bandit"
},
{
"category": "sast",
"message": "Consider possible security implications associated with Popen module.",
"cve": "python/imports/imports-from.py:eb8a0db9cd1a8c1ab39a77e6025021b1261cc2a0b026b2f4a11fca4e0636d8dd:B404",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-from.py",
"start_line": 7,
"end_line": 7
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B404",
"value": "B404"
}
],
"priority": "Low",
"file": "python/imports/imports-from.py",
"line": 7,
"tool": "bandit"
},
{
"category": "sast",
"message": "subprocess call with shell=True seems safe, but may be changed in the future, consider rewriting without shell",
"cve": "python/imports/imports-aliases.py:f99f9721e27537fbcb6699a4cf39c6740d6234d2c6f06cfc2d9ea977313c483d:B602",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-aliases.py",
"start_line": 9,
"end_line": 9
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B602",
"value": "B602",
"url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html"
}
],
"priority": "Low",
"file": "python/imports/imports-aliases.py",
"line": 9,
"url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html",
"tool": "bandit"
},
{
"category": "sast",
"message": "Consider possible security implications associated with subprocess module.",
"cve": "python/imports/imports-from.py:332a12ab1146698f614a905ce6a6a5401497a12281aef200e80522711c69dcf4:B404",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-from.py",
"start_line": 6,
"end_line": 6
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B404",
"value": "B404"
}
],
"priority": "Low",
"file": "python/imports/imports-from.py",
"line": 6,
"tool": "bandit"
},
{
"category": "sast",
"message": "Consider possible security implications associated with Popen module.",
"cve": "python/imports/imports-from.py:0a48de4a3d5348853a03666cb574697e3982998355e7a095a798bd02a5947276:B404",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-from.py",
"start_line": 1,
"end_line": 2
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B404",
"value": "B404"
}
],
"priority": "Low",
"file": "python/imports/imports-from.py",
"line": 1,
"tool": "bandit"
},
{
"category": "sast",
"message": "Consider possible security implications associated with pickle module.",
"cve": "python/imports/imports-aliases.py:51b71661dff994bde3529639a727a678c8f5c4c96f00d300913f6d5be1bbdf26:B403",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-aliases.py",
"start_line": 7,
"end_line": 8
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B403",
"value": "B403"
}
],
"priority": "Low",
"file": "python/imports/imports-aliases.py",
"line": 7,
"tool": "bandit"
},
{
"category": "sast",
"message": "Consider possible security implications associated with loads module.",
"cve": "python/imports/imports-aliases.py:6ff02aeb3149c01ab68484d794a94f58d5d3e3bb0d58557ef4153644ea68ea54:B403",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-aliases.py",
"start_line": 6,
"end_line": 6
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B403",
"value": "B403"
}
],
"priority": "Low",
"file": "python/imports/imports-aliases.py",
"line": 6,
"tool": "bandit"
},
{
"category": "sast",
"message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
"cve": "c/subdir/utils.c:b466873101951fe96e1332f6728eb7010acbbd5dfc3b65d7d53571d091a06d9e:CWE-119!/CWE-120",
"confidence": "Low",
"solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
"scanner": {
"id": "flawfinder",
"name": "Flawfinder"
},
"location": {
"file": "c/subdir/utils.c",
"start_line": 4
},
"identifiers": [
{
"type": "cwe",
"name": "CWE-119",
"value": "119",
"url": "https://cwe.mitre.org/data/definitions/119.html"
},
{
"type": "cwe",
"name": "CWE-120",
"value": "120",
"url": "https://cwe.mitre.org/data/definitions/120.html"
}
],
"file": "c/subdir/utils.c",
"line": 4,
"url": "https://cwe.mitre.org/data/definitions/119.html",
"tool": "flawfinder"
},
{
"category": "sast",
"message": "Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362)",
"cve": "c/subdir/utils.c:bab681140fcc8fc3085b6bba74081b44ea145c1c98b5e70cf19ace2417d30770:CWE-362",
"confidence": "Low",
"scanner": {
"id": "flawfinder",
"name": "Flawfinder"
},
"location": {
"file": "c/subdir/utils.c",
"start_line": 8
},
"identifiers": [
{
"type": "cwe",
"name": "CWE-362",
"value": "362",
"url": "https://cwe.mitre.org/data/definitions/362.html"
}
],
"file": "c/subdir/utils.c",
"line": 8,
"url": "https://cwe.mitre.org/data/definitions/362.html",
"tool": "flawfinder"
},
{
"category": "sast",
"message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
"cve": "cplusplus/src/hello.cpp:c8c6dd0afdae6814194cf0930b719f757ab7b379cf8f261e7f4f9f2f323a818a:CWE-119!/CWE-120",
"confidence": "Low",
"solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
"scanner": {
"id": "flawfinder",
"name": "Flawfinder"
},
"location": {
"file": "cplusplus/src/hello.cpp",
"start_line": 6
},
"identifiers": [
{
"type": "cwe",
"name": "CWE-119",
"value": "119",
"url": "https://cwe.mitre.org/data/definitions/119.html"
},
{
"type": "cwe",
"name": "CWE-120",
"value": "120",
"url": "https://cwe.mitre.org/data/definitions/120.html"
}
],
"file": "cplusplus/src/hello.cpp",
"line": 6,
"url": "https://cwe.mitre.org/data/definitions/119.html",
"tool": "flawfinder"
},
{
"category": "sast",
"message": "Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120)",
"cve": "cplusplus/src/hello.cpp:331c04062c4fe0c7c486f66f59e82ad146ab33cdd76ae757ca41f392d568cbd0:CWE-120",
"confidence": "Low",
"solution": "Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused)",
"scanner": {
"id": "flawfinder",
"name": "Flawfinder"
},
"location": {
"file": "cplusplus/src/hello.cpp",
"start_line": 7
},
"identifiers": [
{
"type": "cwe",
"name": "CWE-120",
"value": "120",
"url": "https://cwe.mitre.org/data/definitions/120.html"
}
],
"file": "cplusplus/src/hello.cpp",
"line": 7,
"url": "https://cwe.mitre.org/data/definitions/120.html",
"tool": "flawfinder"
}
]
{
"image": "registry.gitlab.com/bikebilly/auto-devops-10-6/feature-branch:e7315ba964febb11bac8f5cd6ec433db8a3a1583",
"unapproved": [
"CVE-2017-15651"
],
"vulnerabilities": [
{
"featurename": "musl",
"featureversion": "1.1.14-r15",
"vulnerability": "CVE-2017-15651",
"namespace": "alpine:v3.4",
"description": "",
"link": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-15651",
"severity": "Medium",
"fixedby": "1.1.14-r16"
}
]
}
{
"site": {
"alerts": [
{
"sourceid": "3",
"wascid": "15",
"cweid": "16",
"reference": "<p>http://msdn.microsoft.com/en-us/library/ie/gg622941%28v=vs.85%29.aspx</p><p>https://www.owasp.org/index.php/List_of_useful_HTTP_headers</p>",
"otherinfo": "<p>This issue still applies to error type pages (401, 403, 500, etc) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.</p><p>At \"High\" threshold this scanner will not alert on client or server error responses.</p>",
"solution": "<p>Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.</p><p>If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.</p>",
"count": "2",
"pluginid": "10021",
"alert": "X-Content-Type-Options Header Missing",
"name": "X-Content-Type-Options Header Missing",
"riskcode": "1",
"confidence": "2",
"riskdesc": "Low (Medium)",
"desc": "<p>The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.</p>",
"instances": [
{
"param": "X-Content-Type-Options",
"method": "GET",
"uri": "http://bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io"
},
{
"param": "X-Content-Type-Options",
"method": "GET",
"uri": "http://bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io/"
}
]
}
],
"@ssl": "false",
"@port": "80",
"@host": "bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io",
"@name": "http://bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io"
},
"@generated": "Fri, 13 Apr 2018 09:22:01",
"@version": "2.7.0"
}
[
{
"priority": "Unknown",
"file": "pom.xml",
"cve": "CVE-2012-4386",
"url": "http://struts.apache.org/docs/s2-010.html",
"message": "CSRF protection bypass for org.apache.struts/struts2-core",
"tools": [
"gemnasium"
],
"tool": "gemnasium"
},
{
"priority": "Unknown",
"file": "pom.xml",
"cve": "CVE-2012-4387",
"url": "http://struts.apache.org/docs/s2-011.html",
"message": "Long parameter name DoS for org.apache.struts/struts2-core",
"tools": [
"gemnasium"
],
"tool": "gemnasium"
},
{
"priority": "Unknown",
"file": "pom.xml",
"cve": "CVE-2013-1966",
"url": "http://struts.apache.org/docs/s2-014.html",
"message": "Remote command execution due to flaw in the includeParams attribute of URL and Anchor tags for org.apache.struts/struts2-core",
"tools": [
"gemnasium"
],
"tool": "gemnasium"
}
]
{
"licenses": [
{
"count": 10,
"name": "MIT"
}
],
"dependencies": [
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "mini_portile2",
"url": "http://github.com/flavorjones/mini_portile",
"description": "Simplistic port-like solution for developers",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "mustermann",
"url": "https://github.com/sinatra/mustermann",
"description": "Your personal string matching expert.",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "nokogiri",
"url": "http://nokogiri.org",
"description": "Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "rack",
"url": "https://rack.github.io/",
"description": "a modular Ruby webserver interface",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "rack-protection",
"url": "http://github.com/sinatra/sinatra/tree/master/rack-protection",
"description": "Protect against typical web attacks, works with all Rack apps, including Rails.",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "redis",
"url": "https://github.com/redis/redis-rb",
"description": "A Ruby client library for Redis",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "sinatra",
"url": "http://www.sinatrarb.com/",
"description": "Classy web-development dressed in a DSL",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "slim",
"url": "http://slim-lang.com/",
"description": "Slim is a template language.",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "temple",
"url": "https://github.com/judofyr/temple",
"description": "Template compilation framework in Ruby",
"pathes": [
"."
]
}
},
{
"license": {
"name": "MIT",
"url": "http://opensource.org/licenses/mit-license"
},
"dependency": {
"name": "tilt",
"url": "http://github.com/rtomayko/tilt/",
"description": "Generic interface to multiple Ruby template engines",
"pathes": [
"."
]
}
}
]
}
[
{
"category": "sast",
"message": "Probable insecure usage of temp file/directory.",
"cve": "python/hardcoded/hardcoded-tmp.py:52865813c884a507be1f152d654245af34aba8a391626d01f1ab6d3f52ec8779:B108",
"severity": "Medium",
"confidence": "Medium",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/hardcoded/hardcoded-tmp.py",
"start_line": 1,
"end_line": 1
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B108",
"value": "B108",
"url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
}
],
"priority": "Medium",
"file": "python/hardcoded/hardcoded-tmp.py",
"line": 1,
"url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
"tool": "bandit"
},
{
"category": "sast",
"name": "Predictable pseudorandom number generator",
"message": "Predictable pseudorandom number generator",
"cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:47:PREDICTABLE_RANDOM",
"severity": "Medium",
"confidence": "Medium",
"scanner": {
"id": "find_sec_bugs",
"name": "Find Security Bugs"
},
"location": {
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
"start_line": 47,
"end_line": 47,
"class": "com.gitlab.security_products.tests.App",
"method": "generateSecretToken2"
},
"identifiers": [
{
"type": "find_sec_bugs_type",
"name": "Find Security Bugs-PREDICTABLE_RANDOM",
"value": "PREDICTABLE_RANDOM",
"url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
}
],
"priority": "Medium",
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
"line": 47,
"url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
"tool": "find_sec_bugs"
},
{
"category": "sast",
"name": "Predictable pseudorandom number generator",
"message": "Predictable pseudorandom number generator",
"cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:41:PREDICTABLE_RANDOM",
"severity": "Medium",
"confidence": "Medium",
"scanner": {
"id": "find_sec_bugs",
"name": "Find Security Bugs"
},
"location": {
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
"start_line": 41,
"end_line": 41,
"class": "com.gitlab.security_products.tests.App",
"method": "generateSecretToken1"
},
"identifiers": [
{
"type": "find_sec_bugs_type",
"name": "Find Security Bugs-PREDICTABLE_RANDOM",
"value": "PREDICTABLE_RANDOM",
"url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
}
],
"priority": "Medium",
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
"line": 41,
"url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
"tool": "find_sec_bugs"
},
{
"category": "sast",
"message": "Use of insecure MD2, MD4, or MD5 hash function.",
"cve": "python/imports/imports-aliases.py:cb203b465dffb0cb3a8e8bd8910b84b93b0a5995a938e4b903dbb0cd6ffa1254:B303",
"severity": "Medium",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-aliases.py",
"start_line": 11,
"end_line": 11
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B303",
"value": "B303"
}
],
"priority": "Medium",
"file": "python/imports/imports-aliases.py",
"line": 11,
"tool": "bandit"
},
{
"category": "sast",
"message": "Use of insecure MD2, MD4, or MD5 hash function.",
"cve": "python/imports/imports-aliases.py:a7173c43ae66bd07466632d819d450e0071e02dbf782763640d1092981f9631b:B303",
"severity": "Medium",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-aliases.py",
"start_line": 12,
"end_line": 12
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B303",
"value": "B303"
}
],
"priority": "Medium",
"file": "python/imports/imports-aliases.py",
"line": 12,
"tool": "bandit"
},
{
"category": "sast",
"message": "Use of insecure MD2, MD4, or MD5 hash function.",
"cve": "python/imports/imports-aliases.py:017017b77deb0b8369b6065947833eeea752a92ec8a700db590fece3e934cf0d:B303",
"severity": "Medium",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-aliases.py",
"start_line": 13,
"end_line": 13
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B303",
"value": "B303"
}
],
"priority": "Medium",
"file": "python/imports/imports-aliases.py",
"line": 13,
"tool": "bandit"
},
{
"category": "sast",
"message": "Use of insecure MD2, MD4, or MD5 hash function.",
"cve": "python/imports/imports-aliases.py:45fc8c53aea7b84f06bc4e590cc667678d6073c4c8a1d471177ca2146fb22db2:B303",
"severity": "Medium",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-aliases.py",
"start_line": 14,
"end_line": 14
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B303",
"value": "B303"
}
],
"priority": "Medium",
"file": "python/imports/imports-aliases.py",
"line": 14,
"tool": "bandit"
},
{
"category": "sast",
"message": "Pickle library appears to be in use, possible security issue.",
"cve": "python/imports/imports-aliases.py:5f200d47291e7bbd8352db23019b85453ca048dd98ea0c291260fa7d009963a4:B301",
"severity": "Medium",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-aliases.py",
"start_line": 15,
"end_line": 15
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B301",
"value": "B301"
}
],
"priority": "Medium",
"file": "python/imports/imports-aliases.py",
"line": 15,
"tool": "bandit"
},
{
"category": "sast",
"name": "ECB mode is insecure",
"message": "ECB mode is insecure",
"cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:ECB_MODE",
"severity": "Medium",
"confidence": "High",
"scanner": {
"id": "find_sec_bugs",
"name": "Find Security Bugs"
},
"location": {
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
"start_line": 29,
"end_line": 29,
"class": "com.gitlab.security_products.tests.App",
"method": "insecureCypher"
},
"identifiers": [
{
"type": "find_sec_bugs_type",
"name": "Find Security Bugs-ECB_MODE",
"value": "ECB_MODE",
"url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE"
}
],
"priority": "Medium",
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
"line": 29,
"url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE",
"tool": "find_sec_bugs"
},
{
"category": "sast",
"name": "Cipher with no integrity",
"message": "Cipher with no integrity",
"cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:CIPHER_INTEGRITY",
"severity": "Medium",
"confidence": "High",
"scanner": {
"id": "find_sec_bugs",
"name": "Find Security Bugs"
},
"location": {
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
"start_line": 29,
"end_line": 29,
"class": "com.gitlab.security_products.tests.App",
"method": "insecureCypher"
},
"identifiers": [
{
"type": "find_sec_bugs_type",
"name": "Find Security Bugs-CIPHER_INTEGRITY",
"value": "CIPHER_INTEGRITY",
"url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY"
}
],
"priority": "Medium",
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
"line": 29,
"url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY",
"tool": "find_sec_bugs"
},
{
"category": "sast",
"message": "Probable insecure usage of temp file/directory.",
"cve": "python/hardcoded/hardcoded-tmp.py:63dd4d626855555b816985d82c4614a790462a0a3ada89dc58eb97f9c50f3077:B108",
"severity": "Medium",
"confidence": "Medium",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/hardcoded/hardcoded-tmp.py",
"start_line": 14,
"end_line": 14
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B108",
"value": "B108",
"url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
}
],
"priority": "Medium",
"file": "python/hardcoded/hardcoded-tmp.py",
"line": 14,
"url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
"tool": "bandit"
},
{
"category": "sast",
"message": "Probable insecure usage of temp file/directory.",
"cve": "python/hardcoded/hardcoded-tmp.py:4ad6d4c40a8c263fc265f3384724014e0a4f8dd6200af83e51ff120420038031:B108",
"severity": "Medium",
"confidence": "Medium",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/hardcoded/hardcoded-tmp.py",
"start_line": 10,
"end_line": 10
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B108",
"value": "B108",
"url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
}
],
"priority": "Medium",
"file": "python/hardcoded/hardcoded-tmp.py",
"line": 10,
"url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
"tool": "bandit"
},
{
"category": "sast",
"message": "Consider possible security implications associated with Popen module.",
"cve": "python/imports/imports-aliases.py:2c3e1fa1e54c3c6646e8bcfaee2518153c6799b77587ff8d9a7b0631f6d34785:B404",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-aliases.py",
"start_line": 1,
"end_line": 1
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B404",
"value": "B404"
}
],
"priority": "Low",
"file": "python/imports/imports-aliases.py",
"line": 1,
"tool": "bandit"
},
{
"category": "sast",
"message": "Consider possible security implications associated with pickle module.",
"cve": "python/imports/imports.py:af58d07f6ad519ef5287fcae65bf1a6999448a1a3a8bc1ac2a11daa80d0b96bf:B403",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports.py",
"start_line": 2,
"end_line": 2
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B403",
"value": "B403"
}
],
"priority": "Low",
"file": "python/imports/imports.py",
"line": 2,
"tool": "bandit"
},
{
"category": "sast",
"message": "Consider possible security implications associated with subprocess module.",
"cve": "python/imports/imports.py:8de9bc98029d212db530785a5f6780cfa663548746ff228ab8fa96c5bb82f089:B404",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports.py",
"start_line": 4,
"end_line": 4
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B404",
"value": "B404"
}
],
"priority": "Low",
"file": "python/imports/imports.py",
"line": 4,
"tool": "bandit"
},
{
"category": "sast",
"message": "Possible hardcoded password: 'blerg'",
"cve": "python/hardcoded/hardcoded-passwords.py:97c30f1d76d2a88913e3ce9ae74087874d740f87de8af697a9c455f01119f633:B106",
"severity": "Low",
"confidence": "Medium",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/hardcoded/hardcoded-passwords.py",
"start_line": 22,
"end_line": 22
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B106",
"value": "B106",
"url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html"
}
],
"priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
"line": 22,
"url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html",
"tool": "bandit"
},
{
"category": "sast",
"message": "Possible hardcoded password: 'root'",
"cve": "python/hardcoded/hardcoded-passwords.py:7431c73a0bc16d94ece2a2e75ef38f302574d42c37ac0c3c38ad0b3bf8a59f10:B105",
"severity": "Low",
"confidence": "Medium",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/hardcoded/hardcoded-passwords.py",
"start_line": 5,
"end_line": 5
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B105",
"value": "B105",
"url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
}
],
"priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
"line": 5,
"url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
"tool": "bandit"
},
{
"category": "sast",
"message": "Possible hardcoded password: ''",
"cve": "python/hardcoded/hardcoded-passwords.py:d2d1857c27caedd49c57bfbcdc23afcc92bd66a22701fcdc632869aab4ca73ee:B105",
"severity": "Low",
"confidence": "Medium",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/hardcoded/hardcoded-passwords.py",
"start_line": 9,
"end_line": 9
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B105",
"value": "B105",
"url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
}
],
"priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
"line": 9,
"url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
"tool": "bandit"
},
{
"category": "sast",
"message": "Possible hardcoded password: 'ajklawejrkl42348swfgkg'",
"cve": "python/hardcoded/hardcoded-passwords.py:fb3866215a61393a5c9c32a3b60e2058171a23219c353f722cbd3567acab21d2:B105",
"severity": "Low",
"confidence": "Medium",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/hardcoded/hardcoded-passwords.py",
"start_line": 13,
"end_line": 13
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B105",
"value": "B105",
"url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
}
],
"priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
"line": 13,
"url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
"tool": "bandit"
},
{
"category": "sast",
"message": "Possible hardcoded password: 'blerg'",
"cve": "python/hardcoded/hardcoded-passwords.py:63c62a8b7e1e5224439bd26b28030585ac48741e28ca64561a6071080c560a5f:B105",
"severity": "Low",
"confidence": "Medium",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/hardcoded/hardcoded-passwords.py",
"start_line": 23,
"end_line": 23
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B105",
"value": "B105",
"url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
}
],
"priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
"line": 23,
"url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
"tool": "bandit"
},
{
"category": "sast",
"message": "Possible hardcoded password: 'blerg'",
"cve": "python/hardcoded/hardcoded-passwords.py:4311b06d08df8fa58229b341c531da8e1a31ec4520597bdff920cd5c098d86f9:B105",
"severity": "Low",
"confidence": "Medium",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/hardcoded/hardcoded-passwords.py",
"start_line": 24,
"end_line": 24
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B105",
"value": "B105",
"url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
}
],
"priority": "Low",
"file": "python/hardcoded/hardcoded-passwords.py",
"line": 24,
"url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
"tool": "bandit"
},
{
"category": "sast",
"message": "Consider possible security implications associated with subprocess module.",
"cve": "python/imports/imports-function.py:5858400c2f39047787702de44d03361ef8d954c9d14bd54ee1c2bef9e6a7df93:B404",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-function.py",
"start_line": 4,
"end_line": 4
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B404",
"value": "B404"
}
],
"priority": "Low",
"file": "python/imports/imports-function.py",
"line": 4,
"tool": "bandit"
},
{
"category": "sast",
"message": "Consider possible security implications associated with pickle module.",
"cve": "python/imports/imports-function.py:dbda3cf4190279d30e0aad7dd137eca11272b0b225e8af4e8bf39682da67d956:B403",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-function.py",
"start_line": 2,
"end_line": 2
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B403",
"value": "B403"
}
],
"priority": "Low",
"file": "python/imports/imports-function.py",
"line": 2,
"tool": "bandit"
},
{
"category": "sast",
"message": "Consider possible security implications associated with Popen module.",
"cve": "python/imports/imports-from.py:eb8a0db9cd1a8c1ab39a77e6025021b1261cc2a0b026b2f4a11fca4e0636d8dd:B404",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-from.py",
"start_line": 7,
"end_line": 7
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B404",
"value": "B404"
}
],
"priority": "Low",
"file": "python/imports/imports-from.py",
"line": 7,
"tool": "bandit"
},
{
"category": "sast",
"message": "subprocess call with shell=True seems safe, but may be changed in the future, consider rewriting without shell",
"cve": "python/imports/imports-aliases.py:f99f9721e27537fbcb6699a4cf39c6740d6234d2c6f06cfc2d9ea977313c483d:B602",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-aliases.py",
"start_line": 9,
"end_line": 9
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B602",
"value": "B602",
"url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html"
}
],
"priority": "Low",
"file": "python/imports/imports-aliases.py",
"line": 9,
"url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html",
"tool": "bandit"
},
{
"category": "sast",
"message": "Consider possible security implications associated with subprocess module.",
"cve": "python/imports/imports-from.py:332a12ab1146698f614a905ce6a6a5401497a12281aef200e80522711c69dcf4:B404",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-from.py",
"start_line": 6,
"end_line": 6
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B404",
"value": "B404"
}
],
"priority": "Low",
"file": "python/imports/imports-from.py",
"line": 6,
"tool": "bandit"
},
{
"category": "sast",
"message": "Consider possible security implications associated with Popen module.",
"cve": "python/imports/imports-from.py:0a48de4a3d5348853a03666cb574697e3982998355e7a095a798bd02a5947276:B404",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-from.py",
"start_line": 1,
"end_line": 2
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B404",
"value": "B404"
}
],
"priority": "Low",
"file": "python/imports/imports-from.py",
"line": 1,
"tool": "bandit"
},
{
"category": "sast",
"message": "Consider possible security implications associated with pickle module.",
"cve": "python/imports/imports-aliases.py:51b71661dff994bde3529639a727a678c8f5c4c96f00d300913f6d5be1bbdf26:B403",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-aliases.py",
"start_line": 7,
"end_line": 8
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B403",
"value": "B403"
}
],
"priority": "Low",
"file": "python/imports/imports-aliases.py",
"line": 7,
"tool": "bandit"
},
{
"category": "sast",
"message": "Consider possible security implications associated with loads module.",
"cve": "python/imports/imports-aliases.py:6ff02aeb3149c01ab68484d794a94f58d5d3e3bb0d58557ef4153644ea68ea54:B403",
"severity": "Low",
"confidence": "High",
"scanner": {
"id": "bandit",
"name": "Bandit"
},
"location": {
"file": "python/imports/imports-aliases.py",
"start_line": 6,
"end_line": 6
},
"identifiers": [
{
"type": "bandit_test_id",
"name": "Bandit Test ID B403",
"value": "B403"
}
],
"priority": "Low",
"file": "python/imports/imports-aliases.py",
"line": 6,
"tool": "bandit"
},
{
"category": "sast",
"message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
"cve": "c/subdir/utils.c:b466873101951fe96e1332f6728eb7010acbbd5dfc3b65d7d53571d091a06d9e:CWE-119!/CWE-120",
"confidence": "Low",
"solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
"scanner": {
"id": "flawfinder",
"name": "Flawfinder"
},
"location": {
"file": "c/subdir/utils.c",
"start_line": 4
},
"identifiers": [
{
"type": "cwe",
"name": "CWE-119",
"value": "119",
"url": "https://cwe.mitre.org/data/definitions/119.html"
},
{
"type": "cwe",
"name": "CWE-120",
"value": "120",
"url": "https://cwe.mitre.org/data/definitions/120.html"
}
],
"file": "c/subdir/utils.c",
"line": 4,
"url": "https://cwe.mitre.org/data/definitions/119.html",
"tool": "flawfinder"
},
{
"category": "sast",
"message": "Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362)",
"cve": "c/subdir/utils.c:bab681140fcc8fc3085b6bba74081b44ea145c1c98b5e70cf19ace2417d30770:CWE-362",
"confidence": "Low",
"scanner": {
"id": "flawfinder",
"name": "Flawfinder"
},
"location": {
"file": "c/subdir/utils.c",
"start_line": 8
},
"identifiers": [
{
"type": "cwe",
"name": "CWE-362",
"value": "362",
"url": "https://cwe.mitre.org/data/definitions/362.html"
}
],
"file": "c/subdir/utils.c",
"line": 8,
"url": "https://cwe.mitre.org/data/definitions/362.html",
"tool": "flawfinder"
},
{
"category": "sast",
"message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
"cve": "cplusplus/src/hello.cpp:c8c6dd0afdae6814194cf0930b719f757ab7b379cf8f261e7f4f9f2f323a818a:CWE-119!/CWE-120",
"confidence": "Low",
"solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
"scanner": {
"id": "flawfinder",
"name": "Flawfinder"
},
"location": {
"file": "cplusplus/src/hello.cpp",
"start_line": 6
},
"identifiers": [
{
"type": "cwe",
"name": "CWE-119",
"value": "119",
"url": "https://cwe.mitre.org/data/definitions/119.html"
},
{
"type": "cwe",
"name": "CWE-120",
"value": "120",
"url": "https://cwe.mitre.org/data/definitions/120.html"
}
],
"file": "cplusplus/src/hello.cpp",
"line": 6,
"url": "https://cwe.mitre.org/data/definitions/119.html",
"tool": "flawfinder"
},
{
"category": "sast",
"message": "Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120)",
"cve": "cplusplus/src/hello.cpp:331c04062c4fe0c7c486f66f59e82ad146ab33cdd76ae757ca41f392d568cbd0:CWE-120",
"confidence": "Low",
"solution": "Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused)",
"scanner": {
"id": "flawfinder",
"name": "Flawfinder"
},
"location": {
"file": "cplusplus/src/hello.cpp",
"start_line": 7
},
"identifiers": [
{
"type": "cwe",
"name": "CWE-120",
"value": "120",
"url": "https://cwe.mitre.org/data/definitions/120.html"
}
],
"file": "cplusplus/src/hello.cpp",
"line": 7,
"url": "https://cwe.mitre.org/data/definitions/120.html",
"tool": "flawfinder"
}
]
...@@ -22,34 +22,17 @@ describe TimeHelper do ...@@ -22,34 +22,17 @@ describe TimeHelper do
describe "#duration_in_numbers" do describe "#duration_in_numbers" do
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
context "without passing allow_overflow" do
where(:duration, :formatted_string) do where(:duration, :formatted_string) do
0 | "00:00" 0 | "00:00"
1.second | "00:01" 1.second | "00:01"
42.seconds | "00:42" 42.seconds | "00:42"
2.minutes + 1.second | "02:01" 2.minutes + 1.second | "02:01"
3.hours + 2.minutes + 1.second | "03:02:01" 3.hours + 2.minutes + 1.second | "03:02:01"
30.hours | "06:00:00"
end
with_them do
it { expect(duration_in_numbers(duration)).to eq formatted_string }
end
end
context "with allow_overflow = true" do
where(:duration, :formatted_string) do
0 | "00:00:00"
1.second | "00:00:01"
42.seconds | "00:00:42"
2.minutes + 1.second | "00:02:01"
3.hours + 2.minutes + 1.second | "03:02:01"
30.hours | "30:00:00" 30.hours | "30:00:00"
end end
with_them do with_them do
it { expect(duration_in_numbers(duration, true)).to eq formatted_string } it { expect(duration_in_numbers(duration)).to eq formatted_string }
end
end end
end end
end end
...@@ -40,21 +40,10 @@ describe('new dropdown upload', () => { ...@@ -40,21 +40,10 @@ describe('new dropdown upload', () => {
describe('readFile', () => { describe('readFile', () => {
beforeEach(() => { beforeEach(() => {
spyOn(FileReader.prototype, 'readAsText');
spyOn(FileReader.prototype, 'readAsDataURL'); spyOn(FileReader.prototype, 'readAsDataURL');
}); });
it('calls readAsText for text files', () => { it('calls readAsDataURL for all files', () => {
const file = {
type: 'text/html',
};
vm.readFile(file);
expect(FileReader.prototype.readAsText).toHaveBeenCalledWith(file);
});
it('calls readAsDataURL for non-text files', () => {
const file = { const file = {
type: 'images/png', type: 'images/png',
}; };
...@@ -66,32 +55,37 @@ describe('new dropdown upload', () => { ...@@ -66,32 +55,37 @@ describe('new dropdown upload', () => {
}); });
describe('createFile', () => { describe('createFile', () => {
const target = { const textTarget = {
result: 'content', result: 'base64,cGxhaW4gdGV4dA==',
}; };
const binaryTarget = { const binaryTarget = {
result: 'base64,base64content', result: 'base64,w4I=',
}; };
const file = { const textFile = {
name: 'file', name: 'textFile',
type: 'text/plain',
};
const binaryFile = {
name: 'binaryFile',
type: 'image/png',
}; };
it('creates new file', () => { it('creates file in plain text (without encoding) if the file content is plain text', () => {
vm.createFile(target, file, true); vm.createFile(textTarget, textFile);
expect(vm.$emit).toHaveBeenCalledWith('create', { expect(vm.$emit).toHaveBeenCalledWith('create', {
name: file.name, name: textFile.name,
type: 'blob', type: 'blob',
content: target.result, content: 'plain text',
base64: false, base64: false,
}); });
}); });
it('splits content on base64 if binary', () => { it('splits content on base64 if binary', () => {
vm.createFile(binaryTarget, file, false); vm.createFile(binaryTarget, binaryFile);
expect(vm.$emit).toHaveBeenCalledWith('create', { expect(vm.$emit).toHaveBeenCalledWith('create', {
name: file.name, name: binaryFile.name,
type: 'blob', type: 'blob',
content: binaryTarget.result.split('base64,')[1], content: binaryTarget.result.split('base64,')[1],
base64: true, base64: true,
......
require 'spec_helper' require 'spec_helper'
describe Gitlab::Ci::Build::Artifacts::GzipFileAdapter do describe Gitlab::Ci::Build::Artifacts::Adapters::GzipStream do
describe '#initialize' do describe '#initialize' do
context 'when stream is passed' do context 'when stream is passed' do
let(:stream) { File.open(expand_fixture_path('junit/junit.xml.gz'), 'rb') } let(:stream) { File.open(expand_fixture_path('junit/junit.xml.gz'), 'rb') }
......
require 'spec_helper'
describe Gitlab::Ci::Build::Artifacts::Adapters::RawStream do
describe '#initialize' do
context 'when stream is passed' do
let(:stream) { File.open(expand_fixture_path('junit/junit.xml'), 'rb') }
it 'initialized' do
expect { described_class.new(stream) }.not_to raise_error
end
end
context 'when stream is not passed' do
let(:stream) { nil }
it 'raises an error' do
expect { described_class.new(stream) }.to raise_error(described_class::InvalidStreamError)
end
end
end
describe '#each_blob' do
let(:adapter) { described_class.new(stream) }
context 'when file is not empty' do
let(:stream) { File.open(expand_fixture_path('junit/junit.xml'), 'rb') }
it 'iterates content' do
expect { |b| adapter.each_blob(&b) }
.to yield_with_args(fixture_file('junit/junit.xml'), 'raw')
end
end
context 'when file is empty' do
let(:stream) { Tempfile.new }
after do
stream.unlink
end
it 'does not iterate content' do
expect { |b| adapter.each_blob(&b) }
.not_to yield_control
end
end
end
end
...@@ -26,9 +26,9 @@ describe Gitlab::Ci::Status::Build::Scheduled do ...@@ -26,9 +26,9 @@ describe Gitlab::Ci::Status::Build::Scheduled do
context 'when scheduled_at is expired' do context 'when scheduled_at is expired' do
let(:build) { create(:ci_build, :expired_scheduled, project: project) } let(:build) { create(:ci_build, :expired_scheduled, project: project) }
it 'shows 00:00:00' do it 'shows 00:00' do
Timecop.freeze do Timecop.freeze do
expect(subject.status_tooltip).to include('00:00:00') expect(subject.status_tooltip).to include('00:00')
end end
end end
end end
......
...@@ -194,6 +194,14 @@ describe Ci::JobArtifact do ...@@ -194,6 +194,14 @@ describe Ci::JobArtifact do
end end
end end
context 'when file format is raw' do
let(:artifact) { build(:ci_job_artifact, :codequality, file_format: :raw) }
it 'iterates blob once' do
expect { |b| artifact.each_blob(&b) }.to yield_control.once
end
end
context 'when there are no adapters for the file format' do context 'when there are no adapters for the file format' do
let(:artifact) { build(:ci_job_artifact, :junit, file_format: :zip) } let(:artifact) { build(:ci_job_artifact, :junit, file_format: :zip) }
......
...@@ -40,6 +40,7 @@ describe Ci::BuildRunnerPresenter do ...@@ -40,6 +40,7 @@ describe Ci::BuildRunnerPresenter do
context "with reports" do context "with reports" do
Ci::JobArtifact::DEFAULT_FILE_NAMES.each do |file_type, filename| Ci::JobArtifact::DEFAULT_FILE_NAMES.each do |file_type, filename|
context file_type.to_s do
let(:report) { { "#{file_type}": [filename] } } let(:report) { { "#{file_type}": [filename] } }
let(:build) { create(:ci_build, options: { artifacts: { reports: report } } ) } let(:build) { create(:ci_build, options: { artifacts: { reports: report } } ) }
...@@ -47,7 +48,7 @@ describe Ci::BuildRunnerPresenter do ...@@ -47,7 +48,7 @@ describe Ci::BuildRunnerPresenter do
{ {
name: filename, name: filename,
artifact_type: :"#{file_type}", artifact_type: :"#{file_type}",
artifact_format: :gzip, artifact_format: Ci::JobArtifact::TYPE_AND_FORMAT_PAIRS.fetch(file_type),
paths: [filename], paths: [filename],
when: 'always' when: 'always'
} }
...@@ -58,6 +59,7 @@ describe Ci::BuildRunnerPresenter do ...@@ -58,6 +59,7 @@ describe Ci::BuildRunnerPresenter do
end end
end end
end end
end
context "when option has both archive and reports specification" do context "when option has both archive and reports specification" do
let(:report) { { junit: ['junit.xml'] } } let(:report) { { junit: ['junit.xml'] } }
......
...@@ -5,6 +5,7 @@ describe API::Applications, :api do ...@@ -5,6 +5,7 @@ describe API::Applications, :api do
let(:admin_user) { create(:user, admin: true) } let(:admin_user) { create(:user, admin: true) }
let(:user) { create(:user, admin: false) } let(:user) { create(:user, admin: false) }
let!(:application) { create(:application, name: 'another_application', redirect_uri: 'http://other_application.url', scopes: '') }
describe 'POST /applications' do describe 'POST /applications' do
context 'authenticated and authorized user' do context 'authenticated and authorized user' do
...@@ -15,7 +16,7 @@ describe API::Applications, :api do ...@@ -15,7 +16,7 @@ describe API::Applications, :api do
application = Doorkeeper::Application.find_by(name: 'application_name', redirect_uri: 'http://application.url') application = Doorkeeper::Application.find_by(name: 'application_name', redirect_uri: 'http://application.url')
expect(response).to have_http_status 201 expect(response).to have_gitlab_http_status(201)
expect(json_response).to be_a Hash expect(json_response).to be_a Hash
expect(json_response['application_id']).to eq application.uid expect(json_response['application_id']).to eq application.uid
expect(json_response['secret']).to eq application.secret expect(json_response['secret']).to eq application.secret
...@@ -27,7 +28,7 @@ describe API::Applications, :api do ...@@ -27,7 +28,7 @@ describe API::Applications, :api do
post api('/applications', admin_user), name: 'application_name', redirect_uri: 'wrong_url_format', scopes: '' post api('/applications', admin_user), name: 'application_name', redirect_uri: 'wrong_url_format', scopes: ''
end.not_to change { Doorkeeper::Application.count } end.not_to change { Doorkeeper::Application.count }
expect(response).to have_http_status 400 expect(response).to have_gitlab_http_status(400)
expect(json_response).to be_a Hash expect(json_response).to be_a Hash
expect(json_response['message']['redirect_uri'][0]).to eq('must be an absolute URI.') expect(json_response['message']['redirect_uri'][0]).to eq('must be an absolute URI.')
end end
...@@ -37,7 +38,7 @@ describe API::Applications, :api do ...@@ -37,7 +38,7 @@ describe API::Applications, :api do
post api('/applications', admin_user), redirect_uri: 'http://application.url', scopes: '' post api('/applications', admin_user), redirect_uri: 'http://application.url', scopes: ''
end.not_to change { Doorkeeper::Application.count } end.not_to change { Doorkeeper::Application.count }
expect(response).to have_http_status 400 expect(response).to have_gitlab_http_status(400)
expect(json_response).to be_a Hash expect(json_response).to be_a Hash
expect(json_response['error']).to eq('name is missing') expect(json_response['error']).to eq('name is missing')
end end
...@@ -47,7 +48,7 @@ describe API::Applications, :api do ...@@ -47,7 +48,7 @@ describe API::Applications, :api do
post api('/applications', admin_user), name: 'application_name', scopes: '' post api('/applications', admin_user), name: 'application_name', scopes: ''
end.not_to change { Doorkeeper::Application.count } end.not_to change { Doorkeeper::Application.count }
expect(response).to have_http_status 400 expect(response).to have_gitlab_http_status(400)
expect(json_response).to be_a Hash expect(json_response).to be_a Hash
expect(json_response['error']).to eq('redirect_uri is missing') expect(json_response['error']).to eq('redirect_uri is missing')
end end
...@@ -57,7 +58,7 @@ describe API::Applications, :api do ...@@ -57,7 +58,7 @@ describe API::Applications, :api do
post api('/applications', admin_user), name: 'application_name', redirect_uri: 'http://application.url' post api('/applications', admin_user), name: 'application_name', redirect_uri: 'http://application.url'
end.not_to change { Doorkeeper::Application.count } end.not_to change { Doorkeeper::Application.count }
expect(response).to have_http_status 400 expect(response).to have_gitlab_http_status(400)
expect(json_response).to be_a Hash expect(json_response).to be_a Hash
expect(json_response['error']).to eq('scopes is missing') expect(json_response['error']).to eq('scopes is missing')
end end
...@@ -69,7 +70,7 @@ describe API::Applications, :api do ...@@ -69,7 +70,7 @@ describe API::Applications, :api do
post api('/applications', user), name: 'application_name', redirect_uri: 'http://application.url', scopes: '' post api('/applications', user), name: 'application_name', redirect_uri: 'http://application.url', scopes: ''
end.not_to change { Doorkeeper::Application.count } end.not_to change { Doorkeeper::Application.count }
expect(response).to have_http_status 403 expect(response).to have_gitlab_http_status(403)
end end
end end
...@@ -79,7 +80,62 @@ describe API::Applications, :api do ...@@ -79,7 +80,62 @@ describe API::Applications, :api do
post api('/applications'), name: 'application_name', redirect_uri: 'http://application.url' post api('/applications'), name: 'application_name', redirect_uri: 'http://application.url'
end.not_to change { Doorkeeper::Application.count } end.not_to change { Doorkeeper::Application.count }
expect(response).to have_http_status 401 expect(response).to have_gitlab_http_status(401)
end
end
end
describe 'GET /applications' do
context 'authenticated and authorized user' do
it 'can list application' do
get api('/applications', admin_user)
expect(response).to have_gitlab_http_status(200)
expect(json_response).to be_a(Array)
end
end
context 'authorized user without authorization' do
it 'cannot list application' do
get api('/applications', user)
expect(response).to have_gitlab_http_status(403)
end
end
context 'non-authenticated user' do
it 'cannot list application' do
get api('/applications')
expect(response).to have_gitlab_http_status(401)
end
end
end
describe 'DELETE /applications/:id' do
context 'authenticated and authorized user' do
it 'can delete an application' do
expect do
delete api("/applications/#{application.id}", admin_user)
end.to change { Doorkeeper::Application.count }.by(-1)
expect(response).to have_gitlab_http_status(204)
end
end
context 'authorized user without authorization' do
it 'cannot delete an application' do
delete api("/applications/#{application.id}", user)
expect(response).to have_gitlab_http_status(403)
end
end
context 'non-authenticated user' do
it 'cannot delete an application' do
delete api("/applications/#{application.id}")
expect(response).to have_gitlab_http_status(401)
end end
end end
end end
......
...@@ -11,213 +11,135 @@ describe Ci::ProcessBuildService, '#execute' do ...@@ -11,213 +11,135 @@ describe Ci::ProcessBuildService, '#execute' do
project.add_maintainer(user) project.add_maintainer(user)
end end
shared_examples_for 'Enqueuing properly' do |valid_statuses_for_when| context 'when build has on_success option' do
valid_statuses_for_when.each do |status_for_prior_stages| let(:build) { create(:ci_build, :created, when: :on_success, user: user, project: project) }
context "when status for prior stages is #{status_for_prior_stages}" do
let(:current_status) { status_for_prior_stages }
%w[created skipped manual scheduled].each do |status| context 'when current status is success' do
context "when build status is #{status}" do let(:current_status) { 'success' }
let(:build) { create(:ci_build, status.to_sym, when: when_option, user: user, project: project) }
it 'enqueues the build' do it 'changes the build status' do
expect { subject }.to change { build.status }.to('pending') expect { subject }.to change { build.status }.to('pending')
end end
end end
end
%w[pending running success failed canceled].each do |status| context 'when current status is failed' do
context "when build status is #{status}" do let(:current_status) { 'failed' }
let(:build) { create(:ci_build, status.to_sym, when: when_option, user: user, project: project) }
it 'does not change the build status' do it 'does not change the build status' do
expect { subject }.not_to change { build.status } expect { subject }.to change { build.status }.to('skipped')
end
end
end end
end end
end end
(HasStatus::AVAILABLE_STATUSES - valid_statuses_for_when).each do |status_for_prior_stages| context 'when build has on_failure option' do
let(:current_status) { status_for_prior_stages } let(:build) { create(:ci_build, :created, when: :on_failure, user: user, project: project) }
context "when status for prior stages is #{status_for_prior_stages}" do context 'when current status is success' do
%w[created pending].each do |status| let(:current_status) { 'success' }
context "when build status is #{status}" do
let(:build) { create(:ci_build, status.to_sym, when: when_option, user: user, project: project) }
it 'skips the build' do it 'changes the build status' do
expect { subject }.to change { build.status }.to('skipped') expect { subject }.to change { build.status }.to('skipped')
end end
end end
end
(HasStatus::AVAILABLE_STATUSES - %w[created pending]).each do |status| context 'when current status is failed' do
context "when build status is #{status}" do let(:current_status) { 'failed' }
let(:build) { create(:ci_build, status.to_sym, when: when_option, user: user, project: project) }
it 'does not change build status' do it 'does not change the build status' do
expect { subject }.not_to change { build.status } expect { subject }.to change { build.status }.to('pending')
end
end
end
end end
end end
end end
shared_examples_for 'Actionizing properly' do |valid_statuses_for_when| context 'when build has always option' do
valid_statuses_for_when.each do |status_for_prior_stages| let(:build) { create(:ci_build, :created, when: :always, user: user, project: project) }
context "when status for prior stages is #{status_for_prior_stages}" do
let(:current_status) { status_for_prior_stages }
%w[created].each do |status| context 'when current status is success' do
context "when build status is #{status}" do let(:current_status) { 'success' }
let(:build) { create(:ci_build, status.to_sym, :actionable, user: user, project: project) }
it 'enqueues the build' do it 'changes the build status' do
expect { subject }.to change { build.status }.to('manual') expect { subject }.to change { build.status }.to('pending')
end
end end
end end
%w[manual skipped pending running success failed canceled scheduled].each do |status| context 'when current status is failed' do
context "when build status is #{status}" do let(:current_status) { 'failed' }
let(:build) { create(:ci_build, status.to_sym, :actionable, user: user, project: project) }
it 'does not change the build status' do it 'does not change the build status' do
expect { subject }.not_to change { build.status } expect { subject }.to change { build.status }.to('pending')
end
end
end end
end end
end end
(HasStatus::AVAILABLE_STATUSES - valid_statuses_for_when).each do |status_for_prior_stages| context 'when build has manual option' do
let(:current_status) { status_for_prior_stages } let(:build) { create(:ci_build, :created, :actionable, user: user, project: project) }
context "when status for prior stages is #{status_for_prior_stages}" do context 'when current status is success' do
%w[created pending].each do |status| let(:current_status) { 'success' }
context "when build status is #{status}" do
let(:build) { create(:ci_build, status.to_sym, :actionable, user: user, project: project) }
it 'skips the build' do it 'changes the build status' do
expect { subject }.to change { build.status }.to('skipped') expect { subject }.to change { build.status }.to('manual')
end
end end
end end
(HasStatus::AVAILABLE_STATUSES - %w[created pending]).each do |status| context 'when current status is failed' do
context "when build status is #{status}" do let(:current_status) { 'failed' }
let(:build) { create(:ci_build, status.to_sym, :actionable, user: user, project: project) }
it 'does not change build status' do it 'does not change the build status' do
expect { subject }.not_to change { build.status } expect { subject }.to change { build.status }.to('skipped')
end
end
end
end end
end end
end end
shared_examples_for 'Scheduling properly' do |valid_statuses_for_when| context 'when build has delayed option' do
valid_statuses_for_when.each do |status_for_prior_stages| before do
context "when status for prior stages is #{status_for_prior_stages}" do allow(Ci::BuildScheduleWorker).to receive(:perform_at) { }
let(:current_status) { status_for_prior_stages }
%w[created].each do |status|
context "when build status is #{status}" do
let(:build) { create(:ci_build, status.to_sym, :schedulable, user: user, project: project) }
it 'enqueues the build' do
expect { subject }.to change { build.status }.to('scheduled')
end
end
end end
%w[manual skipped pending running success failed canceled scheduled].each do |status| let(:build) { create(:ci_build, :created, :schedulable, user: user, project: project) }
context "when build status is #{status}" do
let(:build) { create(:ci_build, status.to_sym, :schedulable, user: user, project: project) }
it 'does not change the build status' do context 'when ci_enable_scheduled_build is enabled' do
expect { subject }.not_to change { build.status } before do
end stub_feature_flags(ci_enable_scheduled_build: true)
end
end
end
end end
(HasStatus::AVAILABLE_STATUSES - valid_statuses_for_when).each do |status_for_prior_stages| context 'when current status is success' do
let(:current_status) { status_for_prior_stages } let(:current_status) { 'success' }
context "when status for prior stages is #{status_for_prior_stages}" do
%w[created pending].each do |status|
context "when build status is #{status}" do
let(:build) { create(:ci_build, status.to_sym, :schedulable, user: user, project: project) }
it 'skips the build' do it 'changes the build status' do
expect { subject }.to change { build.status }.to('skipped') expect { subject }.to change { build.status }.to('scheduled')
end
end end
end end
(HasStatus::AVAILABLE_STATUSES - %w[created pending]).each do |status| context 'when current status is failed' do
context "when build status is #{status}" do let(:current_status) { 'failed' }
let(:build) { create(:ci_build, status.to_sym, :schedulable, user: user, project: project) }
it 'does not change build status' do it 'does not change the build status' do
expect { subject }.not_to change { build.status } expect { subject }.to change { build.status }.to('skipped')
end
end
end
end
end
end end
context 'when build has on_success option' do
let(:when_option) { :on_success }
it_behaves_like 'Enqueuing properly', %w[success skipped]
end end
context 'when build has on_failure option' do
let(:when_option) { :on_failure }
it_behaves_like 'Enqueuing properly', %w[failed]
end end
context 'when build has always option' do context 'when ci_enable_scheduled_build is disabled' do
let(:when_option) { :always } before do
stub_feature_flags(ci_enable_scheduled_build: false)
it_behaves_like 'Enqueuing properly', %w[success failed skipped]
end end
context 'when build has manual option' do context 'when current status is success' do
let(:when_option) { :manual } let(:current_status) { 'success' }
it_behaves_like 'Actionizing properly', %w[success skipped] it 'changes the build status' do
expect { subject }.to change { build.status }.to('manual')
end end
context 'when build has delayed option' do
let(:when_option) { :delayed }
before do
allow(Ci::BuildScheduleWorker).to receive(:perform_at) { }
end end
context 'when ci_enable_scheduled_build is enabled' do context 'when current status is failed' do
before do let(:current_status) { 'failed' }
stub_feature_flags(ci_enable_scheduled_build: true)
end
it_behaves_like 'Scheduling properly', %w[success skipped] it 'does not change the build status' do
expect { subject }.to change { build.status }.to('skipped')
end end
context 'when ci_enable_scheduled_build is enabled' do
before do
stub_feature_flags(ci_enable_scheduled_build: false)
end end
it_behaves_like 'Actionizing properly', %w[success skipped]
end end
end end
end end
...@@ -2,17 +2,87 @@ require 'spec_helper' ...@@ -2,17 +2,87 @@ require 'spec_helper'
describe Clusters::CreateService do describe Clusters::CreateService do
let(:access_token) { 'xxx' } let(:access_token) { 'xxx' }
let(:project) { create(:project) }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:service) { described_class.new(user, params) }
describe '#execute' do
before do
allow(ClusterProvisionWorker).to receive(:perform_async)
end
shared_context 'valid cluster create params' do
let(:params) do
{
name: 'test-cluster',
provider_type: :gcp,
provider_gcp_attributes: {
gcp_project_id: 'gcp-project',
zone: 'us-central1-a',
num_nodes: 1,
machine_type: 'machine_type-a',
legacy_abac: 'true'
}
}
end
end
subject { described_class.new(user, params).execute(project: project, access_token: access_token) } shared_context 'invalid cluster create params' do
let(:params) do
{
name: 'test-cluster',
provider_type: :gcp,
provider_gcp_attributes: {
gcp_project_id: '!!!!!!!',
zone: 'us-central1-a',
num_nodes: 1,
machine_type: 'machine_type-a'
}
}
end
end
shared_examples 'create cluster service success' do
it 'creates a cluster object and performs a worker' do
expect(ClusterProvisionWorker).to receive(:perform_async)
expect { subject }
.to change { Clusters::Cluster.count }.by(1)
.and change { Clusters::Providers::Gcp.count }.by(1)
expect(subject.name).to eq('test-cluster')
expect(subject.user).to eq(user)
expect(subject.provider.gcp_project_id).to eq('gcp-project')
expect(subject.provider.zone).to eq('us-central1-a')
expect(subject.provider.num_nodes).to eq(1)
expect(subject.provider.machine_type).to eq('machine_type-a')
expect(subject.provider.access_token).to eq(access_token)
expect(subject.provider).to be_legacy_abac
expect(subject.platform).to be_nil
end
end
shared_examples 'create cluster service error' do
it 'returns an error' do
expect(ClusterProvisionWorker).not_to receive(:perform_async)
expect { subject }.to change { Clusters::Cluster.count }.by(0)
expect(subject.errors[:"provider_gcp.gcp_project_id"]).to be_present
end
end
context 'create cluster for project' do
let(:project) { create(:project) }
subject { service.execute(project: project, access_token: access_token) }
context 'when provider is gcp' do
context 'when project has no clusters' do context 'when project has no clusters' do
context 'when correct params' do context 'when correct params' do
include_context 'valid cluster create params' include_context 'valid cluster create params'
include_examples 'create cluster service success' include_examples 'create cluster service success'
it 'associates project to the cluster' do
expect(subject.project).to eq(project)
end
end end
context 'when invalid params' do context 'when invalid params' do
...@@ -32,4 +102,5 @@ describe Clusters::CreateService do ...@@ -32,4 +102,5 @@ describe Clusters::CreateService do
end end
end end
end end
end
end end
shared_context 'valid cluster create params' do
let(:params) do
{
name: 'test-cluster',
provider_type: :gcp,
provider_gcp_attributes: {
gcp_project_id: 'gcp-project',
zone: 'us-central1-a',
num_nodes: 1,
machine_type: 'machine_type-a',
legacy_abac: 'true'
}
}
end
end
shared_context 'invalid cluster create params' do
let(:params) do
{
name: 'test-cluster',
provider_type: :gcp,
provider_gcp_attributes: {
gcp_project_id: '!!!!!!!',
zone: 'us-central1-a',
num_nodes: 1,
machine_type: 'machine_type-a'
}
}
end
end
shared_examples 'create cluster service success' do
it 'creates a cluster object and performs a worker' do
expect(ClusterProvisionWorker).to receive(:perform_async)
expect { subject }
.to change { Clusters::Cluster.count }.by(1)
.and change { Clusters::Providers::Gcp.count }.by(1)
expect(subject.name).to eq('test-cluster')
expect(subject.user).to eq(user)
expect(subject.project).to eq(project)
expect(subject.provider.gcp_project_id).to eq('gcp-project')
expect(subject.provider.zone).to eq('us-central1-a')
expect(subject.provider.num_nodes).to eq(1)
expect(subject.provider.machine_type).to eq('machine_type-a')
expect(subject.provider.access_token).to eq(access_token)
expect(subject.provider).to be_legacy_abac
expect(subject.platform).to be_nil
end
end
shared_examples 'create cluster service error' do
it 'returns an error' do
expect(ClusterProvisionWorker).not_to receive(:perform_async)
expect { subject }.to change { Clusters::Cluster.count }.by(0)
expect(subject.errors[:"provider_gcp.gcp_project_id"]).to be_present
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