Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
71c5863d7b
commit
e20baee820
|
|
@ -0,0 +1,32 @@
|
|||
<!--Please answer the below questions to the best of your ability.-->
|
||||
|
||||
#### What's this issue all about? (Background and context)
|
||||
|
||||
#### What hypotheses and/or assumptions do you have?
|
||||
|
||||
#### What questions are you trying to answer?
|
||||
|
||||
#### What research methodology do you intend to use?
|
||||
|
||||
<!-- What needs to be answered to move work forward? If you have a completed Opportunity Canvas include a link.-->
|
||||
|
||||
#### What persona, persona segment, or customer type experiences the problem most acutely?
|
||||
|
||||
#### What business decisions will be made based on this information?
|
||||
|
||||
#### What, if any, relevant prior research already exists?
|
||||
|
||||
<!-- Have a look at our UXR_Insights repo: https://gitlab.com/gitlab-org/uxr_insights -->
|
||||
|
||||
#### Who will be leading the research?
|
||||
|
||||
#### What timescales do you have in mind for the research?
|
||||
|
||||
#### Relevant links (problem validation issue, design issue, script, prototype, notes, etc.)
|
||||
|
||||
<!-- #### TODO Checklist
|
||||
Consider adding a checklist in order to keep track of what stage the research is up to. Some possible checklist templates are here:
|
||||
https://about.gitlab.com/handbook/engineering/ux/ux-research-training/templates-resources-for-research-studies/#checklists
|
||||
-->
|
||||
|
||||
/label ~"workflow::solution validation"
|
||||
|
|
@ -204,7 +204,6 @@ Gitlab/DuplicateSpecLocation:
|
|||
Exclude:
|
||||
- ee/spec/helpers/auth_helper_spec.rb
|
||||
- ee/spec/lib/gitlab/gl_repository_spec.rb
|
||||
- ee/spec/lib/gitlab/usage_data_spec.rb
|
||||
- ee/spec/models/namespace_spec.rb
|
||||
- ee/spec/models/note_spec.rb
|
||||
- ee/spec/serializers/environment_entity_spec.rb
|
||||
|
|
@ -215,7 +214,6 @@ Gitlab/DuplicateSpecLocation:
|
|||
- ee/spec/services/system_hooks_service_spec.rb
|
||||
- ee/spec/helpers/ee/auth_helper_spec.rb
|
||||
- ee/spec/lib/ee/gitlab/gl_repository_spec.rb
|
||||
- ee/spec/lib/ee/gitlab/usage_data_spec.rb
|
||||
- ee/spec/models/ee/namespace_spec.rb
|
||||
- ee/spec/models/ee/note_spec.rb
|
||||
- ee/spec/serializers/ee/environment_entity_spec.rb
|
||||
|
|
@ -382,3 +380,6 @@ Style/FloatDivision:
|
|||
|
||||
Cop/BanCatchThrow:
|
||||
Enabled: true
|
||||
|
||||
Performance/ReadlinesEach:
|
||||
Enabled: true
|
||||
|
|
|
|||
|
|
@ -8,13 +8,20 @@ import Flash from '../flash';
|
|||
import Poll from '../lib/utils/poll';
|
||||
import initSettingsPanels from '../settings_panels';
|
||||
import eventHub from './event_hub';
|
||||
import { APPLICATION_STATUS, INGRESS, INGRESS_DOMAIN_SUFFIX, CROSSPLANE } from './constants';
|
||||
import {
|
||||
APPLICATION_STATUS,
|
||||
INGRESS,
|
||||
INGRESS_DOMAIN_SUFFIX,
|
||||
CROSSPLANE,
|
||||
KNATIVE,
|
||||
} from './constants';
|
||||
import ClustersService from './services/clusters_service';
|
||||
import ClustersStore from './stores/clusters_store';
|
||||
import Applications from './components/applications.vue';
|
||||
import RemoveClusterConfirmation from './components/remove_cluster_confirmation.vue';
|
||||
import setupToggleButtons from '../toggle_buttons';
|
||||
import initProjectSelectDropdown from '~/project_select';
|
||||
import initServerlessSurveyBanner from '~/serverless/survey_banner';
|
||||
|
||||
const Environments = () => import('ee_component/clusters/components/environments.vue');
|
||||
|
||||
|
|
@ -326,6 +333,10 @@ export default class Clusters {
|
|||
this.store.state.applications[INGRESS],
|
||||
);
|
||||
}
|
||||
|
||||
if (this.store.state.applications[KNATIVE]?.status === APPLICATION_STATUS.INSTALLED) {
|
||||
initServerlessSurveyBanner();
|
||||
}
|
||||
}
|
||||
|
||||
showToken() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import ServerlessBundle from '~/serverless/serverless_bundle';
|
||||
import initServerlessSurveyBanner from '~/serverless/survey_banner';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
initServerlessSurveyBanner();
|
||||
new ServerlessBundle(); // eslint-disable-line no-new
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
import Vue from 'vue';
|
||||
import { setUrlParams } from '~/lib/utils/url_utility';
|
||||
import SurveyBanner from './survey_banner.vue';
|
||||
|
||||
let bannerInstance;
|
||||
const SURVEY_URL_BASE = 'https://gitlab.fra1.qualtrics.com/jfe/form/SV_00PfofFfY9s8Shf';
|
||||
|
||||
export default function initServerlessSurveyBanner() {
|
||||
const el = document.querySelector('.js-serverless-survey-banner');
|
||||
if (el && !bannerInstance) {
|
||||
const { userName, userEmail } = el.dataset;
|
||||
|
||||
// pre-populate survey fields
|
||||
const surveyUrl = setUrlParams(
|
||||
{
|
||||
Q_PopulateResponse: JSON.stringify({
|
||||
QID1: userEmail,
|
||||
QID2: userName,
|
||||
QID16: '1', // selects "yes" to "do you currently use GitLab?"
|
||||
}),
|
||||
},
|
||||
SURVEY_URL_BASE,
|
||||
);
|
||||
|
||||
bannerInstance = new Vue({
|
||||
el,
|
||||
render(createElement) {
|
||||
return createElement(SurveyBanner, {
|
||||
props: {
|
||||
surveyUrl,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<script>
|
||||
import Cookies from 'js-cookie';
|
||||
import { parseBoolean } from '~/lib/utils/common_utils';
|
||||
import { GlBanner } from '@gitlab/ui';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlBanner,
|
||||
},
|
||||
props: {
|
||||
surveyUrl: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visible: true,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
if (parseBoolean(Cookies.get('hide_serverless_survey'))) {
|
||||
this.visible = false;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClose() {
|
||||
Cookies.set('hide_serverless_survey', 'true', { expires: 365 * 10 });
|
||||
this.visible = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<gl-banner
|
||||
v-if="visible"
|
||||
class="mt-4"
|
||||
:title="s__('Serverless|Help shape the future of Serverless at GitLab')"
|
||||
:button-text="s__('Serverless|Sign up for First Look')"
|
||||
:button-link="surveyUrl"
|
||||
@close="handleClose"
|
||||
>
|
||||
<p>
|
||||
{{
|
||||
s__(
|
||||
'Serverless|We are continually striving to improve our Serverless functionality. As a Knative user, we would love to hear how we can make this experience better for you. Sign up for GitLab First Look today and we will be in touch shortly.',
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
</gl-banner>
|
||||
</template>
|
||||
|
|
@ -8,7 +8,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
|
|||
# ApplicationSetting model uses Gitlab::ThreadMemoryCache for caching and the
|
||||
# cache might be stale immediately after an update.
|
||||
# https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30233
|
||||
before_action :set_application_setting
|
||||
before_action :set_application_setting, except: :integrations
|
||||
|
||||
before_action :whitelist_query_limiting, only: [:usage_data]
|
||||
|
||||
|
|
@ -29,12 +29,11 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
|
|||
|
||||
def integrations
|
||||
if Feature.enabled?(:instance_level_integrations)
|
||||
# TODO: Update this with actual integrations
|
||||
# To be fixed with https://gitlab.com/gitlab-org/gitlab/-/issues/199388
|
||||
@integrations = []
|
||||
@integrations = Service.find_or_initialize_instances.sort_by(&:title)
|
||||
else
|
||||
set_application_setting
|
||||
perform_update if submitted?
|
||||
end
|
||||
|
||||
perform_update if submitted?
|
||||
end
|
||||
|
||||
def update
|
||||
|
|
|
|||
|
|
@ -9,6 +9,11 @@ class Admin::ProjectsController < Admin::ApplicationController
|
|||
def index
|
||||
params[:sort] ||= 'latest_activity_desc'
|
||||
@sort = params[:sort]
|
||||
|
||||
if params[:last_repository_check_failed].present? && params[:archived].nil?
|
||||
params[:archived] = true
|
||||
end
|
||||
|
||||
@projects = Admin::ProjectsFinder.new(params: params, current_user: current_user).execute
|
||||
|
||||
respond_to do |format|
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ class Admin::ServicesController < Admin::ApplicationController
|
|||
before_action :service, only: [:edit, :update]
|
||||
|
||||
def index
|
||||
@services = Service.find_or_create_templates
|
||||
@services = Service.find_or_create_templates.sort_by(&:title)
|
||||
end
|
||||
|
||||
def edit
|
||||
|
|
|
|||
|
|
@ -12,5 +12,8 @@ module Types
|
|||
|
||||
field :id, GraphQL::ID_TYPE, null: false,
|
||||
description: 'ID of the environment'
|
||||
|
||||
field :state, GraphQL::STRING_TYPE, null: false,
|
||||
description: 'State of the environment, for example: available/stopped'
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -160,9 +160,7 @@ module BulkInsertSafe
|
|||
|
||||
attributes = {}
|
||||
column_names.each do |name|
|
||||
value = item.read_attribute(name)
|
||||
value = item.type_for_attribute(name).serialize(value) # rubocop:disable Cop/ActiveRecordSerialize
|
||||
attributes[name] = value
|
||||
attributes[name] = item.read_attribute(name)
|
||||
end
|
||||
|
||||
_bulk_insert_reject_primary_key!(attributes, item.class.primary_key)
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ class Service < ApplicationRecord
|
|||
scope :without_defaults, -> { where(default: false) }
|
||||
scope :by_type, -> (type) { where(type: type) }
|
||||
scope :templates, -> { where(template: true, type: available_services_types) }
|
||||
scope :instances, -> { where(instance: true, type: available_services_types) }
|
||||
|
||||
scope :push_hooks, -> { where(push_events: true, active: true) }
|
||||
scope :tag_push_hooks, -> { where(tag_push_events: true, active: true) }
|
||||
|
|
@ -260,17 +261,16 @@ class Service < ApplicationRecord
|
|||
self.category == :issue_tracker
|
||||
end
|
||||
|
||||
# Find all service templates; if some of them do not exist, create them
|
||||
# within a transaction to perform the lowest possible SQL queries.
|
||||
def self.find_or_create_templates
|
||||
create_nonexistent_templates
|
||||
templates
|
||||
end
|
||||
|
||||
private_class_method def self.create_nonexistent_templates
|
||||
nonexistent_services = available_services_types - templates.map(&:type)
|
||||
nonexistent_services = list_nonexistent_services_for(templates)
|
||||
return if nonexistent_services.empty?
|
||||
|
||||
# Create within a transaction to perform the lowest possible SQL queries.
|
||||
transaction do
|
||||
nonexistent_services.each do |service_type|
|
||||
service_type.constantize.create(template: true)
|
||||
|
|
@ -278,6 +278,20 @@ class Service < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def self.find_or_initialize_instances
|
||||
instances + build_nonexistent_instances
|
||||
end
|
||||
|
||||
private_class_method def self.build_nonexistent_instances
|
||||
list_nonexistent_services_for(instances).map do |service_type|
|
||||
service_type.constantize.new
|
||||
end
|
||||
end
|
||||
|
||||
private_class_method def self.list_nonexistent_services_for(scope)
|
||||
available_services_types - scope.map(&:type)
|
||||
end
|
||||
|
||||
def self.available_services_names
|
||||
service_names = %w[
|
||||
alerts
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
%th Service
|
||||
%th Description
|
||||
%th Last edit
|
||||
- @services.sort_by(&:title).each do |service|
|
||||
- @services.each do |service|
|
||||
%tr
|
||||
%td
|
||||
= boolean_to_icon service.activated?
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@
|
|||
.js-cluster-application-notice
|
||||
.flash-container
|
||||
|
||||
.js-serverless-survey-banner{ data: { user_name: current_user.name, user_email: current_user.email } }
|
||||
|
||||
%h4= @cluster.name
|
||||
= render 'banner'
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
help_path: help_page_path('user/project/clusters/serverless/index') } }
|
||||
|
||||
%div{ class: [('limit-container-width' unless fluid_layout)] }
|
||||
.js-serverless-survey-banner{ data: { user_name: current_user.name, user_email: current_user.email } }
|
||||
|
||||
.js-serverless-functions-notice
|
||||
.flash-container
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
%th{ role: 'columnheader', scope: 'col', 'aria-colindex': 4 }= _('Last updated')
|
||||
|
||||
%tbody{ role: 'rowgroup' }
|
||||
- @integrations&.each do |integration|
|
||||
- @integrations.each do |integration|
|
||||
%tr{ role: 'row' }
|
||||
%td{ role: 'cell', 'aria-colindex': 1 }
|
||||
= boolean_to_icon integration.activated?
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix archived corrupted projects not displaying in admin
|
||||
merge_request: 25171
|
||||
author: erickcspice
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Provide link to a survey for Knative users
|
||||
merge_request: 23025
|
||||
author:
|
||||
type: other
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# This fix is needed to properly support
|
||||
# columns that perform data mutation to a SQL datatype
|
||||
# ex. would be `jsonb` and `enum`
|
||||
#
|
||||
# This is covered by tests in `BulkInsertSafe`
|
||||
# that validates handling of different data types
|
||||
|
||||
if Rails.gem_version > Gem::Version.new("6.0.2")
|
||||
raise Gem::DependencyError,
|
||||
"Remove patch once the https://github.com/rails/rails/pull/38763 is included"
|
||||
end
|
||||
|
||||
module ActiveRecordInsertAllBuilderMixin
|
||||
def extract_types_from_columns_on(table_name, keys:)
|
||||
columns = connection.schema_cache.columns_hash(table_name)
|
||||
|
||||
unknown_column = (keys - columns.keys).first
|
||||
raise UnknownAttributeError.new(model.new, unknown_column) if unknown_column
|
||||
|
||||
keys.index_with { |key| model.type_for_attribute(key) }
|
||||
end
|
||||
end
|
||||
|
||||
ActiveRecord::InsertAll::Builder.prepend(ActiveRecordInsertAllBuilderMixin)
|
||||
|
|
@ -2,19 +2,28 @@
|
|||
|
||||
require_relative File.expand_path('../../lib/gitlab/danger/commit_linter', __dir__)
|
||||
|
||||
URL_GIT_COMMIT = "https://chris.beams.io/posts/git-commit/"
|
||||
COMMIT_MESSAGE_GUIDELINES = "https://docs.gitlab.com/ee/development/contributing/merge_request_workflow.html#commit-messages-guidelines"
|
||||
MORE_INFO = "For more information, take a look at our [Commit message guidelines](#{COMMIT_MESSAGE_GUIDELINES})."
|
||||
THE_DANGER_JOB_TEXT = "the `danger-review` job"
|
||||
MAX_COMMITS_COUNT = 10
|
||||
|
||||
def gitlab_danger
|
||||
@gitlab_danger ||= GitlabDanger.new(helper.gitlab_helper)
|
||||
end
|
||||
|
||||
def fail_commit(commit, message)
|
||||
self.fail("#{commit.sha}: #{message}")
|
||||
def fail_commit(commit, message, more_info: true)
|
||||
self.fail(build_message(commit, message, more_info: more_info))
|
||||
end
|
||||
|
||||
def warn_commit(commit, message)
|
||||
self.warn("#{commit.sha}: #{message}")
|
||||
def warn_commit(commit, message, more_info: true)
|
||||
self.warn(build_message(commit, message, more_info: more_info))
|
||||
end
|
||||
|
||||
def build_message(commit, message, more_info: true)
|
||||
[message].tap do |full_message|
|
||||
full_message << ". #{MORE_INFO}" if more_info
|
||||
full_message.unshift("#{commit.sha}: ") if commit.sha
|
||||
end.join
|
||||
end
|
||||
|
||||
def squash_mr?
|
||||
|
|
@ -25,6 +34,10 @@ def wip_mr?
|
|||
gitlab_danger.ci? ? gitlab.mr_json['work_in_progress'] : false
|
||||
end
|
||||
|
||||
def danger_job_link
|
||||
gitlab_danger.ci? ? "[#{THE_DANGER_JOB_TEXT}](#{ENV['CI_JOB_URL']})" : THE_DANGER_JOB_TEXT
|
||||
end
|
||||
|
||||
# Perform various checks against commits. We're not using
|
||||
# https://github.com/jonallured/danger-commit_lint because its output is not
|
||||
# very helpful, and it doesn't offer the means of ignoring merge commits.
|
||||
|
|
@ -42,11 +55,11 @@ def lint_commit(commit)
|
|||
return linter if linter.fixup? && squash_mr?
|
||||
|
||||
if linter.fixup?
|
||||
msg = 'Squash or fixup commits must be squashed before merge, or enable squash merge option'
|
||||
msg = "Squash or fixup commits must be squashed before merge, or enable squash merge option and re-run #{danger_job_link}."
|
||||
if wip_mr? || squash_mr?
|
||||
warn_commit(commit, msg)
|
||||
warn_commit(commit, msg, more_info: false)
|
||||
else
|
||||
fail_commit(commit, msg)
|
||||
fail_commit(commit, msg, more_info: false)
|
||||
end
|
||||
|
||||
# Makes no sense to process other rules for fixup commits, they trigger just more noise
|
||||
|
|
@ -56,7 +69,7 @@ def lint_commit(commit)
|
|||
# Fail if a suggestion commit is used and squash is not enabled
|
||||
if linter.suggestion?
|
||||
unless squash_mr?
|
||||
fail_commit(commit, "If you are applying suggestions, enable squash in the merge request and re-run the `danger-review` job")
|
||||
fail_commit(commit, "If you are applying suggestions, enable squash in the merge request and re-run #{danger_job_link}.", more_info: false)
|
||||
end
|
||||
|
||||
return linter
|
||||
|
|
@ -93,18 +106,12 @@ def lint_commits(commits)
|
|||
|
||||
if multi_line_commit_linter && multi_line_commit_linter.failed?
|
||||
warn_or_fail_commits(multi_line_commit_linter)
|
||||
fail_message('The commit message that will be used in the squash commit does not meet our Git commit message standards.')
|
||||
else
|
||||
title_linter = lint_mr_title(gitlab.mr_json['title'])
|
||||
if title_linter.failed?
|
||||
warn_or_fail_commits(title_linter)
|
||||
fail_message('The merge request title that will be used in the squash commit does not meet our Git commit message standards.')
|
||||
end
|
||||
end
|
||||
else
|
||||
if failed_commit_linters.any?
|
||||
fail_message('One or more commit messages do not meet our Git commit message standards.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -123,40 +130,4 @@ def warn_or_fail_commits(failed_linters, default_to_fail: true)
|
|||
end
|
||||
end
|
||||
|
||||
def fail_message(intro)
|
||||
markdown(<<~MARKDOWN)
|
||||
## Commit message standards
|
||||
|
||||
#{intro}
|
||||
|
||||
For more information on how to write a good commit message, take a look at
|
||||
[How to Write a Git Commit Message](#{URL_GIT_COMMIT}).
|
||||
|
||||
Here is an example of a good commit message:
|
||||
|
||||
Reject ruby interpolation in externalized strings
|
||||
|
||||
When using ruby interpolation in externalized strings, they can't be
|
||||
detected. Which means they will never be presented to be translated.
|
||||
|
||||
To mix variables into translations we need to use `sprintf`
|
||||
instead.
|
||||
|
||||
Instead of:
|
||||
|
||||
_("Hello \#{subject}")
|
||||
|
||||
Use:
|
||||
|
||||
_("Hello %{subject}") % { subject: 'world' }
|
||||
|
||||
This is an example of a bad commit message:
|
||||
|
||||
updated README.md
|
||||
|
||||
This commit message is bad because although it tells us that README.md is
|
||||
updated, it doesn't tell us why or how it was updated.
|
||||
MARKDOWN
|
||||
end
|
||||
|
||||
lint_commits(git.commits)
|
||||
|
|
|
|||
|
|
@ -96,7 +96,5 @@ they will receive a `Connection failed` message.
|
|||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8413) in GitLab 8.17.
|
||||
|
||||
Terminal sessions use long-lived connections; by default, these may last
|
||||
forever. You can configure a maximum session time in the Admin Area of your
|
||||
GitLab instance if you find this undesirable from a scalability or security
|
||||
point of view.
|
||||
Terminal sessions, by default, do not expire.
|
||||
You can limit terminal session lifetime in your GitLab instance. To do so, navigate to **{admin}** [**Admin Area > Settings > Web terminal**](../../user/admin_area/settings/index.md#general), and set a `max session time`.
|
||||
|
|
|
|||
|
|
@ -21,10 +21,7 @@ This project will be used for self monitoring your GitLab instance.
|
|||
|
||||
1. Navigate to **Admin Area > Settings > Metrics and profiling**, and expand the **Self monitoring** section.
|
||||
1. Toggle the **Create Project** button on.
|
||||
1. It can take a few seconds for the project to be created. After the project is
|
||||
created, GitLab displays a message with a link to the project. The project
|
||||
will also be linked in the help text above the **Create Project** button. You can also
|
||||
find the project under **Projects > Your projects**.
|
||||
1. Once your GitLab instance creates the project, you'll see a link to the project in the text above the **Create Project** toggle. You can also find it under **Projects > Your projects**.
|
||||
|
||||
## Deleting the self monitoring project
|
||||
|
||||
|
|
|
|||
|
|
@ -1869,6 +1869,11 @@ type Environment {
|
|||
Human-readable name of the environment
|
||||
"""
|
||||
name: String!
|
||||
|
||||
"""
|
||||
State of the environment, for example: available/stopped
|
||||
"""
|
||||
state: String!
|
||||
}
|
||||
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -5530,6 +5530,24 @@
|
|||
"description": "Human-readable name of the environment",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "state",
|
||||
"description": "State of the environment, for example: available/stopped",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
|
|
|
|||
|
|
@ -318,6 +318,7 @@ Describes where code is deployed for a project
|
|||
| --- | ---- | ---------- |
|
||||
| `id` | ID! | ID of the environment |
|
||||
| `name` | String! | Human-readable name of the environment |
|
||||
| `state` | String! | State of the environment, for example: available/stopped |
|
||||
|
||||
## Epic
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,10 @@ GET /groups/:id/packages
|
|||
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/:id/packages?exclude_subgroups=true
|
||||
```
|
||||
|
||||
CAUTION: **Deprecation**
|
||||
> The `build_info` attribute in the response is deprecated in favour of `pipeline`.
|
||||
> Introduced [GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28040).
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
|
|
@ -87,15 +91,17 @@ Example response:
|
|||
"delete_api_path": "/namespace1/project1/-/packages/1"
|
||||
},
|
||||
"created_at": "2019-11-27T03:37:38.711Z",
|
||||
"build_info": {
|
||||
"pipeline": {
|
||||
"id": 123,
|
||||
"status": "pending",
|
||||
"ref": "new-pipeline",
|
||||
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
|
||||
"web_url": "https://example.com/foo/bar/pipelines/47",
|
||||
"created_at": "2016-08-11T11:28:34.085Z",
|
||||
"updated_at": "2016-08-11T11:32:35.169Z",
|
||||
"pipeline": {
|
||||
"id": 123,
|
||||
"status": "pending",
|
||||
"ref": "new-pipeline",
|
||||
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
|
||||
"web_url": "https://example.com/foo/bar/pipelines/47",
|
||||
"created_at": "2016-08-11T11:28:34.085Z",
|
||||
"updated_at": "2016-08-11T11:32:35.169Z",
|
||||
"user": {
|
||||
"name": "Administrator",
|
||||
"avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -109,15 +115,17 @@ Example response:
|
|||
"delete_api_path": "/namespace1/project1/-/packages/1"
|
||||
},
|
||||
"created_at": "2019-11-27T03:37:38.711Z",
|
||||
"build_info": {
|
||||
"pipeline": {
|
||||
"id": 123,
|
||||
"status": "pending",
|
||||
"ref": "new-pipeline",
|
||||
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
|
||||
"web_url": "https://example.com/foo/bar/pipelines/47",
|
||||
"created_at": "2016-08-11T11:28:34.085Z",
|
||||
"updated_at": "2016-08-11T11:32:35.169Z",
|
||||
"pipeline": {
|
||||
"id": 123,
|
||||
"status": "pending",
|
||||
"ref": "new-pipeline",
|
||||
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
|
||||
"web_url": "https://example.com/foo/bar/pipelines/47",
|
||||
"created_at": "2016-08-11T11:28:34.085Z",
|
||||
"updated_at": "2016-08-11T11:32:35.169Z",
|
||||
"user": {
|
||||
"name": "Administrator",
|
||||
"avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -150,6 +158,10 @@ GET /projects/:id/packages/:package_id
|
|||
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/:id/packages/:package_id
|
||||
```
|
||||
|
||||
CAUTION: **Deprecation**
|
||||
> The `build_info` attribute in the response is deprecated in favour of `pipeline`.
|
||||
> Introduced [GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28040).
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
|
|
@ -163,15 +175,17 @@ Example response:
|
|||
"delete_api_path": "/namespace1/project1/-/packages/1"
|
||||
},
|
||||
"created_at": "2019-11-27T03:37:38.711Z",
|
||||
"build_info": {
|
||||
"pipeline": {
|
||||
"id": 123,
|
||||
"status": "pending",
|
||||
"ref": "new-pipeline",
|
||||
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
|
||||
"web_url": "https://example.com/foo/bar/pipelines/47",
|
||||
"created_at": "2016-08-11T11:28:34.085Z",
|
||||
"updated_at": "2016-08-11T11:32:35.169Z",
|
||||
"pipeline": {
|
||||
"id": 123,
|
||||
"status": "pending",
|
||||
"ref": "new-pipeline",
|
||||
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
|
||||
"web_url": "https://example.com/foo/bar/pipelines/47",
|
||||
"created_at": "2016-08-11T11:28:34.085Z",
|
||||
"updated_at": "2016-08-11T11:32:35.169Z",
|
||||
"user": {
|
||||
"name": "Administrator",
|
||||
"avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ Complementary reads:
|
|||
- [Working with Merge Request diffs](diffs.md)
|
||||
- [Kubernetes integration guidelines](kubernetes.md)
|
||||
- [Permissions](permissions.md)
|
||||
- [Prometheus metrics](prometheus_metrics.md)
|
||||
- [Prometheus](prometheus.md)
|
||||
- [Guidelines for reusing abstractions](reusing_abstractions.md)
|
||||
- [DeclarativePolicy framework](policies.md)
|
||||
- [How Git object deduplication works in GitLab](git_object_deduplication.md)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
# Working with Prometheus
|
||||
|
||||
For more information on working with [Prometheus metrics](prometheus_metrics.md), see
|
||||
the documentation.
|
||||
|
||||
## Access the UI of a Prometheus managed application in Kubernetes
|
||||
|
||||
You can connect directly to Prometheus, and view the Prometheus user interface, when
|
||||
using a Prometheus managed application in Kubernetes:
|
||||
|
||||
1. Find the name of the Prometheus pod in the user interface of your Kubernetes
|
||||
provider, such as GKE, or by running the following `kubectl` command in your
|
||||
terminal:
|
||||
|
||||
```shell
|
||||
kubectl get pods -n gitlab-managed-apps | grep 'prometheus-prometheus-server'
|
||||
```
|
||||
|
||||
The command should return a result like the following example, where
|
||||
`prometheus-prometheus-server-55b4bd64c9-dpc6b` is the name of the Prometheus pod:
|
||||
|
||||
```plaintext
|
||||
gitlab-managed-apps prometheus-prometheus-server-55b4bd64c9-dpc6b 2/2 Running 0 71d
|
||||
```
|
||||
|
||||
1. Run a `kubectl port-forward` command. In the following example, `9090` is the
|
||||
Prometheus server's listening port:
|
||||
|
||||
```shell
|
||||
kubectl port-forward prometheus-prometheus-server-55b4bd64c9-dpc6b 9090:9090 -n gitlab-managed-apps
|
||||
```
|
||||
|
||||
The `port-forward` command forwards all requests sent to your system's `9090` port
|
||||
to the `9090` port of the Prometheus pod. If the `9090` port on your system is used
|
||||
by another application, you can change the port number before the colon to your
|
||||
desired port. For example, to forward port `8080` of your local system, change the
|
||||
command to:
|
||||
|
||||
```shell
|
||||
kubectl port-forward prometheus-prometheus-server-55b4bd64c9-dpc6b 8080:9090 -n gitlab-managed-apps
|
||||
```
|
||||
|
||||
1. Open `localhost:9090` in your browser to display the Prometheus user interface.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 139 KiB |
|
|
@ -122,6 +122,19 @@ RDS instances as well:
|
|||
| `gitlab-public-10.0.2.0` | public | `us-west-2b` | `10.0.2.0` |
|
||||
| `gitlab-private-10.0.3.0` | private | `us-west-2b` | `10.0.3.0` |
|
||||
|
||||
### Create NAT Gateways
|
||||
|
||||
Instances deployed in our private subnets need to connect to the internet for updates, but should not be reachable from the public internet. To achieve this, we'll make use of [NAT Gateways](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html) deployed in each of our public subnets:
|
||||
|
||||
1. Navigate to the VPC dashboard and click on **NAT Gateways** in the left menu bar.
|
||||
1. Click **Create NAT Gateway** and complete the following:
|
||||
1. **Subnet**: Select `gitlab-public-10.0.0.0` from the dropdown.
|
||||
1. **Elastic IP Allocation ID**: Enter an existing Elastic IP or click **Allocate Elastic IP address** to allocate a new IP to your NAT gateway.
|
||||
1. Add tags if needed.
|
||||
1. Click **Create NAT Gateway**.
|
||||
|
||||
Create a second NAT gateway but this time place it in the second public subnet, `gitlab-public-10.0.2.0`.
|
||||
|
||||
### Route Table
|
||||
|
||||
Up to now all our subnets are private. We need to create a Route Table
|
||||
|
|
|
|||
|
|
@ -16,3 +16,4 @@ comments: false
|
|||
- [Rebuild authorized_keys file](../administration/raketasks/maintenance.md#rebuild-authorized_keys-file) task for administrators
|
||||
- [Uploads Migrate](../administration/raketasks/uploads/migrate.md)
|
||||
- [Uploads Sanitize](../administration/raketasks/uploads/sanitize.md)
|
||||
- [Importing large GitLab project exports](../development/import_project.md#importing-via-a-rake-task)
|
||||
|
|
|
|||
|
|
@ -535,18 +535,14 @@ in the first place, and thus not realize that it needs to re-apply the old confi
|
|||
|
||||
> Introduced in [GitLab Ultimate][ee] 10.4.
|
||||
|
||||
This is an optional step, since it requires a [review app](#auto-review-apps).
|
||||
If that requirement is not met, the job will be silently skipped.
|
||||
|
||||
Dynamic Application Security Testing (DAST) uses the
|
||||
popular open source tool [OWASP ZAProxy](https://github.com/zaproxy/zaproxy)
|
||||
to perform an analysis on the current code and checks for potential security
|
||||
issues. The Auto DAST stage will be skipped on licenses other than Ultimate.
|
||||
|
||||
Once the report is created, it's uploaded as an artifact which you can
|
||||
later download and check out.
|
||||
|
||||
Any security warnings are also shown in the merge request widget. Read how
|
||||
Once the DAST scan is complete, any security warnings are shown
|
||||
on the [Security Dashboard](../../user/application_security/security_dashboard/index.md)
|
||||
and the Merge Request Widget. Read how
|
||||
[DAST works](../../user/application_security/dast/index.md).
|
||||
|
||||
On your default branch, DAST scans an app deployed specifically for that purpose.
|
||||
|
|
|
|||
|
|
@ -4,35 +4,110 @@ type: index
|
|||
|
||||
# Admin Area settings **(CORE ONLY)**
|
||||
|
||||
In the Admin Area **Settings** page, you can find various options for your GitLab
|
||||
instance like sign-up restrictions, account limits and quota, metrics, etc.
|
||||
As an administrator of a GitLab self-managed instance, you can manage the behavior of your deployment. To do so, select **{admin}** **Admin Area > Settings**.
|
||||
|
||||
Navigate to it by going to **Admin Area > Settings**. Some of the settings
|
||||
include:
|
||||
The admin area is not accessible on GitLab.com, and settings can only be changed by the
|
||||
GitLab.com administrators. See the [GitLab.com settings](../../gitlab_com/index.md)
|
||||
documentation for all current settings and limits on the GitLab.com instance.
|
||||
|
||||
- [Account and limit settings](account_and_limit_settings.md) **(STARTER)**
|
||||
- [Continuous Integration and Deployment](continuous_integration.md)
|
||||
- [Email](email.md)
|
||||
- [Sign up restrictions](sign_up_restrictions.md)
|
||||
- [Sign in restrictions](sign_in_restrictions.md)
|
||||
- [Terms](terms.md)
|
||||
- [Third party offers](third_party_offers.md)
|
||||
- [Usage statistics](usage_statistics.md)
|
||||
- [Visibility and access controls](visibility_and_access_controls.md)
|
||||
- [User and IP rate limits](user_and_ip_rate_limits.md)
|
||||
- [Custom templates repository](instance_template_repository.md) **(PREMIUM)**
|
||||
- [Protected paths](protected_paths.md) **(CORE ONLY)**
|
||||
- [Help messages for the `/help` page and the login page](help_page.md)
|
||||
- [Push event activities limit and bulk push events](push_event_activities_limit.md)
|
||||
- [Gitaly timeouts](gitaly_timeouts.md)
|
||||
## General
|
||||
|
||||
Access the default page for admin area settings by navigating to
|
||||
**{admin}** **Admin Area > Settings > General**:
|
||||
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| [Visibility and access controls](visibility_and_access_controls.md) | Set default and restrict visibility levels. Configure import sources and Git access protocol. |
|
||||
| [Account and limit](account_and_limit_settings.md) **(STARTER)** | Set projects and maximum size limits, session duration, user options, and check feature availability for namespace plan. |
|
||||
| [Diff limits](../diff_limits.md) | Diff content limits. |
|
||||
| [Sign-up restrictions](sign_up_restrictions.md) | Configure the way a user creates a new account. |
|
||||
| [Sign in restrictions](sign_in_restrictions.md) | Set requirements for a user to sign-in. Enable mandatory two-factor authentication. |
|
||||
| [Terms of Service and Privacy Policy](terms.md) | Include a Terms of Service agreement and Privacy Policy that all users must accept. |
|
||||
| [External Authentication](external_authorization.md#configuration) | External Classification Policy Authorization |
|
||||
| [Web terminal](../../../administration/integration/terminal.md#limiting-websocket-connection-time) | Set max session time for web terminal. |
|
||||
| [Web IDE](../../project/web_ide/index.md#enabling-client-side-evaluation) | Manage Web IDE Features. |
|
||||
|
||||
## Integrations
|
||||
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| [Elasticsearch](../../../integration/elasticsearch.md#enabling-elasticsearch) | Elasticsearch integration. Elasticsearch AWS IAM. |
|
||||
| [PlantUML](../../../administration/integration/plantuml.md#gitlab) | Allow rendering of PlantUML diagrams in Asciidoc documents. |
|
||||
| [Slack application](../../../user/project/integrations/gitlab_slack_application.md#configuration) **(FREE ONLY)** | Slack integration allows you to interact with GitLab via slash commands in a chat window. This option is only available on GitLab.com, though it may be [available for self-managed instances in the future](https://gitlab.com/gitlab-org/gitlab/-/issues/28164). |
|
||||
| [Third party offers](third_party_offers.md) | Control the display of third party offers. |
|
||||
| [Snowplow](../../../telemetry/index.md#enabling-tracking) | Configure the Snowplow integration. |
|
||||
| [Amazon EKS](../../project/clusters/add_remove_clusters.md#additional-requirements-for-self-managed-instances-core-only) | Amazon EKS integration allows you to provision EKS clusters from GitLab. |
|
||||
|
||||
## Repository
|
||||
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| [Repository mirror](visibility_and_access_controls.md#allow-mirrors-to-be-set-up-for-projects) | Configure repository mirroring. |
|
||||
| [Repository storage](../../../administration/repository_storage_types.md#how-to-migrate-to-hashed-storage) | Configure storage path settings. |
|
||||
| Repository maintenance | ([Repository checks](../../../administration/repository_checks.md) and [Housekeeping](../../../administration/housekeeping.md)). Configure automatic Git checks and housekeeping on repositories. |
|
||||
| [Repository static objects](../../../administration/static_objects_external_storage.md) | Serve repository static objects (e.g. archives, blobs, ...) from an external storage (e.g. a CDN). |
|
||||
|
||||
## Templates **(PREMIUM ONLY)**
|
||||
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| [Templates](instance_template_repository.md#configuration) | Set instance-wide template repository. |
|
||||
| [Custom project templates](../custom_project_templates.md) | Select the custom project template source group. |
|
||||
|
||||
## CI/CD
|
||||
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| [Continuous Integration and Deployment](continuous_integration.md) | Auto DevOps, runners and job artifacts. |
|
||||
| [Required pipeline configuration](continuous_integration.md#required-pipeline-configuration-premium-only) **(PREMIUM ONLY)** | Set an instance-wide auto included [pipeline configuration](../../../ci/yaml/README.md). This pipeline configuration will be run after the project's own configuration. |
|
||||
| [Package Registry](continuous_integration.md#package-registry-configuration-premium-only) **(PREMIUM ONLY)**| Settings related to the use and experience of using GitLab's Package Registry. |
|
||||
|
||||
## Reporting
|
||||
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| [Spam and Anti-bot Protection](../../../integration/recaptcha.md) | Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support [v2](https://developers.google.com/recaptcha/docs/versions). |
|
||||
| [Abuse reports](../abuse_reports.md) | Set notification email for abuse reports. |
|
||||
|
||||
## Metrics and profiling
|
||||
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| [Metrics - Influx](../../../administration/monitoring/performance/gitlab_configuration.md) | Enable and configure InfluxDB metrics. |
|
||||
| [Metrics - Prometheus](../../../administration/monitoring/prometheus/gitlab_metrics.md) | Enable and configure Prometheus metrics. |
|
||||
| [Metrics - Grafana](../../../administration/monitoring/performance/grafana_configuration.md#integration-with-gitlab-ui) | Enable and configure Grafana. |
|
||||
| [Profiling - Performance bar](../../../administration/monitoring/performance/performance_bar.md#enable-the-performance-bar-via-the-admin-panel) | Enable access to the Performance Bar for a given group. |
|
||||
| [Self monitoring](../../../administration/monitoring/gitlab_self_monitoring_project/index.md#creating-the-self-monitoring-project) | Enable or disable instance self monitoring. |
|
||||
| [Usage statistics](usage_statistics.md) | Enable or disable version check and usage ping. |
|
||||
| [Pseudonymizer data collection](../../../administration/pseudonymizer.md) **(ULTIMATE)** | Enable or disable the Pseudonymizer data collection. |
|
||||
|
||||
## Network
|
||||
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| Performance optimization | [Write to "authorized_keys" file](../../../administration/operations/fast_ssh_key_lookup.md#setting-up-fast-lookup-via-gitlab-shell) and [Push event activities limit and bulk push events](push_event_activities_limit.md). Various settings that affect GitLab performance. |
|
||||
| [User and IP rate limits](user_and_ip_rate_limits.md) | Configure limits for web and API requests. |
|
||||
| [Outbound requests](../../../security/webhooks.md) | Allow requests to the local network from hooks and services. |
|
||||
| [Protected Paths](protected_paths.md) | Configure paths to be protected by Rack Attack. |
|
||||
| [Incident Management](../../incident_management/index.md) Limits | Configure limits on the number of inbound alerts able to be sent to a project. |
|
||||
|
||||
## Geo
|
||||
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| Geo | Geo allows you to replicate your GitLab instance to other geographical locations. Redirects to **{admin}** **Admin Area >** **{location-dot}** **Geo >** **{settings}** **Settings**, and will no longer be available at **{admin}** **Admin Area >** **{settings}** **Settings >** **{location-dot}** **Geo** in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/36896). |
|
||||
|
||||
## Preferences
|
||||
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| [Email](email.md) | Various email settings. |
|
||||
| [Help page](../../../customization/help_message.md) | Help page text and support page url. |
|
||||
| [Pages](../../../administration/pages/index.md#custom-domain-verification) | Size and domain settings for static websites |
|
||||
| [Real-time features](../../../administration/polling.md) | Change this value to influence how frequently the GitLab UI polls for updates. |
|
||||
| [Gitaly timeouts](gitaly_timeouts.md) | Configure Gitaly timeouts. |
|
||||
| Localization | [Default first day of the week](../../profile/preferences.md) and [Time tracking](../../project/time_tracking.md#limit-displayed-units-to-hours-core-only). |
|
||||
|
||||
NOTE: **Note:**
|
||||
You can change the [first day of the week](../../profile/preferences.md) for the entire GitLab instance
|
||||
You can change the [Default first day of the week](../../profile/preferences.md) for the entire GitLab instance
|
||||
in the **Localization** section of **Admin Area > Settings > Preferences**.
|
||||
|
||||
## GitLab.com Admin Area settings
|
||||
|
||||
Most of the settings under the Admin Area change the behavior of the whole
|
||||
GitLab instance. For GitLab.com, the admin settings are available only for the
|
||||
GitLab.com administrators, and the parameters can be found on the
|
||||
[GitLab.com settings](../../gitlab_com/index.md) documentation.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
# Analytics workspace
|
||||
# Analytics
|
||||
|
||||
## Analytics workspace
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/12077) in GitLab 12.2.
|
||||
|
||||
|
|
@ -6,27 +8,30 @@ The Analytics workspace will make it possible to aggregate analytics across
|
|||
GitLab, so that users can view information across multiple projects and groups
|
||||
in one place.
|
||||
|
||||
To access the centralized analytics workspace, enable at least
|
||||
[one of the features](#available-analytics) under the workspace.
|
||||
To access the Analytics workspace, click on **More > Analytics** in the top navigation bar.
|
||||
|
||||
Once enabled, click on **Analytics** from the top navigation bar.
|
||||
## Group-level analytics
|
||||
|
||||
## Available analytics
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/195979) in GitLab 12.8.
|
||||
|
||||
From the centralized analytics workspace, the following analytics are available:
|
||||
The following analytics features are available at the group level:
|
||||
|
||||
- [Code Review Analytics](code_review_analytics.md). **(STARTER)**
|
||||
- [Value Stream Analytics](value_stream_analytics.md), enabled with the `cycle_analytics`
|
||||
- [Contribution](../group/contribution_analytics/index.md). **(STARTER)**
|
||||
- [Insights](../group/insights/index.md). **(ULTIMATE)**
|
||||
- [Issues](../group/issues_analytics/index.md). **(PREMIUM)**
|
||||
- [Productivity](productivity_analytics.md), enabled with the `productivity_analytics`
|
||||
[feature flag](../../development/feature_flags/development.md#enabling-a-feature-flag-in-development). **(PREMIUM)**
|
||||
- [Productivity Analytics](productivity_analytics.md), enabled with the `productivity_analytics`
|
||||
- [Value Stream](value_stream_analytics.md), enabled with the `cycle_analytics`
|
||||
[feature flag](../../development/feature_flags/development.md#enabling-a-feature-flag-in-development). **(PREMIUM)**
|
||||
|
||||
NOTE: **Note:**
|
||||
Project-level Value Stream Analytics are still available at a project's **Project > Value Stream Analytics**.
|
||||
## Project-level analytics
|
||||
|
||||
## Other analytics tools
|
||||
The following analytics features are available at the project level:
|
||||
|
||||
In addition to the tools available in the Analytics workspace, GitLab provides:
|
||||
|
||||
- [Contribution analytics](../group/contribution_analytics/index.md). **(STARTER)**
|
||||
- [Issue analytics](../group/issues_analytics/index.md). **(PREMIUM)**
|
||||
- [CI/CD](../../ci/pipelines/index.md#pipeline-success-and-duration-charts). **(STARTER)**
|
||||
- [Code Review](code_review_analytics.md). **(STARTER)**
|
||||
- [Insights](../group/insights/index.md). **(ULTIMATE)**
|
||||
- [Issues](../group/issues_analytics/index.md). **(PREMIUM)**
|
||||
- Repository. **(STARTER)**
|
||||
- [Value Stream](value_stream_analytics.md), enabled with the `cycle_analytics`
|
||||
[feature flag](../../development/feature_flags/development.md#enabling-a-feature-flag-in-development). **(STARTER)**
|
||||
|
|
|
|||
|
|
@ -2,48 +2,62 @@
|
|||
type: reference, howto
|
||||
---
|
||||
|
||||
# Offline deployments
|
||||
# Air-gapped (or offline) environment deployments
|
||||
|
||||
This document describes how to operate Secure scanners offline.
|
||||
It is possible to run most of the GitLab security scanners when not
|
||||
connected to the internet.
|
||||
|
||||
This document describes how to operate Secure scanners in an air-gapped or offline envionment. These instructions also apply to
|
||||
self-managed installations that are secured, have security policies (e.g., firewall policies), or otherwise restricted from
|
||||
accessing the full internet. These instructions are designed for physically disconnected networks,
|
||||
but can also be followed in these other use cases.
|
||||
|
||||
## Air-gapped (or offline) environments
|
||||
|
||||
In this situation, the GitLab instance can be one or more servers and services that can communicate
|
||||
on a local network, but with no or very restricted access to the internet. Assume anything within
|
||||
the GitLab instance and supporting infrastructure (for example, a private Maven repository) can be
|
||||
accessed through a local network connection. Assume any files from the internet must come in through
|
||||
physical media (USB drive, hard drive, writeable DVD, etc.).
|
||||
|
||||
## Overview
|
||||
|
||||
It is possible to run most of the GitLab security scanners when not
|
||||
connected to the internet, in what is sometimes known as an offline,
|
||||
limited connectivity, Local Area Network (LAN), Intranet, or "air-gap"
|
||||
environment.
|
||||
|
||||
In this situation, the GitLab instance can be one, or more, servers and services running in a network that can talk to one another, but have zero, or perhaps very restricted access to the internet. Assume anything within the GitLab instance and supporting infrastructure (private Maven repository for example) can be accessed via local network connection. Assume any files from the internet must come in via physical media (USB drive, hard drive).
|
||||
|
||||
GitLab scanners generally will connect to the internet to download the
|
||||
latest sets of signatures, rules, and patches. A few extra steps are necessary
|
||||
to configure the tools to not do this and to still function properly.
|
||||
to configure the tools to function properly by using resources available on your local network.
|
||||
|
||||
### Container registries and package repositories
|
||||
|
||||
At a high-level, each of the security analyzers are delivered as Docker
|
||||
containers and reference various package repositories. When you run a job on
|
||||
At a high-level, the security analyzers are delivered as Docker images and
|
||||
may leverage various package repositories. When you run a job on
|
||||
an internet-connected GitLab installation, GitLab checks the GitLab.com-hosted
|
||||
container registry and package repositories to ensure that you have
|
||||
the latest versions.
|
||||
container registry to check that you have the latest versions of these Docker images
|
||||
and possibly connect to package repositories to install necessary dependencies.
|
||||
|
||||
In an air-gapped environment, this must be disabled so that GitLab.com is not
|
||||
In an air-gapped environment, these checks must be disabled so that GitLab.com is not
|
||||
queried. Because the GitLab.com registry and repositories are not available,
|
||||
you must update each of the scanners to either reference a different,
|
||||
internally-hosted registry or provide access to the individual scanner images.
|
||||
|
||||
You must also ensure that your app has access to common package repos
|
||||
You must also ensure that your app has access to common package repositories
|
||||
that are not hosted on GitLab.com, such as npm, yarn, or rubygems. Packages
|
||||
from these repos can be obtained by temporarily connecting to a network or by
|
||||
mirroring the packages inside your own offline network.
|
||||
|
||||
### Interacting with the vulnerabilities
|
||||
|
||||
Once a vulnerability is found, you can interact with it. Read more on how to [interact with the vulnerabilities](../index.md#interacting-with-the-vulnerabilities).
|
||||
|
||||
Please note that in some cases the reported vulnerabilities provide metadata that can contain external links exposed in the UI. These links might not be accessible within an air-gapped (or offline) environment.
|
||||
|
||||
### Scanner signature and rule updates
|
||||
|
||||
When connected to the internet, some scanners will reference public databases
|
||||
for the latest sets of signatures and rules to check against. Without connectivity,
|
||||
this is not possible. Depending on the scanner, you must therefore disable
|
||||
these automatic update checks and either use the databases that they came
|
||||
with or manually update those databases.
|
||||
with and manually update those databases or provide access to your own copies
|
||||
hosted within your network.
|
||||
|
||||
## Specific scanner instructions
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 28 KiB |
|
|
@ -18,9 +18,9 @@ that is provided by [Auto DevOps](../../../topics/autodevops/index.md).
|
|||
|
||||
GitLab checks the License Compliance report, compares the licenses between the
|
||||
source and target branches, and shows the information right on the merge request.
|
||||
Blacklisted licenses will be clearly visible with an `x` red icon next to them
|
||||
Denied licenses will be clearly visible with an `x` red icon next to them
|
||||
as well as new licenses which need a decision from you. In addition, you can
|
||||
[manually approve or blacklist](#project-policies-for-license-compliance)
|
||||
[manually allow or deny](#project-policies-for-license-compliance)
|
||||
licenses in your project's settings.
|
||||
|
||||
NOTE: **Note:**
|
||||
|
|
@ -33,7 +33,7 @@ compliance report will be shown properly.
|
|||

|
||||
|
||||
If you are a project or group Maintainer, you can click on a license to be given
|
||||
the choice to approve it or blacklist it.
|
||||
the choice to allow it or deny it.
|
||||
|
||||

|
||||
|
||||
|
|
@ -282,9 +282,9 @@ license_scanning:
|
|||
From the project's settings:
|
||||
|
||||
- The list of licenses and their status can be managed.
|
||||
- Licenses can be manually approved or blacklisted.
|
||||
- Licenses can be manually allowed or denied.
|
||||
|
||||
To approve or blacklist a license:
|
||||
To allow or deny a license:
|
||||
|
||||
1. Either use the **Manage licenses** button in the merge request widget, or
|
||||
navigate to the project's **Settings > CI/CD** and expand the
|
||||
|
|
@ -298,12 +298,12 @@ To approve or blacklist a license:
|
|||
at the top of the list.
|
||||
- Enter arbitrary text in the field at the top of the list. This will cause the text to be
|
||||
added as a license name to the list.
|
||||
1. Select the **Approve** or **Blacklist** radio button to approve or blacklist respectively
|
||||
1. Select the **Allow** or **Deny** radio button to allow or deny respectively
|
||||
the selected license.
|
||||
|
||||
To modify an existing license:
|
||||
|
||||
1. In the **License Compliance** list, click the **Approved/Declined** dropdown to change it to the desired status.
|
||||
1. In the **License Compliance** list, click the **Allow/Deny** dropdown to change it to the desired status.
|
||||
|
||||

|
||||
|
||||
|
|
|
|||
|
|
@ -837,6 +837,11 @@ Prerequisites for embedding from a Grafana instance:
|
|||
|
||||
## Troubleshooting
|
||||
|
||||
When troubleshooting issues with a managed Prometheus app, it is often useful to
|
||||
[view the Prometheus UI](../../../development/prometheus.md#access-the-ui-of-a-prometheus-managed-application-in-kubernetes).
|
||||
|
||||
### "No data found" error on Metrics dashboard page
|
||||
|
||||
If the "No data found" screen continues to appear, it could be due to:
|
||||
|
||||
- No successful deployments have occurred to this environment.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ module Gitlab
|
|||
module StageEvents
|
||||
class ProductionStageEnd < StageEvent
|
||||
def self.name
|
||||
PlanStageStart.name
|
||||
_("Issue first depoloyed to production")
|
||||
end
|
||||
|
||||
def self.identifier
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def details
|
||||
message_parts[2]
|
||||
message_parts[2]&.gsub(/^Signed-off-by.*$/, '')
|
||||
end
|
||||
|
||||
def line_too_long?(line)
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ excluded_attributes:
|
|||
- :runners_token_encrypted
|
||||
- :saml_discovery_token
|
||||
- :visibility_level
|
||||
epics:
|
||||
- :state_id
|
||||
|
||||
methods:
|
||||
labels:
|
||||
|
|
@ -50,6 +52,8 @@ methods:
|
|||
- :action
|
||||
lists:
|
||||
- :list_type
|
||||
epics:
|
||||
- :state
|
||||
|
||||
preloads:
|
||||
|
||||
|
|
|
|||
|
|
@ -6127,12 +6127,6 @@ msgstr ""
|
|||
msgid "CycleAnalyticsEvent|Issue last edited"
|
||||
msgstr ""
|
||||
|
||||
msgid "CycleAnalyticsEvent|Merge Request label was added"
|
||||
msgstr ""
|
||||
|
||||
msgid "CycleAnalyticsEvent|Merge Request label was removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "CycleAnalyticsEvent|Merge request closed"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -6142,6 +6136,12 @@ msgstr ""
|
|||
msgid "CycleAnalyticsEvent|Merge request first deployed to production"
|
||||
msgstr ""
|
||||
|
||||
msgid "CycleAnalyticsEvent|Merge request label was added"
|
||||
msgstr ""
|
||||
|
||||
msgid "CycleAnalyticsEvent|Merge request label was removed"
|
||||
msgstr ""
|
||||
|
||||
msgid "CycleAnalyticsEvent|Merge request last build finish time"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -11161,6 +11161,9 @@ msgstr ""
|
|||
msgid "Issue events"
|
||||
msgstr ""
|
||||
|
||||
msgid "Issue first depoloyed to production"
|
||||
msgstr ""
|
||||
|
||||
msgid "Issue or Merge Request ID is required"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -17972,6 +17975,9 @@ msgstr ""
|
|||
msgid "Serverless|Getting started with serverless"
|
||||
msgstr ""
|
||||
|
||||
msgid "Serverless|Help shape the future of Serverless at GitLab"
|
||||
msgstr ""
|
||||
|
||||
msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -17984,6 +17990,9 @@ msgstr ""
|
|||
msgid "Serverless|No functions available"
|
||||
msgstr ""
|
||||
|
||||
msgid "Serverless|Sign up for First Look"
|
||||
msgstr ""
|
||||
|
||||
msgid "Serverless|The deploy job has not finished."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -17993,6 +18002,9 @@ msgstr ""
|
|||
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Serverless|We are continually striving to improve our Serverless functionality. As a Knative user, we would love to hear how we can make this experience better for you. Sign up for GitLab First Look today and we will be in touch shortly."
|
||||
msgstr ""
|
||||
|
||||
msgid "Serverless|Your %{startTag}.gitlab-ci.yml%{endTag} file is not properly configured."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module RuboCop
|
||||
module Cop
|
||||
module Performance
|
||||
class ReadlinesEach < RuboCop::Cop::Cop
|
||||
MESSAGE = 'Avoid `IO.readlines.each`, since it reads contents into memory in full. ' \
|
||||
'Use `IO.each_line` or `IO.each` instead.'
|
||||
|
||||
def_node_matcher :full_file_read_via_class?, <<~PATTERN
|
||||
(send
|
||||
(send (const nil? {:IO :File}) :readlines _) :each)
|
||||
PATTERN
|
||||
|
||||
def_node_matcher :full_file_read_via_instance?, <<~PATTERN
|
||||
(... (... :readlines) :each)
|
||||
PATTERN
|
||||
|
||||
def on_send(node)
|
||||
full_file_read_via_class?(node) { add_offense(node, location: :selector, message: MESSAGE) }
|
||||
full_file_read_via_instance?(node) { add_offense(node, location: :selector, message: MESSAGE) }
|
||||
end
|
||||
|
||||
def autocorrect(node)
|
||||
lambda do |corrector|
|
||||
corrector.replace(node.loc.expression, node.source.gsub('readlines.each', 'each_line'))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -127,6 +127,10 @@ describe Admin::ApplicationSettingsController do
|
|||
end
|
||||
|
||||
describe 'verify panel actions' do
|
||||
before do
|
||||
stub_feature_flags(instance_level_integrations: false)
|
||||
end
|
||||
|
||||
Admin::ApplicationSettingsController::VALID_SETTING_PANELS.each do |valid_action|
|
||||
it_behaves_like 'renders correct panels' do
|
||||
let(:action) { valid_action }
|
||||
|
|
|
|||
|
|
@ -24,6 +24,18 @@ describe Admin::ProjectsController do
|
|||
expect(response.body).not_to match(project.name)
|
||||
end
|
||||
|
||||
it 'retrieves archived and non archived corrupted projects when last_repository_check_failed is true' do
|
||||
archived_corrupted_project = create(:project, :public, :archived, :last_repository_check_failed, name: 'CorruptedArchived', path: 'A')
|
||||
corrupted_project = create(:project, :public, :last_repository_check_failed, name: 'CorruptedOnly', path: 'C')
|
||||
|
||||
get :index, params: { last_repository_check_failed: true }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(response.body).not_to match(project.name)
|
||||
expect(response.body).to match(archived_corrupted_project.name)
|
||||
expect(response.body).to match(corrupted_project.name)
|
||||
end
|
||||
|
||||
it 'does not respond with projects pending deletion' do
|
||||
pending_delete_project = create(:project, pending_delete: true)
|
||||
|
||||
|
|
|
|||
|
|
@ -114,6 +114,10 @@ FactoryBot.define do
|
|||
archived { true }
|
||||
end
|
||||
|
||||
trait :last_repository_check_failed do
|
||||
last_repository_check_failed { true }
|
||||
end
|
||||
|
||||
storage_version { Project::LATEST_STORAGE_VERSION }
|
||||
|
||||
trait :legacy_storage do
|
||||
|
|
|
|||
|
|
@ -194,6 +194,13 @@ describe 'Admin updates settings', :clean_gitlab_redis_shared_state, :do_not_moc
|
|||
expect(page).to have_content "Application settings saved successfully"
|
||||
expect(current_settings.terminal_max_session_time).to eq(15)
|
||||
end
|
||||
end
|
||||
|
||||
context 'Integrations page' do
|
||||
before do
|
||||
stub_feature_flags(instance_level_integrations: false)
|
||||
visit integrations_admin_application_settings_path
|
||||
end
|
||||
|
||||
it 'Enable hiding third party offers' do
|
||||
page.within('.as-third-party-offers') do
|
||||
|
|
|
|||
|
|
@ -205,10 +205,11 @@ describe 'Gcp Cluster', :js, :do_not_mock_admin_mode do
|
|||
let(:admin) { create(:admin) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(instance_level_integrations: false)
|
||||
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
|
||||
sign_in(admin)
|
||||
gitlab_enable_admin_mode_sign_in(admin)
|
||||
visit general_admin_application_settings_path
|
||||
visit integrations_admin_application_settings_path
|
||||
end
|
||||
|
||||
it 'user does not see the offer' do
|
||||
|
|
|
|||
|
|
@ -1492,7 +1492,7 @@
|
|||
"closed_at": null,
|
||||
"parent_id": null,
|
||||
"relative_position": null,
|
||||
"state_id": "opened",
|
||||
"state": "opened",
|
||||
"start_date_sourcing_epic_id": null,
|
||||
"due_date_sourcing_epic_id": null,
|
||||
"notes": []
|
||||
|
|
@ -1524,7 +1524,7 @@
|
|||
"closed_at": null,
|
||||
"parent_id": null,
|
||||
"relative_position": null,
|
||||
"state_id": "opened",
|
||||
"state": "closed",
|
||||
"start_date_sourcing_epic_id": null,
|
||||
"due_date_sourcing_epic_id": null,
|
||||
"notes": []
|
||||
|
|
@ -1556,7 +1556,7 @@
|
|||
"closed_at": null,
|
||||
"parent_id": null,
|
||||
"relative_position": null,
|
||||
"state_id": "opened",
|
||||
"state": "opened",
|
||||
"start_date_sourcing_epic_id": null,
|
||||
"due_date_sourcing_epic_id": null,
|
||||
"notes": []
|
||||
|
|
@ -1588,7 +1588,7 @@
|
|||
"closed_at": null,
|
||||
"parent_id": null,
|
||||
"relative_position": null,
|
||||
"state_id": "opened",
|
||||
"state": "closed",
|
||||
"start_date_sourcing_epic_id": null,
|
||||
"due_date_sourcing_epic_id": null,
|
||||
"notes": []
|
||||
|
|
@ -1620,7 +1620,7 @@
|
|||
"closed_at": null,
|
||||
"parent_id": null,
|
||||
"relative_position": null,
|
||||
"state_id": "opened",
|
||||
"state": "opened",
|
||||
"start_date_sourcing_epic_id": null,
|
||||
"due_date_sourcing_epic_id": null,
|
||||
"notes": []
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import Cookies from 'js-cookie';
|
||||
import SurveyBanner from '~/serverless/survey_banner.vue';
|
||||
import { GlBanner } from '@gitlab/ui';
|
||||
|
||||
describe('Knative survey banner', () => {
|
||||
let wrapper;
|
||||
|
||||
function mountBanner() {
|
||||
wrapper = shallowMount(SurveyBanner, {
|
||||
propsData: {
|
||||
surveyUrl: 'http://somesurvey.com/',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
wrapper = null;
|
||||
});
|
||||
|
||||
it('should render the banner when the cookie is absent', () => {
|
||||
jest.spyOn(Cookies, 'get').mockReturnValue(undefined);
|
||||
mountBanner();
|
||||
|
||||
expect(Cookies.get).toHaveBeenCalled();
|
||||
expect(wrapper.find(GlBanner).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('should close the banner and set a cookie when close button is clicked', () => {
|
||||
jest.spyOn(Cookies, 'get').mockReturnValue(undefined);
|
||||
jest.spyOn(Cookies, 'set');
|
||||
mountBanner();
|
||||
|
||||
expect(wrapper.find(GlBanner).exists()).toBe(true);
|
||||
wrapper.find(GlBanner).vm.$emit('close');
|
||||
|
||||
return wrapper.vm.$nextTick().then(() => {
|
||||
expect(Cookies.set).toHaveBeenCalledWith('hide_serverless_survey', 'true', { expires: 3650 });
|
||||
expect(wrapper.find(GlBanner).exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not render the banner when the cookie is set', () => {
|
||||
jest.spyOn(Cookies, 'get').mockReturnValue('true');
|
||||
mountBanner();
|
||||
|
||||
expect(Cookies.get).toHaveBeenCalled();
|
||||
expect(wrapper.find(GlBanner).exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
|
@ -7,7 +7,7 @@ describe GitlabSchema.types['Environment'] do
|
|||
|
||||
it 'has the expected fields' do
|
||||
expected_fields = %w[
|
||||
name id
|
||||
name id state
|
||||
]
|
||||
|
||||
expect(described_class).to have_graphql_fields(*expected_fields)
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ describe Gitlab::Danger::CommitLinter do
|
|||
"A commit message" | false
|
||||
"A commit message\n" | false
|
||||
"A commit message\n\n" | false
|
||||
"A commit message\n\nSigned-off-by: User Name <user@name.me>" | false
|
||||
"A commit message\n\nWith details" | true
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ describe BulkInsertSafe do
|
|||
include BulkInsertSafe
|
||||
include ShaAttribute
|
||||
|
||||
validates :name, :enum_value, :secret_value, :sha_value, presence: true
|
||||
validates :name, :enum_value, :secret_value, :sha_value, :jsonb_value, presence: true
|
||||
|
||||
ENUM_VALUES = {
|
||||
case_1: 1
|
||||
|
|
@ -26,6 +26,7 @@ describe BulkInsertSafe do
|
|||
default_value_for :enum_value, 'case_1'
|
||||
default_value_for :secret_value, 'my-secret'
|
||||
default_value_for :sha_value, '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12'
|
||||
default_value_for :jsonb_value, { "key" => "value" }
|
||||
|
||||
def self.valid_list(count)
|
||||
Array.new(count) { |n| new(name: "item-#{n}") }
|
||||
|
|
@ -60,6 +61,7 @@ describe BulkInsertSafe do
|
|||
t.text :encrypted_secret_value, null: false
|
||||
t.string :encrypted_secret_value_iv, null: false
|
||||
t.binary :sha_value, null: false, limit: 20
|
||||
t.jsonb :jsonb_value, null: false
|
||||
|
||||
t.index :name, unique: true
|
||||
end
|
||||
|
|
@ -114,7 +116,7 @@ describe BulkInsertSafe do
|
|||
|
||||
described_class.bulk_insert!(items)
|
||||
|
||||
attribute_names = described_class.attribute_names - %w[id]
|
||||
attribute_names = described_class.attribute_names - %w[id created_at updated_at]
|
||||
expect(described_class.last(items.size).pluck(*attribute_names)).to eq(
|
||||
items.pluck(*attribute_names))
|
||||
end
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ describe IrkerService do
|
|||
irker.execute(sample_data)
|
||||
|
||||
conn = @irker_server.accept
|
||||
conn.readlines.each do |line|
|
||||
conn.each_line do |line|
|
||||
msg = JSON.parse(line.chomp("\n"))
|
||||
expect(msg.keys).to match_array(%w(to privmsg))
|
||||
expect(msg['to']).to match_array(["irc://chat.freenode.net/#commits",
|
||||
|
|
|
|||
|
|
@ -149,6 +149,47 @@ describe Service do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.find_or_initialize_instances' do
|
||||
shared_examples 'service instances' do
|
||||
it 'returns the available service instances' do
|
||||
expect(Service.find_or_initialize_instances.pluck(:type)).to match_array(Service.available_services_types)
|
||||
end
|
||||
|
||||
it 'does not create service instances' do
|
||||
expect { Service.find_or_initialize_instances }.not_to change { Service.count }
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'service instances'
|
||||
|
||||
context 'with all existing instances' do
|
||||
before do
|
||||
Service.insert_all(
|
||||
Service.available_services_types.map { |type| { instance: true, type: type } }
|
||||
)
|
||||
end
|
||||
|
||||
it_behaves_like 'service instances'
|
||||
|
||||
context 'with a previous existing service (Previous) and a new service (Asana)' do
|
||||
before do
|
||||
Service.insert(type: 'PreviousService', instance: true)
|
||||
Service.delete_by(type: 'AsanaService', instance: true)
|
||||
end
|
||||
|
||||
it_behaves_like 'service instances'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a few existing instances' do
|
||||
before do
|
||||
create(:jira_service, :instance)
|
||||
end
|
||||
|
||||
it_behaves_like 'service instances'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'template' do
|
||||
let(:project) { create(:project) }
|
||||
|
||||
|
|
@ -173,7 +214,7 @@ describe Service do
|
|||
end
|
||||
|
||||
it 'does not create service templates' do
|
||||
expect { Service.find_or_create_templates }.to change { Service.count }.by(0)
|
||||
expect { Service.find_or_create_templates }.not_to change { Service.count }
|
||||
end
|
||||
|
||||
it_behaves_like 'retrieves service templates'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require_relative '../../../support/helpers/expect_offense'
|
||||
require_relative '../../../../rubocop/cop/performance/readlines_each'
|
||||
|
||||
describe RuboCop::Cop::Performance::ReadlinesEach do
|
||||
include CopHelper
|
||||
include ExpectOffense
|
||||
|
||||
subject(:cop) { described_class.new }
|
||||
|
||||
let(:message) { 'Avoid `IO.readlines.each`, since it reads contents into memory in full. Use `IO.each_line` or `IO.each` instead.' }
|
||||
|
||||
shared_examples_for(:class_read) do |klass|
|
||||
context "and it is called as a class method on #{klass}" do
|
||||
# We can't use `expect_offense` here because indentation changes based on `klass`
|
||||
it 'flags it as an offense' do
|
||||
inspect_source "#{klass}.readlines(file_path).each { |line| puts line }"
|
||||
|
||||
expect(cop.offenses.map(&:cop_name)).to contain_exactly('Performance/ReadlinesEach')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when just using readlines without each' do
|
||||
it 'does not flag it as an offense' do
|
||||
expect_no_offenses "contents = #{klass}.readlines(file_path)"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when reading all lines using IO.readlines.each' do
|
||||
%w(IO File).each do |klass|
|
||||
it_behaves_like(:class_read, klass)
|
||||
end
|
||||
|
||||
context 'and it is called as an instance method on a return value' do
|
||||
it 'flags it as an offense' do
|
||||
expect_offense <<~SOURCE
|
||||
get_file.readlines.each { |line| puts line }
|
||||
^^^^ #{message}
|
||||
SOURCE
|
||||
end
|
||||
end
|
||||
|
||||
context 'and it is called as an instance method on an assigned variable' do
|
||||
it 'flags it as an offense' do
|
||||
expect_offense <<~SOURCE
|
||||
file = File.new(path)
|
||||
file.readlines.each { |line| puts line }
|
||||
^^^^ #{message}
|
||||
SOURCE
|
||||
end
|
||||
end
|
||||
|
||||
context 'and it is called as an instance method on a new object' do
|
||||
it 'flags it as an offense' do
|
||||
expect_offense <<~SOURCE
|
||||
File.new(path).readlines.each { |line| puts line }
|
||||
^^^^ #{message}
|
||||
SOURCE
|
||||
end
|
||||
end
|
||||
|
||||
it 'autocorrects `readlines.each` to `each_line`' do
|
||||
expect(autocorrect_source('obj.readlines.each { |line| line }')).to(
|
||||
eq('obj.each_line { |line| line }')
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when just using readlines without each' do
|
||||
it 'does not flag it as an offense' do
|
||||
expect_no_offenses 'contents = my_file.readlines'
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue