diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-29 18:09:37 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-29 18:09:37 +0000 |
commit | 5b2abea8db1916c96027ce3a48e797003316e557 (patch) | |
tree | 611bee3c604c65707a4920c051cd18f9ba4d0e0d | |
parent | 09ff71d425b83646eed07d52078111ccbd4b84a9 (diff) | |
download | gitlab-ce-5b2abea8db1916c96027ce3a48e797003316e557.tar.gz |
Add latest changes from gitlab-org/gitlab@master
78 files changed, 963 insertions, 405 deletions
diff --git a/.haml-lint.yml b/.haml-lint.yml index 94e84462862..a6aed05d004 100644 --- a/.haml-lint.yml +++ b/.haml-lint.yml @@ -106,6 +106,7 @@ linters: - Cop/LineBreakAfterGuardClauses - Cop/LineBreakAroundConditionalBlock - Cop/ProjectPathHelper + - Gitlab/FeatureAvailableUsage - GitlabSecurity/PublicSend - Layout/EmptyLineAfterGuardClause - Layout/LeadingCommentSpace diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml index 5a509b3caf3..d2d32691dba 100644 --- a/.rubocop_manual_todo.yml +++ b/.rubocop_manual_todo.yml @@ -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' diff --git a/app/assets/javascripts/boards/components/board_content_sidebar.vue b/app/assets/javascripts/boards/components/board_content_sidebar.vue index 8e84f76ee60..d74057e99bc 100644 --- a/app/assets/javascripts/boards/components/board_content_sidebar.vue +++ b/app/assets/javascripts/boards/components/board_content_sidebar.vue @@ -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> diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js index bf67328bbe6..4763902ce86 100644 --- a/app/assets/javascripts/boards/stores/actions.js +++ b/app/assets/javascripts/boards/stores/actions.js @@ -69,6 +69,7 @@ export default { 'milestoneTitle', 'releaseTag', 'search', + 'myReactionEmoji', ]); filterParams.not = transformNotFilters(filters); commit(types.SET_FILTERS, filterParams); diff --git a/app/assets/javascripts/reports/components/grouped_issues_list.vue b/app/assets/javascripts/reports/components/grouped_issues_list.vue index 585127f901e..ca369022938 100644 --- a/app/assets/javascripts/reports/components/grouped_issues_list.vue +++ b/app/assets/javascripts/reports/components/grouped_issues_list.vue @@ -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, }; }, }, diff --git a/app/assets/javascripts/reports/components/issues_list.vue b/app/assets/javascripts/reports/components/issues_list.vue index ea3f0d78d8c..9df0a1953b6 100644 --- a/app/assets/javascripts/reports/components/issues_list.vue +++ b/app/assets/javascripts/reports/components/issues_list.vue @@ -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, }; }, }, diff --git a/app/assets/javascripts/reports/components/summary_row.vue b/app/assets/javascripts/reports/components/summary_row.vue index 8eb43bcf1ba..6b7d81c4878 100644 --- a/app/assets/javascripts/reports/components/summary_row.vue +++ b/app/assets/javascripts/reports/components/summary_row.vue @@ -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) { diff --git a/app/assets/javascripts/reports/grouped_test_report/components/test_issue_body.vue b/app/assets/javascripts/reports/grouped_test_report/components/test_issue_body.vue index 522245a442d..8913046d62f 100644 --- a/app/assets/javascripts/reports/grouped_test_report/components/test_issue_body.vue +++ b/app/assets/javascripts/reports/grouped_test_report/components/test_issue_body.vue @@ -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> diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue index 1d6db576942..662c9f595ea 100644 --- a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue +++ b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue @@ -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" diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb index 0a1c85eef3f..a61bffec10a 100644 --- a/app/controllers/admin/groups_controller.rb +++ b/app/controllers/admin/groups_controller.rb @@ -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 diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 7b7c2ea9d7b..eaaf9e3687c 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -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 diff --git a/app/models/namespace/admin_note.rb b/app/models/namespace/admin_note.rb new file mode 100644 index 00000000000..3de809d60be --- /dev/null +++ b/app/models/namespace/admin_note.rb @@ -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 diff --git a/app/models/project.rb b/app/models/project.rb index 61f165b9daa..b21d9818953 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -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 diff --git a/app/models/project_feature.rb b/app/models/project_feature.rb index a598bf3f60c..09a20c3509f 100644 --- a/app/models/project_feature.rb +++ b/app/models/project_feature.rb @@ -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 diff --git a/app/views/admin/groups/_form.html.haml b/app/views/admin/groups/_form.html.haml index 15306ab7878..84a9b988d22 100644 --- a/app/views/admin/groups/_form.html.haml +++ b/app/views/admin/groups/_form.html.haml @@ -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 diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index f8c490dd948..e7e86846df6 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -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 diff --git a/app/views/admin/users/_admin_notes.html.haml b/app/views/admin/users/_admin_notes.html.haml index a20b2fbffc4..7c3220e2cee 100644 --- a/app/views/admin/users/_admin_notes.html.haml +++ b/app/views/admin/users/_admin_notes.html.haml @@ -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' diff --git a/app/views/groups/runners/_group_runners.html.haml b/app/views/groups/runners/_group_runners.html.haml index f60cdc9f8da..910b36770f1 100644 --- a/app/views/groups/runners/_group_runners.html.haml +++ b/app/views/groups/runners/_group_runners.html.haml @@ -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 diff --git a/app/views/shared/admin/_admin_note.html.haml b/app/views/shared/admin/_admin_note.html.haml new file mode 100644 index 00000000000..82407705885 --- /dev/null +++ b/app/views/shared/admin/_admin_note.html.haml @@ -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 diff --git a/app/views/shared/admin/_admin_note_form.html.haml b/app/views/shared/admin/_admin_note_form.html.haml new file mode 100644 index 00000000000..0bc26f9120f --- /dev/null +++ b/app/views/shared/admin/_admin_note_form.html.haml @@ -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' diff --git a/changelogs/unreleased/321662-validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.yml b/changelogs/unreleased/321662-validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.yml new file mode 100644 index 00000000000..780c7849eb1 --- /dev/null +++ b/changelogs/unreleased/321662-validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.yml @@ -0,0 +1,5 @@ +--- +title: Validate NOT NULL constraint on gitlab_subscriptions namespace_id +merge_request: 57113 +author: +type: other diff --git a/changelogs/unreleased/323554-setting-updating-assignees-in-the-graphql-sidebar-doesn-t-update-b.yml b/changelogs/unreleased/323554-setting-updating-assignees-in-the-graphql-sidebar-doesn-t-update-b.yml new file mode 100644 index 00000000000..8cd506d5100 --- /dev/null +++ b/changelogs/unreleased/323554-setting-updating-assignees-in-the-graphql-sidebar-doesn-t-update-b.yml @@ -0,0 +1,5 @@ +--- +title: Fix updating GraphQL boards cards on assignees update +merge_request: 57687 +author: +type: fixed diff --git a/changelogs/unreleased/326018-handle-missing-instruction-error.yml b/changelogs/unreleased/326018-handle-missing-instruction-error.yml new file mode 100644 index 00000000000..8a30e030ac3 --- /dev/null +++ b/changelogs/unreleased/326018-handle-missing-instruction-error.yml @@ -0,0 +1,6 @@ +--- +title: Display error message when runner installation instructions modal cannot be + loaded correctly +merge_request: 57588 +author: +type: fixed diff --git a/changelogs/unreleased/admin-group-notes.yml b/changelogs/unreleased/admin-group-notes.yml new file mode 100644 index 00000000000..dda7628336c --- /dev/null +++ b/changelogs/unreleased/admin-group-notes.yml @@ -0,0 +1,5 @@ +--- +title: Allow admin users to define admin notes on groups. +merge_request: 47825 +author: +type: added diff --git a/changelogs/unreleased/fix-mr-issues-list-padding.yml b/changelogs/unreleased/fix-mr-issues-list-padding.yml new file mode 100644 index 00000000000..046526b94e1 --- /dev/null +++ b/changelogs/unreleased/fix-mr-issues-list-padding.yml @@ -0,0 +1,5 @@ +--- +title: Fix test report merge request widget summary and issues alignment +merge_request: 56768 +author: +type: fixed diff --git a/db/migrate/20201218194311_create_admin_notes.rb b/db/migrate/20201218194311_create_admin_notes.rb new file mode 100644 index 00000000000..32f5818cdfb --- /dev/null +++ b/db/migrate/20201218194311_create_admin_notes.rb @@ -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 diff --git a/db/post_migrate/20210322115438_validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.rb b/db/post_migrate/20210322115438_validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.rb new file mode 100644 index 00000000000..96d9f383406 --- /dev/null +++ b/db/post_migrate/20210322115438_validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.rb @@ -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 diff --git a/db/schema_migrations/20201218194311 b/db/schema_migrations/20201218194311 new file mode 100644 index 00000000000..f9beba74a8c --- /dev/null +++ b/db/schema_migrations/20201218194311 @@ -0,0 +1 @@ +7c33bd30af66ebb9a837c72e2ced107f015d4a22c7b6393554a9299bf3907cc0
\ No newline at end of file diff --git a/db/schema_migrations/20210322115438 b/db/schema_migrations/20210322115438 new file mode 100644 index 00000000000..94db65a9a8a --- /dev/null +++ b/db/schema_migrations/20210322115438 @@ -0,0 +1 @@ +e177c2cc0b59eea54de10417445b391cea7dd308547077aea34054fac22b9e40
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index f8a6ddc9f61..be155891f23 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -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; diff --git a/doc/api/dora4_group_analytics.md b/doc/api/dora4_group_analytics.md index 7504d18a5de..0938a9c22c8 100644 --- a/doc/api/dora4_group_analytics.md +++ b/doc/api/dora4_group_analytics.md @@ -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. diff --git a/doc/api/feature_flags.md b/doc/api/feature_flags.md index 59f20e66ae8..fa5481b12a7 100644 --- a/doc/api/feature_flags.md +++ b/doc/api/feature_flags.md @@ -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). diff --git a/doc/api/feature_flags_legacy.md b/doc/api/feature_flags_legacy.md index 33ea2727fb9..6e0763b6015 100644 --- a/doc/api/feature_flags_legacy.md +++ b/doc/api/feature_flags_legacy.md @@ -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. diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md index fe60c963f7f..4337af1db36 100644 --- a/doc/development/documentation/index.md +++ b/doc/development/documentation/index.md @@ -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 diff --git a/doc/development/documentation/structure.md b/doc/development/documentation/structure.md index 90cbc9693b1..8d564078ea2 100644 --- a/doc/development/documentation/structure.md +++ b/doc/development/documentation/structure.md @@ -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. diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md index ce078f78db3..30fea9b0960 100644 --- a/doc/development/migration_style_guide.md +++ b/doc/development/migration_style_guide.md @@ -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. diff --git a/doc/install/azure/img/azure-add-inbound-sec-rule-http.png b/doc/install/azure/img/azure-add-inbound-sec-rule-http.png Binary files differdeleted file mode 100644 index abf500cb63a..00000000000 --- a/doc/install/azure/img/azure-add-inbound-sec-rule-http.png +++ /dev/null diff --git a/doc/install/azure/img/azure-add-inbound-sec-rule-ssh.png b/doc/install/azure/img/azure-add-inbound-sec-rule-ssh.png Binary files differdeleted file mode 100644 index f7a8a04dfa7..00000000000 --- a/doc/install/azure/img/azure-add-inbound-sec-rule-ssh.png +++ /dev/null diff --git a/doc/install/azure/img/azure-create-virtual-machine-basics-password.png b/doc/install/azure/img/azure-create-virtual-machine-basics-password.png Binary files differdeleted file mode 100644 index 80bf39ecb48..00000000000 --- a/doc/install/azure/img/azure-create-virtual-machine-basics-password.png +++ /dev/null diff --git a/doc/install/azure/img/azure-create-virtual-machine-basics.png b/doc/install/azure/img/azure-create-virtual-machine-basics.png Binary files differdeleted file mode 100644 index 229c073fe17..00000000000 --- a/doc/install/azure/img/azure-create-virtual-machine-basics.png +++ /dev/null diff --git a/doc/install/azure/img/azure-create-virtual-machine-deployment.png b/doc/install/azure/img/azure-create-virtual-machine-deployment.png Binary files differdeleted file mode 100644 index 5cfdd973a58..00000000000 --- a/doc/install/azure/img/azure-create-virtual-machine-deployment.png +++ /dev/null diff --git a/doc/install/azure/img/azure-create-virtual-machine-purchase.png b/doc/install/azure/img/azure-create-virtual-machine-purchase.png Binary files differdeleted file mode 100644 index f4de62299f1..00000000000 --- a/doc/install/azure/img/azure-create-virtual-machine-purchase.png +++ /dev/null diff --git a/doc/install/azure/img/azure-create-virtual-machine-settings.png b/doc/install/azure/img/azure-create-virtual-machine-settings.png Binary files differdeleted file mode 100644 index 20097921660..00000000000 --- a/doc/install/azure/img/azure-create-virtual-machine-settings.png +++ /dev/null diff --git a/doc/install/azure/img/azure-create-virtual-machine-size.png b/doc/install/azure/img/azure-create-virtual-machine-size.png Binary files differdeleted file mode 100644 index a408394151f..00000000000 --- a/doc/install/azure/img/azure-create-virtual-machine-size.png +++ /dev/null diff --git a/doc/install/azure/img/azure-dashboard-highlight-nsg.png b/doc/install/azure/img/azure-dashboard-highlight-nsg.png Binary files differdeleted file mode 100644 index 025efd33977..00000000000 --- a/doc/install/azure/img/azure-dashboard-highlight-nsg.png +++ /dev/null diff --git a/doc/install/azure/img/azure-dashboard-running-resources.png b/doc/install/azure/img/azure-dashboard-running-resources.png Binary files differdeleted file mode 100644 index 7e661a6aa65..00000000000 --- a/doc/install/azure/img/azure-dashboard-running-resources.png +++ /dev/null diff --git a/doc/install/azure/img/azure-dashboard.png b/doc/install/azure/img/azure-dashboard.png Binary files differdeleted file mode 100644 index 375ec8622b8..00000000000 --- a/doc/install/azure/img/azure-dashboard.png +++ /dev/null diff --git a/doc/install/azure/img/azure-inbound-sec-rules-list.png b/doc/install/azure/img/azure-inbound-sec-rules-list.png Binary files differdeleted file mode 100644 index 1667671b21d..00000000000 --- a/doc/install/azure/img/azure-inbound-sec-rules-list.png +++ /dev/null diff --git a/doc/install/azure/img/azure-new-gitlab-ce.png b/doc/install/azure/img/azure-new-gitlab-ce.png Binary files differdeleted file mode 100644 index 88949f69a94..00000000000 --- a/doc/install/azure/img/azure-new-gitlab-ce.png +++ /dev/null diff --git a/doc/install/azure/img/azure-new-search-gitlab.png b/doc/install/azure/img/azure-new-search-gitlab.png Binary files differdeleted file mode 100644 index f96ed577d62..00000000000 --- a/doc/install/azure/img/azure-new-search-gitlab.png +++ /dev/null diff --git a/doc/install/azure/img/azure-nsg-inbound-sec-rules-add-highlight.png b/doc/install/azure/img/azure-nsg-inbound-sec-rules-add-highlight.png Binary files differdeleted file mode 100644 index c9a08b87ce6..00000000000 --- a/doc/install/azure/img/azure-nsg-inbound-sec-rules-add-highlight.png +++ /dev/null diff --git a/doc/install/azure/img/azure-nsg-inbound-sec-rules-highlight.png b/doc/install/azure/img/azure-nsg-inbound-sec-rules-highlight.png Binary files differdeleted file mode 100644 index 6423625ca8b..00000000000 --- a/doc/install/azure/img/azure-nsg-inbound-sec-rules-highlight.png +++ /dev/null diff --git a/doc/install/azure/img/azure-vm-domain-name.png b/doc/install/azure/img/azure-vm-domain-name.png Binary files differdeleted file mode 100644 index 01c03004b24..00000000000 --- a/doc/install/azure/img/azure-vm-domain-name.png +++ /dev/null diff --git a/doc/install/azure/img/azure-vm-management-public-ip.png b/doc/install/azure/img/azure-vm-management-public-ip.png Binary files differdeleted file mode 100644 index ef313641db8..00000000000 --- a/doc/install/azure/img/azure-vm-management-public-ip.png +++ /dev/null diff --git a/doc/install/azure/img/gitlab-admin-area-9.4.0.png b/doc/install/azure/img/gitlab-admin-area-9.4.0.png Binary files differdeleted file mode 100644 index b7ee4598731..00000000000 --- a/doc/install/azure/img/gitlab-admin-area-9.4.0.png +++ /dev/null diff --git a/doc/install/azure/img/gitlab-admin-area.png b/doc/install/azure/img/gitlab-admin-area.png Binary files differdeleted file mode 100644 index 028f0b0a0eb..00000000000 --- a/doc/install/azure/img/gitlab-admin-area.png +++ /dev/null diff --git a/doc/install/azure/img/gitlab-change-password.png b/doc/install/azure/img/gitlab-change-password.png Binary files differdeleted file mode 100644 index 7350d604d56..00000000000 --- a/doc/install/azure/img/gitlab-change-password.png +++ /dev/null diff --git a/doc/install/azure/img/gitlab-home.png b/doc/install/azure/img/gitlab-home.png Binary files differdeleted file mode 100644 index 7c935805ea2..00000000000 --- a/doc/install/azure/img/gitlab-home.png +++ /dev/null diff --git a/doc/install/azure/img/gitlab-login.png b/doc/install/azure/img/gitlab-login.png Binary files differdeleted file mode 100644 index 95fe5aec1e0..00000000000 --- a/doc/install/azure/img/gitlab-login.png +++ /dev/null diff --git a/doc/install/azure/img/gitlab-new-project.png b/doc/install/azure/img/gitlab-new-project.png Binary files differdeleted file mode 100644 index 3b6b9a81682..00000000000 --- a/doc/install/azure/img/gitlab-new-project.png +++ /dev/null diff --git a/doc/install/azure/img/gitlab-project-home-empty.png b/doc/install/azure/img/gitlab-project-home-empty.png Binary files differdeleted file mode 100644 index 54d0b36a251..00000000000 --- a/doc/install/azure/img/gitlab-project-home-empty.png +++ /dev/null diff --git a/doc/install/azure/img/gitlab-project-home-instructions.png b/doc/install/azure/img/gitlab-project-home-instructions.png Binary files differdeleted file mode 100644 index fd040d33e95..00000000000 --- a/doc/install/azure/img/gitlab-project-home-instructions.png +++ /dev/null diff --git a/doc/install/azure/img/gitlab-ssh-update-in-progress.png b/doc/install/azure/img/gitlab-ssh-update-in-progress.png Binary files differdeleted file mode 100644 index 8a686ebde26..00000000000 --- a/doc/install/azure/img/gitlab-ssh-update-in-progress.png +++ /dev/null diff --git a/doc/install/azure/index.md b/doc/install/azure/index.md index 0c0a4457413..8fb400c796e 100644 --- a/doc/install/azure/index.md +++ b/doc/install/azure/index.md @@ -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). - -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. - -## Getting started - -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 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? - -## Working with Azure - -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: - -![Azure Dashboard](img/azure-dashboard.png) - -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** +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). - 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)_ +## Prerequisite -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"** +You'll need an account on Azure. Use of the following methods to obtain an account: - 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 +- 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 you can use + those credits and try out GitLab. -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. +## Deploy and configure GitLab -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. +Because GitLab is already installed in a pre-configured image, all you have to do is +create a new VM: -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: +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. -![Azure - Create Virtual Machine - Size](img/azure-create-virtual-machine-size.png) +For the sake of this guide, we'll create the VM from scratch, so +select **Create**. 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. - -## Let's open some ports - -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. - -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. +After you download the key, the deployment begins. -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. +### Finish deployment -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: +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. -![Azure - Dashboard - All resources - Network security group](img/azure-dashboard-highlight-nsg.png) +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. -With the **"Network security group"** blade open, click on **"Inbound security rules"** under -**"Settings"**: +### Set up a domain name -![Azure - Network security group - Inbound security rules](img/azure-nsg-inbound-sec-rules-highlight.png) +The VM has a public IP address (static by default), but Azure allows you +to assign a descriptive DNS name to the VM: -Next, click **"Add"**: +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. -![Azure - Network security group - Inbound security rules - Add](img/azure-nsg-inbound-sec-rules-add-highlight.png) +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). -### Which ports to open? +### Change the GitLab external URL -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: +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. -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))_ +To set up the GitLab external URL: -### Open HTTP on Port 80 +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. -In the **"Add inbound security rule"** blade, let's open port 80 so that our VM will accept HTTP -connections: + In the case of our example: -![Azure - Add inbound security rules - HTTP](img/azure-add-inbound-sec-rule-http.png) + ```shell + ssh -i <private key path> gitlab-azure@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"** + 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). -### Open SSH on Port 22 +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: -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: + ```ruby + external_url 'https://gitlab-prod.eastus.cloudapp.azure.com' + ``` -![Azure - Add inbound security rules - SSH](img/azure-add-inbound-sec-rule-ssh.png) +1. Find the following settings and comment them out, so that GitLab doesn't + pick up the wrong certificates: -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"** + ```ruby + # nginx['redirect_http_to_https'] = true + # nginx['ssl_certificate'] = "/etc/gitlab/ssl/server.crt" + # nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/server.key" + ``` -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: +1. Reconfigure GitLab for the changes to take effect. Run the + following command every time you make changes to `/etc/gitlab/gitlab.rb`: -![Azure - Inbound security rules - List](img/azure-inbound-sec-rules-list.png) + ```shell + sudo gitlab-ctl reconfigure + ``` -## Connecting to GitLab +You can now visit GitLab with your browser at the new external URL. -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: +### Visit GitLab for the first time -![GitLab - Change Password](img/gitlab-change-password.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`. -Enter your _new_ password into both form fields, and then click **"Change your password"**. +The first thing you'll see is the sign-in page. GitLab creates an admin user by default. +The credentials are: -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"**: +- 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 - Login](img/gitlab-login.png) +After signing in, be sure to immediately [change the password](../../user/profile/index.md#change-your-password). -### Success? +## Maintain your GitLab instance -After signing in successfully, you should see the GitLab Projects page displaying a -**"Welcome to GitLab!"** message: +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. Use the information +in this section whenever you need to update GitLab. -![GitLab - Projects Page](img/gitlab-home.png) +### Check the current version -If so, you now have a working GitLab instance on your own private Azure VM. **Congratulations!** +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. -## Creating your first GitLab project +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). -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"**. +### Update GitLab -Let's give our project a name and a description, and then accept the default values for everything -else: +To update GitLab to the latest version: -1. Enter **"demo"** into the `Project path` project name field -1. Enter a `description`, e.g. **"My awesome demo project!"** -1. Click **"Create project"** +1. Connect to the VM through SSH. +1. Update GitLab: -![GitLab - New Project](img/gitlab-new-project.png) + ```shell + sudo apt update + sudo apt install gitlab-ee + ``` -Once the new project has been created (which should only take a moment), you'll be redirected to -homepage for the project: + 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. -![GitLab - Empty Project](img/gitlab-project-home-empty.png) + 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). -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: +1. After the update process is complete, you'll see a message like the + following: -![GitLab - Empty Project - Basic Instructions](img/gitlab-project-home-instructions.png) + ```plaintext + Upgrade complete! If your GitLab server is misbehaving try running -**That's it! You now have your own private GitLab environment installed and running in the cloud!** + sudo gitlab-ctl restart -## Maintaining your GitLab instance + before anything else. + ``` -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. +Refresh your GitLab instance in the browser and go to the Admin Area. You should now have an +up-to-date GitLab instance. -### Checking our current version +## Next steps and further configuration -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. +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. -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: +## Troubleshooting -![GitLab - update asap](img/gitlab-admin-area.png) +This section describes common errors you can encounter. -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. +### Update the GPG key for the GitLab repositories NOTE: -The version of GitLab in your own VM instance may well be different, but the update -process will still be the same. - -### Connect via SSH - -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)). - -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. +This is a temporary fix until the GitLab image is updated with the new +GPG key. -Remember to sign in with the username and password you specified when you -[created your Azure VM](#basics). +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/). -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). +If you try to update the repositories, you'll get the following error: -#### SSH from the command-line +<!-- vale gitlab.ReferenceLinks = NO --> -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. - -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 +```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. ``` -Provide your password at the prompt to authenticate. +<!-- vale gitlab.ReferenceLinks = YES --> -#### 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: +To fix this, fetch the new GPG key: ```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. +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 ``` -#### Check out your updated GitLab - -Refresh your GitLab instance in the browser and navigate 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"**: - -![GitLab up to date](img/gitlab-admin-area-9.4.0.png) - -## Conclusion - -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. - -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. - -## Where to next? - -Check out our other [Technical Articles](../../topics/index.md) or browse the [GitLab Documentation](../../README.md) to learn more about GitLab. - -### Useful links - -- [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-) - -<!-- ## Troubleshooting - -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. - -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. --> +You can now [update GitLab](#update-gitlab). For more information, read about the +[packages signatures](https://docs.gitlab.com/omnibus/update/package_signatures.html). diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md index 67f53020a8e..d0fc0ff62b9 100644 --- a/doc/subscriptions/self_managed/index.md +++ b/doc/subscriptions/self_managed/index.md @@ -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. diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md index 30811a46b25..fe6da524241 100644 --- a/doc/user/packages/container_registry/index.md +++ b/doc/user/packages/container_registry/index.md @@ -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. diff --git a/doc/user/permissions.md b/doc/user/permissions.md index 4ecf9cc0832..2fe9df9f29f 100644 --- a/doc/user/permissions.md +++ b/doc/user/permissions.md @@ -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 | | | ✓ | ✓ | ✓ | diff --git a/lib/gitlab/background_migration/user_mentions/models/namespace.rb b/lib/gitlab/background_migration/user_mentions/models/namespace.rb index 6587417d048..a2b50c41f4a 100644 --- a/lib/gitlab/background_migration/user_mentions/models/namespace.rb +++ b/lib/gitlab/background_migration/user_mentions/models/namespace.rb @@ -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 diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 09bdf1bfa60..63eb1869460 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -2238,9 +2238,6 @@ msgstr "" msgid "AdminDashboard|Error loading the statistics. Please try again" msgstr "" -msgid "AdminNote|Note" -msgstr "" - msgid "AdminProjects| You’re 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 "" diff --git a/rubocop/cop/gitlab/feature_available_usage.rb b/rubocop/cop/gitlab/feature_available_usage.rb new file mode 100644 index 00000000000..b50bdd8ca43 --- /dev/null +++ b/rubocop/cop/gitlab/feature_available_usage.rb @@ -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 diff --git a/spec/controllers/admin/groups_controller_spec.rb b/spec/controllers/admin/groups_controller_spec.rb index 38f4ce54e5c..8441a52b454 100644 --- a/spec/controllers/admin/groups_controller_spec.rb +++ b/spec/controllers/admin/groups_controller_spec.rb @@ -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 diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb index bbdf2f7f4a9..e7634f4e020 100644 --- a/spec/features/admin/admin_groups_spec.rb +++ b/spec/features/admin/admin_groups_spec.rb @@ -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 diff --git a/spec/features/boards/sidebar_assignee_spec.rb b/spec/features/boards/sidebar_assignee_spec.rb index 6835721bb4d..82383ece2d3 100644 --- a/spec/features/boards/sidebar_assignee_spec.rb +++ b/spec/features/boards/sidebar_assignee_spec.rb @@ -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) diff --git a/spec/frontend/reports/grouped_test_report/components/test_issue_body_spec.js b/spec/frontend/reports/grouped_test_report/components/test_issue_body_spec.js index e03a52aad8d..2f6f62ca1d3 100644 --- a/spec/frontend/reports/grouped_test_report/components/test_issue_body_spec.js +++ b/spec/frontend/reports/grouped_test_report/components/test_issue_body_spec.js @@ -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', () => { diff --git a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js index 48db60bfd33..4446c3cd88f 100644 --- a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js +++ b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js @@ -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); + }); + }); }); diff --git a/spec/models/namespace/admin_note_spec.rb b/spec/models/namespace/admin_note_spec.rb new file mode 100644 index 00000000000..65ba1f61416 --- /dev/null +++ b/spec/models/namespace/admin_note_spec.rb @@ -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 diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb index 351486ae801..ce29181dab8 100644 --- a/spec/models/namespace_spec.rb +++ b/spec/models/namespace_spec.rb @@ -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 diff --git a/spec/rubocop/cop/gitlab/feature_available_usage_spec.rb b/spec/rubocop/cop/gitlab/feature_available_usage_spec.rb new file mode 100644 index 00000000000..514ef357785 --- /dev/null +++ b/spec/rubocop/cop/gitlab/feature_available_usage_spec.rb @@ -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 |