Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-03-29 18:09:37 +00:00
parent 09ff71d425
commit 5b2abea8db
78 changed files with 966 additions and 408 deletions

View File

@ -106,6 +106,7 @@ linters:
- Cop/LineBreakAfterGuardClauses
- Cop/LineBreakAroundConditionalBlock
- Cop/ProjectPathHelper
- Gitlab/FeatureAvailableUsage
- GitlabSecurity/PublicSend
- Layout/EmptyLineAfterGuardClause
- Layout/LeadingCommentSpace

View File

@ -3580,3 +3580,239 @@ Gitlab/DelegatePredicateMethods:
- 'ee/app/models/ee/namespace.rb'
- 'ee/app/models/license.rb'
- 'lib/gitlab/ci/trace/stream.rb'
# Offense count: 298
Gitlab/FeatureAvailableUsage:
Exclude:
- 'app/controllers/projects/application_controller.rb'
- 'app/graphql/types/project_type.rb'
- 'app/helpers/events_helper.rb'
- 'app/helpers/labels_helper.rb'
- 'app/policies/project_policy.rb'
- 'app/views/groups/issues.html.haml'
- 'app/views/groups/merge_requests.html.haml'
- 'app/views/shared/boards/_switcher.html.haml'
- 'ee/app/controllers/concerns/description_diff_actions.rb'
- 'ee/app/controllers/concerns/ee/boards_actions.rb'
- 'ee/app/controllers/concerns/security_dashboards_permissions.rb'
- 'ee/app/controllers/ee/boards/lists_controller.rb'
- 'ee/app/controllers/ee/groups/application_controller.rb'
- 'ee/app/controllers/ee/groups/group_members_controller.rb'
- 'ee/app/controllers/ee/projects/autocomplete_sources_controller.rb'
- 'ee/app/controllers/ee/projects/issues_controller.rb'
- 'ee/app/controllers/ee/projects/security/configuration_controller.rb'
- 'ee/app/controllers/ee/projects/settings/ci_cd_controller.rb'
- 'ee/app/controllers/ee/projects/settings/operations_controller.rb'
- 'ee/app/controllers/ee/projects/settings/repository_controller.rb'
- 'ee/app/controllers/groups/analytics/application_controller.rb'
- 'ee/app/controllers/groups/audit_events_controller.rb'
- 'ee/app/controllers/groups/bulk_update_controller.rb'
- 'ee/app/controllers/groups/contribution_analytics_controller.rb'
- 'ee/app/controllers/groups/epics_controller.rb'
- 'ee/app/controllers/groups/hooks_controller.rb'
- 'ee/app/controllers/groups/issues_analytics_controller.rb'
- 'ee/app/controllers/groups/iterations_controller.rb'
- 'ee/app/controllers/projects/analytics/issues_analytics_controller.rb'
- 'ee/app/controllers/projects/audit_events_controller.rb'
- 'ee/app/controllers/projects/cluster_agents_controller.rb'
- 'ee/app/controllers/projects/iterations/inherited_controller.rb'
- 'ee/app/controllers/projects/iterations_controller.rb'
- 'ee/app/controllers/projects/path_locks_controller.rb'
- 'ee/app/controllers/projects/subscriptions_controller.rb'
- 'ee/app/finders/autocomplete/vulnerabilities_autocomplete_finder.rb'
- 'ee/app/finders/clusters/agents_finder.rb'
- 'ee/app/finders/ee/alert_management/alerts_finder.rb'
- 'ee/app/finders/ee/alert_management/http_integrations_finder.rb'
- 'ee/app/finders/ee/group_projects_finder.rb'
- 'ee/app/graphql/ee/types/group_type.rb'
- 'ee/app/graphql/mutations/dast/profiles/create.rb'
- 'ee/app/graphql/mutations/dast/profiles/run.rb'
- 'ee/app/graphql/mutations/dast/profiles/update.rb'
- 'ee/app/graphql/mutations/instance_security_dashboard/remove_project.rb'
- 'ee/app/graphql/resolvers/boards/epic_boards_resolver.rb'
- 'ee/app/graphql/resolvers/clusters/agent_tokens_resolver.rb'
- 'ee/app/graphql/resolvers/epics_resolver.rb'
- 'ee/app/helpers/ee/analytics/navbar_helper.rb'
- 'ee/app/helpers/ee/application_helper.rb'
- 'ee/app/helpers/ee/boards_helper.rb'
- 'ee/app/helpers/ee/clusters_helper.rb'
- 'ee/app/helpers/ee/dashboard_helper.rb'
- 'ee/app/helpers/ee/form_helper.rb'
- 'ee/app/helpers/ee/graph_helper.rb'
- 'ee/app/helpers/ee/groups_helper.rb'
- 'ee/app/helpers/ee/issues_helper.rb'
- 'ee/app/helpers/ee/lock_helper.rb'
- 'ee/app/helpers/ee/operations_helper.rb'
- 'ee/app/helpers/ee/projects/incidents_helper.rb'
- 'ee/app/helpers/ee/projects_helper.rb'
- 'ee/app/helpers/ee/releases_helper.rb'
- 'ee/app/helpers/ee/search_helper.rb'
- 'ee/app/helpers/ee/tree_helper.rb'
- 'ee/app/helpers/groups/security_features_helper.rb'
- 'ee/app/models/approval_state.rb'
- 'ee/app/models/concerns/approvable.rb'
- 'ee/app/models/concerns/ee/project_security_scanners_information.rb'
- 'ee/app/models/concerns/ee/protected_ref_access.rb'
- 'ee/app/models/concerns/has_timelogs_report.rb'
- 'ee/app/models/concerns/insights_feature.rb'
- 'ee/app/models/ee/board.rb'
- 'ee/app/models/ee/ci/build.rb'
- 'ee/app/models/ee/ci/build_dependencies.rb'
- 'ee/app/models/ee/ci/pipeline.rb'
- 'ee/app/models/ee/group.rb'
- 'ee/app/models/ee/group_member.rb'
- 'ee/app/models/ee/issue.rb'
- 'ee/app/models/ee/list.rb'
- 'ee/app/models/ee/merge_request.rb'
- 'ee/app/models/ee/milestone_release.rb'
- 'ee/app/models/ee/namespace.rb'
- 'ee/app/models/ee/namespace_setting.rb'
- 'ee/app/models/ee/project.rb'
- 'ee/app/models/ee/project_ci_cd_setting.rb'
- 'ee/app/models/namespace_statistics.rb'
- 'ee/app/models/project_security_setting.rb'
- 'ee/app/models/saml_provider.rb'
- 'ee/app/policies/compliance_management/framework_policy.rb'
- 'ee/app/policies/compliance_management/framework_policy.rb'
- 'ee/app/policies/ee/group_policy.rb'
- 'ee/app/policies/ee/namespace_policy.rb'
- 'ee/app/policies/ee/project_policy.rb'
- 'ee/app/policies/ee/protected_branch_policy.rb'
- 'ee/app/presenters/ee/label_presenter.rb'
- 'ee/app/presenters/epic_presenter.rb'
- 'ee/app/presenters/merge_request_approver_presenter.rb'
- 'ee/app/serializers/dashboard_operations_project_entity.rb'
- 'ee/app/serializers/ee/environment_entity.rb'
- 'ee/app/serializers/ee/evidences/release_entity.rb'
- 'ee/app/serializers/ee/note_entity.rb'
- 'ee/app/services/boards/epic_boards/update_service.rb'
- 'ee/app/services/ci/audit_variable_change_service.rb'
- 'ee/app/services/clusters/agent_tokens/create_service.rb'
- 'ee/app/services/clusters/agents/create_service.rb'
- 'ee/app/services/dashboard/projects/create_service.rb'
- 'ee/app/services/dashboard/projects/list_service.rb'
- 'ee/app/services/dast/profiles/create_service.rb'
- 'ee/app/services/dast/profiles/update_service.rb'
- 'ee/app/services/dast_on_demand_scans/create_service.rb'
- 'ee/app/services/dast_site_tokens/create_service.rb'
- 'ee/app/services/dast_site_validations/create_service.rb'
- 'ee/app/services/dast_site_validations/revoke_service.rb'
- 'ee/app/services/dast_site_validations/validate_service.rb'
- 'ee/app/services/ee/alert_management/http_integrations/create_service.rb'
- 'ee/app/services/ee/audit_event_service.rb'
- 'ee/app/services/ee/boards/issues/list_service.rb'
- 'ee/app/services/ee/boards/lists/create_service.rb'
- 'ee/app/services/ee/boards/update_service.rb'
- 'ee/app/services/ee/groups/create_service.rb'
- 'ee/app/services/ee/ide/schemas_config_service.rb'
- 'ee/app/services/ee/issuable_base_service.rb'
- 'ee/app/services/ee/issue_links/create_service.rb'
- 'ee/app/services/ee/issues/build_service.rb'
- 'ee/app/services/ee/lfs/lock_file_service.rb'
- 'ee/app/services/ee/lfs/unlock_file_service.rb'
- 'ee/app/services/ee/merge_requests/approval_service.rb'
- 'ee/app/services/ee/merge_requests/build_service.rb'
- 'ee/app/services/ee/merge_requests/merge_base_service.rb'
- 'ee/app/services/ee/merge_requests/refresh_service.rb'
- 'ee/app/services/ee/merge_requests/update_service.rb'
- 'ee/app/services/ee/projects/create_service.rb'
- 'ee/app/services/ee/protected_branches/create_service.rb'
- 'ee/app/services/ee/releases/create_evidence_service.rb'
- 'ee/app/services/ee/search/group_service.rb'
- 'ee/app/services/iterations/cadences/create_service.rb'
- 'ee/app/services/iterations/cadences/update_service.rb'
- 'ee/app/services/iterations/create_service.rb'
- 'ee/app/services/iterations/update_service.rb'
- 'ee/app/services/merge_requests/sync_report_approver_approval_rules.rb'
- 'ee/app/services/merge_requests/update_blocks_service.rb'
- 'ee/app/services/projects/mark_for_deletion_service.rb'
- 'ee/app/services/quality_management/test_cases/create_service.rb'
- 'ee/app/services/requirements_management/process_test_reports_service.rb'
- 'ee/app/services/security/store_scans_service.rb'
- 'ee/app/views/groups/_templates_setting.html.haml'
- 'ee/app/views/groups/contribution_analytics/show.html.haml'
- 'ee/app/views/groups/ee/_settings_nav.html.haml'
- 'ee/app/views/groups/epics/index.html.haml'
- 'ee/app/views/groups/epics/show.html.haml'
- 'ee/app/views/groups/epics/show.html.haml'
- 'ee/app/views/groups/hooks/index.html.haml'
- 'ee/app/views/groups/roadmap/show.html.haml'
- 'ee/app/views/groups/settings/_allowed_email_domain.html.haml'
- 'ee/app/views/groups/settings/_ip_restriction.html.haml'
- 'ee/app/views/layouts/nav/_test_cases_link.html.haml'
- 'ee/app/views/layouts/nav/sidebar/_project_iterations_link.html.haml'
- 'ee/app/views/projects/_merge_request_approvals_settings.html.haml'
- 'ee/app/views/projects/_merge_request_settings.html.haml'
- 'ee/app/views/projects/_merge_request_settings_description_text.html.haml'
- 'ee/app/views/projects/audit_events/index.html.haml'
- 'ee/app/views/projects/blob/_header_file_locks.html.haml'
- 'ee/app/views/projects/issues/_related_issues.html.haml'
- 'ee/app/views/projects/merge_requests/show.html.haml'
- 'ee/app/views/projects/merge_requests/show.html.haml'
- 'ee/app/views/projects/merge_requests/show.html.haml'
- 'ee/app/views/projects/merge_requests/show.html.haml'
- 'ee/app/views/projects/merge_requests/show.html.haml'
- 'ee/app/views/projects/merge_requests/show.html.haml'
- 'ee/app/views/projects/merge_requests/show.html.haml'
- 'ee/app/views/projects/merge_requests/show.html.haml'
- 'ee/app/views/projects/merge_requests/show.html.haml'
- 'ee/app/views/projects/pipelines/_tabs_content.html.haml'
- 'ee/app/views/projects/protected_branches/ee/_code_owner_approval_form.html.haml'
- 'ee/app/views/projects/protected_branches/ee/_code_owner_approval_table.html.haml'
- 'ee/app/views/projects/protected_branches/ee/_code_owner_approval_table_head.html.haml'
- 'ee/app/views/projects/push_rules/_index.html.haml'
- 'ee/app/views/projects/settings/_default_issue_template.html.haml'
- 'ee/app/views/projects/settings/_marked_for_removal.html.haml'
- 'ee/app/views/projects/settings/_restore.html.haml'
- 'ee/app/views/projects/settings/ci_cd/_auto_rollback.html.haml'
- 'ee/app/views/projects/settings/ci_cd/_pipeline_subscriptions.html.haml'
- 'ee/app/views/projects/settings/operations/_status_page.html.haml'
- 'ee/app/views/projects/settings/repository/_protected_branches.html.haml'
- 'ee/app/views/projects/sidebar/_repository_locked_files.html.haml'
- 'ee/app/views/shared/issuable/_board_create_list_dropdown.html.haml'
- 'ee/app/views/shared/issuable/_board_create_list_dropdown.html.haml'
- 'ee/app/views/shared/issuable/_group_bulk_update_sidebar.html.haml'
- 'ee/app/views/shared/issuable/_iteration_select.html.haml'
- 'ee/app/views/shared/issuable/form/_default_templates.html.haml'
- 'ee/app/views/shared/labels/_create_label_help_text.html.haml'
- 'ee/app/views/shared/promotions/_promote_mr_features.html.haml'
- 'ee/app/views/shared/promotions/_promote_mr_features.html.haml'
- 'ee/app/views/shared/promotions/_promote_repository_features.html.haml'
- 'ee/app/views/shared/promotions/_promote_repository_features.html.haml'
- 'ee/app/views/shared/promotions/_promote_repository_features.html.haml'
- 'ee/app/views/shared/promotions/_promote_repository_features.html.haml'
- 'ee/app/views/shared/promotions/_promote_repository_features.html.haml'
- 'ee/app/views/shared/promotions/_promote_repository_features.html.haml'
- 'ee/app/workers/analytics/code_review_metrics_worker.rb'
- 'ee/app/workers/group_saml_group_sync_worker.rb'
- 'ee/lib/api/external_approval_rules.rb'
- 'ee/lib/api/helpers/epics_helpers.rb'
- 'ee/lib/api/ldap_group_links.rb'
- 'ee/lib/ee/api/entities/approval_state.rb'
- 'ee/lib/ee/api/entities/board.rb'
- 'ee/lib/ee/api/entities/group.rb'
- 'ee/lib/ee/api/entities/issue.rb'
- 'ee/lib/ee/api/entities/project.rb'
- 'ee/lib/ee/api/groups.rb'
- 'ee/lib/ee/api/helpers.rb'
- 'ee/lib/ee/api/internal/kubernetes.rb'
- 'ee/lib/ee/api/job_artifacts.rb'
- 'ee/lib/ee/api/projects.rb'
- 'ee/lib/ee/gitlab/alert_management/payload/generic.rb'
- 'ee/lib/ee/gitlab/checks/diff_check.rb'
- 'ee/lib/ee/gitlab/gon_helper.rb'
- 'ee/lib/ee/gitlab/tree_summary.rb'
- 'ee/lib/gitlab/alert_management.rb'
- 'ee/lib/gitlab/auth/group_saml/group_lookup.rb'
- 'ee/lib/gitlab/ci/pipeline/chain/config/content/compliance.rb'
- 'ee/lib/gitlab/code_owners.rb'
- 'ee/lib/gitlab/import_export/group/group_and_descendants_repo_restorer.rb'
- 'ee/lib/gitlab/incident_management.rb'
- 'ee/lib/gitlab/path_locks_finder.rb'
- 'ee/lib/incident_management/incident_sla.rb'
- 'ee/spec/models/ee/namespace_spec.rb'
- 'ee/spec/models/instance_security_dashboard_spec.rb'
- 'ee/spec/models/license_spec.rb'
- 'ee/spec/models/project_spec.rb'
- 'lib/api/helpers/related_resources_helpers.rb'
- 'spec/models/concerns/featurable_spec.rb'

