Commit 2a46ef4d authored by Robert Speicher's avatar Robert Speicher

Merge branch 'ce-to-ee-2018-10-22' into 'master'

CE upstream - 2018-10-22 13:22 UTC

Closes gitlab-ce#52690, #7996, gitlab-ce#52559, gitlab-ce#52728, and gitlab-qa#142

See merge request gitlab-org/gitlab-ee!8029
parents 59834c30 75c5ab57
...@@ -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 });
reader.readAsDataURL(file);
if (isText) {
reader.readAsText(file);
} else {
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
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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