View File

@ -51,10 +51,6 @@ export default {
},
methods: {
...mapActions(['toggleBoardItem', 'setAssignees']),
updateAssignees(data) {
const assignees = data.issueSetAssignees?.issue?.assignees?.nodes || [];
this.setAssignees(assignees);
},
handleClose() {
this.toggleBoardItem({ boardItem: this.activeIssue, sidebarType: this.sidebarType });
},
@ -78,7 +74,7 @@ export default {
:full-path="fullPath"
:initial-assignees="activeIssue.assignees"
class="assignee"
@assignees-updated="updateAssignees"
@assignees-updated="setAssignees"
/>
<board-sidebar-epic-select class="epic" />
<div>

View File

@ -69,6 +69,7 @@ export default {
'milestoneTitle',
'releaseTag',
'search',
'myReactionEmoji',
]);
filterParams.not = transformNotFilters(filters);
commit(types.SET_FILTERS, filterParams);

View File

@ -66,8 +66,8 @@ export default {
},
listClasses() {
return {
'gl-pl-7': this.nestedLevel === 1,
'gl-pl-9': this.nestedLevel === 2,
'gl-pl-9': this.nestedLevel === 1,
'gl-pl-11-5': this.nestedLevel === 2,
};
},
},

View File

@ -88,8 +88,8 @@ export default {
},
listClasses() {
return {
'gl-pl-7': this.nestedLevel === 1,
'gl-pl-8': this.nestedLevel === 2,
'gl-pl-9': this.nestedLevel === 1,
'gl-pl-11-5': this.nestedLevel === 2,
};
},
},

View File

@ -51,7 +51,7 @@ export default {
if (!this.nestedSummary) {
return ['gl-px-5'];
}
return ['gl-pl-7', 'gl-pr-5', { 'gl-bg-gray-10': this.statusIcon === ICON_WARNING }];
return ['gl-pl-9', 'gl-pr-5', { 'gl-bg-gray-10': this.statusIcon === ICON_WARNING }];
},
statusIconSize() {
if (!this.nestedSummary) {

View File

@ -24,7 +24,7 @@ export default {
n__(
'Reports|Failed %{count} time in %{base_branch} in the last 14 days',
'Reports|Failed %{count} times in %{base_branch} in the last 14 days',
this.issue.recent_failures.count,
this.issue.recent_failures?.count,
),
this.issue.recent_failures,
);
@ -44,20 +44,20 @@ export default {
<template>
<div class="gl-display-flex gl-mt-2 gl-mb-2">
<issue-status-icon :status="status" :status-icon-size="24" class="gl-mr-3" />
<gl-badge
v-if="showRecentFailures"
variant="warning"
class="gl-mr-2"
data-testid="test-issue-body-recent-failures"
>
{{ recentFailureMessage }}
</gl-badge>
<gl-button
button-text-classes="gl-white-space-normal! gl-word-break-all gl-text-left"
variant="link"
data-testid="test-issue-body-description"
@click="openModal({ issue })"
>
<gl-badge
v-if="showRecentFailures"
variant="warning"
class="gl-mr-2"
data-testid="test-issue-body-recent-failures"
>
{{ recentFailureMessage }}
</gl-badge>
{{ issue.name }}
</gl-button>
</div>

View File

@ -9,6 +9,7 @@ import {
GlDropdownItem,
GlIcon,
} from '@gitlab/ui';
import { isEmpty } from 'lodash';
import { __, s__ } from '~/locale';
import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
import {
@ -79,7 +80,7 @@ export default {
return Object.keys(this.selectedPlatform).length > 0;
},
instructionsEmpty() {
return Object.keys(this.instructions).length === 0;
return isEmpty(this.instructions);
},
groupId() {
return this.group?.id ?? '';
@ -212,10 +213,7 @@ export default {
<pre
class="gl-bg-gray gl-flex-fill-1 gl-white-space-pre-line"
data-testid="binary-instructions"
>
{{ instructions.installInstructions }}
</pre
>{{ instructions.installInstructions }}</pre
>
<modal-copy-button
:title="$options.i18n.copyInstructions"

View File

@ -30,9 +30,11 @@ class Admin::GroupsController < Admin::ApplicationController
def new
@group = Group.new
@group.build_admin_note
end
def edit
@group.build_admin_note unless @group.admin_note
end
def create
@ -49,6 +51,8 @@ class Admin::GroupsController < Admin::ApplicationController
end
def update
@group.build_admin_note unless @group.admin_note
if @group.update(group_params)
redirect_to [:admin, @group], notice: _('Group was successfully updated.')
else
@ -105,7 +109,10 @@ class Admin::GroupsController < Admin::ApplicationController
:require_two_factor_authentication,
:two_factor_grace_period,
:project_creation_level,
:subgroup_creation_level
:subgroup_creation_level,
admin_note_attributes: [
:note
]
]
end
end

View File

@ -46,6 +46,9 @@ class Namespace < ApplicationRecord
has_one :aggregation_schedule, class_name: 'Namespace::AggregationSchedule'
has_one :package_setting_relation, inverse_of: :namespace, class_name: 'PackageSetting'
has_one :admin_note, inverse_of: :namespace
accepts_nested_attributes_for :admin_note, update_only: true
validates :owner, presence: true, unless: ->(n) { n.type == "Group" }
validates :name,
presence: true,
@ -284,8 +287,13 @@ class Namespace < ApplicationRecord
false
end
# Deprecated, use #licensed_feature_available? instead. Remove once Namespace#feature_available? isn't used anymore.
def feature_available?(feature)
licensed_feature_available?(feature)
end
# Overridden in EE::Namespace
def feature_available?(_feature)
def licensed_feature_available?(_feature)
false
end

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class Namespace::AdminNote < ApplicationRecord
belongs_to :namespace, inverse_of: :admin_note
validates :namespace, presence: true
validates :note, length: { maximum: 1000 }
end

View File

@ -2324,6 +2324,11 @@ class Project < ApplicationRecord
.external_authorization_service_default_label
end
# Overridden in EE::Project
def licensed_feature_available?(_feature)
false
end
def licensed_features
[]
end

View File

@ -3,6 +3,7 @@
class ProjectFeature < ApplicationRecord
include Featurable
# When updating this array, make sure to update rubocop/cop/gitlab/feature_available_usage.rb as well.
FEATURES = %i[
issues
forking

View File

@ -3,6 +3,8 @@
= render 'shared/group_form', f: f
= render 'shared/group_form_description', f: f
= render 'shared/admin/admin_note_form', f: f
= render_if_exists 'shared/old_repository_size_limit_setting', form: f, type: :group
= render_if_exists 'admin/namespace_plan', f: f

View File

@ -103,6 +103,8 @@
%span.monospace= project.full_path + '.git'
.col-md-6
= render 'shared/admin/admin_note'
- if can?(current_user, :admin_group_member, @group)
.card
.card-header

View File

@ -2,6 +2,6 @@
%legend= _('Admin notes')
.form-group.row
.col-sm-2.col-form-label
= f.label :note, s_('AdminNote|Note')
= f.label :note, s_('Admin|Note')
.col-sm-10
= f.text_area :note, class: 'form-control gl-form-input gl-form-textarea'

View File

@ -19,5 +19,5 @@
type: 'group',
reset_token_url: reset_registration_token_group_settings_ci_cd_path,
project_path: '',
group_path: @group.path }
group_path: @group.full_path }
%br

View File

@ -0,0 +1,7 @@
- if @group.admin_note.present?
- text = @group.admin_note.note
.card.border-info
.card-header.bg-info.gl-text-white
= s_('Admin|Admin notes')
.card-body
%p= text

View File

@ -0,0 +1,6 @@
.form-group.row
= f.fields_for :admin_note do |an|
.col-sm-2.col-form-label.gl-text-right
= an.label :note, s_('Admin|Admin notes')
.col-sm-10
= an.text_area :note, class: 'form-control'

View File

@ -0,0 +1,5 @@
---
title: Validate NOT NULL constraint on gitlab_subscriptions namespace_id
merge_request: 57113
author:
type: other

View File

@ -0,0 +1,5 @@
---
title: Fix updating GraphQL boards cards on assignees update
merge_request: 57687
author:
type: fixed

View File

@ -0,0 +1,6 @@
---
title: Display error message when runner installation instructions modal cannot be
loaded correctly
merge_request: 57588
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Allow admin users to define admin notes on groups.
merge_request: 47825
author:
type: added

View File

@ -0,0 +1,5 @@
---
title: Fix test report merge request widget summary and issues alignment
merge_request: 56768
author:
type: fixed

View File

@ -0,0 +1,21 @@
# frozen_string_literal: true
class CreateAdminNotes < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def up
create_table_with_constraints :namespace_admin_notes do |t|
t.timestamps_with_timezone
t.references :namespace, null: false, foreign_key: { on_delete: :cascade }
t.text :note
t.text_limit :note, 1000
end
end
def down
drop_table :namespace_admin_notes
end
end

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
class ValidateNotNullConstraintOnGitlabSubscriptionsNamespaceId < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
validate_not_null_constraint :gitlab_subscriptions, :namespace_id
end
def down
# no-op
end
end

View File

@ -0,0 +1 @@
7c33bd30af66ebb9a837c72e2ced107f015d4a22c7b6393554a9299bf3907cc0

View File

@ -0,0 +1 @@
e177c2cc0b59eea54de10417445b391cea7dd308547077aea34054fac22b9e40

View File

@ -13147,7 +13147,8 @@ CREATE TABLE gitlab_subscriptions (
auto_renew boolean,
seats_in_use integer DEFAULT 0 NOT NULL,
seats_owed integer DEFAULT 0 NOT NULL,
trial_extension_type smallint
trial_extension_type smallint,
CONSTRAINT check_77fea3f0e7 CHECK ((namespace_id IS NOT NULL))
);
CREATE SEQUENCE gitlab_subscriptions_id_seq
@ -14640,6 +14641,24 @@ CREATE SEQUENCE milestones_id_seq
ALTER SEQUENCE milestones_id_seq OWNED BY milestones.id;
CREATE TABLE namespace_admin_notes (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
namespace_id bigint NOT NULL,
note text,
CONSTRAINT check_e9d2e71b5d CHECK ((char_length(note) <= 1000))
);
CREATE SEQUENCE namespace_admin_notes_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE namespace_admin_notes_id_seq OWNED BY namespace_admin_notes.id;
CREATE TABLE namespace_aggregation_schedules (
namespace_id integer NOT NULL
);
@ -19510,6 +19529,8 @@ ALTER TABLE ONLY metrics_users_starred_dashboards ALTER COLUMN id SET DEFAULT ne
ALTER TABLE ONLY milestones ALTER COLUMN id SET DEFAULT nextval('milestones_id_seq'::regclass);
ALTER TABLE ONLY namespace_admin_notes ALTER COLUMN id SET DEFAULT nextval('namespace_admin_notes_id_seq'::regclass);
ALTER TABLE ONLY namespace_statistics ALTER COLUMN id SET DEFAULT nextval('namespace_statistics_id_seq'::regclass);
ALTER TABLE ONLY namespaces ALTER COLUMN id SET DEFAULT nextval('namespaces_id_seq'::regclass);
@ -20238,9 +20259,6 @@ ALTER TABLE ONLY chat_teams
ALTER TABLE vulnerability_scanners
ADD CONSTRAINT check_37608c9db5 CHECK ((char_length(vendor) <= 255)) NOT VALID;
ALTER TABLE gitlab_subscriptions
ADD CONSTRAINT check_77fea3f0e7 CHECK ((namespace_id IS NOT NULL)) NOT VALID;
ALTER TABLE sprints
ADD CONSTRAINT check_ccd8a1eae0 CHECK ((start_date IS NOT NULL)) NOT VALID;
@ -20895,6 +20913,9 @@ ALTER TABLE ONLY milestone_releases
ALTER TABLE ONLY milestones
ADD CONSTRAINT milestones_pkey PRIMARY KEY (id);
ALTER TABLE ONLY namespace_admin_notes
ADD CONSTRAINT namespace_admin_notes_pkey PRIMARY KEY (id);
ALTER TABLE ONLY namespace_aggregation_schedules
ADD CONSTRAINT namespace_aggregation_schedules_pkey PRIMARY KEY (namespace_id);
@ -23122,6 +23143,8 @@ CREATE INDEX index_mr_metrics_on_target_project_id_merged_at_nulls_last ON merge
CREATE INDEX index_mr_metrics_on_target_project_id_merged_at_time_to_merge ON merge_request_metrics USING btree (target_project_id, merged_at, created_at) WHERE (merged_at > created_at);
CREATE INDEX index_namespace_admin_notes_on_namespace_id ON namespace_admin_notes USING btree (namespace_id);
CREATE UNIQUE INDEX index_namespace_aggregation_schedules_on_namespace_id ON namespace_aggregation_schedules USING btree (namespace_id);
CREATE UNIQUE INDEX index_namespace_root_storage_statistics_on_namespace_id ON namespace_root_storage_statistics USING btree (namespace_id);
@ -25964,6 +25987,9 @@ ALTER TABLE ONLY approval_merge_request_rules_approved_approvers
ALTER TABLE ONLY operations_feature_flags_clients
ADD CONSTRAINT fk_rails_6650ed902c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY namespace_admin_notes
ADD CONSTRAINT fk_rails_666166ea7b FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
ALTER TABLE ONLY web_hook_logs
ADD CONSTRAINT fk_rails_666826e111 FOREIGN KEY (web_hook_id) REFERENCES web_hooks(id) ON DELETE CASCADE;

View File

@ -8,10 +8,10 @@ type: reference, api
# DORA4 Analytics Group API **(ULTIMATE SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/291747) in GitLab 13.9.
> - It's [deployed behind a feature flag](../user/feature_flags.md), disabled by default.
> - It's disabled on GitLab.com.
> - It's not recommended for production use.
> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-dora4-analytics-group-api). **(ULTIMATE SELF)**
> - [Deployed behind a feature flag](../user/feature_flags.md), disabled by default.
> - Disabled on GitLab.com.
> - Not recommended for production use.
> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-dora4-analytics-group-api).
WARNING:
This feature might not be available to you. Check the **version history** note above for details.

View File

@ -6,9 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Feature Flags API **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.5.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Starter](https://about.gitlab.com/pricing/) in 13.4.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Free](https://about.gitlab.com/pricing/) in 13.5.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in GitLab Premium 12.5.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to GitLab Free in 13.5.
API for accessing resources of [GitLab Feature Flags](../operations/feature_flags.md).

View File

@ -6,9 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Legacy Feature Flags API **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.5.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Starter](https://about.gitlab.com/pricing/) in 13.4.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Free](https://about.gitlab.com/pricing/) in 13.5.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in GitLab Premium 12.5.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to GitLab Free in 13.5.
WARNING:
This API is deprecated and [scheduled for removal in GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/213369). Use [this API](feature_flags.md) instead.

View File

@ -463,7 +463,8 @@ The following GitLab features are used among others:
## Testing
For more information on documentation testing, see [Documentation testing](testing.md)
For more information about documentation testing, see the [Documentation testing](testing.md)
guide.
## Danger Bot

View File

@ -153,6 +153,14 @@ This issue occurs when...
The workaround is...
```
For the topic title:
- Consider including at least a partial error message in the title.
- Use fewer than 70 characters.
Remember to include the complete error message in the topics content if it is
not complete in the title.
## Other information on a topic
Topics include other information.

View File

@ -1038,7 +1038,7 @@ To identify a high-traffic table for GitLab.com the following measures are consi
Note that the metrics linked here are GitLab-internal only:
- [Read operations](https://thanos.gitlab.net/graph?g0.range_input=2h&g0.max_source_resolution=0s&g0.expr=topk(500%2C%20sum%20by%20(relname)%20(rate(pg_stat_user_tables_seq_tup_read%7Benvironment%3D%22gprd%22%7D%5B12h%5D)%20%2B%20rate(pg_stat_user_tables_idx_scan%7Benvironment%3D%22gprd%22%7D%5B12h%5D)%20%2B%20rate(pg_stat_user_tables_idx_tup_fetch%7Benvironment%3D%22gprd%22%7D%5B12h%5D)))&g0.tab=1)
- [Number of records](https://thanos.gitlab.net/graph?g0.range_input=2h&g0.max_source_resolution=0s&g0.expr=topk(500%2C%20sum%20by%20(relname)%20(rate(pg_stat_user_tables_n_live_tup%7Benvironment%3D%22gprd%22%7D%5B12h%5D)))&g0.tab=1)
- [Size](https://thanos.gitlab.net/graph?g0.range_input=2h&g0.max_source_resolution=0s&g0.expr=topk(500%2C%20sum%20by%20(relname)%20(rate(pg_total_relation_size_bytes%7Benvironment%3D%22gprd%22%7D%5B12h%5D)))&g0.tab=1) is greater than 10 GB
- [Number of records](https://thanos.gitlab.net/graph?g0.range_input=2h&g0.max_source_resolution=0s&g0.expr=topk(500%2C%20max%20by%20(relname)%20(pg_stat_user_tables_n_live_tup%7Benvironment%3D%22gprd%22%7D))&g0.tab=1)
- [Size](https://thanos.gitlab.net/graph?g0.range_input=2h&g0.max_source_resolution=0s&g0.expr=topk(500%2C%20max%20by%20(relname)%20(pg_total_relation_size_bytes%7Benvironment%3D%22gprd%22%7D))&g0.tab=1) is greater than 10 GB
Any table which has some high read operation compared to current [high-traffic tables](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L4) might be a good candidate.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

View File

@ -8,443 +8,316 @@ type: howto
# Install GitLab on Microsoft Azure **(FREE SELF)**
WARNING:
This guide is deprecated and pending an update. For the time being, use the GitLab
[image in the Azure Marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/gitlabinc1586447921813.gitlabee?tab=Overview).
For users of the Microsoft Azure business cloud, GitLab has a pre-configured offering in
the [Azure Marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/).
This tutorial describes installing GitLab
Enterprise Edition in a single Virtual Machine (VM).
Azure is Microsoft's business cloud and GitLab is a pre-configured offering on
the Azure Marketplace. Hopefully, you aren't surprised to hear that Microsoft
and Azure have embraced open source software like Ubuntu, Red Hat Enterprise Linux,
and of course - GitLab! This means that you can spin up a pre-configured
GitLab VM and have your very own private GitLab up and running in around 30
minutes. Let's get started.
## Prerequisite
## Getting started
You'll need an account on Azure. Use of the following methods to obtain an account:
First, you'll need an account on Azure. There are three ways to do this:
- If your company (or you) already has an account, then you are ready to go!
- You can also open your own Azure account for free. _At time of writing_, you get $200
of credit to spend on Azure services for 30 days. You can use this credit to try out paid Azure
services, exploring Microsoft's cloud for free. Even after the first 30 days, you never have to pay
anything unless you decide to transition to paid services with a Pay-As-You-Go Azure subscription.
This is a great way to try out Azure and cloud computing, and you can
[read more in their comprehensive FAQ](https://azure.microsoft.com/en-us/free/free-account-faq/).
- If you or your company already have an account with a subscription, use that account.
If not, you can [open your own Azure account for free](https://azure.microsoft.com/en-us/free/).
Azure's free trial gives you $200 credit to explore Azure for 30 days.
[Read more in Azure's comprehensive FAQ](https://azure.microsoft.com/en-us/free/free-account-faq/).
- If you have an MSDN subscription, you can activate your Azure subscriber benefits. Your MSDN
subscription gives you recurring Azure credits every month, so why not put those credits to use and
try out GitLab right now?
subscription gives you recurring Azure credits every month, so you can use
those credits and try out GitLab.
## Working with Azure
## Deploy and configure GitLab
Once you have an Azure account, you can get started. [Log in to Azure](https://portal.azure.com)
and the first thing you will see is the Dashboard:
Because GitLab is already installed in a pre-configured image, all you have to do is
create a new VM:
![Azure Dashboard](img/azure-dashboard.png)
1. [Visit the GitLab offering in the marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/gitlabinc1586447921813.gitlabee?tab=Overview)
1. Select **Get it now** and you will be presented with the **Create this app in Azure** window.
Select **Continue**.
1. Select one of the following options from the Azure portal:
- Select **Create** to create a VM from scratch.
- Select **Start with a pre-set configuration** to get started with some
pre-configured options. You can modify these configurations at any time.
The Dashboard gives you a quick overview of Azure resources, and from here you can build VMs,
create SQL Databases, author websites, and perform lots of other cloud tasks.
## Create New VM
The [Azure Marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/) is an online store for pre-configured applications and
services which have been optimized for the cloud by software vendors like GitLab,
available on the Azure Marketplace as pre-configured solutions. In this tutorial
we will install GitLab Community Edition.
To begin creating a new GitLab VM, click on the **+ New** icon, type "GitLab" into the search
box, and then click the **"GitLab Community Edition"** search result:
![Azure - New - Search for 'GitLab'](img/azure-new-search-gitlab.png)
A new "blade" window will pop-out, where you can read more about the **"GitLab Community Edition"**
offering which is freely available under the MIT Expat License:
![Azure - New - Select 'GitLab Community Edition'](img/azure-new-gitlab-ce.png)
Click **"Create"** and you will be presented with the "Create virtual machine" blade:
![Azure - Create Virtual Machine - Basics](img/azure-create-virtual-machine-basics.png)
## Basics
The first items we need to configure are the basic settings of the underlying virtual machine:
1. Enter a `Name` for the VM - e.g. **"GitLab-CE"**
1. Select a `VM disk type` - either **HDD** _(slower, lower cost)_ or **SSD** _(faster, higher cost)_
1. Enter a `User name` - e.g. `gitlab-admin`
1. Select an `Authentication type`, either **SSH public key** or **Password**:
NOTE:
If you're unsure which authentication type to use, select **Password**
1. If you chose **SSH public key** - enter your `SSH public key` into the field provided
_(read the [SSH documentation](../../ssh/README.md) to learn more about how to set up SSH
public keys)_
1. If you chose **Password** - enter the password you wish to use _(this is the password that you
will use later in this tutorial to [SSH](https://en.wikipedia.org/wiki/Secure_Shell) into the VM, so make sure it's a strong password/passphrase)_
1. Choose the appropriate `Subscription` tier for your Azure account
1. Choose an existing `Resource Group` or create a new one - e.g. **"GitLab-CE-Azure"**
NOTE:
A "Resource group" is a way to group related resources together for easier administration.
We chose "GitLab-CE-Azure", but your resource group can have the same name as your VM.
1. Choose a `Location` - if you're unsure, select the default location
Here are the settings we've used:
![Azure - Create Virtual Machine - Basics Completed](img/azure-create-virtual-machine-basics-password.png)
Check the settings you have entered, and then click **"OK"** when you're ready to proceed.
## Size
Next, you need to choose the size of your VM - selecting features such as the number of CPU cores,
the amount of RAM, the size of storage (and its speed), etc.
For the sake of this guide, we'll create the VM from scratch, so
select **Create**.
NOTE:
In common with other cloud vendors, Azure operates a resource/usage pricing model, i.e.
the more resources your VM consumes the more it will cost you to run, so make your selection
carefully. You'll see that Azure provides an _estimated_ monthly cost beneath each VM Size to help
guide your selection.
The default size - the lowest cost **"DS1_V2 Standard"** VM - meets the minimum system requirements
to run a small GitLab environment for testing and evaluation purposes, and so we're going to go
ahead and select this one, but please choose the size which best meets your own requirements:
![Azure - Create Virtual Machine - Size](img/azure-create-virtual-machine-size.png)
NOTE:
Be aware that while your VM is active (known as "allocated"), it will incur
"compute charges" which, ultimately, you will be billed for. So, even if you're using the
free trial credits, you'll likely want to learn
Be aware that while your VM is active (known as "allocated"), it incurs
compute charges for which you'll be billed. Even if you're using the
free trial credits, you'll want to know
[how to properly shutdown an Azure VM to save money](https://build5nines.com/properly-shutdown-azure-vm-to-save-money/).
See the [Azure pricing calculator](https://azure.microsoft.com/en-us/pricing/calculator/)
to learn how much resources can cost.
Go ahead and click your chosen size, then click **"Select"** when you're ready to proceed to the
next step.
After you create the virtual machine, use the information in the following
sections to configure it.
## Settings
### Configure the Basics tab
On the next blade, you're asked to configure the Storage, Network and Extension settings.
We've gone with the default settings as they're sufficient for test-driving GitLab, but please
choose the settings which best meet your own requirements:
The first items you need to configure are the basic settings of the underlying virtual machine:
![Azure - Create Virtual Machine - Settings](img/azure-create-virtual-machine-settings.png)
1. Select the subscription model and a resource group (create a new one if it
doesn't exist).
1. Enter a name for the VM, for example `GitLab`.
1. Select a region.
1. In **Availability options**, select **Availability zone** and set it to `1`.
Read more about the [availability zones](https://docs.microsoft.com/en-us/azure/virtual-machines/availability).
1. Ensure the selected image is set to **GitLab - Gen1**.
1. Select the VM size based on the [hardware requirements](../requirements.md#hardware-requirements).
Because the minimum system requirements to run a GitLab environment for up to 500 users
is covered by the `D4s_v3` size, select that option.
1. Set the authentication type to **SSH public key**.
1. Enter a user name or leave the one that is automatically created. This is
the user you'll use to connect to the VM through SSH. By default, the user
has root access.
1. Determine if you want to provide your own SSH key or let Azure create one for you.
Read the [SSH documentation](../../ssh/README.md) to learn more about how to set up SSH
public keys.
Review the settings and then click **"OK"** when you're ready to proceed to the last step.
Review your entered settings, and then proceed to the Disks tab.
## Purchase
### Configure the Disks tab
The Purchase page is the last step and here you will be presented with the price per hour for your
new VM. You'll be billed only for the VM itself (e.g. "Standard DS1 v2") because the
**"GitLab Community Edition"** marketplace solution is free to use at 0 USD/hr:
For the disks:
![Azure - Create Virtual Machine - Purchase](img/azure-create-virtual-machine-purchase.png)
1. For the OS disk type, select **Premium SSD**.
1. Select the default encryption.
NOTE:
At this stage, you can review and modify the any of the settings you have made during all
previous steps, just click on any of the four steps to re-open them.
[Read more about the types of disks](https://docs.microsoft.com/en-us/azure/virtual-machines/managed-disks-overview) that Azure provides.
When you have read and agreed to the terms of use and are ready to proceed, click **"Purchase"**.
Review your settings, and then proceed to the Networking tab.
## Deployment
### Configure the Networking tab
At this point, Azure will begin deploying your new VM. The deployment process will take a few
minutes to complete, with progress displayed on the **"Deployment"** blade:
Use this tab to define the network connectivity for your
virtual machine, by configuring network interface card (NIC) settings.
You can leave them at their default settings.
![Azure - Create Virtual Machine - Deployment](img/azure-create-virtual-machine-deployment.png)
Azure creates a security group by default and the VM is assigned to it.
The GitLab image in the marketplace has the following ports open by default:
Once the deployment process is complete, the new VM and its associated resources will be displayed
on the Azure Dashboard (you may need to refresh the page):
| Port | Description |
|------|-------------|
| 80 | Enable the VM to respond to HTTP requests, allowing public access. |
| 443 | Enable our VM to respond to HTTPS requests, allowing public access. |
| 22 | Enable our VM to respond to SSH connection requests, allowing public access (with authentication) to remote terminal sessions. |
![Azure - Dashboard - All resources](img/azure-dashboard-running-resources.png)
If you want to change the ports or add any rules, you can do it
after the VM is created by going to the Networking settings in the left sidebar,
while in the VM dashboard.
The new VM can also be accessed by clicking the `All resources` or `Virtual machines` icons in the
Azure Portal sidebar navigation menu.
### Configure the Management tab
## Set up a domain name
Use this tab to configure monitoring and management options
for your VM. You don't need to change the default settings.
The VM will have a public IP address (static by default), but Azure allows us to assign a friendly
DNS name to the VM, so let's go ahead and do that.
### Configure the Advanced tab
From the Dashboard, click on the **"GitLab-CE"** tile to open the management blade for the new VM.
The public IP address that the VM uses is shown in the 'Essentials' section:
Use this tab to add additional configuration, agents, scripts
or applications through virtual machine extensions or `cloud-init`. You don't
need to change the default settings.
![Azure - VM - Management - Public IP Address](img/azure-vm-management-public-ip.png)
### Configure the Tags tab
Click on the public IP address - which should open the **"Public IP address - Configuration"** blade,
then click on **"Configuration"** (under "Settings"). Now enter a friendly DNS name for your instance
in the `DNS name label` field:
Use this tab to add name/value pairs that enable you to categorize
resources. You don't need to change the default settings.
![Azure - VM - Domain Name](img/azure-vm-domain-name.png)
### Review and create the VM
In the screenshot above, you'll see that we've set the `DNS name label` to `gitlab-ce-test`.
This will make our VM accessible at `gitlab-ce-test.centralus.cloudapp.azure.com`
_(the full domain name of your own VM will be different, of course)_.
The final tab presents you with all of your selected options,
where you can review and modify your choices from the
previous steps. Azure will run validation tests in the background,
and if you provided all of the required settings, you can
create the VM.
Click **"Save"** for the changes to take effect.
After you select **Create**, if you had opted for Azure to create an SSH key pair
for you, you'll be asked to download the private SSH key. Download the key, as you'll
need it to SSH into the VM.
NOTE:
If you want to use your own domain name, you will need to add a DNS `A` record at your
domain registrar which points to the public IP address of your Azure VM. If you do this, you'll need
to make sure your VM is configured to use a _static_ public IP address (i.e. not a _dynamic_ one)
or you will have to reconfigure the DNS `A` record each time Azure reassigns your VM a new public IP
address. Read [Public IP addresses](https://docs.microsoft.com/en-us/azure/virtual-network/public-ip-addresses) to learn more.
After you download the key, the deployment begins.
## Let's open some ports
### Finish deployment
At this stage you should have a running and fully operational VM. However, none of the services on
your VM (e.g. GitLab) will be publicly accessible via the internet until you have opened up the
necessary ports to enable access to those services.
At this point, Azure begins to deploy your new VM. The deployment process
takes a few minutes to complete. After it's complete, the new VM and its
associated resources are displayed on the Azure Dashboard.
Select **Go to resource** to visit the dashboard of the VM.
Ports are opened by adding _security rules_ to the **"Network security group"** (NSG) which our VM
has been assigned to. If you followed the process above, then Azure will have automatically created
an NSG named `GitLab-CE-nsg` and assigned the `GitLab-CE` VM to it.
GitLab is now deployed and ready to be used. Before doing so, however,
you need to set up the domain name and configure GitLab to use it.
NOTE:
If you gave your VM a different name then the NSG automatically created by Azure will
also have a different name - the name you have your VM, with `-nsg` appended to it.
### Set up a domain name
You can navigate to the NSG settings via many different routes in the Azure Portal, but one of the
simplest ways is to go to the Azure Dashboard, and then click on the Network Security Group listed
in the **"All resources"** tile:
The VM has a public IP address (static by default), but Azure allows you
to assign a descriptive DNS name to the VM:
![Azure - Dashboard - All resources - Network security group](img/azure-dashboard-highlight-nsg.png)
1. From the VM dashboard, select **Configure** under **DNS name**.
1. Enter a descriptive DNS name for your instance in the **DNS name label** field,
for example `gitlab-prod`. This will make the VM accessible at
`gitlab-prod.eastus.cloudapp.azure.com`.
1. Select **Save** for the changes to take effect.
With the **"Network security group"** blade open, click on **"Inbound security rules"** under
**"Settings"**:
Eventually, you'll want to use your own domain name. To do this, you need to add a DNS `A` record
with your domain registrar that points to the public IP address of your Azure VM.
You can use [Azure's DNS](https://docs.microsoft.com/en-us/azure/dns/dns-delegate-domain-azure-dns)
or some [other registrar](https://docs.gitlab.com/omnibus/settings/dns.html).
![Azure - Network security group - Inbound security rules](img/azure-nsg-inbound-sec-rules-highlight.png)
### Change the GitLab external URL
Next, click **"Add"**:
GitLab uses `external_url` in its configuration file to set up the domain name.
If you don't set this up, when you visit the Azure friendly name, you'll
instead be redirected to the public IP.
![Azure - Network security group - Inbound security rules - Add](img/azure-nsg-inbound-sec-rules-add-highlight.png)
To set up the GitLab external URL:
### Which ports to open?
1. Connect to GitLab through SSH by going to **Settings > Connect** from the VM
dashboard, and follow the instructions. Remember to sign in with the username
and SSH key you specified when you [created the VM](#configure-the-basics-tab).
The Azure VM domain name will be the one you
[set up previously](#set-up-a-domain-name). If you didn't set up a domain name for
your VM, you can use the IP address in its place.
Like all servers, our VM will be running many services. However, we want to open up the correct
ports to enable public internet access to two services in particular:
In the case of our example:
1. **HTTP** (port 80) - opening port 80 will enable our VM to respond to HTTP requests, allowing
public access to the instance of GitLab running on our VM.
1. **SSH** (port 22) - opening port 22 will enable our VM to respond to SSH connection requests,
allowing public access (with authentication) to remote terminal sessions
_(you'll see why we need [SSH](https://en.wikipedia.org/wiki/Secure_Shell) access to our VM [later on in this tutorial](#maintaining-your-gitlab-instance))_
```shell
ssh -i <private key path> gitlab-azure@gitlab-prod.eastus.cloudapp.azure.com
```
### Open HTTP on Port 80
NOTE:
If you need to reset your credentials, read
[how to reset SSH credentials for a user on an Azure VM](https://docs.microsoft.com/en-us/troubleshoot/azure/virtual-machines/troubleshoot-ssh-connection#reset-ssh-credentials-for-a-user).
In the **"Add inbound security rule"** blade, let's open port 80 so that our VM will accept HTTP
connections:
1. Open `/etc/gitlab/gitlab.rb` with your editor.
1. Find `external_url` and replace it with your own domain name. For the sake
of this example, we'll use the friendly domain name that Azure set up.
If you use `https` in the URL, Let's Encrypt will be
[automatically enabled](https://docs.gitlab.com/omnibus/settings/ssl.html#lets-encrypt-integration),
and you'll have HTTPS by default:
![Azure - Add inbound security rules - HTTP](img/azure-add-inbound-sec-rule-http.png)
```ruby
external_url 'https://gitlab-prod.eastus.cloudapp.azure.com'
```
1. Enter **"HTTP"** in the `Name` field
1. Select **HTTP** from the options in the `Service` dropdown list
1. Make sure the `Action` is set to **Allow**
1. Click **"OK"**
1. Find the following settings and comment them out, so that GitLab doesn't
pick up the wrong certificates:
### Open SSH on Port 22
```ruby
# nginx['redirect_http_to_https'] = true
# nginx['ssl_certificate'] = "/etc/gitlab/ssl/server.crt"
# nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/server.key"
```
Repeat the above process, adding a second Inbound security rule to open port 22, enabling our VM to
accept [SSH](https://en.wikipedia.org/wiki/Secure_Shell) connections:
1. Reconfigure GitLab for the changes to take effect. Run the
following command every time you make changes to `/etc/gitlab/gitlab.rb`:
![Azure - Add inbound security rules - SSH](img/azure-add-inbound-sec-rule-ssh.png)
```shell
sudo gitlab-ctl reconfigure
```
1. Enter **"SSH"** in the `Name` field
1. Select **SSH** from the options in the `Service` dropdown list
1. Make sure the `Action` is set to **Allow**
1. Click **"OK"**
You can now visit GitLab with your browser at the new external URL.
It will take a moment for Azure to add each new Inbound Security Rule (and you may need to click on
**"Inbound security rules"** to refresh the list), but once completed, you should see the two new
rules in the list:
### Visit GitLab for the first time
![Azure - Inbound security rules - List](img/azure-inbound-sec-rules-list.png)
Use the domain name you set up earlier to visit your new GitLab instance
in your browser. In this example, it's `https://gitlab-prod.eastus.cloudapp.azure.com`.
## Connecting to GitLab
The first thing you'll see is the sign-in page. GitLab creates an admin user by default.
The credentials are:
Use the domain name you set up earlier (or the public IP address) to visit your new GitLab instance
in your browser. If everything has gone according to plan you should be presented with the
following page, asking you to set a _new_ password for the administrator account automatically
created by GitLab:
- Username: `root`
- Password: the password is automatically created, and there are [two ways to
find it](https://docs.bitnami.com/azure/faq/get-started/find-credentials).
![GitLab - Change Password](img/gitlab-change-password.png)
After signing in, be sure to immediately [change the password](../../user/profile/index.md#change-your-password).
Enter your _new_ password into both form fields, and then click **"Change your password"**.
Once you have changed the password you will be redirected to the GitLab login page. Use `root` as
the username, enter the new password you set in the previous step, and then click **"Sign in"**:
![GitLab - Login](img/gitlab-login.png)
### Success?
After signing in successfully, you should see the GitLab Projects page displaying a
**"Welcome to GitLab!"** message:
![GitLab - Projects Page](img/gitlab-home.png)
If so, you now have a working GitLab instance on your own private Azure VM. **Congratulations!**
## Creating your first GitLab project
You can skip this section if you are familiar with Git and GitLab. Otherwise, let's create our first
project. From the Welcome page, click **"New Project"**.
Let's give our project a name and a description, and then accept the default values for everything
else:
1. Enter **"demo"** into the `Project path` project name field
1. Enter a `description`, e.g. **"My awesome demo project!"**
1. Click **"Create project"**
![GitLab - New Project](img/gitlab-new-project.png)
Once the new project has been created (which should only take a moment), you'll be redirected to
homepage for the project:
![GitLab - Empty Project](img/gitlab-project-home-empty.png)
If you scroll further down the project's home page, you'll see some basic instructions on how to
set up a local clone of your new repository and push and pull from it:
![GitLab - Empty Project - Basic Instructions](img/gitlab-project-home-instructions.png)
**That's it! You now have your own private GitLab environment installed and running in the cloud!**
## Maintaining your GitLab instance
## Maintain your GitLab instance
It's important to keep your GitLab environment up-to-date. The GitLab team is constantly making
enhancements and occasionally you may need to update for security reasons. So let's review how to
update GitLab.
enhancements and occasionally you may need to update for security reasons. Use the information
in this section whenever you need to update GitLab.
### Checking our current version
### Check the current version
To check which version of GitLab we're currently running, click on the "Admin Area" link - it's the
the wrench icon displayed in the top-right, next to the search box.
To determine the version of GitLab you're currently running,
go to the **{admin}** **Admin Area**, and you will find the version
under the **Components** table.
In the following screenshot you can see an **"update asap"** notification message in the top-right.
This particular message indicates that there is a newer version of GitLab available which contains
one or more security fixes:
If there's a newer available version of GitLab that contains one or more
security fixes, GitLab displays an **Update asap** notification message that
encourages you to [update](#update-gitlab).
![GitLab - update asap](img/gitlab-admin-area.png)
### Update GitLab
Under the **"Components"** section, we can see that our VM is currently running version `8.6.5` of
GitLab. This is the version of GitLab which was contained in the Azure Marketplace
**"GitLab Community Edition"** offering we used to build the VM when we wrote this tutorial.
To update GitLab to the latest version:
NOTE:
The version of GitLab in your own VM instance may well be different, but the update
process will still be the same.
1. Connect to the VM through SSH.
1. Update GitLab:
### Connect via SSH
```shell
sudo apt update
sudo apt install gitlab-ee
```
To perform an update, we need to connect directly to our Azure VM instance and run some commands
from the terminal. Our Azure VM is actually a server running Linux (Ubuntu), so we'll need to
connect to it using SSH ([Secure Shell](https://en.wikipedia.org/wiki/Secure_Shell)).
This command updates GitLab and its associated components to the latest versions,
and can take time to complete. You'll see various update tasks being
completed in your terminal.
If you're running Windows, you'll need to connect using [PuTTY](https://www.putty.org) or an equivalent Windows SSH client.
If you're running Linux or macOS, then you already have an SSH client installed.
NOTE:
If you get an error like
`E: The repository 'https://packages.gitlab.com/gitlab/gitlab-ee/debian buster InRelease' is not signed.`,
see the [troubleshooting section](#update-the-gpg-key-for-the-gitlab-repositories).
Remember to sign in with the username and password you specified when you
[created your Azure VM](#basics).
1. After the update process is complete, you'll see a message like the
following:
If you need to reset your VM password, read
[how to reset SSH credentials for a user on an Azure VM](https://docs.microsoft.com/en-us/troubleshoot/azure/virtual-machines/troubleshoot-ssh-connection).
```plaintext
Upgrade complete! If your GitLab server is misbehaving try running
#### SSH from the command-line
sudo gitlab-ctl restart
If you're running [SSH](https://en.wikipedia.org/wiki/Secure_Shell) from the command-line (terminal), then type in the following command to
connect to your VM, substituting `username` and `your-azure-domain-name.com` for the correct values.
before anything else.
```
Again, remember that your Azure VM domain name will be the one you
[set up previously in the tutorial](#set-up-a-domain-name). If you didn't set up a domain name for
your VM, you can use the IP address in its place in the following command:
```shell
ssh username@your-azure-domain-name.com
```
Provide your password at the prompt to authenticate.
#### SSH from Windows (PuTTY)
If you're using [PuTTY](https://www.putty.org) in Windows as your [SSH](https://en.wikipedia.org/wiki/Secure_Shell) client, then you might want to take a quick
read on [using PuTTY in Windows](https://mediatemple.net/community/products/dv/204404604/using-ssh-in-putty-).
### Updating GitLab
After signing in by using SSH, enter the following command to update GitLab to
the latest version:
```shell
sudo apt-get update && sudo apt-get install gitlab-ce
```
This command updates GitLab and its associated components to the latest versions,
so it will take a little time to complete. You'll see various update tasks being
completed in your SSH terminal window:
![GitLab updating](img/gitlab-ssh-update-in-progress.png)
After the update process is complete, you'll see a message like this:
```plaintext
Upgrade complete! If your GitLab server is misbehaving try running
sudo gitlab-ctl restart
before anything else.
```
#### Check out your updated GitLab
Refresh your GitLab instance in the browser and navigate to the Admin Area. You should now have an
Refresh your GitLab instance in the browser and go to the Admin Area. You should now have an
up-to-date GitLab instance.
When we wrote this tutorial our Azure VM GitLab instance was updated to the latest version at time
of writing (`9.4.0`). You can see that the message which was previously displaying **"update asap"**
is now showing **"up-to-date"**:
## Next steps and further configuration
![GitLab up to date](img/gitlab-admin-area-9.4.0.png)
Now that you have a functional GitLab instance, follow the
[next steps](../index.md#next-steps) to learn what more you can do with your
new installation.
## Conclusion
## Troubleshooting
Naturally, we believe that GitLab is a great Git repository tool. However, GitLab is a whole lot
more than that too. GitLab unifies issues, code review, CI and CD into a single UI, helping you to
move faster from idea to production, and in this tutorial we showed you how quick and easy it is to
set up and run your own instance of GitLab on Azure, Microsoft's cloud service.
This section describes common errors you can encounter.
Azure is a great way to experiment with GitLab, and if you decide (as we hope) that GitLab is for
you, you can continue to use Azure as your secure, scalable cloud provider or of course run GitLab
on any cloud service you choose.
### Update the GPG key for the GitLab repositories
## Where to next?
NOTE:
This is a temporary fix until the GitLab image is updated with the new
GPG key.
Check out our other [Technical Articles](../../topics/index.md) or browse the [GitLab Documentation](../../README.md) to learn more about GitLab.
The pre-configured GitLab image in Azure (provided by Bitnami) uses
a GPG key [deprecated in April 2020](https://about.gitlab.com/blog/2020/03/30/gpg-key-for-gitlab-package-repositories-metadata-changing/).
### Useful links
If you try to update the repositories, you'll get the following error:
- [GitLab Community Edition](https://about.gitlab.com/features/)
- [GitLab Enterprise Edition](https://about.gitlab.com/features/#ee)
- [Microsoft Azure](https://azure.microsoft.com/en-us/)
- [Azure - Free Account FAQ](https://azure.microsoft.com/en-us/free/free-account-faq/)
- [Azure - Marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/)
- [Azure Portal](https://portal.azure.com)
- [Azure - Pricing Calculator](https://azure.microsoft.com/en-us/pricing/calculator/)
- [Azure - Troubleshoot SSH Connections to an Azure Linux VM](https://docs.microsoft.com/en-us/troubleshoot/azure/virtual-machines/troubleshoot-ssh-connection)
- [Azure - Properly Shutdown an Azure VM](https://build5nines.com/properly-shutdown-azure-vm-to-save-money/)
- [SSH](https://en.wikipedia.org/wiki/Secure_Shell), [PuTTY](https://www.putty.org) and [Using SSH in PuTTY](https://mediatemple.net/community/products/dv/204404604/using-ssh-in-putty-)
<!-- vale gitlab.ReferenceLinks = NO -->
<!-- ## Troubleshooting
```plaintext
[ 21.023494] apt-setup[1198]: W: GPG error: https://packages.gitlab.com/gitlab/gitlab-ee/debian buster InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 3F01618A51312F3F
[ 21.024033] apt-setup[1198]: E: The repository 'https://packages.gitlab.com/gitlab/gitlab-ee/debian buster InRelease' is not signed.
```
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
one might have when setting this up, or when something is changed, or on upgrading, it's
important to describe those, too. Think of things that may go wrong and include them here.
This is important to minimize requests for support and to avoid doc comments with
questions that you know someone might ask.
<!-- vale gitlab.ReferenceLinks = YES -->
Each scenario can be a third-level heading, e.g. `### Getting error message X`.
If you have none to add when creating a doc, leave this section in place
but commented out to help encourage others to add to it in the future. -->
To fix this, fetch the new GPG key:
```shell
sudo apt install gpg-agent
curl "https://gitlab-org.gitlab.io/omnibus-gitlab/gitlab_new_gpg.key" --output /tmp/omnibus_gitlab_gpg.key
sudo apt-key add /tmp/omnibus_gitlab_gpg.key
```
You can now [update GitLab](#update-gitlab). For more information, read about the
[packages signatures](https://docs.gitlab.com/omnibus/update/package_signatures.html).

View File

@ -200,7 +200,7 @@ An invoice is generated for the renewal and available for viewing or download on
### Seat Link
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208832) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.9.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208832) in GitLab 12.9.
Seat Link allows GitLab Inc. to provide our GitLab self-managed customers with prorated charges for user growth throughout the year using a quarterly reconciliation process.
@ -269,7 +269,7 @@ You can view the exact JSON payload in the administration panel. To view the pay
#### Disable Seat Link
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212375) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.10.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212375) in GitLab 12.10.
Seat Link is enabled by default.

View File

@ -670,8 +670,8 @@ and stored by Docker, it is not possible for GitLab to parse this data and meet
## Limitations
- Moving or renaming existing Container Registry repositories is not supported
once you have pushed images, because the images are signed, and the
signature includes the repository name. To move or rename a repository with a
once you have pushed images, because the images are stored in a path that matches
the repository path. To move or rename a repository with a
Container Registry, you must delete all existing images.
- Prior to GitLab 12.10, any tags that use the same image ID as the `latest` tag
are not deleted by the cleanup policy.

View File

@ -93,7 +93,6 @@ The following table depicts the various user permission levels in a project.
| View Code Review analytics **(STARTER)** | | ✓ | ✓ | ✓ | ✓ |
| View Repository analytics | | ✓ | ✓ | ✓ | ✓ |
| View Error Tracking list | | ✓ | ✓ | ✓ | ✓ |
| Create new merge request | | ✓ | ✓ | ✓ | ✓ |
| View metrics dashboard annotations | | ✓ | ✓ | ✓ | ✓ |
| Archive/reopen requirements **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
| Create/edit requirements **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
@ -108,6 +107,7 @@ The following table depicts the various user permission levels in a project.
| Upload [Design Management](project/issues/design_management.md) files | | | ✓ | ✓ | ✓ |
| Create/edit [releases](project/releases/index.md)| | | ✓ | ✓ | ✓ |
| Delete [releases](project/releases/index.md)| | | | ✓ | ✓ |
| Create new merge request | | | ✓ | ✓ | ✓ |
| Create new branches | | | ✓ | ✓ | ✓ |
| Push to non-protected branches | | | ✓ | ✓ | ✓ |
| Force push to non-protected branches | | | ✓ | ✓ | ✓ |

View File

@ -23,8 +23,13 @@ module Gitlab
parent_id.present? || parent.present?
end
# Deprecated, use #licensed_feature_available? instead. Remove once Namespace#feature_available? isn't used anymore.
def feature_available?(feature)
licensed_feature_available?(feature)
end
# Overridden in EE::Namespace
def feature_available?(_feature)
def licensed_feature_available?(_feature)
false
end
end

View File

@ -2238,9 +2238,6 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
msgid "AdminNote|Note"
msgstr ""
msgid "AdminProjects| Youre about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@ -2676,6 +2673,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
msgid "Admin|Admin notes"
msgstr ""
msgid "Admin|Note"
msgstr ""
msgid "Admin|View pending user approvals"
msgstr ""
@ -8642,6 +8645,12 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
msgid "CorpusManagement|New corpus"
msgstr ""
msgid "CorpusManagement|Total Size: %{totalSize}"
msgstr ""
msgid "Could not add admins as members"
msgstr ""

View File

@ -0,0 +1,99 @@
# frozen_string_literal: true
module RuboCop
module Cop
module Gitlab
# Cop that checks for correct calling of #feature_available?
class FeatureAvailableUsage < RuboCop::Cop::Cop
OBSERVED_METHOD = :feature_available?
LICENSED_FEATURE_LITERAL_ARG_MSG = '`feature_available?` should not be called for features that can be licensed (`%s` given), use `licensed_feature_available?(feature)` instead.'
LICENSED_FEATURE_DYNAMIC_ARG_MSG = "`feature_available?` should not be called for features that can be licensed (`%s` isn't a literal so we cannot say if it's legit or not), using `licensed_feature_available?(feature)` may be more appropriate."
NOT_ENOUGH_ARGS_MSG = '`feature_available?` should be called with two arguments: `feature` and `user`.'
FEATURES = %i[
issues
forking
merge_requests
wiki
snippets
builds
repository
pages
metrics_dashboard
analytics
operations
security_and_compliance
container_registry
].freeze
EE_FEATURES = %i[requirements].freeze
ALL_FEATURES = (FEATURES + EE_FEATURES).freeze
SPECIAL_CLASS = %w[License].freeze
def on_send(node)
return unless method_name(node) == OBSERVED_METHOD
return if caller_is_special_case?(node)
return if feature_name(node).nil?
return if ALL_FEATURES.include?(feature_name(node)) && args_count(node) == 2
if !ALL_FEATURES.include?(feature_name(node))
add_offense(node, location: :expression, message: licensed_feature_message(node))
elsif args_count(node) < 2
add_offense(node, location: :expression, message: NOT_ENOUGH_ARGS_MSG)
end
end
def licensed_feature_message(node)
message_template = dynamic_feature?(node) ? LICENSED_FEATURE_DYNAMIC_ARG_MSG : LICENSED_FEATURE_LITERAL_ARG_MSG
message_template % feature_arg_name(node)
end
private
def method_name(node)
node.children[1]
end
def class_caller(node)
node.children[0]&.const_name.to_s
end
def caller_is_special_case?(node)
SPECIAL_CLASS.include?(class_caller(node))
end
def feature_arg(node)
node.children[2]
end
def dynamic_feature?(node)
feature = feature_arg(node)
return false unless feature
!feature.literal?
end
def feature_name(node)
feature = feature_arg(node)
return unless feature
return feature.children.compact.join('.') if dynamic_feature?(node)
return feature.value if feature.respond_to?(:value)
feature.type
end
def feature_arg_name(node)
feature = feature_arg(node)
return unless feature
return feature.children.compact.join('.') if dynamic_feature?(node)
return feature.children[0].inspect if feature.literal?
feature.type
end
def args_count(node)
node.children[2..].size
end
end
end
end
end

View File

@ -37,6 +37,12 @@ RSpec.describe Admin::GroupsController do
post :create, params: { group: { path: 'test', name: 'test' } }
end.to change { NamespaceSetting.count }.by(1)
end
it 'creates admin_note for group' do
expect do
post :create, params: { group: { path: 'test', name: 'test', admin_note_attributes: { note: 'test' } } }
end.to change { Namespace::AdminNote.count }.by(1)
end
end
describe 'PUT #members_update' do

View File

@ -35,6 +35,7 @@ RSpec.describe 'Admin Groups' do
expect(page).to have_field('group_path')
expect(page).to have_field('group_visibility_level_0')
expect(page).to have_field('description')
expect(page).to have_field('group_admin_note_attributes_note')
end
end
@ -47,10 +48,12 @@ RSpec.describe 'Admin Groups' do
path_component = 'gitlab'
group_name = 'GitLab group name'
group_description = 'Description of group for GitLab'
group_admin_note = 'A note about this group by an admin'
fill_in 'group_path', with: path_component
fill_in 'group_name', with: group_name
fill_in 'group_description', with: group_description
fill_in 'group_admin_note_attributes_note', with: group_admin_note
click_button "Create group"
expect(current_path).to eq admin_group_path(Group.find_by(path: path_component))
@ -61,6 +64,8 @@ RSpec.describe 'Admin Groups' do
expect(li_texts).to match group_name
expect(li_texts).to match path_component
expect(li_texts).to match group_description
p_texts = content.all('p').collect(&:text).join('/n')
expect(p_texts).to match group_admin_note
end
it 'shows the visibility level radio populated with the default value' do
@ -116,6 +121,16 @@ RSpec.describe 'Admin Groups' do
expect(page).to have_link(group.name, href: group_path(group))
end
it 'has a note if one is available' do
group = create(:group, :private)
note_text = 'A group administrator note'
group.update!(admin_note_attributes: { note: note_text })
visit admin_group_path(group)
expect(page).to have_text(note_text)
end
end
describe 'group edit' do
@ -145,6 +160,36 @@ RSpec.describe 'Admin Groups' do
expect(name_field.value).to eq original_name
end
it 'adding an admin note to group without one' do
group = create(:group, :private)
expect(group.admin_note).to be_nil
visit admin_group_edit_path(group)
admin_note_text = 'A note by an administrator'
fill_in 'group_admin_note_attributes_note', with: admin_note_text
click_button 'Save changes'
expect(page).to have_content(admin_note_text)
end
it 'editing an existing group admin note' do
admin_note_text = 'A note by an administrator'
new_admin_note_text = 'A new note by an administrator'
group = create(:group, :private)
group.create_admin_note(note: admin_note_text)
visit admin_group_edit_path(group)
admin_note_field = find('#group_admin_note_attributes_note')
expect(admin_note_field.value).to eq(admin_note_text)
fill_in 'group_admin_note_attributes_note', with: new_admin_note_text
click_button 'Save changes'
expect(page).to have_content(new_admin_note_text)
end
end
describe 'add user into a group', :js do

View File

@ -17,8 +17,6 @@ RSpec.describe 'Project issue boards sidebar assignee', :js do
let(:card) { find('.board:nth-child(2)').first('.board-card') }
before do
stub_feature_flags(graphql_board_lists: false)
project.add_maintainer(user)
sign_in(user)

View File

@ -52,7 +52,7 @@ describe('Test issue body', () => {
});
it('renders issue name', () => {
expect(findDescription().text()).toBe(failedIssue.name);
expect(findDescription().text()).toContain(failedIssue.name);
});
it('renders failed status icon', () => {

View File

@ -1,3 +1,4 @@
import { GlAlert } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
@ -14,7 +15,10 @@ localVue.use(VueApollo);
describe('RunnerInstructions component', () => {
let wrapper;
let fakeApollo;
let runnerPlatformsHandler;
let runnerSetupInstructionsHandler;
const findAlert = () => wrapper.findComponent(GlAlert);
const findModalButton = () => wrapper.find('[data-testid="show-modal-button"]');
const findPlatformButtons = () => wrapper.findAll('[data-testid="platform-button"]');
const findArchitectureDropdownItems = () =>
@ -22,10 +26,10 @@ describe('RunnerInstructions component', () => {
const findBinaryInstructionsSection = () => wrapper.find('[data-testid="binary-instructions"]');
const findRunnerInstructionsSection = () => wrapper.find('[data-testid="runner-instructions"]');
beforeEach(async () => {
const createComponent = () => {
const requestHandlers = [
[getRunnerPlatforms, jest.fn().mockResolvedValue(mockGraphqlRunnerPlatforms)],
[getRunnerSetupInstructions, jest.fn().mockResolvedValue(mockGraphqlInstructions)],
[getRunnerPlatforms, runnerPlatformsHandler],
[getRunnerSetupInstructions, runnerSetupInstructionsHandler],
];
fakeApollo = createMockApollo(requestHandlers);
@ -37,6 +41,13 @@ describe('RunnerInstructions component', () => {
localVue,
apolloProvider: fakeApollo,
});
};
beforeEach(async () => {
runnerPlatformsHandler = jest.fn().mockResolvedValue(mockGraphqlRunnerPlatforms);
runnerSetupInstructionsHandler = jest.fn().mockResolvedValue(mockGraphqlInstructions);
createComponent();
await wrapper.vm.$nextTick();
});
@ -46,6 +57,10 @@ describe('RunnerInstructions component', () => {
wrapper = null;
});
it('should not show alert', () => {
expect(findAlert().exists()).toBe(false);
});
it('should show the "Show Runner installation instructions" button', () => {
const button = findModalButton();
@ -110,4 +125,23 @@ describe('RunnerInstructions component', () => {
expect(runner.text()).toMatch(mockGraphqlInstructions.data.runnerSetup.registerInstructions);
});
describe('when instructions cannot be loaded', () => {
beforeEach(async () => {
runnerSetupInstructionsHandler.mockRejectedValue();
createComponent();
await wrapper.vm.$nextTick();
});
it('should show alert', () => {
expect(findAlert().exists()).toBe(true);
});
it('should not show instructions', () => {
expect(findBinaryInstructionsSection().exists()).toBe(false);
expect(findRunnerInstructionsSection().exists()).toBe(false);
});
});
});

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Namespace::AdminNote, type: :model do
let!(:namespace) { create(:namespace) }
describe 'associations' do
it { is_expected.to belong_to :namespace }
end
describe 'validations' do
it { is_expected.to validate_presence_of(:namespace) }
it { is_expected.to validate_length_of(:note).is_at_most(1000) }
end
end

View File

@ -21,6 +21,7 @@ RSpec.describe Namespace do
it { is_expected.to have_many :custom_emoji }
it { is_expected.to have_one :package_setting_relation }
it { is_expected.to have_one :onboarding_progress }
it { is_expected.to have_one :admin_note }
end
describe 'validations' do

View File

@ -0,0 +1,96 @@
# frozen_string_literal: true
require 'fast_spec_helper'
require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/feature_available_usage'
RSpec.describe RuboCop::Cop::Gitlab::FeatureAvailableUsage do
subject(:cop) { described_class.new }
context 'no arguments given' do
it 'does not flag the use of Gitlab::Sourcegraph.feature_available? with no arguments' do
expect_no_offenses('Gitlab::Sourcegraph.feature_available?')
expect_no_offenses('subject { described_class.feature_available? }')
end
end
context 'one argument given' do
it 'does not flag the use of License.feature_available?' do
expect_no_offenses('License.feature_available?(:push_rules)')
end
it 'flags the use with a dynamic feature as nil' do
expect_offense(<<~SOURCE)
feature_available?(nil)
^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`nil` given), use `licensed_feature_available?(feature)` instead.
SOURCE
expect_offense(<<~SOURCE)
project.feature_available?(nil)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`nil` given), use `licensed_feature_available?(feature)` instead.
SOURCE
end
it 'flags the use with an OSS project feature' do
expect_offense(<<~SOURCE)
project.feature_available?(:issues)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should be called with two arguments: `feature` and `user`.
SOURCE
expect_offense(<<~SOURCE)
feature_available?(:issues)
^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should be called with two arguments: `feature` and `user`.
SOURCE
end
it 'flags the use with a feature that is not a project feature' do
expect_offense(<<~SOURCE)
feature_available?(:foo)
^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`:foo` given), use `licensed_feature_available?(feature)` instead.
SOURCE
expect_offense(<<~SOURCE)
project.feature_available?(:foo)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`:foo` given), use `licensed_feature_available?(feature)` instead.
SOURCE
expect_offense(<<~SOURCE)
feature_available?(foo)
^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`foo` isn't a literal so we cannot say if it's legit or not), using `licensed_feature_available?(feature)` may be more appropriate.
SOURCE
expect_offense(<<~SOURCE)
foo = :feature
feature_available?(foo)
^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`foo` isn't a literal so we cannot say if it's legit or not), using `licensed_feature_available?(feature)` may be more appropriate.
SOURCE
end
end
context 'two arguments given' do
it 'does not flag the use with an OSS project feature' do
expect_no_offenses('feature_available?(:issues, user)')
expect_no_offenses('project.feature_available?(:issues, user)')
end
it 'does not flag the use with an EE project feature' do
expect_no_offenses('feature_available?(:requirements, user)')
expect_no_offenses('project.feature_available?(:requirements, user)')
end
it 'flags the use with a dynamic feature as a method call with two args' do
expect_offense(<<~SOURCE)
feature_available?(:foo, current_user)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`:foo` given), use `licensed_feature_available?(feature)` instead.
SOURCE
expect_offense(<<~SOURCE)
project.feature_available?(:foo, current_user)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`:foo` given), use `licensed_feature_available?(feature)` instead.
SOURCE
expect_offense(<<~SOURCE)
feature_available?(foo, current_user)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`foo` isn't a literal so we cannot say if it's legit or not), using `licensed_feature_available?(feature)` may be more appropriate.
SOURCE
expect_offense(<<~SOURCE)
project.feature_available?(foo, current_user)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`foo` isn't a literal so we cannot say if it's legit or not), using `licensed_feature_available?(feature)` may be more appropriate.
SOURCE
end
end
end