From 6e4e1050d9dba2b7b2523fdd1768823ab85feef4 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 20 Aug 2020 18:42:06 +0000 Subject: Add latest changes from gitlab-org/gitlab@13-3-stable-ee --- doc/.vale/gitlab/Acronyms.yml | 1 + doc/.vale/gitlab/AlertBoxStyle.yml | 8 +- doc/.vale/gitlab/Contractions.yml | 45 - doc/.vale/gitlab/ContractionsDiscard.yml | 32 + doc/.vale/gitlab/ContractionsKeep.yml | 25 + doc/.vale/gitlab/FutureTense.yml | 8 +- doc/.vale/gitlab/OutdatedVersions.yml | 2 +- doc/.vale/gitlab/spelling-exceptions.txt | 6 + doc/README.md | 79 +- doc/administration/audit_events.md | 37 +- doc/administration/audit_reports.md | 31 + doc/administration/auth/ldap/index.md | 4 +- doc/administration/auth/okta.md | 2 +- doc/administration/auth/smartcard.md | 4 + doc/administration/consul.md | 239 + doc/administration/environment_variables.md | 1 + doc/administration/feature_flags.md | 4 +- doc/administration/file_hooks.md | 7 + .../disaster_recovery/background_verification.md | 8 +- .../geo/disaster_recovery/planned_failover.md | 14 +- .../geo/replication/configuration.md | 11 +- doc/administration/geo/replication/database.md | 64 +- doc/administration/geo/replication/datatypes.md | 41 +- doc/administration/geo/replication/disable_geo.md | 2 +- .../geo/replication/docker_registry.md | 2 +- .../geo/replication/external_database.md | 49 - .../geo/replication/geo_validation_tests.md | 22 +- .../replication/img/adding_a_secondary_node.png | Bin 23555 -> 0 bytes .../img/adding_a_secondary_node_v13_3.png | Bin 0 -> 20195 bytes doc/administration/geo/replication/index.md | 3 +- .../geo/replication/multiple_servers.md | 41 +- .../geo/replication/object_storage.md | 2 +- .../geo/replication/remove_geo_node.md | 2 +- .../geo/replication/troubleshooting.md | 347 +- doc/administration/geo/replication/tuning.md | 17 +- .../geo/replication/version_specific_updates.md | 162 +- doc/administration/git_annex.md | 8 +- doc/administration/git_protocol.md | 4 + .../gitaly/img/cluster_example_v13_3.png | Bin 0 -> 27703 bytes .../gitaly/img/shard_example_v13_3.png | Bin 0 -> 14869 bytes doc/administration/gitaly/index.md | 2 +- doc/administration/gitaly/praefect.md | 308 +- doc/administration/gitaly/reference.md | 2 +- .../high_availability/alpha_database.md | 2 +- doc/administration/high_availability/consul.md | 197 +- doc/administration/high_availability/gitaly.md | 59 +- doc/administration/high_availability/gitlab.md | 214 +- .../high_availability/load_balancer.md | 134 +- .../high_availability/monitoring_node.md | 103 +- doc/administration/high_availability/nfs.md | 321 +- .../high_availability/nfs_host_client_setup.md | 156 +- doc/administration/high_availability/pgbouncer.md | 165 +- doc/administration/high_availability/sidekiq.md | 189 +- .../img/repository_storages_admin_ui_v13_1.png | Bin 85160 -> 26234 bytes doc/administration/index.md | 8 +- doc/administration/instance_limits.md | 76 +- doc/administration/integration/plantuml.md | 7 + doc/administration/integration/terminal.md | 4 +- doc/administration/invalidate_markdown_cache.md | 7 + doc/administration/issue_closing_pattern.md | 11 +- doc/administration/job_artifacts.md | 45 +- doc/administration/lfs/index.md | 45 +- doc/administration/load_balancer.md | 126 + doc/administration/logs.md | 28 + doc/administration/merge_request_diffs.md | 7 + doc/administration/monitoring/github_imports.md | 3 +- .../img/self_monitoring_default_dashboard.png | Bin 51508 -> 0 bytes .../img/self_monitoring_overview_dashboard.png | Bin 0 -> 51508 bytes .../gitlab_self_monitoring_project/index.md | 8 +- .../performance/grafana_configuration.md | 4 +- .../monitoring/performance/performance_bar.md | 6 +- .../monitoring/performance/request_profiling.md | 6 +- .../monitoring/prometheus/gitlab_metrics.md | 7 +- doc/administration/monitoring/prometheus/index.md | 93 +- doc/administration/nfs.md | 368 + doc/administration/object_storage.md | 84 +- .../operations/cleaning_up_redis_sessions.md | 3 +- .../operations/extra_sidekiq_processes.md | 2 +- .../operations/filesystem_benchmarking.md | 2 +- .../operations/moving_repositories.md | 47 +- doc/administration/operations/puma.md | 2 +- .../operations/sidekiq_memory_killer.md | 2 +- doc/administration/packages/container_registry.md | 75 +- doc/administration/packages/index.md | 2 +- doc/administration/pages/index.md | 77 +- doc/administration/pages/source.md | 14 +- doc/administration/postgresql/external.md | 2 +- doc/administration/postgresql/index.md | 2 +- doc/administration/postgresql/pgbouncer.md | 168 + .../postgresql/replication_and_failover.md | 51 +- doc/administration/raketasks/check.md | 19 + doc/administration/raketasks/maintenance.md | 51 +- .../raketasks/project_import_export.md | 2 +- doc/administration/raketasks/storage.md | 4 +- doc/administration/raketasks/uploads/migrate.md | 10 +- .../redis/replication_and_failover.md | 75 +- .../redis/replication_and_failover_external.md | 10 +- doc/administration/redis/standalone.md | 51 +- .../reference_architectures/10k_users.md | 2115 ++- .../reference_architectures/1k_users.md | 109 +- .../reference_architectures/25k_users.md | 2115 ++- .../reference_architectures/2k_users.md | 31 +- .../reference_architectures/3k_users.md | 84 +- .../reference_architectures/50k_users.md | 2115 ++- .../reference_architectures/5k_users.md | 81 +- .../img/reference-architectures.png | Bin 47459 -> 12585 bytes .../reference_architectures/index.md | 151 +- .../reference_architectures/troubleshooting.md | 10 +- doc/administration/reply_by_email.md | 8 + doc/administration/reply_by_email_postfix_setup.md | 2 +- doc/administration/repository_checks.md | 7 + doc/administration/repository_storage_paths.md | 4 +- doc/administration/server_hooks.md | 10 +- doc/administration/sidekiq.md | 188 + doc/administration/smime_signing_email.md | 2 +- doc/administration/snippets/index.md | 17 +- .../static_objects_external_storage.md | 11 +- doc/administration/terraform_state.md | 2 - doc/administration/troubleshooting/debug.md | 8 +- .../troubleshooting/gitlab_rails_cheat_sheet.md | 23 +- .../troubleshooting/group_saml_scim.md | 2 +- .../troubleshooting/img/network_monitor_xid.png | Bin 0 -> 131339 bytes doc/administration/troubleshooting/postgresql.md | 4 +- doc/administration/troubleshooting/sidekiq.md | 22 +- .../troubleshooting/tracing_correlation_id.md | 126 + doc/administration/wikis/index.md | 75 + doc/api/README.md | 17 +- doc/api/access_requests.md | 9 +- doc/api/admin_sidekiq_queues.md | 2 +- doc/api/api_resources.md | 3 +- doc/api/branches.md | 7 + doc/api/commits.md | 37 +- doc/api/discussions.md | 5 +- doc/api/environments.md | 18 +- doc/api/epic_links.md | 3 +- doc/api/epics.md | 48 +- doc/api/error_tracking.md | 3 +- doc/api/events.md | 12 +- doc/api/feature_flags.md | 20 +- doc/api/feature_flags_legacy.md | 5 + doc/api/geo_nodes.md | 12 +- doc/api/graphql/audit_report.md | 116 + doc/api/graphql/getting_started.md | 5 +- doc/api/graphql/img/sample_issue_boards_v13_2.png | Bin 0 -> 33251 bytes doc/api/graphql/img/user_query_example_v13_2.png | Bin 0 -> 91751 bytes doc/api/graphql/index.md | 10 +- doc/api/graphql/reference/gitlab_schema.graphql | 2676 +++- doc/api/graphql/reference/gitlab_schema.json | 14249 ++++++++++++++----- doc/api/graphql/reference/index.md | 327 +- doc/api/graphql/sample_issue_boards.md | 44 + doc/api/group_activity_analytics.md | 2 +- doc/api/group_milestones.md | 15 +- doc/api/group_wikis.md | 7 + doc/api/groups.md | 55 +- doc/api/instance_level_ci_variables.md | 10 +- doc/api/issues.md | 205 +- doc/api/job_artifacts.md | 265 + doc/api/jobs.md | 281 +- doc/api/keys.md | 7 + doc/api/lint.md | 6 + doc/api/markdown.md | 7 +- doc/api/members.md | 12 + doc/api/merge_request_approvals.md | 15 +- doc/api/merge_request_context_commits.md | 7 + doc/api/merge_requests.md | 12 + doc/api/milestones.md | 15 +- doc/api/namespaces.md | 49 +- doc/api/notes.md | 23 +- doc/api/notification_settings.md | 11 +- doc/api/packages.md | 2 +- doc/api/personal_access_tokens.md | 88 + doc/api/pipeline_schedules.md | 6 + doc/api/pipeline_triggers.md | 6 + doc/api/pipelines.md | 18 +- doc/api/project_aliases.md | 7 + doc/api/project_badges.md | 7 + doc/api/project_import_export.md | 7 + doc/api/project_level_variables.md | 24 +- doc/api/project_snippets.md | 7 + doc/api/project_statistics.md | 7 + doc/api/project_templates.md | 16 +- doc/api/project_vulnerabilities.md | 7 + doc/api/projects.md | 21 +- doc/api/protected_branches.md | 9 +- doc/api/protected_tags.md | 9 +- doc/api/releases/index.md | 2 +- doc/api/remote_mirrors.md | 7 + doc/api/repositories.md | 18 +- doc/api/repository_files.md | 7 + doc/api/repository_submodules.md | 7 + doc/api/resource_milestone_events.md | 2 + doc/api/resource_state_events.md | 2 + doc/api/resource_weight_events.md | 2 + doc/api/scim.md | 10 +- doc/api/search.md | 25 +- doc/api/services.md | 20 +- doc/api/settings.md | 43 +- doc/api/sidekiq_metrics.md | 2 +- doc/api/snippets.md | 7 + doc/api/suggestions.md | 7 + doc/api/tags.md | 7 + doc/api/templates/dockerfiles.md | 4 + doc/api/templates/gitignores.md | 2 +- doc/api/templates/gitlab_ci_ymls.md | 17 +- doc/api/templates/licenses.md | 2 +- doc/api/users.md | 15 +- doc/api/version.md | 2 +- doc/api/visual_review_discussions.md | 7 + doc/api/vulnerabilities.md | 2 +- doc/api/vulnerability_findings.md | 2 +- doc/api/wikis.md | 7 + doc/articles/index.md | 17 +- doc/ci/README.md | 2 +- .../ci_cd_for_external_repos/github_integration.md | 2 +- doc/ci/cloud_deployment/index.md | 70 +- doc/ci/directed_acyclic_graph/index.md | 5 +- doc/ci/docker/using_docker_build.md | 40 +- doc/ci/docker/using_docker_images.md | 118 +- doc/ci/docker/using_kaniko.md | 1 + doc/ci/environments/deployment_safety.md | 6 + .../img/vault-read-secrets-production.png | Bin 326852 -> 108684 bytes .../img/vault-read-secrets-staging.png | Bin 400945 -> 133506 bytes .../laravel_with_gitlab_and_envoy/index.md | 12 +- .../test_phoenix_app_with_gitlab_ci_cd/index.md | 5 +- doc/ci/img/ci_lint.png | Bin 0 -> 37745 bytes doc/ci/img/ci_lint_dry_run.png | Bin 0 -> 18688 bytes doc/ci/img/metrics_reports_advanced_v13_0.png | Bin 41131 -> 13879 bytes doc/ci/introduction/index.md | 2 +- doc/ci/jenkins/index.md | 358 +- doc/ci/junit_test_reports.md | 37 +- doc/ci/large_repositories/index.md | 12 + doc/ci/lint.md | 41 + doc/ci/merge_request_pipelines/index.md | 52 +- .../pipelines_for_merged_results/index.md | 2 - .../merge_trains/index.md | 2 + doc/ci/migration/circleci.md | 3 + doc/ci/migration/jenkins.md | 359 + doc/ci/multi_project_pipelines.md | 27 +- doc/ci/parent_child_pipelines.md | 6 +- doc/ci/pipelines/index.md | 38 +- doc/ci/pipelines/job_artifacts.md | 72 +- doc/ci/pipelines/settings.md | 7 +- doc/ci/quick_start/README.md | 42 +- doc/ci/runners/README.md | 49 +- doc/ci/services/redis.md | 2 +- doc/ci/ssh_keys/README.md | 2 +- doc/ci/triggers/README.md | 35 +- doc/ci/troubleshooting.md | 23 +- doc/ci/variables/README.md | 196 +- doc/ci/variables/predefined_variables.md | 20 +- doc/ci/yaml/README.md | 659 +- doc/development/README.md | 16 + doc/development/api_graphql_styleguide.md | 153 +- doc/development/api_styleguide.md | 7 +- doc/development/architecture.md | 164 +- doc/development/auto_devops.md | 6 + doc/development/background_migrations.md | 10 +- doc/development/build_test_package.md | 6 + doc/development/changelog.md | 2 + doc/development/chatops_on_gitlabcom.md | 6 + doc/development/cicd/img/ci_architecture.png | Bin 102944 -> 42677 bytes .../cicd/img/ci_template_selection_v13_1.png | Bin 21284 -> 8676 bytes doc/development/cicd/index.md | 7 + doc/development/cicd/templates.md | 48 +- doc/development/code_review.md | 12 +- doc/development/contributing/issue_workflow.md | 20 +- doc/development/contributing/style_guides.md | 19 +- doc/development/dangerbot.md | 2 +- doc/development/database_debugging.md | 2 +- doc/development/database_review.md | 4 +- doc/development/deleting_migrations.md | 2 +- doc/development/deprecation_guidelines/index.md | 23 + doc/development/diffs.md | 9 +- doc/development/distributed_tracing.md | 6 + doc/development/doc_styleguide.md | 2 + doc/development/documentation/feature_flags.md | 8 +- doc/development/documentation/index.md | 104 +- .../site_architecture/deployment_process.md | 58 + .../documentation/site_architecture/global_nav.md | 6 +- .../documentation/site_architecture/index.md | 2 + .../site_architecture/release_process.md | 98 +- doc/development/documentation/structure.md | 117 +- doc/development/documentation/styleguide.md | 382 +- doc/development/ee_features.md | 23 +- doc/development/elasticsearch.md | 9 + doc/development/fe_guide/frontend_faq.md | 30 + doc/development/fe_guide/graphql.md | 37 +- doc/development/fe_guide/icons.md | 83 + .../fe_guide/img/webpack_report_v12_8.png | Bin 0 -> 47453 bytes doc/development/fe_guide/index.md | 2 +- doc/development/fe_guide/style/javascript.md | 2 +- doc/development/fe_guide/style/scss.md | 12 +- doc/development/fe_guide/tooling.md | 3 +- doc/development/fe_guide/vue.md | 8 +- doc/development/fe_guide/vue3_migration.md | 3 + doc/development/fe_guide/vuex.md | 142 +- doc/development/feature_categorization/index.md | 2 +- doc/development/feature_flags.md | 4 + doc/development/feature_flags/controls.md | 2 +- doc/development/feature_flags/development.md | 414 +- doc/development/feature_flags/process.md | 3 +- doc/development/filtering_by_label.md | 5 + doc/development/geo.md | 115 - doc/development/geo/framework.md | 147 +- doc/development/go_guide/index.md | 4 +- doc/development/gotchas.md | 31 + doc/development/graphql_guide/index.md | 13 + doc/development/i18n/externalization.md | 77 +- doc/development/i18n/merging_translations.md | 9 +- doc/development/i18n/proofreader.md | 7 +- doc/development/img/bullet_v13_0.png | Bin 1085958 -> 407482 bytes doc/development/img/deployment_pipeline_v13_3.png | Bin 0 -> 7695 bytes doc/development/img/telemetry_system_overview.png | Bin 429082 -> 103618 bytes doc/development/instrumentation.md | 6 + .../elasticsearch_for_paid_tiers_on_gitlabcom.md | 28 - doc/development/integrations/example_vuln.png | Bin 102950 -> 36208 bytes doc/development/integrations/jenkins.md | 2 +- doc/development/integrations/jira_connect.md | 2 +- doc/development/integrations/secure.md | 2 +- doc/development/internal_api.md | 86 +- doc/development/issuable-like-models.md | 11 +- doc/development/issue_types.md | 6 + doc/development/kubernetes.md | 6 + doc/development/licensed_feature_availability.md | 2 +- doc/development/logging.md | 8 +- .../merge_request_performance_guidelines.md | 2 +- doc/development/migration_style_guide.md | 92 +- doc/development/multi_version_compatibility.md | 164 + .../new_fe_guide/development/performance.md | 4 +- doc/development/new_fe_guide/tips.md | 4 +- doc/development/packages.md | 21 +- doc/development/performance.md | 4 + doc/development/pipelines.md | 55 +- doc/development/prometheus.md | 6 + doc/development/prometheus_metrics.md | 6 + doc/development/query_recorder.md | 3 +- doc/development/redis.md | 12 +- doc/development/reference_processing.md | 28 + doc/development/service_measurement.md | 2 +- doc/development/sidekiq_style_guide.md | 53 +- doc/development/sql.md | 6 +- doc/development/telemetry/event_dictionary.md | 32 + doc/development/telemetry/index.md | 178 +- doc/development/telemetry/snowplow.md | 18 +- doc/development/telemetry/usage_ping.md | 422 +- doc/development/testing_guide/best_practices.md | 110 +- .../testing_guide/end_to_end/best_practices.md | 27 + doc/development/testing_guide/end_to_end/index.md | 7 + .../testing_guide/end_to_end/page_objects.md | 26 +- .../running_tests_that_require_special_setup.md | 86 + doc/development/testing_guide/frontend_testing.md | 217 +- doc/development/testing_guide/review_apps.md | 12 +- .../testing_guide/testing_migrations_guide.md | 31 +- doc/development/uploads.md | 3 +- doc/development/what_requires_downtime.md | 5 +- doc/gitlab-basics/README.md | 3 + doc/gitlab-basics/add-file.md | 3 + doc/gitlab-basics/command-line-commands.md | 3 + doc/gitlab-basics/create-branch.md | 3 + doc/gitlab-basics/create-project.md | 3 + doc/gitlab-basics/create-your-ssh-keys.md | 4 + doc/gitlab-basics/feature_branch_workflow.md | 3 + doc/gitlab-basics/fork-project.md | 3 + doc/gitlab-basics/start-using-git.md | 3 + doc/img/devops-stages-13_3.png | Bin 0 -> 24935 bytes doc/img/devops-stages.png | Bin 10654 -> 0 bytes .../aws/img/aws_ha_architecture_diagram.png | Bin 144735 -> 42277 bytes doc/install/aws/index.md | 23 +- doc/install/azure/index.md | 40 +- doc/install/installation.md | 85 +- doc/install/openshift_and_gitlab/index.md | 6 +- doc/install/relative_url.md | 2 +- doc/install/requirements.md | 14 +- doc/integration/bitbucket.md | 2 +- doc/integration/elasticsearch.md | 190 +- doc/integration/jenkins.md | 24 +- doc/integration/jenkins_deprecated.md | 3 +- doc/integration/jira_development_panel.md | 146 +- doc/integration/kerberos.md | 2 +- doc/integration/omniauth.md | 62 +- doc/integration/recaptcha.md | 4 +- doc/integration/saml.md | 9 +- doc/integration/shibboleth.md | 2 +- doc/integration/sourcegraph.md | 3 + doc/intro/README.md | 3 + doc/migrate_ci_to_ce/README.md | 2 +- doc/operations/error_tracking.md | 97 + doc/operations/feature_flags.md | 79 +- doc/operations/img/error_details_v12_7.png | Bin 0 -> 92858 bytes .../img/error_details_with_issue_v12_8.png | Bin 0 -> 32459 bytes doc/operations/img/error_tracking_list_v12_6.png | Bin 0 -> 41388 bytes doc/operations/incident_management/alertdetails.md | 194 + doc/operations/incident_management/alerts.md | 118 + .../img/alert_detail_add_todo_v13_1.png | Bin 0 -> 16822 bytes .../img/alert_detail_added_todo_v13_1.png | Bin 0 -> 18170 bytes .../img/alert_detail_full_v13_1.png | Bin 0 -> 26957 bytes .../img/alert_detail_metrics_v13_2.png | Bin 0 -> 27616 bytes .../img/alert_detail_overview_v13_1.png | Bin 0 -> 14827 bytes .../img/alert_detail_system_notes_v13_1.png | Bin 0 -> 22329 bytes .../img/alert_details_assignees_v13_1.png | Bin 0 -> 31091 bytes .../img/alert_list_assignees_v13_1.png | Bin 0 -> 29011 bytes .../img/alert_list_search_v13_1.png | Bin 0 -> 12166 bytes .../img/alert_list_sort_v13_1.png | Bin 0 -> 13919 bytes .../img/alert_management_severity_v13_0.png | Bin 0 -> 10972 bytes .../img/alert_todo_assignees_v13_1.png | Bin 0 -> 10157 bytes .../incident_management/img/incident_list.png | Bin 0 -> 34194 bytes .../img/incident_list_create_v13_3.png | Bin 0 -> 21931 bytes .../img/incident_list_search_v13_3.png | Bin 0 -> 29780 bytes .../img/incident_list_sort_v13_3.png | Bin 0 -> 39524 bytes .../img/incident_management_settings_v13_3.png | Bin 0 -> 21262 bytes .../img/pagerduty_incidents_integration_v13_3.png | Bin 0 -> 43318 bytes .../img/status_page_detail_link_v13_1.png | Bin 0 -> 107718 bytes .../img/status_page_detail_v12_10.png | Bin 0 -> 37911 bytes .../img/status_page_incidents_v12_10.png | Bin 0 -> 16149 bytes doc/operations/incident_management/incidents.md | 103 + doc/operations/incident_management/index.md | 68 + doc/operations/incident_management/status_page.md | 179 + doc/operations/index.md | 91 +- doc/operations/metrics/alerts.md | 39 +- doc/operations/metrics/dashboards/default.md | 38 + doc/operations/metrics/dashboards/develop.md | 33 + .../img/actions_menu_create_add_panel_v13_3.png | Bin 0 -> 9982 bytes .../actions_menu_create_new_dashboard_v13_3.png | Bin 0 -> 14957 bytes .../img/dashboard_external_link_v13_1.png | Bin 0 -> 12708 bytes .../img/dashboard_local_timezone_v13_1.png | Bin 0 -> 65094 bytes .../dashboards/img/external_dashboard_link.png | Bin 0 -> 20192 bytes .../img/heatmap_chart_too_much_data_v_13_2.png | Bin 0 -> 7310 bytes .../metrics/dashboards/img/heatmap_panel_type.png | Bin 0 -> 8272 bytes .../img/k8s_pod_health_dashboard_v13_3.png | Bin 0 -> 60933 bytes .../img/metrics_dashboard_annotations_ui_v13.0.png | Bin 0 -> 31654 bytes .../img/metrics_dashboard_panel_preview_v13_3.png | Bin 0 -> 67972 bytes .../metrics_dashboard_template_selection_v13_3.png | Bin 0 -> 36268 bytes ..._dashboard_template_selection_web_ide_v13_3.png | Bin 0 -> 26123 bytes .../img/metrics_settings_button_v13_3.png | Bin 0 -> 3903 bytes .../dashboards/img/panel_context_menu_v13_3.png | Bin 0 -> 14538 bytes .../prometheus_dashboard_anomaly_panel_type.png | Bin 0 -> 41015 bytes .../prometheus_dashboard_area_panel_type_v12_8.png | Bin 0 -> 53370 bytes ...theus_dashboard_bar_chart_panel_type_v12.10.png | Bin 0 -> 4761 bytes .../img/prometheus_dashboard_column_panel_type.png | Bin 0 -> 13219 bytes ...prometheus_dashboard_gauge_panel_type_v13_3.png | Bin 0 -> 17303 bytes ...ometheus_dashboard_label_variable_shorthand.png | Bin 0 -> 3897 bytes .../img/prometheus_dashboard_label_variables.png | Bin 0 -> 8076 bytes .../img/prometheus_dashboard_repeated_label.png | Bin 0 -> 3116 bytes ...prometheus_dashboard_single_stat_panel_type.png | Bin 0 -> 6871 bytes ...s_dashboard_stacked_column_panel_type_v12_8.png | Bin 0 -> 13898 bytes .../prometheus_dashboard_yaml_validation_v13_1.png | Bin 0 -> 27694 bytes .../metrics/dashboards/img/related_links_v13_1.png | Bin 0 -> 4086 bytes doc/operations/metrics/dashboards/index.md | 262 +- doc/operations/metrics/dashboards/panel_types.md | 69 +- doc/operations/metrics/dashboards/settings.md | 52 + .../metrics/dashboards/templating_variables.md | 2 +- doc/operations/metrics/dashboards/variables.md | 6 +- doc/operations/metrics/dashboards/yaml.md | 48 +- .../metrics/dashboards/yaml_number_format.md | 2 +- doc/operations/metrics/embed.md | 66 +- doc/operations/metrics/embed_grafana.md | 70 +- .../metrics/img/copy_link_to_chart_v12_10.png | Bin 0 -> 21559 bytes .../metrics/img/embed_metrics_issue_template.png | Bin 0 -> 43908 bytes .../img/embedded_metrics_markdown_v12_8.png | Bin 0 -> 13818 bytes .../img/embedded_metrics_rendered_v12_8.png | Bin 0 -> 66002 bytes .../metrics/img/example-dashboard_v13_1.png | Bin 31439 -> 0 bytes .../metrics/img/example-dashboard_v13_3.png | Bin 0 -> 64275 bytes doc/operations/metrics/img/grafana_embedded.png | Bin 0 -> 28071 bytes doc/operations/metrics/img/grafana_live_embed.png | Bin 0 -> 44603 bytes doc/operations/metrics/img/grafana_panel_v12_5.png | Bin 0 -> 44193 bytes .../metrics/img/grafana_sharing_dialog_v12_5.png | Bin 0 -> 41203 bytes .../metrics/img/hide_embedded_metrics_v12_10.png | Bin 0 -> 21312 bytes .../metrics/img/http_proxy_access_v12_5.png | Bin 0 -> 47813 bytes .../metrics/img/linked_runbooks_on_charts.png | Bin 0 -> 16966 bytes .../metrics/img/prometheus_add_metric.png | Bin 0 -> 24607 bytes doc/operations/metrics/img/prometheus_alert.png | Bin 0 -> 6611 bytes .../img/prometheus_cluster_health_embed_v12_9.png | Bin 0 -> 50178 bytes ...rometheus_dashboard_edit_metric_link_v_12_9.png | Bin 0 -> 29178 bytes .../img/prometheus_monitoring_dashboard_v13_3.png | Bin 0 -> 64275 bytes .../metrics/img/prometheus_service_alerts.png | Bin 0 -> 16084 bytes .../metrics/img/rendered_grafana_embed_v12_5.png | Bin 0 -> 61194 bytes .../metrics/img/select_query_variables_v12_5.png | Bin 0 -> 7368 bytes .../metrics/img/view_embedded_metrics_v12_10.png | Bin 0 -> 36717 bytes doc/operations/metrics/index.md | 113 +- doc/operations/product_analytics.md | 82 + doc/policy/maintenance.md | 6 +- doc/push_rules/push_rules.md | 5 +- doc/raketasks/README.md | 1 + doc/raketasks/backup_restore.md | 94 +- doc/raketasks/cleanup.md | 4 + doc/raketasks/spdx.md | 18 + doc/security/README.md | 1 + doc/security/cicd_environment_variables.md | 4 +- ...swords_for_integrated_authentication_methods.md | 14 + doc/security/ssh_keys_restrictions.md | 3 + doc/security/two_factor_authentication.md | 8 +- doc/security/user_email_confirmation.md | 3 + doc/security/user_file_uploads.md | 5 +- doc/security/webhooks.md | 2 +- doc/ssh/README.md | 31 +- doc/subscriptions/index.md | 113 +- doc/topics/authentication/index.md | 1 - doc/topics/autodevops/customize.md | 15 +- doc/topics/autodevops/index.md | 20 +- doc/topics/autodevops/quick_start_guide.md | 8 +- doc/topics/autodevops/stages.md | 19 +- doc/topics/cron/index.md | 63 + doc/topics/git/feature_branch_development.md | 3 + doc/topics/git/how_to_install_git/index.md | 3 + doc/topics/git/img/create_merge_request_v13_1.png | Bin 16387 -> 6275 bytes doc/topics/git/img/modify_branches_v13_1.png | Bin 75159 -> 25337 bytes doc/topics/git/index.md | 3 + doc/topics/git/lfs/index.md | 4 + .../git/lfs/migrate_from_git_annex_to_git_lfs.md | 11 +- doc/topics/git/lfs/migrate_to_git_lfs.md | 18 +- .../numerous_undo_possibilities_in_git/index.md | 3 + doc/topics/git/partial_clone.md | 51 + doc/topics/git/troubleshooting_git.md | 3 + doc/topics/git/useful_git_commands.md | 3 + doc/topics/gitlab_flow.md | 13 +- doc/topics/index.md | 4 +- doc/topics/offline/index.md | 123 - doc/topics/offline/quick_start_guide.md | 6 +- doc/university/bookclub/booklist.md | 117 +- doc/university/bookclub/index.md | 23 +- doc/university/glossary/README.md | 10 +- doc/university/process/README.md | 29 +- doc/university/training/end-user/README.md | 369 +- doc/university/training/topics/explore_gitlab.md | 11 +- doc/update/README.md | 15 +- doc/update/upgrading_from_source.md | 8 +- doc/user/admin_area/abuse_reports.md | 8 + doc/user/admin_area/custom_project_templates.md | 4 +- .../img/scope_mr_approval_settings_v13_1.png | Bin 69238 -> 46908 bytes doc/user/admin_area/index.md | 16 +- doc/user/admin_area/license.md | 8 + doc/user/admin_area/merge_requests_approvals.md | 2 +- .../settings/account_and_limit_settings.md | 26 +- doc/user/admin_area/settings/gitaly_timeouts.md | 4 + .../img/import_export_rate_limits_v13_2.png | Bin 54802 -> 18320 bytes doc/user/admin_area/settings/index.md | 11 +- .../settings/instance_template_repository.md | 19 +- .../settings/project_integration_management.md | 54 + .../settings/push_event_activities_limit.md | 3 + .../settings/visibility_and_access_controls.md | 7 +- .../img/merge_request_analytics_v13_3.png | Bin 0 -> 54156 bytes doc/user/analytics/img/new_value_stream_v13_3.png | Bin 0 -> 82797 bytes .../analytics/img/repository_analytics_v13_0.png | Bin 91755 -> 35278 bytes doc/user/analytics/img/vsa_filter_bar_v13.3.png | Bin 0 -> 117834 bytes doc/user/analytics/img/vsa_time_metrics_v13_0.png | Bin 240523 -> 70839 bytes doc/user/analytics/index.md | 11 +- doc/user/analytics/merge_request_analytics.md | 42 + doc/user/analytics/value_stream_analytics.md | 58 +- .../application_security/configuration/index.md | 29 +- .../container_scanning/index.md | 40 +- .../application_security/coverage_fuzzing/index.md | 92 +- .../dast/img/dast_on_demand_v13_2.png | Bin 91775 -> 26144 bytes doc/user/application_security/dast/index.md | 132 +- .../dependency_scanning/analyzers.md | 16 +- .../dependency_scanning/index.md | 37 +- .../img/adding_a_dismissal_reason_v13_0.png | Bin 109979 -> 35841 bytes .../img/interacting_with_vulnerability_v13_0.png | Bin 90299 -> 29141 bytes .../img/vulnerability-check_v13_0.png | Bin 51019 -> 30789 bytes ...lnerability_related_issues_add_button_v13_2.png | Bin 0 -> 33345 bytes .../vulnerability_related_issues_remove_v13_2.gif | Bin 0 -> 35842 bytes ...rability_related_issues_text_box_tags_v13_2.gif | Bin 0 -> 69338 bytes doc/user/application_security/index.md | 54 +- .../offline_deployments/index.md | 123 + doc/user/application_security/sast/index.md | 219 +- .../application_security/secret_detection/index.md | 30 +- .../group_security_dashboard_export_csv_v13_1.png | Bin 105028 -> 42309 bytes .../img/group_security_dashboard_v13_2_noNav.png | Bin 53913 -> 0 bytes .../img/group_security_dashboard_v13_3.png | Bin 0 -> 29038 bytes .../img/group_vulnerability_report_v13_3.png | Bin 0 -> 36339 bytes .../img/pipeline_security_v13_3.gif | Bin 0 -> 548942 bytes .../img/standalone_vulnerability_page_v13_1.png | Bin 79341 -> 0 bytes .../img/vulnerability_page_v13_1.png | Bin 0 -> 79341 bytes .../security_dashboard/index.md | 67 +- .../threat_monitoring/index.md | 5 + ...nerability_page_download_patch_button_v13_1.png | Bin 8979 -> 0 bytes ...ty_page_merge_request_button_dropdown_v13_1.png | Bin 144464 -> 0 bytes ...lnerability_page_merge_request_button_v13_1.png | Bin 40058 -> 0 bytes .../img/standalone_vulnerability_page_v13_1.png | Bin 110282 -> 0 bytes ...nerability_page_download_patch_button_v13_1.png | Bin 0 -> 8979 bytes ...ty_page_merge_request_button_dropdown_v13_1.png | Bin 0 -> 53561 bytes ...lnerability_page_merge_request_button_v13_1.png | Bin 0 -> 15394 bytes .../img/vulnerability_page_v13_1.png | Bin 0 -> 41387 bytes .../application_security/vulnerabilities/index.md | 12 +- doc/user/asciidoc.md | 90 + doc/user/clusters/applications.md | 83 +- doc/user/clusters/management_project.md | 4 +- .../img/compliance_dashboard_v13_2.png | Bin 84922 -> 0 bytes .../img/compliance_dashboard_v13_3_1.png | Bin 0 -> 298542 bytes .../compliance_dashboard/img/failed_icon_v13_3.png | Bin 0 -> 4118 bytes .../img/success_icon_v13_3.png | Bin 0 -> 4121 bytes .../img/warning_icon_v13_3.png | Bin 0 -> 4095 bytes doc/user/compliance/compliance_dashboard/index.md | 42 +- .../img/denied_licenses_v13_3.png | Bin 0 -> 29503 bytes .../img/license_compliance_add_license_v13_0.png | Bin 61862 -> 21244 bytes .../img/license_compliance_decision_v13_0.png | Bin 40646 -> 12536 bytes .../img/license_compliance_pipeline_tab_v13_0.png | Bin 51906 -> 18910 bytes .../img/license_compliance_search_v13_0.png | Bin 29857 -> 10686 bytes .../img/license_compliance_settings_v13_0.png | Bin 17567 -> 6763 bytes .../img/license_compliance_v13_0.png | Bin 85525 -> 31922 bytes .../license_compliance/img/license_list_v13_0.png | Bin 89930 -> 29652 bytes .../license_compliance/img/policies_v13_0.png | Bin 69562 -> 22618 bytes doc/user/compliance/license_compliance/index.md | 170 +- .../img/quickly_assign_commenter_v13_1.png | Bin 216812 -> 69299 bytes doc/user/discussions/img/resolve_thread_button.png | Bin 9842 -> 0 bytes .../img/resolve_thread_button_v13_3.png | Bin 0 -> 10093 bytes doc/user/discussions/index.md | 24 +- doc/user/gitlab_com/index.md | 23 +- doc/user/group/clusters/index.md | 2 +- doc/user/group/custom_project_templates.md | 45 +- .../epics/img/epic_activity_sort_order_v13_2.png | Bin 20531 -> 5903 bytes doc/user/group/epics/img/issue_list_v13_1.png | Bin 24946 -> 14825 bytes doc/user/group/epics/img/new_epic_form_v13.2.png | Bin 96690 -> 50977 bytes .../group/epics/img/new_epic_from_groups_v13.2.png | Bin 78168 -> 39158 bytes doc/user/group/epics/index.md | 9 +- doc/user/group/epics/manage_epics.md | 23 +- doc/user/group/img/add_new_members.png | Bin 66513 -> 79358 bytes doc/user/group/img/ldap_sync_cn_v13_1.png | Bin 120390 -> 38094 bytes doc/user/group/img/ldap_sync_filter_v13_1.png | Bin 135425 -> 44302 bytes doc/user/group/img/manual_permissions_v13_1.png | Bin 31008 -> 11115 bytes doc/user/group/index.md | 44 +- .../issues_analytics/img/issues_table_v13_1.png | Bin 125190 -> 45232 bytes doc/user/group/issues_analytics/index.md | 6 +- doc/user/group/saml_sso/group_managed_accounts.md | 29 +- .../group/saml_sso/img/group_saml_settings.png | Bin 50300 -> 0 bytes .../saml_sso/img/group_saml_settings_v13_3.png | Bin 0 -> 25867 bytes doc/user/group/saml_sso/img/scim_token.png | Bin 57095 -> 0 bytes doc/user/group/saml_sso/img/scim_token_v13_3.png | Bin 0 -> 56821 bytes doc/user/group/saml_sso/index.md | 20 +- doc/user/group/saml_sso/scim_setup.md | 8 +- doc/user/group/settings/import_export.md | 14 +- doc/user/group/subgroups/index.md | 5 +- doc/user/img/completed_tasks_v13_3.png | Bin 0 -> 10844 bytes doc/user/img/inline_diff_01_v13_3.png | Bin 0 -> 10258 bytes doc/user/img/inline_diff_02_v13_3.png | Bin 0 -> 7719 bytes .../img/incident_management_settings.png | Bin 14916 -> 0 bytes .../img/pagerduty_incidents_integration_13_2.png | Bin 34698 -> 0 bytes doc/user/incident_management/index.md | 135 +- doc/user/index.md | 1 + doc/user/infrastructure/index.md | 180 +- doc/user/instance_statistics/dev_ops_score.md | 2 +- doc/user/markdown.md | 130 +- doc/user/packages/composer_repository/index.md | 25 +- doc/user/packages/conan_repository/index.md | 59 +- doc/user/packages/container_registry/index.md | 226 +- doc/user/packages/dependency_proxy/index.md | 14 +- doc/user/packages/go_proxy/index.md | 7 +- doc/user/packages/img/package_activity_v12_10.png | Bin 14515 -> 0 bytes doc/user/packages/index.md | 125 +- doc/user/packages/maven_repository/index.md | 41 +- doc/user/packages/npm_registry/index.md | 39 +- doc/user/packages/nuget_repository/index.md | 58 +- .../img/package_activity_v12_10.png | Bin 0 -> 14515 bytes doc/user/packages/package_registry/index.md | 93 + doc/user/packages/pypi_repository/index.md | 23 +- doc/user/packages/workflows/monorepo.md | 51 +- doc/user/packages/workflows/project_registry.md | 6 + doc/user/permissions.md | 68 +- .../profile/account/two_factor_authentication.md | 8 +- doc/user/profile/index.md | 14 +- doc/user/profile/notifications.md | 2 +- doc/user/profile/personal_access_tokens.md | 39 +- doc/user/project/autocomplete_characters.md | 8 + doc/user/project/badges.md | 21 + doc/user/project/clusters/add_eks_clusters.md | 33 +- doc/user/project/clusters/add_gke_clusters.md | 4 +- doc/user/project/clusters/add_remove_clusters.md | 8 +- .../clusters/img/sidebar_menu_pod_logs_v12_10.png | Bin 14897 -> 0 bytes doc/user/project/clusters/index.md | 8 +- doc/user/project/clusters/kubernetes_pod_logs.md | 90 +- doc/user/project/clusters/runbooks/index.md | 2 +- doc/user/project/clusters/securing.md | 21 +- doc/user/project/clusters/serverless/aws.md | 2 +- doc/user/project/code_intelligence.md | 35 +- doc/user/project/code_owners.md | 5 +- doc/user/project/deploy_boards.md | 2 +- .../project/deploy_keys/img/deploy_keys_v13_0.png | Bin 74337 -> 27295 bytes .../deploy_keys/img/public_deploy_key_v13_0.png | Bin 45326 -> 17220 bytes doc/user/project/deploy_keys/index.md | 2 +- doc/user/project/deploy_tokens/index.md | 2 +- doc/user/project/file_lock.md | 7 + doc/user/project/git_attributes.md | 7 + doc/user/project/highlighting.md | 7 + .../code_intelligence_find_references_v13_3.png | Bin 0 -> 40239 bytes doc/user/project/img/code_intelligence_v13_1.png | Bin 83690 -> 26799 bytes .../project/img/sectional_code_owners_v13.2.png | Bin 106361 -> 29051 bytes .../service_desk_custom_email_address_v13_0.png | Bin 89721 -> 50234 bytes .../project/img/status_page_detail_link_v13_1.png | Bin 107718 -> 0 bytes doc/user/project/img/status_page_detail_v12_10.png | Bin 37911 -> 0 bytes .../project/img/status_page_incidents_v12_10.png | Bin 16149 -> 0 bytes doc/user/project/import/clearcase.md | 4 +- doc/user/project/import/gitea.md | 2 +- doc/user/project/import/github.md | 4 +- doc/user/project/import/gitlab_com.md | 2 +- .../jira/import_issues_from_jira_form_v12_10.png | Bin 56306 -> 31679 bytes .../jira/import_issues_from_jira_form_v13_2.png | Bin 108152 -> 55269 bytes doc/user/project/import/img/manifest_status.png | Bin 34878 -> 0 bytes .../project/import/img/manifest_status_v13_3.png | Bin 0 -> 90811 bytes doc/user/project/import/jira.md | 5 +- doc/user/project/import/manifest.md | 2 +- doc/user/project/import/tfvc.md | 14 +- doc/user/project/index.md | 29 +- doc/user/project/integrations/bamboo.md | 6 + doc/user/project/integrations/bugzilla.md | 6 + .../project/integrations/custom_issue_tracker.md | 8 +- .../project/integrations/discord_notifications.md | 6 + doc/user/project/integrations/emails_on_push.md | 6 + doc/user/project/integrations/generic_alerts.md | 8 +- doc/user/project/integrations/github.md | 8 +- .../integrations/gitlab_slack_application.md | 10 +- doc/user/project/integrations/hangouts_chat.md | 6 + doc/user/project/integrations/hipchat.md | 6 + .../actions_menu_create_new_dashboard_v13_2.png | Bin 11479 -> 0 bytes .../integrations/img/copy_link_to_chart_v12_10.png | Bin 21559 -> 0 bytes .../img/embed_metrics_issue_template.png | Bin 43908 -> 0 bytes .../img/embedded_metrics_markdown_v12_8.png | Bin 13818 -> 0 bytes .../img/embedded_metrics_rendered_v12_8.png | Bin 66002 -> 0 bytes .../project/integrations/img/grafana_embedded.png | Bin 28071 -> 0 bytes .../integrations/img/grafana_live_embed.png | Bin 44603 -> 0 bytes .../integrations/img/grafana_panel_v12_5.png | Bin 44193 -> 0 bytes .../img/grafana_sharing_dialog_v12_5.png | Bin 41203 -> 0 bytes .../img/heatmap_chart_too_much_data_v_13_2.png | Bin 7310 -> 0 bytes .../integrations/img/heatmap_panel_type.png | Bin 8272 -> 0 bytes .../img/hide_embedded_metrics_v12_10.png | Bin 21312 -> 0 bytes .../integrations/img/http_proxy_access_v12_5.png | Bin 47813 -> 0 bytes .../img/metrics_dashboard_annotations_ui_v13.0.png | Bin 31654 -> 0 bytes .../img/metrics_settings_button_v13_2.png | Bin 1901 -> 0 bytes .../integrations/img/panel_context_menu_v13_0.png | Bin 34737 -> 0 bytes .../img/project_integrations_v13_3.png | Bin 0 -> 38249 bytes .../project/integrations/img/project_services.png | Bin 11109 -> 0 bytes .../integrations/img/prometheus_add_metric.png | Bin 47690 -> 0 bytes .../project/integrations/img/prometheus_alert.png | Bin 8192 -> 0 bytes .../img/prometheus_cluster_health_embed_v12_9.png | Bin 50178 -> 0 bytes .../prometheus_dashboard_anomaly_panel_type.png | Bin 41015 -> 0 bytes .../prometheus_dashboard_area_panel_type_v12_8.png | Bin 53370 -> 0 bytes ...theus_dashboard_bar_chart_panel_type_v12.10.png | Bin 4761 -> 0 bytes .../img/prometheus_dashboard_column_panel_type.png | Bin 13219 -> 0 bytes ...rometheus_dashboard_edit_metric_link_v_12_9.png | Bin 29178 -> 0 bytes .../prometheus_dashboard_environments_v12_8.png | Bin 7422 -> 0 bytes ...ometheus_dashboard_label_variable_shorthand.png | Bin 3897 -> 0 bytes .../img/prometheus_dashboard_label_variables.png | Bin 8076 -> 0 bytes .../img/prometheus_dashboard_repeated_label.png | Bin 3116 -> 0 bytes .../img/prometheus_dashboard_select_v_13_0.png | Bin 14284 -> 0 bytes ...prometheus_dashboard_single_stat_panel_type.png | Bin 6871 -> 0 bytes ...s_dashboard_stacked_column_panel_type_v12_8.png | Bin 13898 -> 0 bytes .../prometheus_dashboard_yaml_validation_v13_1.png | Bin 27694 -> 0 bytes .../img/prometheus_monitoring_dashboard_v13_1.png | Bin 40765 -> 0 bytes .../integrations/img/prometheus_service_alerts.png | Bin 16084 -> 0 bytes .../integrations/img/related_links_v13_1.png | Bin 4086 -> 0 bytes .../img/rendered_grafana_embed_v12_5.png | Bin 61194 -> 0 bytes .../img/select_query_variables_v12_5.png | Bin 7368 -> 0 bytes .../img/view_embedded_metrics_v12_10.png | Bin 36717 -> 0 bytes .../integrations/img/webex_teams_configuration.png | Bin 250628 -> 75327 bytes doc/user/project/integrations/index.md | 6 + doc/user/project/integrations/irker.md | 6 + doc/user/project/integrations/jira.md | 53 +- .../integrations/jira_cloud_configuration.md | 6 + doc/user/project/integrations/jira_integrations.md | 35 + .../integrations/jira_server_configuration.md | 6 + doc/user/project/integrations/mattermost.md | 6 + .../integrations/mattermost_slash_commands.md | 12 +- doc/user/project/integrations/microsoft_teams.md | 6 + doc/user/project/integrations/mock_ci.md | 6 + doc/user/project/integrations/overview.md | 20 +- doc/user/project/integrations/prometheus.md | 5 +- .../integrations/prometheus_library/cloudwatch.md | 2 +- doc/user/project/integrations/redmine.md | 6 + .../project/integrations/services_templates.md | 6 + doc/user/project/integrations/slack.md | 8 +- .../project/integrations/slack_slash_commands.md | 6 + doc/user/project/integrations/unify_circuit.md | 6 + doc/user/project/integrations/webex_teams.md | 6 + doc/user/project/integrations/webhooks.md | 102 +- doc/user/project/integrations/youtrack.md | 6 + doc/user/project/issue_board.md | 9 +- doc/user/project/issues/confidential_issues.md | 3 +- doc/user/project/issues/design_management.md | 34 +- .../img/design_drag_and_drop_uploads_v13_2.png | Bin 1260905 -> 350728 bytes .../issues/img/design_management_upload_v13.2.png | Bin 62146 -> 0 bytes .../issues/img/design_management_upload_v13.3.png | Bin 0 -> 15001 bytes .../project/issues/img/design_management_v13_2.png | Bin 1017975 -> 286600 bytes .../issues/img/designs_reordering_v13_3.gif | Bin 0 -> 7068938 bytes .../issues/img/epic_tree_health_status_v12_10.png | Bin 116773 -> 38018 bytes .../resolve_design-discussion_checkbox_v13_1.png | Bin 56634 -> 15228 bytes .../img/resolve_design-discussion_icon_v13_1.png | Bin 36747 -> 11426 bytes doc/user/project/issues/index.md | 9 + doc/user/project/issues/issue_data_and_actions.md | 2 +- doc/user/project/issues/managing_issues.md | 4 + doc/user/project/issues/related_issues.md | 44 +- doc/user/project/labels.md | 5 +- .../project/merge_requests/allow_collaboration.md | 3 + .../authorization_for_merge_requests.md | 3 + .../project/merge_requests/cherry_pick_changes.md | 3 + doc/user/project/merge_requests/code_quality.md | 137 +- .../merge_requests/creating_merge_requests.md | 39 +- .../project/merge_requests/fail_fast_testing.md | 13 +- .../project/merge_requests/fast_forward_merge.md | 3 + doc/user/project/merge_requests/getting_started.md | 3 + .../img/accessibility_mr_widget_v13_0.png | Bin 130072 -> 61149 bytes .../img/approvals_premium_mr_widget_v12_7.png | Bin 50214 -> 0 bytes .../img/approvals_premium_mr_widget_v13_3.png | Bin 0 -> 42034 bytes .../img/approvals_premium_project_edit_v12_5.png | Bin 21293 -> 0 bytes .../img/browser_performance_testing.png | Bin 95312 -> 26201 bytes .../project/merge_requests/img/code_quality.png | Bin 511302 -> 147457 bytes .../img/comment-on-any-diff-line.png | Bin 55593 -> 33199 bytes .../img/draft_blocked_merge_button_v13_2.png | Bin 32770 -> 11774 bytes .../img/load_performance_testing.png | Bin 60196 -> 17506 bytes .../project/merge_requests/img/merge_request.png | Bin 386345 -> 0 bytes .../img/multiline-comment-highlighted.png | Bin 0 -> 38822 bytes .../merge_requests/img/multiline-comment-saved.png | Bin 0 -> 34361 bytes .../merge_requests/img/squash_squashed_commit.png | Bin 23726 -> 16725 bytes .../img/versions_compare_head_v12_10.png | Bin 30717 -> 11637 bytes doc/user/project/merge_requests/index.md | 13 +- .../merge_requests/load_performance_testing.md | 3 +- .../merge_requests/merge_request_approvals.md | 49 +- .../merge_requests/merge_request_dependencies.md | 3 + .../merge_requests/merge_when_pipeline_succeeds.md | 2 +- .../project/merge_requests/resolve_conflicts.md | 3 + doc/user/project/merge_requests/revert_changes.md | 3 + .../reviewing_and_managing_merge_requests.md | 52 +- .../project/merge_requests/squash_and_merge.md | 26 +- .../merge_requests/test_coverage_visualization.md | 32 +- .../work_in_progress_merge_requests.md | 3 + doc/user/project/milestones/burndown_charts.md | 2 +- doc/user/project/operations/alert_management.md | 273 +- doc/user/project/operations/dashboard_settings.md | 51 +- doc/user/project/operations/error_tracking.md | 94 +- .../operations/img/alert_detail_full_v13_1.png | Bin 26957 -> 0 bytes .../operations/img/alert_detail_metrics_v13_2.png | Bin 27616 -> 0 bytes .../operations/img/alert_detail_overview_v13_1.png | Bin 14827 -> 0 bytes .../img/alert_detail_system_notes_v13_1.png | Bin 22329 -> 0 bytes .../img/alert_details_assignees_v13_1.png | Bin 31091 -> 0 bytes .../operations/img/alert_list_assignees_v13_1.png | Bin 29011 -> 0 bytes .../operations/img/alert_list_search_v13_1.png | Bin 12166 -> 0 bytes .../operations/img/alert_list_sort_v13_1.png | Bin 13919 -> 0 bytes .../img/alert_management_severity_v13_0.png | Bin 10972 -> 0 bytes .../operations/img/alert_todo_assignees_v13_1.png | Bin 10157 -> 0 bytes .../img/dashboard_external_link_v13_1.png | Bin 12708 -> 0 bytes .../img/dashboard_local_timezone_v13_1.png | Bin 65094 -> 0 bytes .../project/operations/img/error_details_v12_7.png | Bin 92858 -> 0 bytes .../img/error_details_with_issue_v12_8.png | Bin 32459 -> 0 bytes .../operations/img/error_tracking_list_v12_6.png | Bin 41388 -> 0 bytes .../operations/img/external_dashboard_link.png | Bin 20192 -> 0 bytes .../operations/linking_to_an_external_dashboard.md | 4 +- .../dns_concepts.md | 2 +- .../custom_domains_ssl_tls_certification/index.md | 19 +- .../ssl_tls_concepts.md | 6 +- .../pages/getting_started/pages_from_scratch.md | 5 +- doc/user/project/pages/getting_started_part_one.md | 2 +- doc/user/project/pages/img/change_path_v12_10.png | Bin 61162 -> 21747 bytes .../project/pages/img/choose_ci_template_v13_1.png | Bin 33333 -> 10343 bytes .../pages/img/pages_project_templates_v13_1.png | Bin 181998 -> 56290 bytes .../pages/img/remove_fork_relationship_v13_1.png | Bin 34206 -> 11640 bytes doc/user/project/pages/index.md | 1 - doc/user/project/protected_branches.md | 3 + doc/user/project/protected_tags.md | 3 + doc/user/project/push_options.md | 5 +- doc/user/project/quick_actions.md | 6 +- .../project/releases/img/deploy_freeze_v13_2.png | Bin 0 -> 33428 bytes .../img/milestone_list_with_releases_v12_5.png | Bin 105666 -> 31786 bytes .../releases/img/release_with_milestone_v12_9.png | Bin 57689 -> 17670 bytes .../project/releases/img/releases_count_v13_2.png | Bin 27254 -> 9753 bytes doc/user/project/releases/index.md | 68 +- doc/user/project/repository/branches/index.md | 5 +- doc/user/project/repository/file_finder.md | 6 +- doc/user/project/repository/forking_workflow.md | 9 +- doc/user/project/repository/git_blame.md | 3 + doc/user/project/repository/git_history.md | 3 + .../project/repository/gpg_signed_commits/index.md | 3 + .../img/file_finder_find_button_v12_10.png | Bin 70732 -> 26036 bytes .../img/file_finder_find_file_v12_10.png | Bin 59474 -> 22366 bytes .../img/forking_workflow_choose_namespace.png | Bin 35084 -> 0 bytes .../forking_workflow_choose_namespace_v13_2.png | Bin 0 -> 37495 bytes doc/user/project/repository/index.md | 3 + .../project/repository/jupyter_notebooks/index.md | 6 + .../repository/reducing_the_repo_size_using_git.md | 108 +- .../project/repository/repository_mirroring.md | 87 +- doc/user/project/repository/web_editor.md | 5 +- .../repository/x509_signed_commits/index.md | 3 + .../img/requirements_archived_list_view_v13_1.png | Bin 47662 -> 19539 bytes .../requirements/img/requirements_list_v13_1.png | Bin 113403 -> 68346 bytes doc/user/project/service_desk.md | 2 +- doc/user/project/settings/import_export.md | 13 +- doc/user/project/settings/index.md | 41 +- doc/user/project/settings/project_access_tokens.md | 60 +- .../img/wysiwyg_editor_v13_0.png | Bin 49012 -> 0 bytes .../img/wysiwyg_editor_v13_3.png | Bin 0 -> 57177 bytes doc/user/project/static_site_editor/index.md | 12 +- doc/user/project/status_page/index.md | 133 +- doc/user/project/web_ide/index.md | 48 +- doc/user/project/wiki/index.md | 7 + doc/user/search/advanced_global_search.md | 17 +- doc/user/search/advanced_search_syntax.md | 24 + .../filter_approved_by_merge_requests_v13_0.png | Bin 46764 -> 31363 bytes doc/user/search/index.md | 7 + doc/user/snippets.md | 7 + doc/user/todos.md | 12 +- doc/user/upgrade_email_bypass.md | 123 + 897 files changed, 33922 insertions(+), 13258 deletions(-) delete mode 100644 doc/.vale/gitlab/Contractions.yml create mode 100644 doc/.vale/gitlab/ContractionsDiscard.yml create mode 100644 doc/.vale/gitlab/ContractionsKeep.yml create mode 100644 doc/administration/audit_reports.md create mode 100644 doc/administration/consul.md delete mode 100644 doc/administration/geo/replication/img/adding_a_secondary_node.png create mode 100644 doc/administration/geo/replication/img/adding_a_secondary_node_v13_3.png create mode 100644 doc/administration/gitaly/img/cluster_example_v13_3.png create mode 100644 doc/administration/gitaly/img/shard_example_v13_3.png create mode 100644 doc/administration/load_balancer.md delete mode 100644 doc/administration/monitoring/gitlab_self_monitoring_project/img/self_monitoring_default_dashboard.png create mode 100644 doc/administration/monitoring/gitlab_self_monitoring_project/img/self_monitoring_overview_dashboard.png create mode 100644 doc/administration/nfs.md create mode 100644 doc/administration/postgresql/pgbouncer.md create mode 100644 doc/administration/sidekiq.md create mode 100644 doc/administration/troubleshooting/img/network_monitor_xid.png create mode 100644 doc/administration/troubleshooting/tracing_correlation_id.md create mode 100644 doc/administration/wikis/index.md create mode 100644 doc/api/graphql/audit_report.md create mode 100644 doc/api/graphql/img/sample_issue_boards_v13_2.png create mode 100644 doc/api/graphql/img/user_query_example_v13_2.png create mode 100644 doc/api/graphql/sample_issue_boards.md create mode 100644 doc/api/job_artifacts.md create mode 100644 doc/api/personal_access_tokens.md create mode 100644 doc/ci/img/ci_lint.png create mode 100644 doc/ci/img/ci_lint_dry_run.png create mode 100644 doc/ci/lint.md create mode 100644 doc/ci/migration/jenkins.md create mode 100644 doc/development/deprecation_guidelines/index.md create mode 100644 doc/development/documentation/site_architecture/deployment_process.md create mode 100644 doc/development/fe_guide/img/webpack_report_v12_8.png create mode 100644 doc/development/graphql_guide/index.md create mode 100644 doc/development/img/deployment_pipeline_v13_3.png delete mode 100644 doc/development/integrations/elasticsearch_for_paid_tiers_on_gitlabcom.md create mode 100644 doc/development/telemetry/event_dictionary.md create mode 100644 doc/img/devops-stages-13_3.png delete mode 100644 doc/img/devops-stages.png create mode 100644 doc/operations/error_tracking.md create mode 100644 doc/operations/img/error_details_v12_7.png create mode 100644 doc/operations/img/error_details_with_issue_v12_8.png create mode 100644 doc/operations/img/error_tracking_list_v12_6.png create mode 100644 doc/operations/incident_management/alertdetails.md create mode 100644 doc/operations/incident_management/alerts.md create mode 100644 doc/operations/incident_management/img/alert_detail_add_todo_v13_1.png create mode 100644 doc/operations/incident_management/img/alert_detail_added_todo_v13_1.png create mode 100644 doc/operations/incident_management/img/alert_detail_full_v13_1.png create mode 100644 doc/operations/incident_management/img/alert_detail_metrics_v13_2.png create mode 100644 doc/operations/incident_management/img/alert_detail_overview_v13_1.png create mode 100644 doc/operations/incident_management/img/alert_detail_system_notes_v13_1.png create mode 100644 doc/operations/incident_management/img/alert_details_assignees_v13_1.png create mode 100644 doc/operations/incident_management/img/alert_list_assignees_v13_1.png create mode 100644 doc/operations/incident_management/img/alert_list_search_v13_1.png create mode 100644 doc/operations/incident_management/img/alert_list_sort_v13_1.png create mode 100644 doc/operations/incident_management/img/alert_management_severity_v13_0.png create mode 100644 doc/operations/incident_management/img/alert_todo_assignees_v13_1.png create mode 100644 doc/operations/incident_management/img/incident_list.png create mode 100644 doc/operations/incident_management/img/incident_list_create_v13_3.png create mode 100644 doc/operations/incident_management/img/incident_list_search_v13_3.png create mode 100644 doc/operations/incident_management/img/incident_list_sort_v13_3.png create mode 100644 doc/operations/incident_management/img/incident_management_settings_v13_3.png create mode 100644 doc/operations/incident_management/img/pagerduty_incidents_integration_v13_3.png create mode 100644 doc/operations/incident_management/img/status_page_detail_link_v13_1.png create mode 100644 doc/operations/incident_management/img/status_page_detail_v12_10.png create mode 100644 doc/operations/incident_management/img/status_page_incidents_v12_10.png create mode 100644 doc/operations/incident_management/incidents.md create mode 100644 doc/operations/incident_management/index.md create mode 100644 doc/operations/incident_management/status_page.md create mode 100644 doc/operations/metrics/dashboards/default.md create mode 100644 doc/operations/metrics/dashboards/develop.md create mode 100644 doc/operations/metrics/dashboards/img/actions_menu_create_add_panel_v13_3.png create mode 100644 doc/operations/metrics/dashboards/img/actions_menu_create_new_dashboard_v13_3.png create mode 100644 doc/operations/metrics/dashboards/img/dashboard_external_link_v13_1.png create mode 100644 doc/operations/metrics/dashboards/img/dashboard_local_timezone_v13_1.png create mode 100644 doc/operations/metrics/dashboards/img/external_dashboard_link.png create mode 100644 doc/operations/metrics/dashboards/img/heatmap_chart_too_much_data_v_13_2.png create mode 100644 doc/operations/metrics/dashboards/img/heatmap_panel_type.png create mode 100644 doc/operations/metrics/dashboards/img/k8s_pod_health_dashboard_v13_3.png create mode 100644 doc/operations/metrics/dashboards/img/metrics_dashboard_annotations_ui_v13.0.png create mode 100644 doc/operations/metrics/dashboards/img/metrics_dashboard_panel_preview_v13_3.png create mode 100644 doc/operations/metrics/dashboards/img/metrics_dashboard_template_selection_v13_3.png create mode 100644 doc/operations/metrics/dashboards/img/metrics_dashboard_template_selection_web_ide_v13_3.png create mode 100644 doc/operations/metrics/dashboards/img/metrics_settings_button_v13_3.png create mode 100644 doc/operations/metrics/dashboards/img/panel_context_menu_v13_3.png create mode 100644 doc/operations/metrics/dashboards/img/prometheus_dashboard_anomaly_panel_type.png create mode 100644 doc/operations/metrics/dashboards/img/prometheus_dashboard_area_panel_type_v12_8.png create mode 100644 doc/operations/metrics/dashboards/img/prometheus_dashboard_bar_chart_panel_type_v12.10.png create mode 100644 doc/operations/metrics/dashboards/img/prometheus_dashboard_column_panel_type.png create mode 100644 doc/operations/metrics/dashboards/img/prometheus_dashboard_gauge_panel_type_v13_3.png create mode 100644 doc/operations/metrics/dashboards/img/prometheus_dashboard_label_variable_shorthand.png create mode 100644 doc/operations/metrics/dashboards/img/prometheus_dashboard_label_variables.png create mode 100644 doc/operations/metrics/dashboards/img/prometheus_dashboard_repeated_label.png create mode 100644 doc/operations/metrics/dashboards/img/prometheus_dashboard_single_stat_panel_type.png create mode 100644 doc/operations/metrics/dashboards/img/prometheus_dashboard_stacked_column_panel_type_v12_8.png create mode 100644 doc/operations/metrics/dashboards/img/prometheus_dashboard_yaml_validation_v13_1.png create mode 100644 doc/operations/metrics/dashboards/img/related_links_v13_1.png create mode 100644 doc/operations/metrics/dashboards/settings.md create mode 100644 doc/operations/metrics/img/copy_link_to_chart_v12_10.png create mode 100644 doc/operations/metrics/img/embed_metrics_issue_template.png create mode 100644 doc/operations/metrics/img/embedded_metrics_markdown_v12_8.png create mode 100644 doc/operations/metrics/img/embedded_metrics_rendered_v12_8.png delete mode 100644 doc/operations/metrics/img/example-dashboard_v13_1.png create mode 100644 doc/operations/metrics/img/example-dashboard_v13_3.png create mode 100644 doc/operations/metrics/img/grafana_embedded.png create mode 100644 doc/operations/metrics/img/grafana_live_embed.png create mode 100644 doc/operations/metrics/img/grafana_panel_v12_5.png create mode 100644 doc/operations/metrics/img/grafana_sharing_dialog_v12_5.png create mode 100644 doc/operations/metrics/img/hide_embedded_metrics_v12_10.png create mode 100644 doc/operations/metrics/img/http_proxy_access_v12_5.png create mode 100644 doc/operations/metrics/img/linked_runbooks_on_charts.png create mode 100644 doc/operations/metrics/img/prometheus_add_metric.png create mode 100644 doc/operations/metrics/img/prometheus_alert.png create mode 100644 doc/operations/metrics/img/prometheus_cluster_health_embed_v12_9.png create mode 100644 doc/operations/metrics/img/prometheus_dashboard_edit_metric_link_v_12_9.png create mode 100644 doc/operations/metrics/img/prometheus_monitoring_dashboard_v13_3.png create mode 100644 doc/operations/metrics/img/prometheus_service_alerts.png create mode 100644 doc/operations/metrics/img/rendered_grafana_embed_v12_5.png create mode 100644 doc/operations/metrics/img/select_query_variables_v12_5.png create mode 100644 doc/operations/metrics/img/view_embedded_metrics_v12_10.png create mode 100644 doc/operations/product_analytics.md create mode 100644 doc/raketasks/spdx.md create mode 100644 doc/security/passwords_for_integrated_authentication_methods.md create mode 100644 doc/topics/cron/index.md create mode 100644 doc/user/admin_area/settings/project_integration_management.md create mode 100644 doc/user/analytics/img/merge_request_analytics_v13_3.png create mode 100644 doc/user/analytics/img/new_value_stream_v13_3.png create mode 100644 doc/user/analytics/img/vsa_filter_bar_v13.3.png create mode 100644 doc/user/analytics/merge_request_analytics.md create mode 100644 doc/user/application_security/img/vulnerability_related_issues_add_button_v13_2.png create mode 100644 doc/user/application_security/img/vulnerability_related_issues_remove_v13_2.gif create mode 100644 doc/user/application_security/img/vulnerability_related_issues_text_box_tags_v13_2.gif delete mode 100644 doc/user/application_security/security_dashboard/img/group_security_dashboard_v13_2_noNav.png create mode 100644 doc/user/application_security/security_dashboard/img/group_security_dashboard_v13_3.png create mode 100644 doc/user/application_security/security_dashboard/img/group_vulnerability_report_v13_3.png create mode 100644 doc/user/application_security/security_dashboard/img/pipeline_security_v13_3.gif delete mode 100644 doc/user/application_security/security_dashboard/img/standalone_vulnerability_page_v13_1.png create mode 100644 doc/user/application_security/security_dashboard/img/vulnerability_page_v13_1.png delete mode 100644 doc/user/application_security/vulnerabilities/img/standalone_vulnerability_page_download_patch_button_v13_1.png delete mode 100644 doc/user/application_security/vulnerabilities/img/standalone_vulnerability_page_merge_request_button_dropdown_v13_1.png delete mode 100644 doc/user/application_security/vulnerabilities/img/standalone_vulnerability_page_merge_request_button_v13_1.png delete mode 100644 doc/user/application_security/vulnerabilities/img/standalone_vulnerability_page_v13_1.png create mode 100644 doc/user/application_security/vulnerabilities/img/vulnerability_page_download_patch_button_v13_1.png create mode 100644 doc/user/application_security/vulnerabilities/img/vulnerability_page_merge_request_button_dropdown_v13_1.png create mode 100644 doc/user/application_security/vulnerabilities/img/vulnerability_page_merge_request_button_v13_1.png create mode 100644 doc/user/application_security/vulnerabilities/img/vulnerability_page_v13_1.png delete mode 100644 doc/user/compliance/compliance_dashboard/img/compliance_dashboard_v13_2.png create mode 100644 doc/user/compliance/compliance_dashboard/img/compliance_dashboard_v13_3_1.png create mode 100644 doc/user/compliance/compliance_dashboard/img/failed_icon_v13_3.png create mode 100644 doc/user/compliance/compliance_dashboard/img/success_icon_v13_3.png create mode 100644 doc/user/compliance/compliance_dashboard/img/warning_icon_v13_3.png create mode 100644 doc/user/compliance/license_compliance/img/denied_licenses_v13_3.png delete mode 100644 doc/user/discussions/img/resolve_thread_button.png create mode 100644 doc/user/discussions/img/resolve_thread_button_v13_3.png delete mode 100644 doc/user/group/saml_sso/img/group_saml_settings.png create mode 100644 doc/user/group/saml_sso/img/group_saml_settings_v13_3.png delete mode 100644 doc/user/group/saml_sso/img/scim_token.png create mode 100644 doc/user/group/saml_sso/img/scim_token_v13_3.png create mode 100644 doc/user/img/completed_tasks_v13_3.png create mode 100644 doc/user/img/inline_diff_01_v13_3.png create mode 100644 doc/user/img/inline_diff_02_v13_3.png delete mode 100644 doc/user/incident_management/img/incident_management_settings.png delete mode 100644 doc/user/incident_management/img/pagerduty_incidents_integration_13_2.png delete mode 100644 doc/user/packages/img/package_activity_v12_10.png create mode 100644 doc/user/packages/package_registry/img/package_activity_v12_10.png create mode 100644 doc/user/packages/package_registry/index.md delete mode 100644 doc/user/project/clusters/img/sidebar_menu_pod_logs_v12_10.png create mode 100644 doc/user/project/img/code_intelligence_find_references_v13_3.png delete mode 100644 doc/user/project/img/status_page_detail_link_v13_1.png delete mode 100644 doc/user/project/img/status_page_detail_v12_10.png delete mode 100644 doc/user/project/img/status_page_incidents_v12_10.png delete mode 100644 doc/user/project/import/img/manifest_status.png create mode 100644 doc/user/project/import/img/manifest_status_v13_3.png delete mode 100644 doc/user/project/integrations/img/actions_menu_create_new_dashboard_v13_2.png delete mode 100644 doc/user/project/integrations/img/copy_link_to_chart_v12_10.png delete mode 100644 doc/user/project/integrations/img/embed_metrics_issue_template.png delete mode 100644 doc/user/project/integrations/img/embedded_metrics_markdown_v12_8.png delete mode 100644 doc/user/project/integrations/img/embedded_metrics_rendered_v12_8.png delete mode 100644 doc/user/project/integrations/img/grafana_embedded.png delete mode 100644 doc/user/project/integrations/img/grafana_live_embed.png delete mode 100644 doc/user/project/integrations/img/grafana_panel_v12_5.png delete mode 100644 doc/user/project/integrations/img/grafana_sharing_dialog_v12_5.png delete mode 100644 doc/user/project/integrations/img/heatmap_chart_too_much_data_v_13_2.png delete mode 100644 doc/user/project/integrations/img/heatmap_panel_type.png delete mode 100644 doc/user/project/integrations/img/hide_embedded_metrics_v12_10.png delete mode 100644 doc/user/project/integrations/img/http_proxy_access_v12_5.png delete mode 100644 doc/user/project/integrations/img/metrics_dashboard_annotations_ui_v13.0.png delete mode 100644 doc/user/project/integrations/img/metrics_settings_button_v13_2.png delete mode 100644 doc/user/project/integrations/img/panel_context_menu_v13_0.png create mode 100644 doc/user/project/integrations/img/project_integrations_v13_3.png delete mode 100644 doc/user/project/integrations/img/project_services.png delete mode 100644 doc/user/project/integrations/img/prometheus_add_metric.png delete mode 100644 doc/user/project/integrations/img/prometheus_alert.png delete mode 100644 doc/user/project/integrations/img/prometheus_cluster_health_embed_v12_9.png delete mode 100644 doc/user/project/integrations/img/prometheus_dashboard_anomaly_panel_type.png delete mode 100644 doc/user/project/integrations/img/prometheus_dashboard_area_panel_type_v12_8.png delete mode 100644 doc/user/project/integrations/img/prometheus_dashboard_bar_chart_panel_type_v12.10.png delete mode 100644 doc/user/project/integrations/img/prometheus_dashboard_column_panel_type.png delete mode 100644 doc/user/project/integrations/img/prometheus_dashboard_edit_metric_link_v_12_9.png delete mode 100644 doc/user/project/integrations/img/prometheus_dashboard_environments_v12_8.png delete mode 100644 doc/user/project/integrations/img/prometheus_dashboard_label_variable_shorthand.png delete mode 100644 doc/user/project/integrations/img/prometheus_dashboard_label_variables.png delete mode 100644 doc/user/project/integrations/img/prometheus_dashboard_repeated_label.png delete mode 100644 doc/user/project/integrations/img/prometheus_dashboard_select_v_13_0.png delete mode 100644 doc/user/project/integrations/img/prometheus_dashboard_single_stat_panel_type.png delete mode 100644 doc/user/project/integrations/img/prometheus_dashboard_stacked_column_panel_type_v12_8.png delete mode 100644 doc/user/project/integrations/img/prometheus_dashboard_yaml_validation_v13_1.png delete mode 100644 doc/user/project/integrations/img/prometheus_monitoring_dashboard_v13_1.png delete mode 100644 doc/user/project/integrations/img/prometheus_service_alerts.png delete mode 100644 doc/user/project/integrations/img/related_links_v13_1.png delete mode 100644 doc/user/project/integrations/img/rendered_grafana_embed_v12_5.png delete mode 100644 doc/user/project/integrations/img/select_query_variables_v12_5.png delete mode 100644 doc/user/project/integrations/img/view_embedded_metrics_v12_10.png create mode 100644 doc/user/project/integrations/jira_integrations.md delete mode 100644 doc/user/project/issues/img/design_management_upload_v13.2.png create mode 100644 doc/user/project/issues/img/design_management_upload_v13.3.png create mode 100644 doc/user/project/issues/img/designs_reordering_v13_3.gif delete mode 100644 doc/user/project/merge_requests/img/approvals_premium_mr_widget_v12_7.png create mode 100644 doc/user/project/merge_requests/img/approvals_premium_mr_widget_v13_3.png delete mode 100644 doc/user/project/merge_requests/img/approvals_premium_project_edit_v12_5.png delete mode 100644 doc/user/project/merge_requests/img/merge_request.png create mode 100644 doc/user/project/merge_requests/img/multiline-comment-highlighted.png create mode 100644 doc/user/project/merge_requests/img/multiline-comment-saved.png delete mode 100644 doc/user/project/operations/img/alert_detail_full_v13_1.png delete mode 100644 doc/user/project/operations/img/alert_detail_metrics_v13_2.png delete mode 100644 doc/user/project/operations/img/alert_detail_overview_v13_1.png delete mode 100644 doc/user/project/operations/img/alert_detail_system_notes_v13_1.png delete mode 100644 doc/user/project/operations/img/alert_details_assignees_v13_1.png delete mode 100644 doc/user/project/operations/img/alert_list_assignees_v13_1.png delete mode 100644 doc/user/project/operations/img/alert_list_search_v13_1.png delete mode 100644 doc/user/project/operations/img/alert_list_sort_v13_1.png delete mode 100644 doc/user/project/operations/img/alert_management_severity_v13_0.png delete mode 100644 doc/user/project/operations/img/alert_todo_assignees_v13_1.png delete mode 100644 doc/user/project/operations/img/dashboard_external_link_v13_1.png delete mode 100644 doc/user/project/operations/img/dashboard_local_timezone_v13_1.png delete mode 100644 doc/user/project/operations/img/error_details_v12_7.png delete mode 100644 doc/user/project/operations/img/error_details_with_issue_v12_8.png delete mode 100644 doc/user/project/operations/img/error_tracking_list_v12_6.png delete mode 100644 doc/user/project/operations/img/external_dashboard_link.png create mode 100644 doc/user/project/releases/img/deploy_freeze_v13_2.png delete mode 100644 doc/user/project/repository/img/forking_workflow_choose_namespace.png create mode 100644 doc/user/project/repository/img/forking_workflow_choose_namespace_v13_2.png delete mode 100644 doc/user/project/static_site_editor/img/wysiwyg_editor_v13_0.png create mode 100644 doc/user/project/static_site_editor/img/wysiwyg_editor_v13_3.png create mode 100644 doc/user/upgrade_email_bypass.md (limited to 'doc') diff --git a/doc/.vale/gitlab/Acronyms.yml b/doc/.vale/gitlab/Acronyms.yml index d166e71491c..c347c663bbf 100644 --- a/doc/.vale/gitlab/Acronyms.yml +++ b/doc/.vale/gitlab/Acronyms.yml @@ -68,6 +68,7 @@ exceptions: - SSH - SSL - SSO + - SVG - SVN - TCP - TIP diff --git a/doc/.vale/gitlab/AlertBoxStyle.yml b/doc/.vale/gitlab/AlertBoxStyle.yml index 831d5395fc8..8f9e444edc1 100644 --- a/doc/.vale/gitlab/AlertBoxStyle.yml +++ b/doc/.vale/gitlab/AlertBoxStyle.yml @@ -5,12 +5,12 @@ # # For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles extends: existence -message: 'Alert box "%s" must use the formatting detailed in the documentation style guide.' +message: 'Alert box "%s" must use the formatting in the style guide.' link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#alert-boxes level: error scope: raw raw: - '((NOTE|TIP|CAUTION|DANGER): \*\*[^:]*\*\*)|' - - '((NOTE: \*\*NOTE:\*\*)|(TIP: \*\*TIP:\*\*)|(CAUTION: \*\*CAUTION:\*\*)|(DANGER: \*\*DANGER:\*\*))|' - - '((NOTE: \*\*note:\*\*)|(TIP: \*\*tip:\*\*)|(CAUTION: \*\*caution:\*\*)|(DANGER: \*\*danger:\*\*))|' - - '((NOTE|TIP|CAUTION|DANGER): \*\*.*\*\*.+)' + - '((NOTE: \*\*(NOTE|note):\*\*)|(TIP: \*\*(TIP|tip):\*\*)|(CAUTION: \*\*(CAUTION|caution):\*\*)|(DANGER: \*\*(DANGER|danger):\*\*))|' + - '((NOTE|TIP|CAUTION|DANGER): \*\*.*\*\*.+)|' + - '((\n[> ]*(\*){1,2}(NOTE|Note|note|TIP|Tip|tip|CAUTION|Caution|caution|DANGER|Danger|danger):(\*){1,2}))' diff --git a/doc/.vale/gitlab/Contractions.yml b/doc/.vale/gitlab/Contractions.yml deleted file mode 100644 index dc48b876f40..00000000000 --- a/doc/.vale/gitlab/Contractions.yml +++ /dev/null @@ -1,45 +0,0 @@ ---- -# Suggestion: gitlab.Contractions -# -# Checks for use of common and uncommon contractions. -# -# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles -extends: substitution -message: 'Use "%s" instead of "%s", for a friendly, informal tone.' -link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#language -level: suggestion -nonword: false -ignorecase: true -swap: - - # Common contractions are ok - it is: it's - can not: can't - cannot: can't - do not: don't - have not: haven't - that is: that's - we are: we're - would not: wouldn't - you are: you're - you have: you've - - # Uncommon contractions are not ok - aren't: are not - couldn't: could not - didn't: did not - doesn't: does not - hasn't: has not - how's: how is - isn't: is not - shouldn't: should not - they're: they are - wasn't: was not - weren't: were not - we've: we have - what's: what is - when's: when is - where's: where is - who's: who is - why's: why is - diff --git a/doc/.vale/gitlab/ContractionsDiscard.yml b/doc/.vale/gitlab/ContractionsDiscard.yml new file mode 100644 index 00000000000..698fda86b5b --- /dev/null +++ b/doc/.vale/gitlab/ContractionsDiscard.yml @@ -0,0 +1,32 @@ +--- +# Suggestion: gitlab.ContractionsDiscard +# +# Suggests a list of agreed-upon contractions to discard. +# +# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles +extends: substitution +message: 'Use "%s" instead of "%s", for a friendly, informal tone.' +link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#language +level: suggestion +nonword: false +ignorecase: true +swap: + + # Uncommon contractions are not ok + aren't: are not + couldn't: could not + didn't: did not + doesn't: does not + hasn't: has not + how's: how is + isn't: is not + shouldn't: should not + they're: they are + wasn't: was not + weren't: were not + we've: we have + what's: what is + when's: when is + where's: where is + who's: who is + why's: why is diff --git a/doc/.vale/gitlab/ContractionsKeep.yml b/doc/.vale/gitlab/ContractionsKeep.yml new file mode 100644 index 00000000000..eeaf65e0829 --- /dev/null +++ b/doc/.vale/gitlab/ContractionsKeep.yml @@ -0,0 +1,25 @@ +--- +# Suggestion: gitlab.ContractionsKeep +# +# Suggests a list of agreed-upon contractions to keep. +# +# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles +extends: substitution +message: 'Use "%s" instead of "%s", for a friendly, informal tone.' +link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#language +level: suggestion +nonword: false +ignorecase: true +swap: + + # Common contractions are ok + it is: it's + can not: can't + cannot: can't + do not: don't + have not: haven't + that is: that's + we are: we're + would not: wouldn't + you are: you're + you have: you've diff --git a/doc/.vale/gitlab/FutureTense.yml b/doc/.vale/gitlab/FutureTense.yml index a53a7dd29cc..4a74ee87331 100644 --- a/doc/.vale/gitlab/FutureTense.yml +++ b/doc/.vale/gitlab/FutureTense.yml @@ -11,7 +11,7 @@ ignorecase: true level: warning link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#language-to-avoid raw: - - "(going to( |\n|[[:punct:]])[a-zA-Z]*|" - - "will( |\n|[[:punct:]])[a-zA-Z]*|" - - "won't( |\n|[[:punct:]])[a-zA-Z]*|" - - "[a-zA-Z]*'ll( |\n|[[:punct:]])[a-zA-Z]*)" + - "(going to( |\n|[[:punct:]])[a-zA-Z]*|" + - "will( |\n|[[:punct:]])[a-zA-Z]*|" + - "won't( |\n|[[:punct:]])[a-zA-Z]*|" + - "[a-zA-Z]*'ll( |\n|[[:punct:]])[a-zA-Z]*)" diff --git a/doc/.vale/gitlab/OutdatedVersions.yml b/doc/.vale/gitlab/OutdatedVersions.yml index 3252481a523..1bc0bf58f90 100644 --- a/doc/.vale/gitlab/OutdatedVersions.yml +++ b/doc/.vale/gitlab/OutdatedVersions.yml @@ -3,7 +3,7 @@ # # Checks for references to versions of GitLab that are no longer supported. # -# For a list of all options, see https://errata-ai.github.io/vale/styles/ +# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles extends: existence message: 'Can this reference to "%s" be refactored?' link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#importance-of-referencing-gitlab-versions-and-tiers diff --git a/doc/.vale/gitlab/spelling-exceptions.txt b/doc/.vale/gitlab/spelling-exceptions.txt index 28da80557ec..1301e8c4ca1 100644 --- a/doc/.vale/gitlab/spelling-exceptions.txt +++ b/doc/.vale/gitlab/spelling-exceptions.txt @@ -191,6 +191,7 @@ http https idempotence idmapper +inclusivity Ingress initializer initializers @@ -308,6 +309,8 @@ Piwik PgBouncer plaintext Poedit +polyfill +polyfills pooler PostgreSQL precompile @@ -330,6 +333,7 @@ profiler Prometheus proxied proxies +proxyable proxying pseudonymized pseudonymizer @@ -384,6 +388,7 @@ reverify Rubix Rubocop Rubular +ruleset runbook runbooks runit @@ -464,6 +469,7 @@ TypeScript Twilio Twitter Ubuntu +unapplied unarchive unarchived unarchives diff --git a/doc/README.md b/doc/README.md index 115026dae6e..b73300accab 100644 --- a/doc/README.md +++ b/doc/README.md @@ -50,12 +50,12 @@ Have a look at some of our most popular topics: ## The entire DevOps Lifecycle GitLab is the first single application for software development, security, -and operations that enables [Concurrent DevOps](https://about.gitlab.com/concurrent-devops/), +and operations that enables [Concurrent DevOps](https://about.gitlab.com/topics/concurrent-devops/), making the software lifecycle faster and radically improving the speed of business. GitLab provides solutions for [each of the stages of the DevOps lifecycle](https://about.gitlab.com/stages-devops-lifecycle/): -![DevOps Stages](img/devops-stages.png) +![DevOps Stages](img/devops-stages-13_3.png) GitLab is like a top-of-the-line kitchen for making software. As the executive chef, you decide what software you want to serve. Using your recipe, GitLab handles @@ -71,10 +71,11 @@ The following sections provide links to documentation for each DevOps stage: | [Create](#create) | Source code, data creation, and management features. | | [Verify](#verify) | Testing, code quality, and continuous integration features. | | [Package](#package) | Docker container registry. | +| [Secure](#secure) | Security capability features. | | [Release](#release) | Application release and delivery features. | | [Configure](#configure) | Application and infrastructure configuration tools. | | [Monitor](#monitor) | Application monitoring and metrics features. | -| [Secure](#secure) | Security capability features. | +| [Defend](#defend) | Protection against security intrusions. |
@@ -155,7 +156,8 @@ The following documentation relates to the DevOps **Create** stage: | [File locking](user/project/file_lock.md) **(PREMIUM)** | Lock files to avoid merge conflicts. | | [GitLab Pages](user/project/pages/index.md) | Build, test, and deploy your static website with GitLab Pages. | | [Groups](user/group/index.md) and [Subgroups](user/group/subgroups/index.md) | Organize your projects in groups. | -| [Issues Analytics](user/group/issues_analytics/index.md) **(PREMIUM)** | Check how many issues were created per month. | +| [Issue Analytics](user/group/issues_analytics/index.md) **(PREMIUM)** | Check how many issues were created per month. | +| [Merge Request Analytics](user/analytics/merge_request_analytics.md) **(PREMIUM)** | Check your throughput productivity - how many merge requests were merged per month. | | [Projects](user/project/index.md), including [project access](public_access/public_access.md)
and [settings](user/project/settings/index.md) | Host source code, and control your project's visibility and set configuration. | | [Search through GitLab](user/search/index.md) | Search for issues, merge requests, projects, groups, and todos. | | [Snippets](user/snippets.md) | Snippets allow you to create little bits of code. | @@ -212,7 +214,8 @@ The following documentation relates to the DevOps **Create** stage: | Create topics - Integration and Automation | Description | |:------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------| -| [GitLab API](api/README.md) | Integrate GitLab via a simple and powerful API. | +| [GitLab REST API](api/README.md) | Integrate with GitLab using our REST API. | +| [GitLab GraphQL API](api/graphql/index.md) | Integrate with GitLab using our GraphQL API. | | [GitLab Integration](integration/README.md) | Integrate with multiple third-party services with GitLab to allow external issue trackers and external authentication. | | [GitLab Webhooks](user/project/integrations/webhooks.md) | Let GitLab notify you when new code has been pushed to your project. | | [Jira Development Panel](integration/jira_development_panel.md) **(PREMIUM)** | See GitLab information in the Jira Development Panel. | @@ -264,9 +267,9 @@ The following documentation relates to the DevOps **Package** stage: |:----------------------------------------------------------------|:-------------------------------------------------------| | [Container Registry](user/packages/container_registry/index.md) | The GitLab Container Registry enables every project in GitLab to have its own space to store [Docker](https://www.docker.com/) images. | | [Dependency Proxy](user/packages/dependency_proxy/index.md) **(PREMIUM)** | The GitLab Dependency Proxy sets up a local proxy for frequently used upstream images/packages. | -| [Conan Repository](user/packages/conan_repository/index.md) **(PREMIUM)** | The GitLab Conan Repository enables every project in GitLab to have its own space to store [Conan](https://conan.io/) packages. | -| [Maven Repository](user/packages/maven_repository/index.md) **(PREMIUM)** | The GitLab Maven Repository enables every project in GitLab to have its own space to store [Maven](https://maven.apache.org/) packages. | -| [NPM Registry](user/packages/npm_registry/index.md) **(PREMIUM)** | The GitLab NPM Registry enables every project in GitLab to have its own space to store [NPM](https://www.npmjs.com/) packages. | +| [Conan Repository](user/packages/conan_repository/index.md) | The GitLab Conan Repository enables every project in GitLab to have its own space to store [Conan](https://conan.io/) packages. | +| [Maven Repository](user/packages/maven_repository/index.md) | The GitLab Maven Repository enables every project in GitLab to have its own space to store [Maven](https://maven.apache.org/) packages. | +| [NPM Registry](user/packages/npm_registry/index.md) | The GitLab NPM Registry enables every project in GitLab to have its own space to store [NPM](https://www.npmjs.com/) packages. |
@@ -274,6 +277,30 @@ The following documentation relates to the DevOps **Package** stage:
+### Secure + +Check your application for security vulnerabilities that may lead to unauthorized access, data +leaks, or denial of service. GitLab can perform static and dynamic tests on your application's code, +looking for known flaws and reporting them in the merge request. You can then fix flaws prior to +merge. Security teams can use dashboards to get a high-level view on projects and groups, and start +remediation processes when needed. + +The following documentation relates to the DevOps **Secure** stage: + +| Secure topics | Description | +|:------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------| +| [Compliance Dashboard](user/compliance/compliance_dashboard/index.md) **(ULTIMATE)** | View the most recent Merge Request activity in a group. | +| [Container Scanning](user/application_security/container_scanning/index.md) **(ULTIMATE)** | Use Clair to scan Docker images for known vulnerabilities. | +| [Dependency List](user/application_security/dependency_list/index.md) **(ULTIMATE)** | View your project's dependencies and their known vulnerabilities. | +| [Dependency Scanning](user/application_security/dependency_scanning/index.md) **(ULTIMATE)** | Analyze your dependencies for known vulnerabilities. | +| [Dynamic Application Security Testing (DAST)](user/application_security/dast/index.md) **(ULTIMATE)** | Analyze running web applications for known vulnerabilities. | +| [Group Security Dashboard](user/application_security/security_dashboard/index.md#group-security-dashboard) **(ULTIMATE)** | View vulnerabilities in all the projects in a group and its subgroups. | +| [Instance Security Dashboard](user/application_security/security_dashboard/index.md#instance-security-dashboard) **(ULTIMATE)** | View vulnerabilities in all the projects you're interested in. | +| [License Compliance](user/compliance/license_compliance/index.md) **(ULTIMATE)** | Search your project's dependencies for their licenses. | +| [Pipeline Security](user/application_security/security_dashboard/index.md#pipeline-security) **(ULTIMATE)** | View the security reports for your project's pipelines. | +| [Project Security Dashboard](user/application_security/security_dashboard/index.md#project-security-dashboard) **(ULTIMATE)** | View the latest security reports for your project. | +| [Static Application Security Testing (SAST)](user/application_security/sast/index.md) **(ULTIMATE)** | Analyze source code for known vulnerabilities. | + ### Release Spend less time configuring your tools, and more time creating. Whether you’re @@ -344,7 +371,7 @@ The following documentation relates to the DevOps **Monitor** stage: | [Health check](user/admin_area/monitoring/health_check.md) | GitLab provides liveness and readiness probes to indicate service health and reachability to required services. | | [Prometheus project integration](user/project/integrations/prometheus.md) | Configure the Prometheus integration per project and monitor your CI/CD environments. | | [Prometheus metrics](user/project/integrations/prometheus_library/index.md) | Let Prometheus collect metrics from various services, like Kubernetes, NGINX, NGINX Ingress controller, HAProxy, and Amazon Cloud Watch. | -| [Incident management](user/incident_management/index.md) | Use GitLab to help you better respond to incidents that may occur in your systems. | +| [Incident management](operations/incident_management/index.md) | Use GitLab to help you better respond to incidents that may occur in your systems. |
@@ -352,29 +379,22 @@ The following documentation relates to the DevOps **Monitor** stage:
-### Secure +### Defend -Check your application for security vulnerabilities that may lead to unauthorized access, -data leaks, and denial of services. GitLab will perform static and dynamic tests on the -code of your application, looking for known flaws and report them in the merge request -so you can fix them before merging. Security teams can use dashboards to get a -high-level view on projects and groups, and start remediation processes when needed. +GitLab Defend enables organizations to proactively protect cloud-native environments by providing +context-aware technologies to reduce overall security risk. Defend is a natural extension of your +existing operation's practices and provides security visibility across the entire DevSecOps +lifecycle. This visibility empowers your organization to apply DevSecOps best practices from the +first line of code written and extends all the way through to greater monitoring and protection for +your applications that are deployed in production. -The following documentation relates to the DevOps **Secure** stage: +The following documentation relates to the DevOps **Defend** stage: -| Secure topics | Description | +| Defend topics | Description | |:------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------| -| [Compliance Dashboard](user/compliance/compliance_dashboard/index.md) **(ULTIMATE)** | View the most recent Merge Request activity in a group. | -| [Container Scanning](user/application_security/container_scanning/index.md) **(ULTIMATE)** | Use Clair to scan Docker images for known vulnerabilities. | -| [Dependency List](user/application_security/dependency_list/index.md) **(ULTIMATE)** | View your project's dependencies and their known vulnerabilities. | -| [Dependency Scanning](user/application_security/dependency_scanning/index.md) **(ULTIMATE)** | Analyze your dependencies for known vulnerabilities. | -| [Dynamic Application Security Testing (DAST)](user/application_security/dast/index.md) **(ULTIMATE)** | Analyze running web applications for known vulnerabilities. | -| [Group Security Dashboard](user/application_security/security_dashboard/index.md#group-security-dashboard) **(ULTIMATE)** | View vulnerabilities in all the projects in a group and its subgroups. | -| [Instance Security Dashboard](user/application_security/security_dashboard/index.md#instance-security-dashboard) **(ULTIMATE)** | View vulnerabilities in all the projects you're interested in. | -| [License Compliance](user/compliance/license_compliance/index.md) **(ULTIMATE)** | Search your project's dependencies for their licenses. | -| [Pipeline Security](user/application_security/security_dashboard/index.md#pipeline-security) **(ULTIMATE)** | View the security reports for your project's pipelines. | -| [Project Security Dashboard](user/application_security/security_dashboard/index.md#project-security-dashboard) **(ULTIMATE)** | View the latest security reports for your project. | -| [Static Application Security Testing (SAST)](user/application_security/sast/index.md) **(ULTIMATE)** | Analyze source code for known vulnerabilities. | +| [Web Application Firewall with ModSecurity](user/compliance/compliance_dashboard/index.md) | Filter, monitor, and block HTTP traffic to and from a web application. | +| [Container Host Security](user/clusters/applications.md#install-falco-using-gitlab-cicd) | Detect and respond to security threats at the Kubernetes, network, and host level. | +| [Container Network Security](user/clusters/applications.md#install-cilium-using-gitlab-cicd) | Detect and block unauthorized network traffic between pods and to/from the internet.| ## New to Git and GitLab? @@ -450,7 +470,8 @@ There are many ways to integrate with GitLab, including: | Topic | Description | |:-----------------------------------------------------------|:------------------------------------------------| -| [GitLab API](api/README.md) | Integrate GitLab via a simple and powerful API. | +| [GitLab REST API](api/README.md) | Integrate with GitLab using our REST API. | +| [GitLab GraphQL API](api/graphql/index.md) | Integrate with GitLab using our GraphQL API. | | [Integrations and automation](#integration-and-automation) | All GitLab integration and automation options. |
diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md index c85fb2d2e47..e7eab5a291e 100644 --- a/doc/administration/audit_events.md +++ b/doc/administration/audit_events.md @@ -1,6 +1,6 @@ --- stage: Manage -group: Analytics +group: Compliance info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers --- @@ -48,24 +48,25 @@ You need Owner [permissions](../user/permissions.md) to view the group Audit Eve To view a group's audit events, navigate to **Group > Settings > Audit Events**. From there, you can see the following actions: -- Group name or path changed -- Group repository size limit changed -- Group created or deleted -- Group changed visibility -- User was added to group and with which [permissions](../user/permissions.md) -- User sign-in via [Group SAML](../user/group/saml_sso/index.md) -- Permissions changes of a user assigned to a group -- Removed user from group -- Project repository imported into group +- Group name or path changed. +- Group repository size limit changed. +- Group created or deleted. +- Group changed visibility. +- User was added to group and with which [permissions](../user/permissions.md). +- User sign-in via [Group SAML](../user/group/saml_sso/index.md). +- Permissions changes of a user assigned to a group. +- Removed user from group. +- Project repository imported into group. - [Project shared with group](../user/project/members/share_project_with_groups.md) - and with which [permissions](../user/permissions.md) -- Removal of a previously shared group with a project -- LFS enabled or disabled -- Shared runners minutes limit changed -- Membership lock enabled or disabled -- Request access enabled or disabled -- 2FA enforcement or grace period changed -- Roles allowed to create project changed + and with which [permissions](../user/permissions.md). +- Removal of a previously shared group with a project. +- LFS enabled or disabled. +- Shared runners minutes limit changed. +- Membership lock enabled or disabled. +- Request access enabled or disabled. +- 2FA enforcement or grace period changed. +- Roles allowed to create project changed. +- Group CI/CD variable added, removed, or protected status changed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30857) in GitLab 13.3. Group events can also be accessed via the [Group Audit Events API](../api/audit_events.md#group-audit-events-starter) diff --git a/doc/administration/audit_reports.md b/doc/administration/audit_reports.md new file mode 100644 index 00000000000..d5a08b711be --- /dev/null +++ b/doc/administration/audit_reports.md @@ -0,0 +1,31 @@ +--- +stage: Manage +group: Compliance +description: 'Learn how to create evidence artifacts typically requested by a 3rd party auditor.' +--- + +# Audit Reports + +GitLab can help owners and administrators respond to auditors by generating +comprehensive reports. These **Audit Reports** vary in scope, depending on the +need: + +## Use cases + +- Generate a report of audit events to provide to an external auditor requesting proof of certain logging capabilities. +- Provide a report of all users showing their group and project memberships for a quarterly access review so the auditor can verify compliance with an organization's access management policy. + +## APIs + +- `https://docs.gitlab.com/ee/api/audit_events.html` +- `https://docs.gitlab.com/ee/api/graphql/reference/#user` +- `https://docs.gitlab.com/ee/api/graphql/reference/#groupmember` +- `https://docs.gitlab.com/ee/api/graphql/reference/#projectmember` + +## Features + +- `https://docs.gitlab.com/ee/administration/audit_events.html` +- `https://docs.gitlab.com/ee/administration/logs.html` + +We plan on making Audit Events [downloadable as a CSV](https://gitlab.com/gitlab-org/gitlab/-/issues/1449) +in the near future. diff --git a/doc/administration/auth/ldap/index.md b/doc/administration/auth/ldap/index.md index aef6c70ff92..548e734c931 100644 --- a/doc/administration/auth/ldap/index.md +++ b/doc/administration/auth/ldap/index.md @@ -548,7 +548,7 @@ or more LDAP group links](#adding-group-links-starter-only). ### Adding group links **(STARTER ONLY)** -For information on adding group links via CNs and filters, refer to [the GitLab groups documentation](../../../user/group/index.md#manage-group-memberships-via-ldap). +For information on adding group links via CNs and filters, refer to [the GitLab groups documentation](../../../user/group/index.md#manage-group-memberships-via-ldap-starter-only). ### Administrator sync **(STARTER ONLY)** @@ -596,6 +596,8 @@ group, as opposed to the full DN. ### Global group memberships lock **(STARTER ONLY)** +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1793) in GitLab 12.0. + "Lock memberships to LDAP synchronization" setting allows instance administrators to lock down user abilities to invite new members to a group. diff --git a/doc/administration/auth/okta.md b/doc/administration/auth/okta.md index 78b10aedb77..7a55e127733 100644 --- a/doc/administration/auth/okta.md +++ b/doc/administration/auth/okta.md @@ -156,7 +156,7 @@ You might want to try this out on an incognito browser window. ## Configuring groups ->**Note:** +NOTE: **Note:** Make sure the groups exist and are assigned to the Okta app. You can take a look of the [SAML documentation](../../integration/saml.md#saml-groups) on configuring groups. diff --git a/doc/administration/auth/smartcard.md b/doc/administration/auth/smartcard.md index 80d2efbad84..0ecf3ca090d 100644 --- a/doc/administration/auth/smartcard.md +++ b/doc/administration/auth/smartcard.md @@ -310,6 +310,10 @@ attribute. As a prerequisite, you must use an LDAP server that: 1. Save the file and [restart](../restart_gitlab.md#installations-from-source) GitLab for the changes to take effect. +## Passwords for users created via smartcard authentication + +The [Generated passwords for users created through integrated authentication](../../security/passwords_for_integrated_authentication_methods.md) guide provides an overview of how GitLab generates and sets passwords for users created via smartcard authentication. + +This document was moved to [another location](../gitaly/index.md). diff --git a/doc/administration/high_availability/gitlab.md b/doc/administration/high_availability/gitlab.md index dc8c997bab5..748373c8941 100644 --- a/doc/administration/high_availability/gitlab.md +++ b/doc/administration/high_availability/gitlab.md @@ -1,215 +1,5 @@ --- -type: reference +redirect_to: ../reference_architectures/index.md --- -# Configuring GitLab application (Rails) - -This section describes how to configure the GitLab application (Rails) component. - -NOTE: **Note:** -There is some additional configuration near the bottom for -additional GitLab application servers. It's important to read and understand -these additional steps before proceeding with GitLab installation. - -NOTE: **Note:** -[Cloud Object Storage service](object_storage.md) with [Gitaly](gitaly.md) -is recommended over [NFS](nfs.md) wherever possible for improved performance. - -1. If necessary, install the NFS client utility packages using the following - commands: - - ```shell - # Ubuntu/Debian - apt-get install nfs-common - - # CentOS/Red Hat - yum install nfs-utils nfs-utils-lib - ``` - -1. Specify the necessary NFS exports in `/etc/fstab`. - The exact contents of `/etc/fstab` will depend on how you chose - to configure your NFS server. See [NFS documentation](nfs.md#nfs-client-mount-options) - for examples and the various options. - -1. Create the shared directories. These may be different depending on your NFS - mount locations. - - ```shell - mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data - ``` - -1. Download/install Omnibus GitLab using **steps 1 and 2** from - [GitLab downloads](https://about.gitlab.com/install/). Do not complete other - steps on the download page. -1. Create/edit `/etc/gitlab/gitlab.rb` and use the following configuration. - Be sure to change the `external_url` to match your eventual GitLab front-end - URL. Depending your the NFS configuration, you may need to change some GitLab - data locations. See [NFS documentation](nfs.md) for `/etc/gitlab/gitlab.rb` - configuration values for various scenarios. The example below assumes you've - added NFS mounts in the default data locations. Additionally the UID and GIDs - given are just examples and you should configure with your preferred values. - - ```ruby - external_url 'https://gitlab.example.com' - - # Prevent GitLab from starting if NFS data mounts are not available - high_availability['mountpoint'] = '/var/opt/gitlab/git-data' - - # Disable components that will not be on the GitLab application server - roles ['application_role'] - nginx['enable'] = true - - # PostgreSQL connection details - gitlab_rails['db_adapter'] = 'postgresql' - gitlab_rails['db_encoding'] = 'unicode' - gitlab_rails['db_host'] = '10.1.0.5' # IP/hostname of database server - gitlab_rails['db_password'] = 'DB password' - - # Redis connection details - gitlab_rails['redis_port'] = '6379' - gitlab_rails['redis_host'] = '10.1.0.6' # IP/hostname of Redis server - gitlab_rails['redis_password'] = 'Redis Password' - - # Ensure UIDs and GIDs match between servers for permissions via NFS - user['uid'] = 9000 - user['gid'] = 9000 - web_server['uid'] = 9001 - web_server['gid'] = 9001 - registry['uid'] = 9002 - registry['gid'] = 9002 - ``` - -1. [Enable monitoring](#enable-monitoring) - - NOTE: **Note:** - To maintain uniformity of links across HA clusters, the `external_url` - on the first application server as well as the additional application - servers should point to the external URL that users will use to access GitLab. - In a typical HA setup, this will be the URL of the load balancer which will - route traffic to all GitLab application servers in the HA cluster. - - NOTE: **Note:** - When you specify `https` in the `external_url`, as in the example - above, GitLab assumes you have SSL certificates in `/etc/gitlab/ssl/`. If - certificates are not present, NGINX will fail to start. See - [NGINX documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https) - for more information. - - NOTE: **Note:** - It is best to set the `uid` and `gid`s prior to the initial reconfigure - of GitLab. Omnibus will not recursively `chown` directories if set after the initial reconfigure. - -## First GitLab application server - -On the first application server, run: - -```shell -sudo gitlab-ctl reconfigure -``` - -This should compile the configuration and initialize the database. Do -not run this on additional application servers until the next step. - -## Extra configuration for additional GitLab application servers - -Additional GitLab servers (servers configured **after** the first GitLab server) -need some extra configuration. - -1. Configure shared secrets. These values can be obtained from the primary - GitLab server in `/etc/gitlab/gitlab-secrets.json`. Copy this file to the - secondary servers **prior to** running the first `reconfigure` in the steps - above. - - ```ruby - gitlab_shell['secret_token'] = 'fbfb19c355066a9afb030992231c4a363357f77345edd0f2e772359e5be59b02538e1fa6cae8f93f7d23355341cea2b93600dab6d6c3edcdced558fc6d739860' - gitlab_rails['otp_key_base'] = 'b719fe119132c7810908bba18315259ed12888d4f5ee5430c42a776d840a396799b0a5ef0a801348c8a357f07aa72bbd58e25a84b8f247a25c72f539c7a6c5fa' - gitlab_rails['secret_key_base'] = '6e657410d57c71b4fc3ed0d694e7842b1895a8b401d812c17fe61caf95b48a6d703cb53c112bc01ebd197a85da81b18e29682040e99b4f26594772a4a2c98c6d' - gitlab_rails['db_key_base'] = 'bf2e47b68d6cafaef1d767e628b619365becf27571e10f196f98dc85e7771042b9203199d39aff91fcb6837c8ed83f2a912b278da50999bb11a2fbc0fba52964' - ``` - -1. Run `touch /etc/gitlab/skip-auto-reconfigure` to prevent database migrations - from running on upgrade. Only the primary GitLab application server should - handle migrations. - -1. **Recommended** Configure host keys. Copy the contents (private and public keys) of `/etc/ssh/` on - the primary application server to `/etc/ssh` on all secondary servers. This - prevents false man-in-the-middle-attack alerts when accessing servers in your - High Availability cluster behind a load balancer. - -1. Run `sudo gitlab-ctl reconfigure` to compile the configuration. - -NOTE: **Note:** -You will need to restart the GitLab applications nodes after an update has occurred and database -migrations performed. - -## Enable Monitoring - -> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3786) in GitLab 12.0. - -If you enable Monitoring, it must be enabled on **all** GitLab servers. - -1. Make sure to collect [`CONSUL_SERVER_NODES`](../postgresql/replication_and_failover.md#consul-information), which are the IP addresses or DNS records of the Consul server nodes, for the next step. Note they are presented as `Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z` - -1. Create/edit `/etc/gitlab/gitlab.rb` and add the following configuration: - - ```ruby - # Enable service discovery for Prometheus - consul['enable'] = true - consul['monitoring_service_discovery'] = true - - # Replace placeholders - # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z - # with the addresses of the Consul server nodes - consul['configuration'] = { - retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z), - } - - # Set the network addresses that the exporters will listen on - node_exporter['listen_address'] = '0.0.0.0:9100' - gitlab_workhorse['prometheus_listen_addr'] = '0.0.0.0:9229' - sidekiq['listen_address'] = "0.0.0.0" - puma['listen'] = '0.0.0.0' - - # Add the monitoring node's IP address to the monitoring whitelist and allow it to - # scrape the NGINX metrics. Replace placeholder `monitoring.gitlab.example.com` with - # the address and/or subnets gathered from the monitoring node(s). - gitlab_rails['monitoring_whitelist'] = ['monitoring.gitlab.example.com', '127.0.0.0/8'] - nginx['status']['options']['allow'] = ['monitoring.gitlab.example.com', '127.0.0.0/8'] - ``` - -1. Run `sudo gitlab-ctl reconfigure` to compile the configuration. - - CAUTION: **Warning:** - If running Unicorn, after changing `unicorn['listen']` in `gitlab.rb`, and - running `sudo gitlab-ctl reconfigure`, it can take an extended period of time - for Unicorn to complete reloading after receiving a `HUP`. For more - information, see the - [issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4401). - -## Troubleshooting - -- `mount: wrong fs type, bad option, bad superblock on` - -You have not installed the necessary NFS client utilities. See step 1 above. - -- `mount: mount point /var/opt/gitlab/... does not exist` - -This particular directory does not exist on the NFS server. Ensure -the share is exported and exists on the NFS server and try to remount. - ---- - -## Upgrading GitLab HA - -GitLab HA installations can be upgraded with no downtime, but the -upgrade process must be carefully coordinated to avoid failures. See the -[Omnibus GitLab multi-node upgrade -document](https://docs.gitlab.com/omnibus/update/#multi-node--ha-deployment) -for more details. - -Read more on high-availability configuration: - -1. [Configure the database](../postgresql/replication_and_failover.md) -1. [Configure Redis](redis.md) -1. [Configure NFS](nfs.md) -1. [Configure the load balancers](load_balancer.md) +This document was moved to [another location](../reference_architectures/index.md). diff --git a/doc/administration/high_availability/load_balancer.md b/doc/administration/high_availability/load_balancer.md index 75703327140..5cedc4e11ae 100644 --- a/doc/administration/high_availability/load_balancer.md +++ b/doc/administration/high_availability/load_balancer.md @@ -1,135 +1,5 @@ --- -type: reference +redirect_to: ../load_balancer.md --- -# Load Balancer for multi-node GitLab - -In an multi-node GitLab configuration, you will need a load balancer to route -traffic to the application servers. The specifics on which load balancer to use -or the exact configuration is beyond the scope of GitLab documentation. We hope -that if you're managing HA systems like GitLab you have a load balancer of -choice already. Some examples including HAProxy (open-source), F5 Big-IP LTM, -and Citrix Net Scaler. This documentation will outline what ports and protocols -you need to use with GitLab. - -## SSL - -How will you handle SSL in your multi-node environment? There are several different -options: - -- Each application node terminates SSL -- The load balancer(s) terminate SSL and communication is not secure between - the load balancer(s) and the application nodes -- The load balancer(s) terminate SSL and communication is *secure* between the - load balancer(s) and the application nodes - -### Application nodes terminate SSL - -Configure your load balancer(s) to pass connections on port 443 as 'TCP' rather -than 'HTTP(S)' protocol. This will pass the connection to the application nodes -NGINX service untouched. NGINX will have the SSL certificate and listen on port 443. - -See [NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https) -for details on managing SSL certificates and configuring NGINX. - -### Load Balancer(s) terminate SSL without backend SSL - -Configure your load balancer(s) to use the 'HTTP(S)' protocol rather than 'TCP'. -The load balancer(s) will then be responsible for managing SSL certificates and -terminating SSL. - -Since communication between the load balancer(s) and GitLab will not be secure, -there is some additional configuration needed. See -[NGINX Proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#supporting-proxied-ssl) -for details. - -### Load Balancer(s) terminate SSL with backend SSL - -Configure your load balancer(s) to use the 'HTTP(S)' protocol rather than 'TCP'. -The load balancer(s) will be responsible for managing SSL certificates that -end users will see. - -Traffic will also be secure between the load balancer(s) and NGINX in this -scenario. There is no need to add configuration for proxied SSL since the -connection will be secure all the way. However, configuration will need to be -added to GitLab to configure SSL certificates. See -[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https) -for details on managing SSL certificates and configuring NGINX. - -## Ports - -### Basic ports - -| LB Port | Backend Port | Protocol | -| ------- | ------------ | ------------------------ | -| 80 | 80 | HTTP (*1*) | -| 443 | 443 | TCP or HTTPS (*1*) (*2*) | -| 22 | 22 | TCP | - -- (*1*): [Web terminal](../../ci/environments/index.md#web-terminals) support requires - your load balancer to correctly handle WebSocket connections. When using - HTTP or HTTPS proxying, this means your load balancer must be configured - to pass through the `Connection` and `Upgrade` hop-by-hop headers. See the - [web terminal](../integration/terminal.md) integration guide for - more details. -- (*2*): When using HTTPS protocol for port 443, you will need to add an SSL - certificate to the load balancers. If you wish to terminate SSL at the - GitLab application server instead, use TCP protocol. - -### GitLab Pages Ports - -If you're using GitLab Pages with custom domain support you will need some -additional port configurations. -GitLab Pages requires a separate virtual IP address. Configure DNS to point the -`pages_external_url` from `/etc/gitlab/gitlab.rb` at the new virtual IP address. See the -[GitLab Pages documentation](../pages/index.md) for more information. - -| LB Port | Backend Port | Protocol | -| ------- | ------------- | --------- | -| 80 | Varies (*1*) | HTTP | -| 443 | Varies (*1*) | TCP (*2*) | - -- (*1*): The backend port for GitLab Pages depends on the - `gitlab_pages['external_http']` and `gitlab_pages['external_https']` - setting. See [GitLab Pages documentation](../pages/index.md) for more details. -- (*2*): Port 443 for GitLab Pages should always use the TCP protocol. Users can - configure custom domains with custom SSL, which would not be possible - if SSL was terminated at the load balancer. - -### Alternate SSH Port - -Some organizations have policies against opening SSH port 22. In this case, -it may be helpful to configure an alternate SSH hostname that allows users -to use SSH on port 443. An alternate SSH hostname will require a new virtual IP address -compared to the other GitLab HTTP configuration above. - -Configure DNS for an alternate SSH hostname such as `altssh.gitlab.example.com`. - -| LB Port | Backend Port | Protocol | -| ------- | ------------ | -------- | -| 443 | 22 | TCP | - -## Readiness check - -It is strongly recommend that multi-node deployments configure load balancers to utilize the [readiness check](../../user/admin_area/monitoring/health_check.md#readiness) to ensure a node is ready to accept traffic, before routing traffic to it. This is especially important when utilizing Puma, as there is a brief period during a restart where Puma will not accept requests. - ---- - -Read more on high-availability configuration: - -1. [Configure the database](../postgresql/replication_and_failover.md) -1. [Configure Redis](redis.md) -1. [Configure NFS](nfs.md) -1. [Configure the GitLab application servers](gitlab.md) - - +This document was moved to [another location](../load_balancer.md). diff --git a/doc/administration/high_availability/monitoring_node.md b/doc/administration/high_availability/monitoring_node.md index 6b6f0ae9ea3..76bcf6d0d40 100644 --- a/doc/administration/high_availability/monitoring_node.md +++ b/doc/administration/high_availability/monitoring_node.md @@ -1,104 +1,5 @@ --- -type: reference +redirect_to: ../monitoring/prometheus/index.md --- -# Configuring a Monitoring node for Scaling and High Availability - -> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3786) in GitLab 12.0. - -You can configure a Prometheus node to monitor GitLab. - -## Standalone Monitoring node using Omnibus GitLab - -The Omnibus GitLab package can be used to configure a standalone Monitoring node running [Prometheus](../monitoring/prometheus/index.md) and [Grafana](../monitoring/performance/grafana_configuration.md). -The monitoring node is not highly available. See [Scaling and High Availability](../reference_architectures/index.md) -for an overview of GitLab scaling and high availability options. - -The steps below are the minimum necessary to configure a Monitoring node running Prometheus and Grafana with -Omnibus: - -1. SSH into the Monitoring node. -1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab - package you want using **steps 1 and 2** from the GitLab downloads page. - - Do not complete any other steps on the download page. - -1. Make sure to collect [`CONSUL_SERVER_NODES`](../postgresql/replication_and_failover.md#consul-information), which are the IP addresses or DNS records of the Consul server nodes, for the next step. Note they are presented as `Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z` - -1. Edit `/etc/gitlab/gitlab.rb` and add the contents: - - ```ruby - external_url 'http://gitlab.example.com' - - # Enable Prometheus - prometheus['enable'] = true - prometheus['listen_address'] = '0.0.0.0:9090' - prometheus['monitor_kubernetes'] = false - - # Enable Login form - grafana['disable_login_form'] = false - - # Enable Grafana - grafana['enable'] = true - grafana['admin_password'] = 'toomanysecrets' - - # Enable service discovery for Prometheus - consul['enable'] = true - consul['monitoring_service_discovery'] = true - - # Replace placeholders - # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z - # with the addresses of the Consul server nodes - consul['configuration'] = { - retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z), - } - - # Disable all other services - gitlab_rails['auto_migrate'] = false - alertmanager['enable'] = false - gitaly['enable'] = false - gitlab_exporter['enable'] = false - gitlab_workhorse['enable'] = false - nginx['enable'] = true - postgres_exporter['enable'] = false - postgresql['enable'] = false - redis['enable'] = false - redis_exporter['enable'] = false - sidekiq['enable'] = false - puma['enable'] = false - node_exporter['enable'] = false - gitlab_exporter['enable'] = false - ``` - -1. Run `sudo gitlab-ctl reconfigure` to compile the configuration. - -The next step is to tell all the other nodes where the monitoring node is: - -1. Edit `/etc/gitlab/gitlab.rb`, and add, or find and uncomment the following line: - - ```ruby - gitlab_rails['prometheus_address'] = '10.0.0.1:9090' - ``` - - Where `10.0.0.1:9090` is the IP address and port of the Prometheus node. - -1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to - take effect. - -## Migrating to Service Discovery - -Once monitoring using Service Discovery is enabled with `consul['monitoring_service_discovery'] = true`, -ensure that `prometheus['scrape_configs']` is not set in `/etc/gitlab/gitlab.rb`. Setting both -`consul['monitoring_service_discovery'] = true` and `prometheus['scrape_configs']` in `/etc/gitlab/gitlab.rb` -will result in errors. - - +This document was moved to [another location](../monitoring/prometheus/index.md). diff --git a/doc/administration/high_availability/nfs.md b/doc/administration/high_availability/nfs.md index 6e8dc2c6c57..e3342fa0813 100644 --- a/doc/administration/high_availability/nfs.md +++ b/doc/administration/high_availability/nfs.md @@ -1,322 +1,5 @@ --- -type: reference +redirect_to: ../nfs.md --- -# NFS - -You can view information and options set for each of the mounted NFS file -systems by running `nfsstat -m` and `cat /etc/fstab`. - -CAUTION: **Caution:** -From GitLab 13.0, using NFS for Git repositories is deprecated. In GitLab 14.0, -support for NFS for Git repositories is scheduled to be removed. Upgrade to -[Gitaly Cluster](../gitaly/praefect.md) as soon as possible. - -NOTE: **Note:** -Filesystem performance has a big impact on overall GitLab -performance, especially for actions that read or write to Git repositories. See -[Filesystem Performance Benchmarking](../operations/filesystem_benchmarking.md) -for steps to test filesystem performance. - -## Known kernel version incompatibilities - -RedHat Enterprise Linux (RHEL) and CentOS v7.7 and v7.8 ship with kernel -version `3.10.0-1127`, which [contains a -bug](https://bugzilla.redhat.com/show_bug.cgi?id=1783554) that causes -[uploads to fail to copy over NFS](https://gitlab.com/gitlab-org/gitlab/-/issues/218999). The -following GitLab versions include a fix to work properly with that -kernel version: - -1. [12.10.12](https://about.gitlab.com/releases/2020/06/25/gitlab-12-10-12-released/) -1. [13.0.7](https://about.gitlab.com/releases/2020/06/25/gitlab-13-0-7-released/) -1. [13.1.1](https://about.gitlab.com/releases/2020/06/24/gitlab-13-1-1-released/) -1. 13.2 and up - -If you are using that kernel version, be sure to upgrade GitLab to avoid -errors. - -## NFS Server features - -### Required features - -**File locking**: GitLab **requires** advisory file locking, which is only -supported natively in NFS version 4. NFSv3 also supports locking as long as -Linux Kernel 2.6.5+ is used. We recommend using version 4 and do not -specifically test NFSv3. - -### Recommended options - -When you define your NFS exports, we recommend you also add the following -options: - -- `no_root_squash` - NFS normally changes the `root` user to `nobody`. This is - a good security measure when NFS shares will be accessed by many different - users. However, in this case only GitLab will use the NFS share so it - is safe. GitLab recommends the `no_root_squash` setting because we need to - manage file permissions automatically. Without the setting you may receive - errors when the Omnibus package tries to alter permissions. Note that GitLab - and other bundled components do **not** run as `root` but as non-privileged - users. The recommendation for `no_root_squash` is to allow the Omnibus package - to set ownership and permissions on files, as needed. In some cases where the - `no_root_squash` option is not available, the `root` flag can achieve the same - result. -- `sync` - Force synchronous behavior. Default is asynchronous and under certain - circumstances it could lead to data loss if a failure occurs before data has - synced. - -Due to the complexities of running Omnibus with LDAP and the complexities of -maintaining ID mapping without LDAP, in most cases you should enable numeric UIDs -and GIDs (which is off by default in some cases) for simplified permission -management between systems: - -- [NetApp instructions](https://library.netapp.com/ecmdocs/ECMP1401220/html/GUID-24367A9F-E17B-4725-ADC1-02D86F56F78E.html) -- For non-NetApp devices, disable NFSv4 `idmapping` by performing opposite of [enable NFSv4 idmapper](https://wiki.archlinux.org/index.php/NFS#Enabling_NFSv4_idmapping) - -### Disable NFS server delegation - -We recommend that all NFS users disable the NFS server delegation feature. This -is to avoid a [Linux kernel bug](https://bugzilla.redhat.com/show_bug.cgi?id=1552203) -which causes NFS clients to slow precipitously due to -[excessive network traffic from numerous `TEST_STATEID` NFS messages](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/52017). - -To disable NFS server delegation, do the following: - -1. On the NFS server, run: - - ```shell - echo 0 > /proc/sys/fs/leases-enable - sysctl -w fs.leases-enable=0 - ``` - -1. Restart the NFS server process. For example, on CentOS run `service nfs restart`. - -#### Important notes - -The kernel bug may be fixed in -[more recent kernels with this commit](https://github.com/torvalds/linux/commit/95da1b3a5aded124dd1bda1e3cdb876184813140). - -Red Hat Enterprise 7 [shipped a kernel update](https://access.redhat.com/errata/RHSA-2019:2029) -on August 6, 2019 that may also have resolved this problem. - -You may not need to disable NFS server delegation if you know you are using a version of -the Linux kernel that has been fixed. That said, GitLab still encourages instance -administrators to keep NFS server delegation disabled. - -### Improving NFS performance with GitLab - -#### Improving NFS performance with Unicorn - -NOTE: **Note:** -From GitLab 12.1, it will automatically be detected if Rugged can and should be used per storage. - -If you previously enabled Rugged using the feature flag, you will need to unset the feature flag by using: - -```shell -sudo gitlab-rake gitlab:features:unset_rugged -``` - -If the Rugged feature flag is explicitly set to either true or false, GitLab will use the value explicitly set. - -#### Improving NFS performance with Puma - -NOTE: **Note:** -From GitLab 12.7, Rugged auto-detection is disabled if Puma thread count is greater than 1. - -If you want to use Rugged with Puma, it is recommended to [set Puma thread count to 1](https://docs.gitlab.com/omnibus/settings/puma.html#puma-settings). - -If you want to use Rugged with Puma thread count more than 1, Rugged can be enabled using the [feature flag](../../development/gitaly.md#legacy-rugged-code) - -If the Rugged feature flag is explicitly set to either true or false, GitLab will use the value explicitly set. - -### Known issues - -#### Avoid using AWS's Elastic File System (EFS) - -GitLab strongly recommends against using AWS Elastic File System (EFS). -Our support team will not be able to assist on performance issues related to -file system access. - -Customers and users have reported that AWS EFS does not perform well for GitLab's -use-case. Workloads where many small files are written in a serialized manner, like `git`, -are not well-suited for EFS. EBS with an NFS server on top will perform much better. - -If you do choose to use EFS, avoid storing GitLab log files (e.g. those in `/var/log/gitlab`) -there because this will also affect performance. We recommend that the log files be -stored on a local volume. - -For more details on another person's experience with EFS, see this [Commit Brooklyn 2019 video](https://youtu.be/K6OS8WodRBQ?t=313). - -#### Avoid using CephFS and GlusterFS - -GitLab strongly recommends against using CephFS and GlusterFS. -These distributed file systems are not well-suited for GitLab's input/output access patterns because Git uses many small files and access times and file locking times to propagate will make Git activity very slow. - -#### Avoid using PostgreSQL with NFS - -GitLab strongly recommends against running your PostgreSQL database -across NFS. The GitLab support team will not be able to assist on performance issues related to -this configuration. - -Additionally, this configuration is specifically warned against in the -[PostgreSQL Documentation](https://www.postgresql.org/docs/current/creating-cluster.html#CREATING-CLUSTER-NFS): - ->PostgreSQL does nothing special for NFS file systems, meaning it assumes NFS behaves exactly like ->locally-connected drives. If the client or server NFS implementation does not provide standard file ->system semantics, this can cause reliability problems. Specifically, delayed (asynchronous) writes ->to the NFS server can cause data corruption problems. - -For supported database architecture, please see our documentation on -[Configuring a Database for GitLab HA](../postgresql/replication_and_failover.md). - -## NFS Client mount options - -Here is an example snippet to add to `/etc/fstab`: - - ```plaintext - 10.1.0.1:/var/opt/gitlab/.ssh /var/opt/gitlab/.ssh nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 - 10.1.0.1:/var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/uploads nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 - 10.1.0.1:/var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-rails/shared nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 - 10.1.0.1:/var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/gitlab-ci/builds nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 - 10.1.0.1:/var/opt/gitlab/git-data /var/opt/gitlab/git-data nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 - ``` - -Note there are several options that you should consider using: - -| Setting | Description | -| ------- | ----------- | -| `vers=4.1` |NFS v4.1 should be used instead of v4.0 because there is a Linux [NFS client bug in v4.0](https://gitlab.com/gitlab-org/gitaly/-/issues/1339) that can cause significant problems due to stale data. -| `nofail` | Don't halt boot process waiting for this mount to become available -| `lookupcache=positive` | Tells the NFS client to honor `positive` cache results but invalidates any `negative` cache results. Negative cache results cause problems with Git. Specifically, a `git push` can fail to register uniformly across all NFS clients. The negative cache causes the clients to 'remember' that the files did not exist previously. -| `hard` | Instead of `soft`. [Further details](#soft-mount-option). - -### soft mount option - -We recommend that you use `hard` in your mount options, unless you have a specific -reason to use `soft`. - -On GitLab.com, we use `soft` because there were times when we had NFS servers -reboot and `soft` improved availability, but everyone's infrastructure is different. -If your NFS is provided by on-premise storage arrays with redundant controllers, -for example, you shouldn't need to worry about NFS server availability. - -The NFS man page states: - -> "soft" timeout can cause silent data corruption in certain cases - -Read the [Linux man page](https://linux.die.net/man/5/nfs) to understand the difference, -and if you do use `soft`, ensure that you've taken steps to mitigate the risks. - -If you experience behavior that might have been caused by -writes to disk on the NFS server not occurring, such as commits going missing, -use the `hard` option, because (from the man page): - -> use the soft option only when client responsiveness is more important than data integrity - -Other vendors make similar recommendations, including -[SAP](http://wiki.scn.sap.com/wiki/x/PARnFQ) and NetApp's -[knowledge base](https://kb.netapp.com/Advice_and_Troubleshooting/Data_Storage_Software/ONTAP_OS/What_are_the_differences_between_hard_mount_and_soft_mount), -they highlight that if the NFS client driver caches data, `soft` means there is no certainty if -writes by GitLab are actually on disk. - -Mount points set with the option `hard` may not perform as well, and if the -NFS server goes down, `hard` will cause processes to hang when interacting with -the mount point. Use `SIGKILL` (`kill -9`) to deal with hung processes. -The `intr` option -[stopped working in the 2.6 kernel](https://access.redhat.com/solutions/157873). - -## A single NFS mount - -It's recommended to nest all GitLab data directories within a mount, that allows automatic -restore of backups without manually moving existing data. - -```plaintext -mountpoint -└── gitlab-data - ├── builds - ├── git-data - ├── shared - └── uploads -``` - -To do so, we'll need to configure Omnibus with the paths to each directory nested -in the mount point as follows: - -Mount `/gitlab-nfs` then use the following Omnibus -configuration to move each data location to a subdirectory: - -```ruby -git_data_dirs({"default" => { "path" => "/gitlab-nfs/gitlab-data/git-data"} }) -gitlab_rails['uploads_directory'] = '/gitlab-nfs/gitlab-data/uploads' -gitlab_rails['shared_path'] = '/gitlab-nfs/gitlab-data/shared' -gitlab_ci['builds_directory'] = '/gitlab-nfs/gitlab-data/builds' -``` - -Run `sudo gitlab-ctl reconfigure` to start using the central location. Please -be aware that if you had existing data you will need to manually copy/rsync it -to these new locations and then restart GitLab. - -## Bind mounts - -Alternatively to changing the configuration in Omnibus, bind mounts can be used -to store the data on an NFS mount. - -Bind mounts provide a way to specify just one NFS mount and then -bind the default GitLab data locations to the NFS mount. Start by defining your -single NFS mount point as you normally would in `/etc/fstab`. Let's assume your -NFS mount point is `/gitlab-nfs`. Then, add the following bind mounts in -`/etc/fstab`: - -```shell -/gitlab-nfs/gitlab-data/git-data /var/opt/gitlab/git-data none bind 0 0 -/gitlab-nfs/gitlab-data/.ssh /var/opt/gitlab/.ssh none bind 0 0 -/gitlab-nfs/gitlab-data/uploads /var/opt/gitlab/gitlab-rails/uploads none bind 0 0 -/gitlab-nfs/gitlab-data/shared /var/opt/gitlab/gitlab-rails/shared none bind 0 0 -/gitlab-nfs/gitlab-data/builds /var/opt/gitlab/gitlab-ci/builds none bind 0 0 -``` - -Using bind mounts will require manually making sure the data directories -are empty before attempting a restore. Read more about the -[restore prerequisites](../../raketasks/backup_restore.md). - -## Multiple NFS mounts - -When using default Omnibus configuration you will need to share 4 data locations -between all GitLab cluster nodes. No other locations should be shared. The -following are the 4 locations need to be shared: - -| Location | Description | Default configuration | -| -------- | ----------- | --------------------- | -| `/var/opt/gitlab/git-data` | Git repository data. This will account for a large portion of your data | `git_data_dirs({"default" => { "path" => "/var/opt/gitlab/git-data"} })` -| `/var/opt/gitlab/gitlab-rails/uploads` | User uploaded attachments | `gitlab_rails['uploads_directory'] = '/var/opt/gitlab/gitlab-rails/uploads'` -| `/var/opt/gitlab/gitlab-rails/shared` | Build artifacts, GitLab Pages, LFS objects, temp files, etc. If you're using LFS this may also account for a large portion of your data | `gitlab_rails['shared_path'] = '/var/opt/gitlab/gitlab-rails/shared'` -| `/var/opt/gitlab/gitlab-ci/builds` | GitLab CI/CD build traces | `gitlab_ci['builds_directory'] = '/var/opt/gitlab/gitlab-ci/builds'` - -Other GitLab directories should not be shared between nodes. They contain -node-specific files and GitLab code that does not need to be shared. To ship -logs to a central location consider using remote syslog. Omnibus GitLab packages -provide configuration for [UDP log shipping](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-shipping-gitlab-enterprise-edition-only). - -Having multiple NFS mounts will require manually making sure the data directories -are empty before attempting a restore. Read more about the -[restore prerequisites](../../raketasks/backup_restore.md). - ---- - -Read more on high-availability configuration: - -1. [Configure the database](../postgresql/replication_and_failover.md) -1. [Configure Redis](redis.md) -1. [Configure the GitLab application servers](gitlab.md) -1. [Configure the load balancers](load_balancer.md) - - +This document was moved to [another location](../nfs.md). diff --git a/doc/administration/high_availability/nfs_host_client_setup.md b/doc/administration/high_availability/nfs_host_client_setup.md index 213680e2f64..e3342fa0813 100644 --- a/doc/administration/high_availability/nfs_host_client_setup.md +++ b/doc/administration/high_availability/nfs_host_client_setup.md @@ -1,157 +1,5 @@ --- -type: reference +redirect_to: ../nfs.md --- -# Configuring NFS for GitLab HA - -Setting up NFS for a GitLab HA setup allows all applications nodes in a cluster -to share the same files and maintain data consistency. Application nodes in an HA -setup act as clients while the NFS server plays host. - -> Note: The instructions provided in this documentation allow for setting a quick -proof of concept but will leave NFS as potential single point of failure and -therefore not recommended for use in production. Explore options such as [Pacemaker -and Corosync](https://clusterlabs.org) for highly available NFS in production. - -Below are instructions for setting up an application node(client) in an HA cluster -to read from and write to a central NFS server(host). - -NOTE: **Note:** -Using EFS may negatively impact performance. Please review the [relevant documentation](nfs.md#avoid-using-awss-elastic-file-system-efs) for additional details. - -## NFS Server Setup - -> Follow the instructions below to set up and configure your NFS server. - -### Step 1 - Install NFS Server on Host - -Installing the `nfs-kernel-server` package allows you to share directories with the clients running the GitLab application. - -```shell -apt-get update -apt-get install nfs-kernel-server -``` - -### Step 2 - Export Host's Home Directory to Client - -In this setup we will share the home directory on the host with the client. Edit the exports file as below to share the host's home directory with the client. If you have multiple clients running GitLab you must enter the client IP addresses in line in the `/etc/exports` file. - -```plaintext -#/etc/exports for one client -/home (rw,sync,no_root_squash,no_subtree_check) - -#/etc/exports for three clients -/home (rw,sync,no_root_squash,no_subtree_check) (rw,sync,no_root_squash,no_subtree_check) (rw,sync,no_root_squash,no_subtree_check) -``` - -Restart the NFS server after making changes to the `exports` file for the changes -to take effect. - -```shell -systemctl restart nfs-kernel-server -``` - -NOTE: **Note:** -You may need to update your server's firewall. See the [firewall section](#nfs-in-a-firewalled-environment) at the end of this guide. - -## Client / GitLab application node Setup - -> Follow the instructions below to connect any GitLab Rails application node running -inside your HA environment to the NFS server configured above. - -### Step 1 - Install NFS Common on Client - -The `nfs-common` provides NFS functionality without installing server components which -we don't need running on the application nodes. - -```shell -apt-get update -apt-get install nfs-common -``` - -### Step 2 - Create Mount Points on Client - -Create a directory on the client that we can mount the shared directory from the host. -Please note that if your mount point directory contains any files they will be hidden -once the remote shares are mounted. An empty/new directory on the client is recommended -for this purpose. - -```shell -mkdir -p /nfs/home -``` - -Confirm that the mount point works by mounting it on the client and checking that -it is mounted with the command below: - -```shell -mount :/home -df -h -``` - -### Step 3 - Set up Automatic Mounts on Boot - -Edit `/etc/fstab` on the client as below to mount the remote shares automatically at boot. -Note that GitLab requires advisory file locking, which is only supported natively in -NFS version 4. NFSv3 also supports locking as long as Linux Kernel 2.6.5+ is used. -We recommend using version 4 and do not specifically test NFSv3. -See [NFS documentation](nfs.md#nfs-client-mount-options) for guidance on mount options. - -```plaintext -#/etc/fstab -:/home /nfs/home nfs4 defaults,hard,vers=4.1,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 -``` - -Reboot the client and confirm that the mount point is mounted automatically. - -NOTE: **Note:** -If you followed our guide to [GitLab Pages on a separate server](../pages/index.md#running-gitlab-pages-on-a-separate-server) -here, please continue there with the pages-specific NFS mounts. -The step below is for broader use-cases than only sharing pages data. - -### Step 4 - Set up GitLab to Use NFS mounts - -When using the default Omnibus configuration you will need to share 4 data locations -between all GitLab cluster nodes. No other locations should be shared. Changing the -default file locations in `gitlab.rb` on the client allows you to have one main mount -point and have all the required locations as subdirectories to use the NFS mount for -`git-data`. - -```plaintext -git_data_dirs({"default" => {"path" => "/nfs/home/var/opt/gitlab-data/git-data"}}) -gitlab_rails['uploads_directory'] = '/nfs/home/var/opt/gitlab-data/uploads' -gitlab_rails['shared_path'] = '/nfs/home/var/opt/gitlab-data/shared' -gitlab_ci['builds_directory'] = '/nfs/home/var/opt/gitlab-data/builds' -``` - -Save the changes in `gitlab.rb` and run `gitlab-ctl reconfigure`. - -## NFS in a Firewalled Environment - -If the traffic between your NFS server and NFS client(s) is subject to port filtering -by a firewall, then you will need to reconfigure that firewall to allow NFS communication. - -[This guide from TDLP](http://tldp.org/HOWTO/NFS-HOWTO/security.html#FIREWALLS) -covers the basics of using NFS in a firewalled environment. Additionally, we encourage you to -search for and review the specific documentation for your operating system or distribution and your firewall software. - -Example for Ubuntu: - -Check that NFS traffic from the client is allowed by the firewall on the host by running -the command: `sudo ufw status`. If it's being blocked, then you can allow traffic from a specific -client with the command below. - -```shell -sudo ufw allow from to any port nfs -``` - - +This document was moved to [another location](../nfs.md). diff --git a/doc/administration/high_availability/pgbouncer.md b/doc/administration/high_availability/pgbouncer.md index 15e4da5b1f7..44f4aa37651 100644 --- a/doc/administration/high_availability/pgbouncer.md +++ b/doc/administration/high_availability/pgbouncer.md @@ -1,166 +1,5 @@ --- -type: reference +redirect_to: ../postgresql/pgbouncer.md --- -# Working with the bundled PgBouncer service **(PREMIUM ONLY)** - -As part of its High Availability stack, GitLab Premium includes a bundled version of [PgBouncer](http://www.pgbouncer.org/) that can be managed through `/etc/gitlab/gitlab.rb`. PgBouncer is used to seamlessly migrate database connections between servers in a failover scenario. Additionally, it can be used in a non-HA setup to pool connections, speeding up response time while reducing resource usage. - -In a HA setup, it's recommended to run a PgBouncer node separately for each database node with an internal load balancer (TCP) serving each accordingly. - -## Operations - -### Running PgBouncer as part of an HA GitLab installation - -This content has been moved to a [new location](../postgresql/replication_and_failover.md#configuring-the-pgbouncer-node). - -### Running PgBouncer as part of a non-HA GitLab installation - -1. Generate PGBOUNCER_USER_PASSWORD_HASH with the command `gitlab-ctl pg-password-md5 pgbouncer` - -1. Generate SQL_USER_PASSWORD_HASH with the command `gitlab-ctl pg-password-md5 gitlab`. We'll also need to enter the plaintext SQL_USER_PASSWORD later - -1. On your database node, ensure the following is set in your `/etc/gitlab/gitlab.rb` - - ```ruby - postgresql['pgbouncer_user_password'] = 'PGBOUNCER_USER_PASSWORD_HASH' - postgresql['sql_user_password'] = 'SQL_USER_PASSWORD_HASH' - postgresql['listen_address'] = 'XX.XX.XX.Y' # Where XX.XX.XX.Y is the ip address on the node postgresql should listen on - postgresql['md5_auth_cidr_addresses'] = %w(AA.AA.AA.B/32) # Where AA.AA.AA.B is the IP address of the pgbouncer node - ``` - -1. Run `gitlab-ctl reconfigure` - - **Note:** If the database was already running, it will need to be restarted after reconfigure by running `gitlab-ctl restart postgresql`. - -1. On the node you are running PgBouncer on, make sure the following is set in `/etc/gitlab/gitlab.rb` - - ```ruby - pgbouncer['enable'] = true - pgbouncer['databases'] = { - gitlabhq_production: { - host: 'DATABASE_HOST', - user: 'pgbouncer', - password: 'PGBOUNCER_USER_PASSWORD_HASH' - } - } - ``` - -1. Run `gitlab-ctl reconfigure` - -1. On the node running Puma, make sure the following is set in `/etc/gitlab/gitlab.rb` - - ```ruby - gitlab_rails['db_host'] = 'PGBOUNCER_HOST' - gitlab_rails['db_port'] = '6432' - gitlab_rails['db_password'] = 'SQL_USER_PASSWORD' - ``` - -1. Run `gitlab-ctl reconfigure` - -1. At this point, your instance should connect to the database through PgBouncer. If you are having issues, see the [Troubleshooting](#troubleshooting) section - -## Enable Monitoring - -> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3786) in GitLab 12.0. - -If you enable Monitoring, it must be enabled on **all** PgBouncer servers. - -1. Create/edit `/etc/gitlab/gitlab.rb` and add the following configuration: - - ```ruby - # Enable service discovery for Prometheus - consul['enable'] = true - consul['monitoring_service_discovery'] = true - - # Replace placeholders - # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z - # with the addresses of the Consul server nodes - consul['configuration'] = { - retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z), - } - - # Set the network addresses that the exporters will listen on - node_exporter['listen_address'] = '0.0.0.0:9100' - pgbouncer_exporter['listen_address'] = '0.0.0.0:9188' - ``` - -1. Run `sudo gitlab-ctl reconfigure` to compile the configuration. - -### Interacting with PgBouncer - -#### Administrative console - -As part of Omnibus GitLab, we provide a command `gitlab-ctl pgb-console` to automatically connect to the PgBouncer administrative console. Please see the [PgBouncer documentation](https://www.pgbouncer.org/usage.html#admin-console) for detailed instructions on how to interact with the console. - -To start a session, run - -```shell -# gitlab-ctl pgb-console -Password for user pgbouncer: -psql (11.7, server 1.7.2/bouncer) -Type "help" for help. - -pgbouncer=# -``` - -The password you will be prompted for is the PGBOUNCER_USER_PASSWORD - -To get some basic information about the instance, run - -```shell -pgbouncer=# show databases; show clients; show servers; - name | host | port | database | force_user | pool_size | reserve_pool | pool_mode | max_connections | current_connections ----------------------+-----------+------+---------------------+------------+-----------+--------------+-----------+-----------------+--------------------- - gitlabhq_production | 127.0.0.1 | 5432 | gitlabhq_production | | 100 | 5 | | 0 | 1 - pgbouncer | | 6432 | pgbouncer | pgbouncer | 2 | 0 | statement | 0 | 0 -(2 rows) - - type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link -| remote_pid | tls -------+-----------+---------------------+--------+-----------+-------+------------+------------+---------------------+---------------------+-----------+------ -+------------+----- - C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44590 | 127.0.0.1 | 6432 | 2018-04-24 22:13:10 | 2018-04-24 22:17:10 | 0x12444c0 | -| 0 | - C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44592 | 127.0.0.1 | 6432 | 2018-04-24 22:13:10 | 2018-04-24 22:17:10 | 0x12447c0 | -| 0 | - C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44594 | 127.0.0.1 | 6432 | 2018-04-24 22:13:10 | 2018-04-24 22:17:10 | 0x1244940 | -| 0 | - C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44706 | 127.0.0.1 | 6432 | 2018-04-24 22:14:22 | 2018-04-24 22:16:31 | 0x1244ac0 | -| 0 | - C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44708 | 127.0.0.1 | 6432 | 2018-04-24 22:14:22 | 2018-04-24 22:15:15 | 0x1244c40 | -| 0 | - C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44794 | 127.0.0.1 | 6432 | 2018-04-24 22:15:15 | 2018-04-24 22:15:15 | 0x1244dc0 | -| 0 | - C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44798 | 127.0.0.1 | 6432 | 2018-04-24 22:15:15 | 2018-04-24 22:16:31 | 0x1244f40 | -| 0 | - C | pgbouncer | pgbouncer | active | 127.0.0.1 | 44660 | 127.0.0.1 | 6432 | 2018-04-24 22:13:51 | 2018-04-24 22:17:12 | 0x1244640 | -| 0 | -(8 rows) - - type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link | rem -ote_pid | tls -------+--------+---------------------+-------+-----------+------+------------+------------+---------------------+---------------------+-----------+------+---- ---------+----- - S | gitlab | gitlabhq_production | idle | 127.0.0.1 | 5432 | 127.0.0.1 | 35646 | 2018-04-24 22:15:15 | 2018-04-24 22:17:10 | 0x124dca0 | | - 19980 | -(1 row) -``` - -## Troubleshooting - -In case you are experiencing any issues connecting through PgBouncer, the first place to check is always the logs: - -```shell -# gitlab-ctl tail pgbouncer -``` - -Additionally, you can check the output from `show databases` in the [Administrative console](#administrative-console). In the output, you would expect to see values in the `host` field for the `gitlabhq_production` database. Additionally, `current_connections` should be greater than 1. - -### Message: `LOG: invalid CIDR mask in address` - -See the suggested fix [in Geo documentation](../geo/replication/troubleshooting.md#message-log--invalid-cidr-mask-in-address). - -### Message: `LOG: invalid IP mask "md5": Name or service not known` - -See the suggested fix [in Geo documentation](../geo/replication/troubleshooting.md#message-log--invalid-ip-mask-md5-name-or-service-not-known). +This document was moved to [another location](../postgresql/pgbouncer.md). diff --git a/doc/administration/high_availability/sidekiq.md b/doc/administration/high_availability/sidekiq.md index 98a9af64e5e..ac92ae2eaaa 100644 --- a/doc/administration/high_availability/sidekiq.md +++ b/doc/administration/high_availability/sidekiq.md @@ -1,190 +1,5 @@ --- -type: reference +redirect_to: ../sidekiq.md --- -# Configuring Sidekiq - -This section discusses how to configure an external Sidekiq instance. - -Sidekiq requires connection to the Redis, PostgreSQL and Gitaly instance. -To configure the Sidekiq node: - -1. SSH into the Sidekiq server. - -1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab package -you want using steps 1 and 2 from the GitLab downloads page. -**Do not complete any other steps on the download page.** - -1. Open `/etc/gitlab/gitlab.rb` with your editor. - -1. Generate the Sidekiq configuration: - - ```ruby - sidekiq['listen_address'] = "10.10.1.48" - - ## Optional: Enable extra Sidekiq processes - sidekiq_cluster['enable'] = true - sidekiq_cluster['enable'] = true - "elastic_indexer" - ] - ``` - -1. Setup Sidekiq's connection to Redis: - - ```ruby - ## Must be the same in every sentinel node - redis['master_name'] = 'gitlab-redis' - - ## The same password for Redis authentication you set up for the master node. - redis['master_password'] = 'YOUR_PASSOWORD' - - ## A list of sentinels with `host` and `port` - gitlab_rails['redis_sentinels'] = [ - {'host' => '10.10.1.34', 'port' => 26379}, - {'host' => '10.10.1.35', 'port' => 26379}, - {'host' => '10.10.1.36', 'port' => 26379}, - ] - ``` - -1. Setup Sidekiq's connection to Gitaly: - - ```ruby - git_data_dirs({ - 'default' => { 'gitaly_address' => 'tcp://gitaly:8075' }, - }) - gitlab_rails['gitaly_token'] = 'YOUR_TOKEN' - ``` - -1. Setup Sidekiq's connection to PostgreSQL: - - ```ruby - gitlab_rails['db_host'] = '10.10.1.30' - gitlab_rails['db_password'] = 'YOUR_PASSOWORD' - gitlab_rails['db_port'] = '5432' - gitlab_rails['db_adapter'] = 'postgresql' - gitlab_rails['db_encoding'] = 'unicode' - gitlab_rails['auto_migrate'] = false - ``` - - Remember to add the Sidekiq nodes to the PostgreSQL whitelist: - - ```ruby - postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.10.1.30/32 10.10.1.31/32 10.10.1.32/32 10.10.1.33/32 10.10.1.38/32) - ``` - -1. Disable other services: - - ```ruby - nginx['enable'] = false - grafana['enable'] = false - prometheus['enable'] = false - gitlab_rails['auto_migrate'] = false - alertmanager['enable'] = false - gitaly['enable'] = false - gitlab_monitor['enable'] = false - gitlab_workhorse['enable'] = false - nginx['enable'] = false - postgres_exporter['enable'] = false - postgresql['enable'] = false - redis['enable'] = false - redis_exporter['enable'] = false - puma['enable'] = false - gitlab_exporter['enable'] = false - ``` - -1. Run `gitlab-ctl reconfigure`. - -NOTE: **Note:** -You will need to restart the Sidekiq nodes after an update has occurred and database -migrations performed. - -## Example configuration - -Here's what the ending `/etc/gitlab/gitlab.rb` would look like: - -```ruby -######################################## -##### Services Disabled ### -######################################## - -nginx['enable'] = false -grafana['enable'] = false -prometheus['enable'] = false -gitlab_rails['auto_migrate'] = false -alertmanager['enable'] = false -gitaly['enable'] = false -gitlab_monitor['enable'] = false -gitlab_workhorse['enable'] = false -nginx['enable'] = false -postgres_exporter['enable'] = false -postgresql['enable'] = false -redis['enable'] = false -redis_exporter['enable'] = false -puma['enable'] = false -gitlab_exporter['enable'] = false - -######################################## -#### Redis ### -######################################## - -## Must be the same in every sentinel node -redis['master_name'] = 'gitlab-redis' - -## The same password for Redis authentication you set up for the master node. -redis['master_password'] = 'YOUR_PASSOWORD' - -## A list of sentinels with `host` and `port` -gitlab_rails['redis_sentinels'] = [ - {'host' => '10.10.1.34', 'port' => 26379}, - {'host' => '10.10.1.35', 'port' => 26379}, - {'host' => '10.10.1.36', 'port' => 26379}, - ] - -####################################### -### Gitaly ### -####################################### - -git_data_dirs({ - 'default' => { 'gitaly_address' => 'tcp://gitaly:8075' }, -}) -gitlab_rails['gitaly_token'] = 'YOUR_TOKEN' - -####################################### -### Postgres ### -####################################### -gitlab_rails['db_host'] = '10.10.1.30' -gitlab_rails['db_password'] = 'YOUR_PASSOWORD' -gitlab_rails['db_port'] = '5432' -gitlab_rails['db_adapter'] = 'postgresql' -gitlab_rails['db_encoding'] = 'unicode' -gitlab_rails['auto_migrate'] = false - -####################################### -### Sidekiq configuration ### -####################################### -sidekiq['listen_address'] = "10.10.1.48" - -####################################### -### Monitoring configuration ### -####################################### -consul['enable'] = true -consul['monitoring_service_discovery'] = true - -consul['configuration'] = { - bind_addr: '10.10.1.48', - retry_join: %w(10.10.1.34 10.10.1.35 10.10.1.36) -} - -# Set the network addresses that the exporters will listen on -node_exporter['listen_address'] = '10.10.1.48:9100' - -# Rails Status for prometheus -gitlab_rails['monitoring_whitelist'] = ['10.10.1.42', '127.0.0.1'] -``` - -## Further reading - -Related Sidekiq configuration: - -1. [Extra Sidekiq processes](../operations/extra_sidekiq_processes.md) -1. [Using the GitLab-Sidekiq chart](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/) +This document was moved to [another location](../sidekiq.md). diff --git a/doc/administration/img/repository_storages_admin_ui_v13_1.png b/doc/administration/img/repository_storages_admin_ui_v13_1.png index f8c13a35369..a2b88d14a36 100644 Binary files a/doc/administration/img/repository_storages_admin_ui_v13_1.png and b/doc/administration/img/repository_storages_admin_ui_v13_1.png differ diff --git a/doc/administration/index.md b/doc/administration/index.md index fa415e5f78d..ed079abf708 100644 --- a/doc/administration/index.md +++ b/doc/administration/index.md @@ -138,7 +138,7 @@ Learn how to install, configure, update, and maintain your GitLab instance. ## Package Registry administration - [Container Registry](packages/container_registry.md): Configure Container Registry with GitLab. -- [Package Registry](packages/index.md): Enable GitLab to act as an NPM Registry and a Maven Repository. **(PREMIUM ONLY)** +- [Package Registry](packages/index.md): Enable GitLab to act as an NPM Registry and a Maven Repository. - [Dependency Proxy](packages/dependency_proxy.md): Configure the Dependency Proxy, a local proxy for frequently used upstream images/packages. **(PREMIUM ONLY)** ### Repository settings @@ -163,7 +163,11 @@ Learn how to install, configure, update, and maintain your GitLab instance. ## Snippet settings -- [Setting snippet content size limit](snippets/index.md): Set a maximum size limit for snippets' content. +- [Setting snippet content size limit](snippets/index.md): Set a maximum content size limit for snippets. + +## Wiki settings + +- [Setting wiki page content size limit](wikis/index.md): Set a maximum content size limit for wiki pages. ## Git configuration options diff --git a/doc/administration/instance_limits.md b/doc/administration/instance_limits.md index 6d2fbd95d5e..f30dba331b8 100644 --- a/doc/administration/instance_limits.md +++ b/doc/administration/instance_limits.md @@ -160,7 +160,7 @@ There is a limit when embedding metrics in GFM for performance reasons. ## Number of webhooks -On GitLab.com, the [maximum number of webhooks](../user/gitlab_com/index.md#maximum-number-of-webhooks) per project, and per group, is limited. +On GitLab.com, the [maximum number of webhooks and their size](../user/gitlab_com/index.md#webhooks) per project, and per group, is limited. To set this limit on a self-managed installation, run the following in the [GitLab Rails console](troubleshooting/debug.md#starting-a-rails-console-session): @@ -314,6 +314,58 @@ To update this limit to a new value on a self-managed installation, run the foll Plan.default.actual_limits.update!(ci_instance_level_variables: 30) ``` +### Maximum file size per type of artifact + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37226) in GitLab 13.3. + +Job artifacts defined with [`artifacts:reports`](../ci/pipelines/job_artifacts.md#artifactsreports) +that are uploaded by the Runner are rejected if the file size exceeds the maximum +file size limit. The limit is determined by comparing the project's +[maximum artifact size setting](../user/admin_area/settings/continuous_integration.md#maximum-artifacts-size-core-only) +with the instance limit for the given artifact type, and choosing the smaller value. + +Limits are set in megabytes, so the smallest possible value that can be defined is `1 MB`. + +Each type of artifact has a size limit that can be set. A default of `0` means there +is no limit for that specific artifact type, and the project's maximum artifact size +setting is used: + +| Artifact limit name | Default value | +|---------------------------------------------|---------------| +| `ci_max_artifact_size_accessibility` | 0 | +| `ci_max_artifact_size_archive` | 0 | +| `ci_max_artifact_size_browser_performance` | 0 | +| `ci_max_artifact_size_cluster_applications` | 0 | +| `ci_max_artifact_size_cobertura` | 0 | +| `ci_max_artifact_size_codequality` | 0 | +| `ci_max_artifact_size_container_scanning` | 0 | +| `ci_max_artifact_size_coverage_fuzzing` | 0 | +| `ci_max_artifact_size_dast` | 0 | +| `ci_max_artifact_size_dependency_scanning` | 0 | +| `ci_max_artifact_size_dotenv` | 0 | +| `ci_max_artifact_size_junit` | 0 | +| `ci_max_artifact_size_license_management` | 0 | +| `ci_max_artifact_size_license_scanning` | 0 | +| `ci_max_artifact_size_load_performance` | 0 | +| `ci_max_artifact_size_lsif` | 20 MB ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37226) in GitLab 13.3) | +| `ci_max_artifact_size_metadata` | 0 | +| `ci_max_artifact_size_metrics_referee` | 0 | +| `ci_max_artifact_size_metrics` | 0 | +| `ci_max_artifact_size_network_referee` | 0 | +| `ci_max_artifact_size_performance` | 0 | +| `ci_max_artifact_size_requirements` | 0 | +| `ci_max_artifact_size_sast` | 0 | +| `ci_max_artifact_size_secret_detection` | 0 | +| `ci_max_artifact_size_terraform` | 5 MB ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37018) in GitLab 13.3) | +| `ci_max_artifact_size_trace` | 0 | + +For example, to set the `ci_max_artifact_size_junit` limit to 10MB on a self-managed +installation, run the following in the [GitLab Rails console](troubleshooting/debug.md#starting-a-rails-console-session): + +```ruby +Plan.default.actual_limits.update!(ci_max_artifact_size_junit: 10) +``` + ## Instance monitoring and metrics ### Incident Management inbound alert limits @@ -388,6 +440,24 @@ Reports that go over the 20 MB limit won't be loaded. Affected reports: ## Advanced Global Search limits +### Maximum file size indexed + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8638) in GitLab 13.3. + +You can set a limit on the content of repository files that are indexed in +Elasticsearch. Any files larger than this limit will not be indexed, and thus +will not be searchable. + +Setting a limit helps reduce the memory usage of the indexing processes as well +as the overall index size. This value defaults to `1024 KiB` (1 MiB) as any +text files larger than this likely aren't meant to be read by humans. + +NOTE: **Note:** +You must set a limit, as an unlimited file size is not supported. Setting this +value to be greater than the amount of memory on GitLab's Sidekiq nodes will +lead to GitLab's Sidekiq nodes running out of memory as they will pre-allocate +this amount of memory during indexing. + ### Maximum field length > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/201826) in GitLab 12.8. @@ -396,6 +466,9 @@ You can set a limit on the content of text fields indexed for Global Search. Setting a maximum helps to reduce the load of the indexing processes. If any text field exceeds this limit then the text will be truncated to this number of characters and the rest will not be indexed and hence will not be searchable. +This is applicable to all indexed data except repository files that get +indexed, which have a separate limit (see [Maximum file size +indexed](#maximum-file-size-indexed)). - On GitLab.com this is limited to 20000 characters - For self-managed installations it is unlimited by default @@ -408,6 +481,7 @@ Set the limit to `0` to disable it. ## Wiki limits +- [Wiki page content size limit](wikis/index.md#wiki-page-content-size-limit). - [Length restrictions for file and directory names](../user/project/wiki/index.md#length-restrictions-for-file-and-directory-names). ## Snippets limits diff --git a/doc/administration/integration/plantuml.md b/doc/administration/integration/plantuml.md index 2a30eced7c4..49ea59d239c 100644 --- a/doc/administration/integration/plantuml.md +++ b/doc/administration/integration/plantuml.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, howto +--- + # PlantUML & GitLab > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8537) in GitLab 8.16. diff --git a/doc/administration/integration/terminal.md b/doc/administration/integration/terminal.md index fd9e09dc17a..c363bd30543 100644 --- a/doc/administration/integration/terminal.md +++ b/doc/administration/integration/terminal.md @@ -57,7 +57,7 @@ through to the next one in the chain. If you installed GitLab using Omnibus, or from source, starting with GitLab 8.15, this should be done by the default configuration, so there's no need for you to do anything. -However, if you run a [load balancer](../high_availability/load_balancer.md) in +However, if you run a [load balancer](../load_balancer.md) in front of GitLab, you may need to make some changes to your configuration. These guides document the necessary steps for a selection of popular reverse proxies: @@ -98,4 +98,4 @@ they will receive a `Connection failed` message. > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8413) in GitLab 8.17. Terminal sessions, by default, do not expire. -You can limit terminal session lifetime in your GitLab instance. To do so, navigate to **{admin}** [**Admin Area > Settings > Web terminal**](../../user/admin_area/settings/index.md#general), and set a `max session time`. +You can limit terminal session lifetime in your GitLab instance. To do so, navigate to [**Admin Area > Settings > Web terminal**](../../user/admin_area/settings/index.md#general), and set a `max session time`. diff --git a/doc/administration/invalidate_markdown_cache.md b/doc/administration/invalidate_markdown_cache.md index 5fd804e11dc..ac43d0eae63 100644 --- a/doc/administration/invalidate_markdown_cache.md +++ b/doc/administration/invalidate_markdown_cache.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference +--- + # Invalidate Markdown Cache For performance reasons, GitLab caches the HTML version of Markdown text diff --git a/doc/administration/issue_closing_pattern.md b/doc/administration/issue_closing_pattern.md index 579b957eb47..7abe0f725f2 100644 --- a/doc/administration/issue_closing_pattern.md +++ b/doc/administration/issue_closing_pattern.md @@ -1,6 +1,13 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference +--- + # Issue closing pattern **(CORE ONLY)** ->**Note:** +NOTE: **Note:** This is the administration documentation. There is a separate [user documentation](../user/project/issues/managing_issues.md#closing-issues-automatically) on issue closing pattern. @@ -16,7 +23,7 @@ is installed on. The default pattern can be located in [`gitlab.yml.example`](https://gitlab.com/gitlab-org/gitlab/blob/master/config/gitlab.yml.example) under the "Automatic issue closing" section. -> **Tip:** +TIP: **Tip:** You are advised to use to test the issue closing pattern. Because Rubular doesn't understand `%{issue_ref}`, you can replace this by `#\d+` when testing your patterns, which matches only local issue references like `#123`. diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md index cb31a8934b1..66a7bcb90f6 100644 --- a/doc/administration/job_artifacts.md +++ b/doc/administration/job_artifacts.md @@ -164,9 +164,30 @@ _The artifacts are stored by default in gitlab-rake gitlab:artifacts:migrate ``` +1. Optional: Verify all files migrated properly. + From [PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database) + (`sudo gitlab-psql -d gitlabhq_production`) verify `objectstg` below (where `file_store=2`) has count of all artifacts: + + ```shell + gitlabhq_production=# SELECT count(*) AS total, sum(case when file_store = '1' then 1 else 0 end) AS filesystem, sum(case when file_store = '2' then 1 else 0 end) AS objectstg FROM ci_job_artifacts; + + total | filesystem | objectstg + ------+------------+----------- + 2409 | 0 | 2409 + ``` + + Verify no files on disk in `artifacts` folder: + + ```shell + sudo find /var/opt/gitlab/gitlab-rails/shared/artifacts -type f | grep -v tmp/cache | wc -l + ``` + + In some cases, you may need to run the [orphan artifact file cleanup Rake task](../raketasks/cleanup.md#remove-orphan-artifact-files) + to clean up orphaned artifacts. + CAUTION: **Caution:** JUnit test report artifact (`junit.xml.gz`) migration -[is not supported](https://gitlab.com/gitlab-org/gitlab/-/issues/27698) +[was not supported until GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/27698#note_317190991) by the `gitlab:artifacts:migrate` script. **In installations from source:** @@ -197,9 +218,29 @@ _The artifacts are stored by default in sudo -u git -H bundle exec rake gitlab:artifacts:migrate RAILS_ENV=production ``` +1. Optional: Verify all files migrated properly. + From PostgreSQL console (`sudo -u git -H psql -d gitlabhq_production`) verify `objectstg` below (where `file_store=2`) has count of all artifacts: + + ```shell + gitlabhq_production=# SELECT count(*) AS total, sum(case when file_store = '1' then 1 else 0 end) AS filesystem, sum(case when file_store = '2' then 1 else 0 end) AS objectstg FROM ci_job_artifacts; + + total | filesystem | objectstg + ------+------------+----------- + 2409 | 0 | 2409 + ``` + + Verify no files on disk in `artifacts` folder: + + ```shell + sudo find /var/opt/gitlab/gitlab-rails/shared/artifacts -type f | grep -v tmp/cache | wc -l + ``` + + In some cases, you may need to run the [orphan artifact file cleanup Rake task](../raketasks/cleanup.md#remove-orphan-artifact-files) + to clean up orphaned artifacts. + CAUTION: **Caution:** JUnit test report artifact (`junit.xml.gz`) migration -[is not supported](https://gitlab.com/gitlab-org/gitlab/-/issues/27698) +[was not supported until GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/27698#note_317190991) by the `gitlab:artifacts:migrate` script. ### OpenStack example diff --git a/doc/administration/lfs/index.md b/doc/administration/lfs/index.md index 4a8151bd091..5c1a9519a35 100644 --- a/doc/administration/lfs/index.md +++ b/doc/administration/lfs/index.md @@ -1,4 +1,8 @@ --- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, howto disqus_identifier: 'https://docs.gitlab.com/ee/workflow/lfs/lfs_administration.html' --- @@ -152,7 +156,24 @@ On Omnibus installations, the settings are prefixed by `lfs_object_store_`: This will migrate existing LFS objects to object storage. New LFS objects will be forwarded to object storage unless - `gitlab_rails['lfs_object_store_background_upload']` is set to false. + `gitlab_rails['lfs_object_store_background_upload']` and `gitlab_rails['lfs_object_store_direct_upload']` is set to `false`. +1. Optional: Verify all files migrated properly. + From [PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database) + (`sudo gitlab-psql -d gitlabhq_production`) verify `objectstg` below (where `file_store=2`) has count of all artifacts: + + ```shell + gitlabhq_production=# SELECT count(*) AS total, sum(case when file_store = '1' then 1 else 0 end) AS filesystem, sum(case when file_store = '2' then 1 else 0 end) AS objectstg FROM lfs_objects; + + total | filesystem | objectstg + ------+------------+----------- + 2409 | 0 | 2409 + ``` + + Verify no files on disk in `artifacts` folder: + + ```shell + sudo find /var/opt/gitlab/gitlab-rails/shared/lfs-objects -type f | grep -v tmp/cache | wc -l + ``` ### S3 for installations from source @@ -187,14 +208,30 @@ For source installations the settings are nested under `lfs:` and then ``` This will migrate existing LFS objects to object storage. New LFS objects - will be forwarded to object storage unless `background_upload` is set to - false. + will be forwarded to object storage unless `background_upload` and `direct_upload` is set to + `false`. +1. Optional: Verify all files migrated properly. + From PostgreSQL console (`sudo -u git -H psql -d gitlabhq_production`) verify `objectstg` below (where `file_store=2`) has count of all artifacts: + + ```shell + gitlabhq_production=# SELECT count(*) AS total, sum(case when file_store = '1' then 1 else 0 end) AS filesystem, sum(case when file_store = '2' then 1 else 0 end) AS objectstg FROM lfs_objects; + + total | filesystem | objectstg + ------+------------+----------- + 2409 | 0 | 2409 + ``` + + Verify no files on disk in `artifacts` folder: + + ```shell + sudo find /var/opt/gitlab/gitlab-rails/shared/lfs-objects -type f | grep -v tmp/cache | wc -l + ``` ### Migrating back to local storage In order to migrate back to local storage: -1. Set both `direct_upload` and `background_upload` to false under the LFS object storage settings. Don't forget to restart GitLab. +1. Set both `direct_upload` and `background_upload` to `false` under the LFS object storage settings. Don't forget to restart GitLab. 1. Run `rake gitlab:lfs:migrate_to_local` on your console. 1. Disable `object_storage` for LFS objects in `gitlab.rb`. Remember to restart GitLab afterwards. diff --git a/doc/administration/load_balancer.md b/doc/administration/load_balancer.md new file mode 100644 index 00000000000..fe534f30f66 --- /dev/null +++ b/doc/administration/load_balancer.md @@ -0,0 +1,126 @@ +--- +type: reference +--- + +# Load Balancer for multi-node GitLab + +In an multi-node GitLab configuration, you will need a load balancer to route +traffic to the application servers. The specifics on which load balancer to use +or the exact configuration is beyond the scope of GitLab documentation. We hope +that if you're managing HA systems like GitLab you have a load balancer of +choice already. Some examples including HAProxy (open-source), F5 Big-IP LTM, +and Citrix Net Scaler. This documentation will outline what ports and protocols +you need to use with GitLab. + +## SSL + +How will you handle SSL in your multi-node environment? There are several different +options: + +- Each application node terminates SSL +- The load balancer(s) terminate SSL and communication is not secure between + the load balancer(s) and the application nodes +- The load balancer(s) terminate SSL and communication is *secure* between the + load balancer(s) and the application nodes + +### Application nodes terminate SSL + +Configure your load balancer(s) to pass connections on port 443 as 'TCP' rather +than 'HTTP(S)' protocol. This will pass the connection to the application nodes +NGINX service untouched. NGINX will have the SSL certificate and listen on port 443. + +See [NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https) +for details on managing SSL certificates and configuring NGINX. + +### Load Balancer(s) terminate SSL without backend SSL + +Configure your load balancer(s) to use the 'HTTP(S)' protocol rather than 'TCP'. +The load balancer(s) will then be responsible for managing SSL certificates and +terminating SSL. + +Since communication between the load balancer(s) and GitLab will not be secure, +there is some additional configuration needed. See +[NGINX Proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#supporting-proxied-ssl) +for details. + +### Load Balancer(s) terminate SSL with backend SSL + +Configure your load balancer(s) to use the 'HTTP(S)' protocol rather than 'TCP'. +The load balancer(s) will be responsible for managing SSL certificates that +end users will see. + +Traffic will also be secure between the load balancer(s) and NGINX in this +scenario. There is no need to add configuration for proxied SSL since the +connection will be secure all the way. However, configuration will need to be +added to GitLab to configure SSL certificates. See +[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https) +for details on managing SSL certificates and configuring NGINX. + +## Ports + +### Basic ports + +| LB Port | Backend Port | Protocol | +| ------- | ------------ | ------------------------ | +| 80 | 80 | HTTP (*1*) | +| 443 | 443 | TCP or HTTPS (*1*) (*2*) | +| 22 | 22 | TCP | + +- (*1*): [Web terminal](../ci/environments/index.md#web-terminals) support requires + your load balancer to correctly handle WebSocket connections. When using + HTTP or HTTPS proxying, this means your load balancer must be configured + to pass through the `Connection` and `Upgrade` hop-by-hop headers. See the + [web terminal](integration/terminal.md) integration guide for + more details. +- (*2*): When using HTTPS protocol for port 443, you will need to add an SSL + certificate to the load balancers. If you wish to terminate SSL at the + GitLab application server instead, use TCP protocol. + +### GitLab Pages Ports + +If you're using GitLab Pages with custom domain support you will need some +additional port configurations. +GitLab Pages requires a separate virtual IP address. Configure DNS to point the +`pages_external_url` from `/etc/gitlab/gitlab.rb` at the new virtual IP address. See the +[GitLab Pages documentation](pages/index.md) for more information. + +| LB Port | Backend Port | Protocol | +| ------- | ------------- | --------- | +| 80 | Varies (*1*) | HTTP | +| 443 | Varies (*1*) | TCP (*2*) | + +- (*1*): The backend port for GitLab Pages depends on the + `gitlab_pages['external_http']` and `gitlab_pages['external_https']` + setting. See [GitLab Pages documentation](pages/index.md) for more details. +- (*2*): Port 443 for GitLab Pages should always use the TCP protocol. Users can + configure custom domains with custom SSL, which would not be possible + if SSL was terminated at the load balancer. + +### Alternate SSH Port + +Some organizations have policies against opening SSH port 22. In this case, +it may be helpful to configure an alternate SSH hostname that allows users +to use SSH on port 443. An alternate SSH hostname will require a new virtual IP address +compared to the other GitLab HTTP configuration above. + +Configure DNS for an alternate SSH hostname such as `altssh.gitlab.example.com`. + +| LB Port | Backend Port | Protocol | +| ------- | ------------ | -------- | +| 443 | 22 | TCP | + +## Readiness check + +It is strongly recommend that multi-node deployments configure load balancers to utilize the [readiness check](../user/admin_area/monitoring/health_check.md#readiness) to ensure a node is ready to accept traffic, before routing traffic to it. This is especially important when utilizing Puma, as there is a brief period during a restart where Puma will not accept requests. + + diff --git a/doc/administration/logs.md b/doc/administration/logs.md index 3db9d32563e..2e8d0bf7461 100644 --- a/doc/administration/logs.md +++ b/doc/administration/logs.md @@ -14,6 +14,11 @@ Find more about them [in Audit Events documentation](audit_events.md). System log files are typically plain text in a standard log file format. This guide talks about how to read and use these system log files. +[Read more about how to customise logging on Omnibus GitLab +installations](https://docs.gitlab.com/omnibus/settings/logs.html) +including adjusting log retention, log forwarding, +switching logs from JSON to plain text logging, and more. + ## `production_json.log` This file lives in `/var/log/gitlab/gitlab-rails/production_json.log` for @@ -832,6 +837,29 @@ For example: This message shows that Geo detected that a repository update was needed for project `1`. +## `update_mirror_service_json.log` + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/commit/7f637e2af7006dc2b1b2649d9affc0b86cfb33c4) in GitLab 11.12. + +This file is stored in: + +- `/var/log/gitlab/gitlab-rails/update_mirror_service_json.log` for Omnibus GitLab installations. +- `/home/git/gitlab/log/update_mirror_service_json.log` for installations from source. + +This file contains information about any errors that occurred during project mirroring. + +```json +{ + "severity":"ERROR", + "time":"2020-07-28T23:29:29.473Z", + "correlation_id":"5HgIkCJsO53", + "user_id":"x", + "project_id":"x", + "import_url":"https://mirror-source/group/project.git", + "error_message":"The LFS objects download list couldn't be imported. Error: Unauthorized" +} +``` + ## Registry Logs For Omnibus installations, Container Registry logs reside in `/var/log/gitlab/registry/current`. diff --git a/doc/administration/merge_request_diffs.md b/doc/administration/merge_request_diffs.md index 93cdbff6621..3f4cd6e2751 100644 --- a/doc/administration/merge_request_diffs.md +++ b/doc/administration/merge_request_diffs.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Editor +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference +--- + # Merge request diffs storage **(CORE ONLY)** > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/52568) in GitLab 11.8. diff --git a/doc/administration/monitoring/github_imports.md b/doc/administration/monitoring/github_imports.md index 21cc4c708a8..0d79684c951 100644 --- a/doc/administration/monitoring/github_imports.md +++ b/doc/administration/monitoring/github_imports.md @@ -6,8 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Monitoring GitHub imports ->**Note:** -Available since [GitLab 10.2](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14731). +> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14731) in GitLab 10.2. The GitHub importer exposes various Prometheus metrics that you can use to monitor the health and progress of the importer. diff --git a/doc/administration/monitoring/gitlab_self_monitoring_project/img/self_monitoring_default_dashboard.png b/doc/administration/monitoring/gitlab_self_monitoring_project/img/self_monitoring_default_dashboard.png deleted file mode 100644 index 1d61823ce41..00000000000 Binary files a/doc/administration/monitoring/gitlab_self_monitoring_project/img/self_monitoring_default_dashboard.png and /dev/null differ diff --git a/doc/administration/monitoring/gitlab_self_monitoring_project/img/self_monitoring_overview_dashboard.png b/doc/administration/monitoring/gitlab_self_monitoring_project/img/self_monitoring_overview_dashboard.png new file mode 100644 index 00000000000..1d61823ce41 Binary files /dev/null and b/doc/administration/monitoring/gitlab_self_monitoring_project/img/self_monitoring_overview_dashboard.png differ diff --git a/doc/administration/monitoring/gitlab_self_monitoring_project/index.md b/doc/administration/monitoring/gitlab_self_monitoring_project/index.md index 44ba26296b9..e272cccb7ce 100644 --- a/doc/administration/monitoring/gitlab_self_monitoring_project/index.md +++ b/doc/administration/monitoring/gitlab_self_monitoring_project/index.md @@ -55,10 +55,10 @@ panels, provide a regular expression in the **Instance label regex** field. The dashboard uses metrics available in [Omnibus GitLab](https://docs.gitlab.com/omnibus/) installations. -![GitLab self monitoring default dashboard](img/self_monitoring_default_dashboard.png) +![GitLab self monitoring overview dashboard](img/self_monitoring_overview_dashboard.png) You can also -[create your own dashboards](../../../operations/metrics/dashboards/index.md#defining-custom-dashboards-per-project). +[create your own dashboards](../../../operations/metrics/dashboards/index.md). ## Connection to Prometheus @@ -83,8 +83,8 @@ Once the webhook is setup, you can You can add custom metrics in the self monitoring project by: -1. [Duplicating](../../../operations/metrics/dashboards/index.md#duplicating-a-gitlab-defined-dashboard) the default dashboard. -1. [Editing](../../../operations/metrics/dashboards/index.md#view-and-edit-the-source-file-of-a-custom-dashboard) the newly created dashboard file and configuring it with [dashboard YAML properties](../../../operations/metrics/dashboards/yaml.md). +1. [Duplicating](../../../operations/metrics/dashboards/index.md#duplicate-a-gitlab-defined-dashboard) the overview dashboard. +1. [Editing](../../../operations/metrics/index.md) the newly created dashboard file and configuring it with [dashboard YAML properties](../../../operations/metrics/dashboards/yaml.md). ## Troubleshooting diff --git a/doc/administration/monitoring/performance/grafana_configuration.md b/doc/administration/monitoring/performance/grafana_configuration.md index 96f1377fb73..136a2749e80 100644 --- a/doc/administration/monitoring/performance/grafana_configuration.md +++ b/doc/administration/monitoring/performance/grafana_configuration.md @@ -68,7 +68,7 @@ repository. After setting up Grafana, you can enable a link to access it easily from the GitLab sidebar: -1. Navigate to the **{admin}** **Admin Area > Settings > Metrics and profiling**. +1. Navigate to the **Admin Area > Settings > Metrics and profiling**. 1. Expand **Metrics - Grafana**. 1. Check the **Enable access to Grafana** checkbox. 1. Configure the **Grafana URL**: @@ -77,7 +77,7 @@ GitLab sidebar: - *Otherwise,* enter the full URL of the Grafana instance. 1. Click **Save changes**. -GitLab displays your link in the **{admin}** **Admin Area > Monitoring > Metrics Dashboard**. +GitLab displays your link in the **Admin Area > Monitoring > Metrics Dashboard**. ## Security Update diff --git a/doc/administration/monitoring/performance/performance_bar.md b/doc/administration/monitoring/performance/performance_bar.md index 8002a9ab296..e247ec3708c 100644 --- a/doc/administration/monitoring/performance/performance_bar.md +++ b/doc/administration/monitoring/performance/performance_bar.md @@ -23,7 +23,7 @@ From left to right, it displays: details: ![Gitaly profiling using the Performance Bar](img/performance_bar_gitaly_calls.png) - **Rugged calls**: the time taken (in milliseconds) and the total number of - [Rugged](../../high_availability/nfs.md#improving-nfs-performance-with-gitlab) calls. + [Rugged](../../nfs.md#improving-nfs-performance-with-gitlab) calls. Click to display a modal window with more details: ![Rugged profiling using the Performance Bar](img/performance_bar_rugged_calls.png) - **Redis calls**: the time taken (in milliseconds) and the total number of @@ -72,8 +72,8 @@ Requests with warnings display `(!)` after their path in the **Request selector* The GitLab Performance Bar is disabled by default. To enable it for a given group: 1. Sign in as a user with Administrator [permissions](../../../user/permissions.md). -1. In the menu bar, click the **{admin}** **Admin Area** icon. -1. Navigate to **{settings}** **Settings > Metrics and profiling** +1. In the menu bar, click **Admin Area**. +1. Navigate to **Settings > Metrics and profiling** (`admin/application_settings/metrics_and_profiling`), and expand the section **Profiling - Performance bar**. 1. Click **Enable access to the Performance Bar**. diff --git a/doc/administration/monitoring/performance/request_profiling.md b/doc/administration/monitoring/performance/request_profiling.md index a3b29493d84..5746b95eb44 100644 --- a/doc/administration/monitoring/performance/request_profiling.md +++ b/doc/administration/monitoring/performance/request_profiling.md @@ -9,8 +9,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w To profile a request: 1. Sign in to GitLab as a user with Administrator or Maintainer [permissions](../../../user/permissions.md). -1. In the navigation bar, click **{admin}** **Admin area**. -1. Navigate to **{monitor}** **Monitoring > Requests Profiles**. +1. In the navigation bar, click **Admin area**. +1. Navigate to **Monitoring > Requests Profiles**. 1. In the **Requests Profiles** section, copy the token. 1. Pass the headers `X-Profile-Token: ` and `X-Profile-Mode: `(where `` can be `execution` or `memory`) to the request you want to profile. When @@ -29,7 +29,7 @@ To profile a request: Profiled requests can take longer than usual. After the request completes, you can view the profiling output from the -**{monitor}** **Monitoring > Requests Profiles** administration page: +**Monitoring > Requests Profiles** administration page: ![Profiling output](img/request_profile_result.png) diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md index fa5e5da80c3..bff689c0c0c 100644 --- a/doc/administration/monitoring/prometheus/gitlab_metrics.md +++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md @@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w To enable the GitLab Prometheus metrics: 1. Log into GitLab as a user with [administrator permissions](../../../user/permissions.md). -1. Navigate to **{admin}** **Admin Area > Settings > Metrics and profiling**. +1. Navigate to **Admin Area > Settings > Metrics and profiling**. 1. Find the **Metrics - Prometheus** section, and click **Enable Prometheus Metrics**. 1. [Restart GitLab](../../restart_gitlab.md#omnibus-gitlab-restart) for the changes to take effect. @@ -50,7 +50,8 @@ The following metrics are available: | `gitlab_page_out_of_bounds` | Counter | 12.8 | Counter for the PageLimiter pagination limit being hit | `controller`, `action`, `bot` | | `gitlab_rails_queue_duration_seconds` | Histogram | 9.4 | Measures latency between GitLab Workhorse forwarding a request to Rails | | | `gitlab_sql_duration_seconds` | Histogram | 10.2 | SQL execution time, excluding `SCHEMA` operations and `BEGIN` / `COMMIT` | | -| `gitlab_transaction_allocated_memory_bytes` | Histogram | 10.2 | Allocated memory for all transactions (`gitlab_transaction_*` metrics) | | +| `gitlab_ruby_threads_max_expected_threads` | Gauge | 13.3 | Maximum number of threads expected to be running and performing application work | +| `gitlab_ruby_threads_running_threads` | Gauge | 13.3 | Number of running Ruby threads by name | | `gitlab_transaction_cache__count_total` | Counter | 10.2 | Counter for total Rails cache calls (per key) | | | `gitlab_transaction_cache__duration_total` | Counter | 10.2 | Counter for total time (seconds) spent in Rails cache calls (per key) | | | `gitlab_transaction_cache_count_total` | Counter | 10.2 | Counter for total Rails cache calls (aggregate) | | @@ -95,8 +96,6 @@ The following metrics are available: | `gitlab_transaction_db_count_total` | Counter | 13.1 | Counter for total number of SQL calls | `controller`, `action` | | `gitlab_transaction_db_write_count_total` | Counter | 13.1 | Counter for total number of write SQL calls | `controller`, `action` | | `gitlab_transaction_db_cached_count_total` | Counter | 13.1 | Counter for total number of cached SQL calls | `controller`, `action` | -| `http_redis_requests_duration_seconds` | Histogram | 13.1 | Redis requests duration during web transactions | `controller`, `action` | -| `http_redis_requests_total` | Counter | 13.1 | Redis requests count during web transactions | `controller`, `action` | | `http_elasticsearch_requests_duration_seconds` **(STARTER)** | Histogram | 13.1 | Elasticsearch requests duration during web transactions | `controller`, `action` | | `http_elasticsearch_requests_total` **(STARTER)** | Counter | 13.1 | Elasticsearch requests count during web transactions | `controller`, `action` | | `pipelines_created_total` | Counter | 9.4 | Counter of pipelines created | | diff --git a/doc/administration/monitoring/prometheus/index.md b/doc/administration/monitoring/prometheus/index.md index f0ad0a1a2e6..7d93e9797be 100644 --- a/doc/administration/monitoring/prometheus/index.md +++ b/doc/administration/monitoring/prometheus/index.md @@ -109,6 +109,81 @@ prometheus['scrape_configs'] = [ ] ``` +### Standalone Prometheus using Omnibus GitLab + +The Omnibus GitLab package can be used to configure a standalone Monitoring node running Prometheus and [Grafana](../performance/grafana_configuration.md). + +The steps below are the minimum necessary to configure a Monitoring node running Prometheus and Grafana with Omnibus GitLab: + +1. SSH into the Monitoring node. +1. [Install](https://about.gitlab.com/install/) the Omnibus GitLab + package you want using **steps 1 and 2** from the GitLab downloads page, but + do not follow the remaining steps. +1. Make sure to collect the IP addresses or DNS records of the Consul server nodes, for the next step. +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + external_url 'http://gitlab.example.com' + + # Enable Prometheus + prometheus['enable'] = true + prometheus['listen_address'] = '0.0.0.0:9090' + prometheus['monitor_kubernetes'] = false + + # Enable Login form + grafana['disable_login_form'] = false + + # Enable Grafana + grafana['enable'] = true + grafana['admin_password'] = 'toomanysecrets' + + # Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # The addresses can be IPs or FQDNs + consul['configuration'] = { + retry_join: %w(10.0.0.1 10.0.0.2 10.0.0.3), + } + + # Disable all other services + gitlab_rails['auto_migrate'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_exporter['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = true + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + sidekiq['enable'] = false + puma['enable'] = false + node_exporter['enable'] = false + gitlab_exporter['enable'] = false + ``` + +1. Run `sudo gitlab-ctl reconfigure` to compile the configuration. + +The next step is to tell all the other nodes where the monitoring node is: + +1. Edit `/etc/gitlab/gitlab.rb`, and add, or find and uncomment the following line: + + ```ruby + gitlab_rails['prometheus_address'] = '10.0.0.1:9090' + ``` + + Where `10.0.0.1:9090` is the IP address and port of the Prometheus node. + +1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to + take effect. + +NOTE: **Note:** +Once monitoring using Service Discovery is enabled with `consul['monitoring_service_discovery'] = true`, +ensure that `prometheus['scrape_configs']` is not set in `/etc/gitlab/gitlab.rb`. Setting both +`consul['monitoring_service_discovery'] = true` and `prometheus['scrape_configs']` in `/etc/gitlab/gitlab.rb` +will result in errors. + ### Using an external Prometheus server NOTE: **Note:** @@ -128,14 +203,24 @@ To use an external Prometheus server: 1. Set each bundled service's [exporter](#bundled-software-metrics) to listen on a network address, for example: ```ruby + node_exporter['listen_address'] = '0.0.0.0:9100' + gitlab_workhorse['prometheus_listen_addr'] = "0.0.0.0:9229" + + # Rails nodes gitlab_exporter['listen_address'] = '0.0.0.0' - sidekiq['listen_address'] = '0.0.0.0' gitlab_exporter['listen_port'] = '9168' - node_exporter['listen_address'] = '0.0.0.0:9100' + + # Sidekiq nodes + sidekiq['listen_address'] = '0.0.0.0' + + # Redis nodes redis_exporter['listen_address'] = '0.0.0.0:9121' + + # PostgreSQL nodes postgres_exporter['listen_address'] = '0.0.0.0:9187' + + # Gitaly nodes gitaly['prometheus_listen_addr'] = "0.0.0.0:9236" - gitlab_workhorse['prometheus_listen_addr'] = "0.0.0.0:9229" ``` 1. Install and set up a dedicated Prometheus instance, if necessary, using the [official installation instructions](https://prometheus.io/docs/prometheus/latest/installation/). @@ -227,7 +312,7 @@ To use an external Prometheus server: You can visit `http://localhost:9090` for the dashboard that Prometheus offers by default. ->**Note:** +NOTE: **Note:** If SSL has been enabled on your GitLab instance, you may not be able to access Prometheus on the same browser as GitLab if using the same FQDN due to [HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security). We plan to [provide access via GitLab](https://gitlab.com/gitlab-org/multi-user-prometheus), but in the interim there are diff --git a/doc/administration/nfs.md b/doc/administration/nfs.md new file mode 100644 index 00000000000..bae6bd0dd6c --- /dev/null +++ b/doc/administration/nfs.md @@ -0,0 +1,368 @@ +--- +type: reference +--- + +# Using NFS with GitLab + +NFS can be used as an alternative for object storage but this isn't typically +recommended for performance reasons. Note however it is required for [GitLab +Pages](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196). + +For data objects such as LFS, Uploads, Artifacts, etc., an [Object Storage service](object_storage.md) +is recommended over NFS where possible, due to better performance. + +CAUTION: **Caution:** +From GitLab 13.0, using NFS for Git repositories is deprecated. In GitLab 14.0, +support for NFS for Git repositories is scheduled to be removed. Upgrade to +[Gitaly Cluster](gitaly/praefect.md) as soon as possible. + +NOTE: **Note:** +Filesystem performance has a big impact on overall GitLab +performance, especially for actions that read or write to Git repositories. See +[Filesystem Performance Benchmarking](operations/filesystem_benchmarking.md) +for steps to test filesystem performance. + +## Known kernel version incompatibilities + +RedHat Enterprise Linux (RHEL) and CentOS v7.7 and v7.8 ship with kernel +version `3.10.0-1127`, which [contains a +bug](https://bugzilla.redhat.com/show_bug.cgi?id=1783554) that causes +[uploads to fail to copy over NFS](https://gitlab.com/gitlab-org/gitlab/-/issues/218999). The +following GitLab versions include a fix to work properly with that +kernel version: + +1. [12.10.12](https://about.gitlab.com/releases/2020/06/25/gitlab-12-10-12-released/) +1. [13.0.7](https://about.gitlab.com/releases/2020/06/25/gitlab-13-0-7-released/) +1. [13.1.1](https://about.gitlab.com/releases/2020/06/24/gitlab-13-1-1-released/) +1. 13.2 and up + +If you are using that kernel version, be sure to upgrade GitLab to avoid +errors. + +## Fast lookup of authorized SSH keys + +The [fast SSH key lookup](operations/fast_ssh_key_lookup.md) feature can improve +performance of GitLab instances even if they're using block storage. + +[Fast SSH key lookup](operations/fast_ssh_key_lookup.md) is a replacement for +`authorized_keys` (in `/var/opt/gitlab/.ssh`) using the GitLab database. + +NFS increases latency, so fast lookup is recommended if `/var/opt/gitlab` +is moved to NFS. + +We are investigating the use of +[fast lookup as the default](https://gitlab.com/groups/gitlab-org/-/epics/3104). + +## NFS server + +Installing the `nfs-kernel-server` package allows you to share directories with +the clients running the GitLab application: + +```shell +sudo apt-get update +sudo apt-get install nfs-kernel-server +``` + +### Required features + +**File locking**: GitLab **requires** advisory file locking, which is only +supported natively in NFS version 4. NFSv3 also supports locking as long as +Linux Kernel 2.6.5+ is used. We recommend using version 4 and do not +specifically test NFSv3. + +### Recommended options + +When you define your NFS exports, we recommend you also add the following +options: + +- `no_root_squash` - NFS normally changes the `root` user to `nobody`. This is + a good security measure when NFS shares will be accessed by many different + users. However, in this case only GitLab will use the NFS share so it + is safe. GitLab recommends the `no_root_squash` setting because we need to + manage file permissions automatically. Without the setting you may receive + errors when the Omnibus package tries to alter permissions. Note that GitLab + and other bundled components do **not** run as `root` but as non-privileged + users. The recommendation for `no_root_squash` is to allow the Omnibus package + to set ownership and permissions on files, as needed. In some cases where the + `no_root_squash` option is not available, the `root` flag can achieve the same + result. +- `sync` - Force synchronous behavior. Default is asynchronous and under certain + circumstances it could lead to data loss if a failure occurs before data has + synced. + +Due to the complexities of running Omnibus with LDAP and the complexities of +maintaining ID mapping without LDAP, in most cases you should enable numeric UIDs +and GIDs (which is off by default in some cases) for simplified permission +management between systems: + +- [NetApp instructions](https://library.netapp.com/ecmdocs/ECMP1401220/html/GUID-24367A9F-E17B-4725-ADC1-02D86F56F78E.html) +- For non-NetApp devices, disable NFSv4 `idmapping` by performing opposite of [enable NFSv4 idmapper](https://wiki.archlinux.org/index.php/NFS#Enabling_NFSv4_idmapping) + +### Disable NFS server delegation + +We recommend that all NFS users disable the NFS server delegation feature. This +is to avoid a [Linux kernel bug](https://bugzilla.redhat.com/show_bug.cgi?id=1552203) +which causes NFS clients to slow precipitously due to +[excessive network traffic from numerous `TEST_STATEID` NFS messages](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/52017). + +To disable NFS server delegation, do the following: + +1. On the NFS server, run: + + ```shell + echo 0 > /proc/sys/fs/leases-enable + sysctl -w fs.leases-enable=0 + ``` + +1. Restart the NFS server process. For example, on CentOS run `service nfs restart`. + +NOTE: **Important note:** +The kernel bug may be fixed in +[more recent kernels with this commit](https://github.com/torvalds/linux/commit/95da1b3a5aded124dd1bda1e3cdb876184813140). +Red Hat Enterprise 7 [shipped a kernel update](https://access.redhat.com/errata/RHSA-2019:2029) +on August 6, 2019 that may also have resolved this problem. +You may not need to disable NFS server delegation if you know you are using a version of +the Linux kernel that has been fixed. That said, GitLab still encourages instance +administrators to keep NFS server delegation disabled. + +### Improving NFS performance with GitLab + +#### Improving NFS performance with Unicorn + +NOTE: **Note:** +From GitLab 12.1, it will automatically be detected if Rugged can and should be used per storage. + +If you previously enabled Rugged using the feature flag, you will need to unset the feature flag by using: + +```shell +sudo gitlab-rake gitlab:features:unset_rugged +``` + +If the Rugged feature flag is explicitly set to either true or false, GitLab will use the value explicitly set. + +#### Improving NFS performance with Puma + +NOTE: **Note:** +From GitLab 12.7, Rugged auto-detection is disabled if Puma thread count is greater than 1. + +If you want to use Rugged with Puma, it is recommended to [set Puma thread count to 1](https://docs.gitlab.com/omnibus/settings/puma.html#puma-settings). + +If you want to use Rugged with Puma thread count more than 1, Rugged can be enabled using the [feature flag](../development/gitaly.md#legacy-rugged-code) + +If the Rugged feature flag is explicitly set to either true or false, GitLab will use the value explicitly set. + +## NFS client + +The `nfs-common` provides NFS functionality without installing server components which +we don't need running on the application nodes. + +```shell +apt-get update +apt-get install nfs-common +``` + +### Mount options + +Here is an example snippet to add to `/etc/fstab`: + +```plaintext +10.1.0.1:/var/opt/gitlab/.ssh /var/opt/gitlab/.ssh nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 +10.1.0.1:/var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/uploads nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 +10.1.0.1:/var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-rails/shared nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 +10.1.0.1:/var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/gitlab-ci/builds nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 +10.1.0.1:/var/opt/gitlab/git-data /var/opt/gitlab/git-data nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2 +``` + +Note there are several options that you should consider using: + +| Setting | Description | +| ------- | ----------- | +| `vers=4.1` |NFS v4.1 should be used instead of v4.0 because there is a Linux [NFS client bug in v4.0](https://gitlab.com/gitlab-org/gitaly/-/issues/1339) that can cause significant problems due to stale data. +| `nofail` | Don't halt boot process waiting for this mount to become available +| `lookupcache=positive` | Tells the NFS client to honor `positive` cache results but invalidates any `negative` cache results. Negative cache results cause problems with Git. Specifically, a `git push` can fail to register uniformly across all NFS clients. The negative cache causes the clients to 'remember' that the files did not exist previously. +| `hard` | Instead of `soft`. [Further details](#soft-mount-option). + +#### `soft` mount option + +It's recommended that you use `hard` in your mount options, unless you have a specific +reason to use `soft`. + +On GitLab.com, we use `soft` because there were times when we had NFS servers +reboot and `soft` improved availability, but everyone's infrastructure is different. +If your NFS is provided by on-premise storage arrays with redundant controllers, +for example, you shouldn't need to worry about NFS server availability. + +The NFS man page states: + +> "soft" timeout can cause silent data corruption in certain cases + +Read the [Linux man page](https://linux.die.net/man/5/nfs) to understand the difference, +and if you do use `soft`, ensure that you've taken steps to mitigate the risks. + +If you experience behavior that might have been caused by +writes to disk on the NFS server not occurring, such as commits going missing, +use the `hard` option, because (from the man page): + +> use the soft option only when client responsiveness is more important than data integrity + +Other vendors make similar recommendations, including +[SAP](http://wiki.scn.sap.com/wiki/x/PARnFQ) and NetApp's +[knowledge base](https://kb.netapp.com/Advice_and_Troubleshooting/Data_Storage_Software/ONTAP_OS/What_are_the_differences_between_hard_mount_and_soft_mount), +they highlight that if the NFS client driver caches data, `soft` means there is no certainty if +writes by GitLab are actually on disk. + +Mount points set with the option `hard` may not perform as well, and if the +NFS server goes down, `hard` will cause processes to hang when interacting with +the mount point. Use `SIGKILL` (`kill -9`) to deal with hung processes. +The `intr` option +[stopped working in the 2.6 kernel](https://access.redhat.com/solutions/157873). + +### A single NFS mount + +It's recommended to nest all GitLab data directories within a mount, that allows automatic +restore of backups without manually moving existing data. + +```plaintext +mountpoint +└── gitlab-data + ├── builds + ├── git-data + ├── shared + └── uploads +``` + +To do so, we'll need to configure Omnibus with the paths to each directory nested +in the mount point as follows: + +Mount `/gitlab-nfs` then use the following Omnibus +configuration to move each data location to a subdirectory: + +```ruby +git_data_dirs({"default" => { "path" => "/gitlab-nfs/gitlab-data/git-data"} }) +gitlab_rails['uploads_directory'] = '/gitlab-nfs/gitlab-data/uploads' +gitlab_rails['shared_path'] = '/gitlab-nfs/gitlab-data/shared' +gitlab_ci['builds_directory'] = '/gitlab-nfs/gitlab-data/builds' +``` + +Run `sudo gitlab-ctl reconfigure` to start using the central location. Please +be aware that if you had existing data you will need to manually copy/rsync it +to these new locations and then restart GitLab. + +### Bind mounts + +Alternatively to changing the configuration in Omnibus, bind mounts can be used +to store the data on an NFS mount. + +Bind mounts provide a way to specify just one NFS mount and then +bind the default GitLab data locations to the NFS mount. Start by defining your +single NFS mount point as you normally would in `/etc/fstab`. Let's assume your +NFS mount point is `/gitlab-nfs`. Then, add the following bind mounts in +`/etc/fstab`: + +```shell +/gitlab-nfs/gitlab-data/git-data /var/opt/gitlab/git-data none bind 0 0 +/gitlab-nfs/gitlab-data/.ssh /var/opt/gitlab/.ssh none bind 0 0 +/gitlab-nfs/gitlab-data/uploads /var/opt/gitlab/gitlab-rails/uploads none bind 0 0 +/gitlab-nfs/gitlab-data/shared /var/opt/gitlab/gitlab-rails/shared none bind 0 0 +/gitlab-nfs/gitlab-data/builds /var/opt/gitlab/gitlab-ci/builds none bind 0 0 +``` + +Using bind mounts will require manually making sure the data directories +are empty before attempting a restore. Read more about the +[restore prerequisites](../raketasks/backup_restore.md). + +You can view information and options set for each of the mounted NFS file +systems by running `nfsstat -m` and `cat /etc/fstab`. + +### Multiple NFS mounts + +When using default Omnibus configuration you will need to share 4 data locations +between all GitLab cluster nodes. No other locations should be shared. The +following are the 4 locations need to be shared: + +| Location | Description | Default configuration | +| -------- | ----------- | --------------------- | +| `/var/opt/gitlab/git-data` | Git repository data. This will account for a large portion of your data | `git_data_dirs({"default" => { "path" => "/var/opt/gitlab/git-data"} })` +| `/var/opt/gitlab/gitlab-rails/uploads` | User uploaded attachments | `gitlab_rails['uploads_directory'] = '/var/opt/gitlab/gitlab-rails/uploads'` +| `/var/opt/gitlab/gitlab-rails/shared` | Build artifacts, GitLab Pages, LFS objects, temp files, etc. If you're using LFS this may also account for a large portion of your data | `gitlab_rails['shared_path'] = '/var/opt/gitlab/gitlab-rails/shared'` +| `/var/opt/gitlab/gitlab-ci/builds` | GitLab CI/CD build traces | `gitlab_ci['builds_directory'] = '/var/opt/gitlab/gitlab-ci/builds'` + +Other GitLab directories should not be shared between nodes. They contain +node-specific files and GitLab code that does not need to be shared. To ship +logs to a central location consider using remote syslog. Omnibus GitLab packages +provide configuration for [UDP log shipping](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-shipping-gitlab-enterprise-edition-only). + +Having multiple NFS mounts will require manually making sure the data directories +are empty before attempting a restore. Read more about the +[restore prerequisites](../raketasks/backup_restore.md). + +## NFS in a Firewalled Environment + +If the traffic between your NFS server and NFS client(s) is subject to port filtering +by a firewall, then you will need to reconfigure that firewall to allow NFS communication. + +[This guide from TDLP](http://tldp.org/HOWTO/NFS-HOWTO/security.html#FIREWALLS) +covers the basics of using NFS in a firewalled environment. Additionally, we encourage you to +search for and review the specific documentation for your operating system or distribution and your firewall software. + +Example for Ubuntu: + +Check that NFS traffic from the client is allowed by the firewall on the host by running +the command: `sudo ufw status`. If it's being blocked, then you can allow traffic from a specific +client with the command below. + +```shell +sudo ufw allow from to any port nfs +``` + +## Known issues + +### Avoid using AWS's Elastic File System (EFS) + +GitLab strongly recommends against using AWS Elastic File System (EFS). +Our support team will not be able to assist on performance issues related to +file system access. + +Customers and users have reported that AWS EFS does not perform well for GitLab's +use-case. Workloads where many small files are written in a serialized manner, like `git`, +are not well-suited for EFS. EBS with an NFS server on top will perform much better. + +If you do choose to use EFS, avoid storing GitLab log files (e.g. those in `/var/log/gitlab`) +there because this will also affect performance. We recommend that the log files be +stored on a local volume. + +For more details on another person's experience with EFS, see this [Commit Brooklyn 2019 video](https://youtu.be/K6OS8WodRBQ?t=313). + +### Avoid using CephFS and GlusterFS + +GitLab strongly recommends against using CephFS and GlusterFS. +These distributed file systems are not well-suited for GitLab's input/output access patterns because Git uses many small files and access times and file locking times to propagate will make Git activity very slow. + +### Avoid using PostgreSQL with NFS + +GitLab strongly recommends against running your PostgreSQL database +across NFS. The GitLab support team will not be able to assist on performance issues related to +this configuration. + +Additionally, this configuration is specifically warned against in the +[PostgreSQL Documentation](https://www.postgresql.org/docs/current/creating-cluster.html#CREATING-CLUSTER-NFS): + +>PostgreSQL does nothing special for NFS file systems, meaning it assumes NFS behaves exactly like +>locally-connected drives. If the client or server NFS implementation does not provide standard file +>system semantics, this can cause reliability problems. Specifically, delayed (asynchronous) writes +>to the NFS server can cause data corruption problems. + +For supported database architecture, please see our documentation on +[Configuring a Database for GitLab HA](postgresql/replication_and_failover.md). + + diff --git a/doc/administration/object_storage.md b/doc/administration/object_storage.md index b51b722fbd7..49716883310 100644 --- a/doc/administration/object_storage.md +++ b/doc/administration/object_storage.md @@ -15,12 +15,18 @@ GitLab has been tested on a number of object storage providers: - [Amazon S3](https://aws.amazon.com/s3/) - [Google Cloud Storage](https://cloud.google.com/storage) -- [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces) +- [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces/) - [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm) - [Openstack Swift](https://docs.openstack.org/swift/latest/s3_compat.html) - On-premises hardware and appliances from various storage vendors. - MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation. +### Known compatibility issues + +- Dell EMC ECS: Prior to GitLab 13.3, there is a [known bug in GitLab Workhorse that prevents + HTTP Range Requests from working with CI job artifacts](https://gitlab.com/gitlab-org/gitlab/-/issues/223806). + Be sure to upgrade to GitLab v13.3.0 or above if you use S3 storage with this hardware. + ## Configuration guides There are two ways of specifying object storage configuration in GitLab: @@ -55,6 +61,10 @@ NOTE: **Note:** Consolidated object storage configuration cannot be used for backups or Mattermost. See [the full table for a complete list](#storage-specific-configuration). +NOTE: **Note:** +Enabling consolidated object storage will enable object storage for all object types. +If you wish to use local storage for specific object types, you can [selectively disable object storages](#selectively-disabling-object-storage). + Most types of objects, such as CI artifacts, LFS files, upload attachments, and so on can be saved in object storage by specifying a single credential for object storage with multiple buckets. A [different bucket @@ -84,6 +94,11 @@ See the section on [ETag mismatch errors](#etag-mismatch) for more details. 'aws_access_key_id' => '', 'aws_secret_access_key' => '' } + # OPTIONAL: The following lines are only needed if server side encryption is required + gitlab_rails['object_store']['storage_options'] = { + 'server_side_encryption' => '', + 'server_side_encryption_kms_key_id' => '' + } gitlab_rails['object_store']['objects']['artifacts']['bucket'] = '' gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = '' gitlab_rails['object_store']['objects']['lfs']['bucket'] = '' @@ -119,6 +134,9 @@ See the section on [ETag mismatch errors](#etag-mismatch) for more details. aws_access_key_id: aws_secret_access_key: region: + storage_options: + server_side_encryption: + server_side_encryption_key_kms_id: objects: artifacts: bucket: @@ -184,7 +202,8 @@ gitlab_rails['object_store']['connection'] = { |---------|-------------| | `enabled` | Enable/disable object storage | | `proxy_download` | Set to `true` to [enable proxying all files served](#proxy-download). Option allows to reduce egress traffic as this allows clients to download directly from remote storage instead of proxying all data | -| `connection` | Various connection options described below | +| `connection` | Various [connection options](#connection-settings) described below | +| `storage_options` | Options to use when saving new objects, such as [server side encryption](#server-side-encryption-headers). Introduced in GitLab 13.3 | | `objects` | [Object-specific configuration](#object-specific-configuration) ### Connection settings @@ -494,16 +513,18 @@ If you configure GitLab to use object storage for CI logs and artifacts, ### Proxy Download -A number of the use cases for object storage allow client traffic to be redirected to the -object storage back end, like when Git clients request large files via LFS or when -downloading CI artifacts and logs. +Clients can download files in object storage by receiving a pre-signed, time-limited URL, +or by GitLab proxying the data from object storage to the client. +Downloading files from object storage directly +helps reduce the amount of egress traffic GitLab +needs to process. When the files are stored on local block storage or NFS, GitLab has to act as a proxy. This is not the default behavior with object storage. The `proxy_download` setting controls this behavior: the default is generally `false`. -Verify this in the documentation for each use case. Set it to `true` so that GitLab proxies -the files. +Verify this in the documentation for each use case. Set it to `true` if you want +GitLab to proxy the files. When not proxying files, GitLab returns an [HTTP 302 redirect with a pre-signed, time-limited object storage URL](https://gitlab.com/gitlab-org/gitlab/-/issues/32117#note_218532298). @@ -524,7 +545,9 @@ certificate, or may return common TLS errors such as: x509: certificate signed by unknown authority ``` -- Clients will need network access to the object storage. Errors that might result +- Clients will need network access to the object storage. +Network firewalls could block access. +Errors that might result if this access is not in place include: ```plaintext @@ -535,6 +558,10 @@ Getting a `403 Forbidden` response is specifically called out on the [package repository documentation](packages/index.md#using-object-storage) as a side effect of how some build tools work. +Additionally for a short time period users could share pre-signed, time-limited object storage URLs +with others without authentication. Also bandwidth charges may be incurred +between the object storage provider and the client. + ### ETag mismatch Using the default GitLab settings, some object storage back-ends such as @@ -576,21 +603,46 @@ configuration. #### Encrypted S3 buckets -> - Introduced in [GitLab 13.1](https://gitlab.com/gitlab-org/gitlab-workhorse/-/merge_requests/466) for instance profiles only. -> - Introduced in [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34460) for static credentials when [consolidated object storage configuration](#consolidated-object-storage-configuration) is used. +> - Introduced in [GitLab 13.1](https://gitlab.com/gitlab-org/gitlab-workhorse/-/merge_requests/466) for instance profiles only and [S3 default encryption](https://docs.aws.amazon.com/AmazonS3/latest/dev/bucket-encryption.html). +> - Introduced in [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34460) for static credentials when [consolidated object storage configuration](#consolidated-object-storage-configuration) and [S3 default encryption](https://docs.aws.amazon.com/AmazonS3/latest/dev/bucket-encryption.html) are used. When configured either with an instance profile or with the consolidated -object configuration, GitLab Workhorse properly uploads files to S3 buckets -that have [SSE-S3 or SSE-KMS encryption enabled by +object configuration, GitLab Workhorse properly uploads files to S3 +buckets that have [SSE-S3 or SSE-KMS encryption enabled by default](https://docs.aws.amazon.com/kms/latest/developerguide/services-s3.html). -Note that customer master keys (CMKs) and -SSE-C encryption are [not yet supported since this requires supplying -keys to the GitLab configuration](https://gitlab.com/gitlab-org/gitlab/-/issues/226006). +Note that customer master keys (CMKs) and SSE-C encryption are [not +supported since this requires sending the encryption keys in every request](https://gitlab.com/gitlab-org/gitlab/-/issues/226006). + +##### Server-side encryption headers + +> Introduced in [GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38240). + +Setting a default encryption on an S3 bucket is the easiest way to +enable encryption, but you may want to [set a bucket policy to ensure +only encrypted objects are uploaded](https://aws.amazon.com/premiumsupport/knowledge-center/s3-bucket-store-kms-encrypted-objects/). +To do this, you must configure GitLab to send the proper encryption headers +in the `storage_options` configuration section: + +| Setting | Description | +|-------------------------------------|-------------| +| `server_side_encryption` | Encryption mode (AES256 or aws:kms) | +| `server_side_encryption_kms_key_id` | Amazon Resource Name. Only needed when `aws:kms` is used in `server_side_encryption`. See the [Amazon documentation on using KMS encryption](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingKMSEncryption.html) | + +As with the case for default encryption, these options only work when +the Workhorse S3 client is enabled. One of the following two conditions +must be fulfilled: + +- `use_iam_profile` is `true` in the connection settings. +- Consolidated object storage settings are in use. + +[ETag mismatch errors](#etag-mismatch) will occur if server side +encryption headers are used without enabling the Workhorse S3 client. ##### Disabling the feature The Workhorse S3 client is enabled by default when the -[`use_iam_profile` configuration option](#iam-permissions) is set to `true`. +[`use_iam_profile` configuration option](#iam-permissions) is set to `true` or consolidated +object storage settings are configured. The feature can be disabled using the `:use_workhorse_s3_client` feature flag. To disable the feature, ask a GitLab administrator with diff --git a/doc/administration/operations/cleaning_up_redis_sessions.md b/doc/administration/operations/cleaning_up_redis_sessions.md index 38fac8a0eca..d2aec2f7c47 100644 --- a/doc/administration/operations/cleaning_up_redis_sessions.md +++ b/doc/administration/operations/cleaning_up_redis_sessions.md @@ -15,7 +15,8 @@ prefixed with `session:gitlab:`, so they would look like `session:gitlab:976aa289e2189b17d7ef525a6702ace9`. Below we describe how to remove the keys in the old format. -**Note:** the instructions below must be modified in accordance with your +NOTE: **Note:** +The instructions below must be modified in accordance with your configuration settings if you have used the advanced Redis settings outlined in [Configuration Files Documentation](https://gitlab.com/gitlab-org/gitlab/blob/master/config/README.md). diff --git a/doc/administration/operations/extra_sidekiq_processes.md b/doc/administration/operations/extra_sidekiq_processes.md index 155680354da..e589ecc4216 100644 --- a/doc/administration/operations/extra_sidekiq_processes.md +++ b/doc/administration/operations/extra_sidekiq_processes.md @@ -82,7 +82,7 @@ To start multiple processes: ``` After the extra Sidekiq processes are added, navigate to -**{admin}** **Admin Area > Monitoring > Background Jobs** (`/admin/background_jobs`) in GitLab. +**Admin Area > Monitoring > Background Jobs** (`/admin/background_jobs`) in GitLab. ![Multiple Sidekiq processes](img/sidekiq-cluster.png) diff --git a/doc/administration/operations/filesystem_benchmarking.md b/doc/administration/operations/filesystem_benchmarking.md index 856061348ed..64afd1b44f3 100644 --- a/doc/administration/operations/filesystem_benchmarking.md +++ b/doc/administration/operations/filesystem_benchmarking.md @@ -26,7 +26,7 @@ To install: Then run the following: ```shell -fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --filename=/path/to/git-data/testfile --bs=4k --iodepth=64 --size=4G --readwrite=randrw --rwmixread=75 +fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --bs=4k --iodepth=64 --readwrite=randrw --rwmixread=75 --size=4G --filename=/path/to/git-data/testfile ``` This will create a 4GB file in `/path/to/git-data/testfile`. It performs diff --git a/doc/administration/operations/moving_repositories.md b/doc/administration/operations/moving_repositories.md index 960005fe25d..4763c012538 100644 --- a/doc/administration/operations/moving_repositories.md +++ b/doc/administration/operations/moving_repositories.md @@ -9,16 +9,17 @@ We will look at three scenarios: the target directory is empty, the target directory contains an outdated copy of the repositories, and how to deal with thousands of repositories. -**Each of the approaches we list can/will overwrite data in the +DANGER: **Danger:** +Each of the approaches we list can/will overwrite data in the target directory `/mnt/gitlab/repositories`. Do not mix up the -source and the target.** +source and the target. -## Target directory is empty: use a tar pipe +## Target directory is empty: use a `tar` pipe If the target directory `/mnt/gitlab/repositories` is empty the -simplest thing to do is to use a tar pipe. This method has low -overhead and tar is almost always already installed on your system. -However, it is not possible to resume an interrupted tar pipe: if +simplest thing to do is to use a `tar` pipe. This method has low +overhead and `tar` is almost always already installed on your system. +However, it is not possible to resume an interrupted `tar` pipe: if that happens then all data must be copied again. ```shell @@ -28,9 +29,9 @@ sudo -u git sh -c 'tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\ If you want to see progress, replace `-xf` with `-xvf`. -### Tar pipe to another server +### `tar` pipe to another server -You can also use a tar pipe to copy data to another server. If your +You can also use a `tar` pipe to copy data to another server. If your `git` user has SSH access to the new server as `git@newserver`, you can pipe the data through SSH. @@ -42,13 +43,13 @@ sudo -u git sh -c 'tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\ If you want to compress the data before it goes over the network (which will cost you CPU cycles) you can replace `ssh` with `ssh -C`. -## The target directory contains an outdated copy of the repositories: use rsync +## The target directory contains an outdated copy of the repositories: use `rsync` If the target directory already contains a partial / outdated copy of the repositories it may be wasteful to copy all the data again -with tar. In this scenario it is better to use rsync. This utility +with `tar`. In this scenario it is better to use `rsync`. This utility is either already installed on your system or easily installable -via apt, yum etc. +via `apt`, `yum`, etc. ```shell sudo -u git sh -c 'rsync -a --delete /var/opt/gitlab/git-data/repositories/. \ @@ -59,30 +60,30 @@ The `/.` in the command above is very important, without it you can easily get the wrong directory structure in the target directory. If you want to see progress, replace `-a` with `-av`. -### Single rsync to another server +### Single `rsync` to another server If the `git` user on your source system has SSH access to the target -server you can send the repositories over the network with rsync. +server you can send the repositories over the network with `rsync`. ```shell sudo -u git sh -c 'rsync -a --delete /var/opt/gitlab/git-data/repositories/. \ git@newserver:/mnt/gitlab/repositories' ``` -## Thousands of Git repositories: use one rsync per repository +## Thousands of Git repositories: use one `rsync` per repository -Every time you start an rsync job it has to inspect all files in +Every time you start an `rsync` job it has to inspect all files in the source directory, all files in the target directory, and then decide what files to copy or not. If the source or target directory -has many contents this startup phase of rsync can become a burden -for your GitLab server. In cases like this you can make rsync's +has many contents this startup phase of `rsync` can become a burden +for your GitLab server. In cases like this you can make `rsync`'s life easier by dividing its work in smaller pieces, and sync one repository at a time. -In addition to rsync we will use [GNU +In addition to `rsync` we will use [GNU Parallel](http://www.gnu.org/software/parallel/). This utility is -not included in GitLab so you need to install it yourself with apt -or yum. Also note that the GitLab scripts we used below were added +not included in GitLab so you need to install it yourself with `apt` +or `yum`. Also note that the GitLab scripts we used below were added in GitLab 8.1. **This process does not clean up repositories at the target location that no @@ -90,9 +91,9 @@ longer exist at the source.** If you start using your GitLab instance with `/mnt/gitlab/repositories`, you need to run `gitlab-rake gitlab:cleanup:repos` after switching to the new repository storage directory. -### Parallel rsync for all repositories known to GitLab +### Parallel `rsync` for all repositories known to GitLab -This will sync repositories with 10 rsync processes at a time. We keep +This will sync repositories with 10 `rsync` processes at a time. We keep track of progress so that the transfer can be restarted if necessary. First we create a new directory, owned by `git`, to hold transfer @@ -147,7 +148,7 @@ cat /home/git/transfer-logs/* | sort | uniq -u |\ ` ``` -### Parallel rsync only for repositories with recent activity +### Parallel `rsync` only for repositories with recent activity Suppose you have already done one sync that started after 2015-10-1 12:00 UTC. Then you might only want to sync repositories that were changed via GitLab diff --git a/doc/administration/operations/puma.md b/doc/administration/operations/puma.md index 62b93d40a6b..e7b4bb88faf 100644 --- a/doc/administration/operations/puma.md +++ b/doc/administration/operations/puma.md @@ -27,7 +27,7 @@ will _not_ carry over automatically, due to differences between the two applicat deployments, see [Configuring Puma Settings](https://docs.gitlab.com/omnibus/settings/puma.html#configuring-puma-settings). For Helm based deployments, see the [Webservice Chart documentation](https://docs.gitlab.com/charts/charts/gitlab/webservice/index.html). -Additionally we strongly recommend that multi-node deployments [configure their load balancers to utilize the readiness check](../high_availability/load_balancer.md#readiness-check) due to a difference between Unicorn and Puma in how they handle connections during a restart of the service. +Additionally we strongly recommend that multi-node deployments [configure their load balancers to utilize the readiness check](../load_balancer.md#readiness-check) due to a difference between Unicorn and Puma in how they handle connections during a restart of the service. ## Performance caveat when using Puma with Rugged diff --git a/doc/administration/operations/sidekiq_memory_killer.md b/doc/administration/operations/sidekiq_memory_killer.md index fdccfacc8a9..e829d735c4f 100644 --- a/doc/administration/operations/sidekiq_memory_killer.md +++ b/doc/administration/operations/sidekiq_memory_killer.md @@ -71,5 +71,5 @@ The MemoryKiller is controlled using environment variables. If the process hard shutdown/restart is not performed by Sidekiq, the Sidekiq process will be forcefully terminated after - `Sidekiq.options[:timeout] * 2` seconds. An external supervision mechanism + `Sidekiq.options[:timeout] + 2` seconds. An external supervision mechanism (e.g. runit) must restart Sidekiq afterwards. diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md index 44f1d075a5e..1883f6659e6 100644 --- a/doc/administration/packages/container_registry.md +++ b/doc/administration/packages/container_registry.md @@ -331,6 +331,9 @@ The different supported drivers are: | swift | OpenStack Swift Object Storage | | oss | Aliyun OSS | +NOTE: **Note:** +Although most S3 compatible services (like [MinIO](https://min.io/)) should work with the registry, we only guarantee support for AWS S3. Because we cannot assert the correctness of third-party S3 implementations, we can debug issues, but we cannot patch the registry unless an issue is reproducible against an AWS S3 bucket. + Read more about the individual driver's configuration options in the [Docker Registry docs](https://docs.docker.com/registry/configuration/#storage). @@ -446,27 +449,62 @@ to be in read-only mode for a while. During this time, you can pull from the Container Registry, but you cannot push. 1. Optional: To reduce the amount of data to be migrated, run the [garbage collection tool without downtime](#performing-garbage-collection-without-downtime). -1. Copy initial data to your S3 bucket, for example with the AWS CLI [`cp`](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/cp.html) +1. This example uses the `aws` CLI. If you haven't configured the + CLI before, you have to configure your credentials by running `sudo aws configure`. + Because a non-admin user likely can't access the Container Registry folder, + ensure you use `sudo`. To check your credential configuration, run + [`ls`](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/ls.html) to list + all buckets. + + ```shell + sudo aws --endpoint-url https://your-object-storage-backend.com s3 ls + ``` + + If you are using AWS as your back end, you do not need the [`--endpoint-url`](https://docs.aws.amazon.com/cli/latest/reference/#options). +1. Copy initial data to your S3 bucket, for example with the `aws` CLI + [`cp`](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/cp.html) or [`sync`](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/sync.html) command. Make sure to keep the `docker` folder as the top-level folder inside the bucket. ```shell - aws s3 sync registry s3://mybucket + sudo aws --endpoint-url https://your-object-storage-backend.com s3 sync registry s3://mybucket ``` + TIP: **Tip:** + If you have a lot of data, you may be able to improve performance by + [running parallel sync operations](https://aws.amazon.com/premiumsupport/knowledge-center/s3-improve-transfer-sync-command/). + 1. To perform the final data sync, [put the Container Registry in `read-only` mode](#performing-garbage-collection-without-downtime) and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). 1. Sync any changes since the initial data load to your S3 bucket and delete files that exist in the destination bucket but not in the source: ```shell - aws s3 sync registry s3://mybucket --delete + sudo aws --endpoint-url https://your-object-storage-backend.com s3 sync registry s3://mybucket --delete --dryrun ``` + After verifying the command is going to perform as expected, remove the + [`--dryrun`](https://docs.aws.amazon.com/cli/latest/reference/s3/sync.html) + flag and run the command. + DANGER: **Danger:** - The `--delete` flag will delete files that exist in the destination but not in the source. + The [`--delete`](https://docs.aws.amazon.com/cli/latest/reference/s3/sync.html) + flag will delete files that exist in the destination but not in the source. Make sure not to swap the source and destination, or you will delete all data in the Registry. +1. Verify all Container Registry files have been uploaded to object storage + by looking at the file count returned by these two commands: + + ```shell + sudo find registry -type f | wc -l + ``` + + ```shell + sudo aws --endpoint-url https://your-object-storage-backend.com s3 ls s3://mybucket --recursive | wc -l + ``` + + The output of these commands should match, except for the content in the + `_uploads` directories and sub-directories. 1. Configure your registry to [use the S3 bucket for storage](#use-object-storage). 1. For the changes to take effect, set the Registry back to `read-write` mode and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). @@ -693,6 +731,35 @@ notifications: backoff: 1000 ``` +## Run the Cleanup policy now + +To reduce the amount of [Container Registry disk space used by a given project](../troubleshooting/gitlab_rails_cheat_sheet.md#registry-disk-space-usage-by-project), +administrators can clean up image tags +and [run garbage collection](#container-registry-garbage-collection). + +To remove image tags by running the cleanup policy, run the following commands in the +[GitLab Rails console](../troubleshooting/navigating_gitlab_via_rails_console.md): + +```ruby +# Numeric ID of the project whose container registry should be cleaned up +P = + +# Numeric ID of a developer, maintainer or owner in that project +U = + +# Get required details / objects +user = User.find_by_id(U) +project = Project.find_by_id(P) +repo = ContainerRepository.find_by(project_id: P) +policy = ContainerExpirationPolicy.find_by(project_id: P) + +# Start the tag cleanup +Projects::ContainerRepository::CleanupTagsService.new(project, user, policy.attributes.except("created_at", "updated_at")).execute(repo) +``` + +NOTE: **Note:** +You can also [run cleanup on a schedule](../../user/packages/container_registry/index.md#cleanup-policy). + ## Container Registry garbage collection NOTE: **Note:** diff --git a/doc/administration/packages/index.md b/doc/administration/packages/index.md index 5d07136ef40..3af1f0c933b 100644 --- a/doc/administration/packages/index.md +++ b/doc/administration/packages/index.md @@ -4,7 +4,7 @@ group: Package info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers --- -# GitLab Package Registry administration **(PREMIUM ONLY)** +# GitLab Package Registry administration GitLab Packages allows organizations to utilize GitLab as a private repository for a variety of common package managers. Users are able to build and publish diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md index 4efd92eaa07..9e2aa602767 100644 --- a/doc/administration/pages/index.md +++ b/doc/administration/pages/index.md @@ -114,7 +114,7 @@ since that is needed in all configurations. --- -URL scheme: `http://page.example.io` +URL scheme: `http://.example.io/` This is the minimum setup that you can use Pages with. It is the base for all other setups as described below. NGINX will proxy all requests to the daemon. @@ -139,7 +139,7 @@ Watch the [video tutorial](https://youtu.be/dD8c7WNcc6s) for this configuration. --- -URL scheme: `https://page.example.io` +URL scheme: `https://.example.io/` NGINX will proxy all requests to the daemon. Pages daemon doesn't listen to the outside world. @@ -204,6 +204,7 @@ control over how the Pages daemon runs and serves content in your environment. | `external_https` | Configure Pages to bind to one or more secondary IP addresses, serving HTTPS requests. Multiple addresses can be given as an array, along with exact ports, for example `['1.2.3.4', '1.2.3.5:8063']`. Sets value for `listen_https`. | `gitlab_client_http_timeout` | GitLab API HTTP client connection timeout in seconds (default: 10s). | `gitlab_client_jwt_expiry` | JWT Token expiry time in seconds (default: 30s). +| `domain_config_source` | Domain configuration source (default: `disk`) | `gitlab_id` | The OAuth application public ID. Leave blank to automatically fill when Pages authenticates with GitLab. | `gitlab_secret` | The OAuth application secret. Leave blank to automatically fill when Pages authenticates with GitLab. | `gitlab_server` | Server to use for authentication when access control is enabled; defaults to GitLab `external_url`. @@ -254,7 +255,7 @@ you have IPv6 as well as IPv4 addresses, you can use them both. --- -URL scheme: `http://page.example.io` and `http://domain.com` +URL scheme: `http://.example.io/` and `http://custom-domain.com` In that case, the Pages daemon is running, NGINX still proxies requests to the daemon but the daemon is also able to receive requests from the outside @@ -285,7 +286,7 @@ world. Custom domains are supported, but no TLS. --- -URL scheme: `https://page.example.io` and `https://domain.com` +URL scheme: `https://.example.io/` and `https://custom-domain.com` In that case, the Pages daemon is running, NGINX still proxies requests to the daemon but the daemon is also able to receive requests from the outside @@ -388,9 +389,9 @@ To do that: 1. Click **Save changes**. CAUTION: **Warning:** -This action will not make all currently public web-sites private until they redeployed. -This issue among others will be resolved by -[changing GitLab Pages configuration mechanism](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/282). +For self-managed installations, all public websites remain private until they are +redeployed. This issue will be resolved by +[sourcing domain configuration from the GitLab API](https://gitlab.com/gitlab-org/gitlab/-/issues/218357). ### Running behind a proxy @@ -409,7 +410,7 @@ pages: ### Using a custom Certificate Authority (CA) NOTE: **Note:** -[Before 13.2](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4289), when using Omnibus, a [workaround was required](https://docs.gitlab.com/13.1/ee/administration/pages/index.html#using-a-custom-certificate-authority-ca). +[Before 13.3](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4411), when using Omnibus, a [workaround was required](https://docs.gitlab.com/13.1/ee/administration/pages/index.html#using-a-custom-certificate-authority-ca). When using certificates issued by a custom CA, [Access Control](../../user/project/pages/pages_access_control.md#gitlab-pages-access-control) and the [online view of HTML job artifacts](../../ci/pipelines/job_artifacts.md#browsing-artifacts) @@ -536,7 +537,7 @@ database encryption. Proceed with caution. 1. Set up a new server. This will become the **Pages server**. -1. Create an [NFS share](../high_availability/nfs_host_client_setup.md) +1. Create an [NFS share](../nfs.md) on the **Pages server** and configure this share to allow access from your main **GitLab server**. Note that the example there is more general and @@ -601,6 +602,43 @@ configuring a load balancer to work at the IP level, and so on. If you wish to set up GitLab Pages on multiple servers, perform the above procedure for each Pages server. +## Domain source configuration + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217912) in GitLab 13.3. + +GitLab Pages can use different sources to get domain configuration. +The default value is `nil`; however, GitLab Pages will default to `disk`. + + ```ruby + gitlab_pages['domain_config_source'] = nil + ``` + +You can specify `gitlab` to enable [API-based configuration](#gitlab-api-based-configuration). + +For more details see this [blog post](https://about.gitlab.com/blog/2020/08/03/how-gitlab-pages-uses-the-gitlab-api-to-serve-content/). + +### GitLab API-based configuration + +GitLab Pages can use an API-based configuration. This replaces disk source configuration, which +was used prior to GitLab 13.0. Follow these steps to enable it: + +1. Add the following to your `/etc/gitlab/gitlab.erb` file: + + ```ruby + gitlab_pages['domain_config_source'] = "gitlab" + ``` + +1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + +If you encounter an issue, you can disable it by choosing `disk` or `nil`: + +```ruby +gitlab_pages['domain_config_source'] = nil +``` + +For other common issues, see the [troubleshooting section](#failed-to-connect-to-the-internal-gitlab-api) +or report an issue. + ## Backup GitLab Pages are part of the [regular backup](../../raketasks/backup_restore.md), so there is no separate backup to configure. @@ -696,3 +734,24 @@ date > /var/opt/gitlab/gitlab-rails/shared/pages/.update ``` If you've customized the Pages storage path, adjust the command above to use your custom path. + +### Failed to connect to the internal GitLab API + +If you have enabled [API-based configuration](#gitlab-api-based-configuration) and see the following error: + +```plaintext +ERRO[0010] Failed to connect to the internal GitLab API after 0.50s error="failed to connect to internal Pages API: HTTP status: 401" +``` + +If you are [Running GitLab Pages on a separate server](#running-gitlab-pages-on-a-separate-server) +you must copy the `/etc/gitlab/gitlab-secrets.json` file +from the **GitLab server** to the **Pages server** after upgrading to GitLab 13.3, +as described in that section. + +Other reasons may include network connectivity issues between your +**GitLab server** and your **Pages server** such as firewall configurations or closed ports. +For example, if there is a connection timeout: + +```plaintext +error="failed to connect to internal Pages API: Get \"https://gitlab.example.com:3000/api/v4/internal/pages/status\": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)" +``` diff --git a/doc/administration/pages/source.md b/doc/administration/pages/source.md index d5b49bdf839..486bc7a8777 100644 --- a/doc/administration/pages/source.md +++ b/doc/administration/pages/source.md @@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w # GitLab Pages administration for source installations ->**Note:** +NOTE: **Note:** Before attempting to enable GitLab Pages, first make sure you have [installed GitLab](../../install/installation.md) successfully. @@ -77,7 +77,7 @@ host that GitLab runs. For example, an entry would look like this: where `example.io` is the domain under which GitLab Pages will be served and `192.0.2.1` is the IP address of your GitLab instance. -> **Note:** +NOTE: **Note:** You should not use the GitLab domain to serve user pages. For more information see the [security section](#security). @@ -94,7 +94,7 @@ since that is needed in all configurations. - [Wildcard DNS setup](#dns-configuration) -URL scheme: `http://page.example.io` +URL scheme: `http://.example.io/` This is the minimum setup that you can use Pages with. It is the base for all other setups as described below. NGINX will proxy all requests to the daemon. @@ -157,7 +157,7 @@ The Pages daemon doesn't listen to the outside world. - [Wildcard DNS setup](#dns-configuration) - Wildcard TLS certificate -URL scheme: `https://page.example.io` +URL scheme: `https://.example.io/` NGINX will proxy all requests to the daemon. Pages daemon doesn't listen to the outside world. @@ -221,7 +221,7 @@ that without TLS certificates. - [Wildcard DNS setup](#dns-configuration) - Secondary IP -URL scheme: `http://page.example.io` and `http://domain.com` +URL scheme: `http://.example.io/` and `http://custom-domain.com` In that case, the pages daemon is running, NGINX still proxies requests to the daemon but the daemon is also able to receive requests from the outside @@ -286,7 +286,7 @@ world. Custom domains are supported, but no TLS. - Wildcard TLS certificate - Secondary IP -URL scheme: `https://page.example.io` and `https://domain.com` +URL scheme: `https://.example.io/` and `https://custom-domain.com` In that case, the pages daemon is running, NGINX still proxies requests to the daemon but the daemon is also able to receive requests from the outside @@ -349,7 +349,7 @@ world. Custom domains and TLS are supported. ## NGINX caveats ->**Note:** +NOTE: **Note:** The following information applies only for installations from source. Be extra careful when setting up the domain name in the NGINX configuration. You must diff --git a/doc/administration/postgresql/external.md b/doc/administration/postgresql/external.md index 6e2bbc0aae1..e2cfb95ec48 100644 --- a/doc/administration/postgresql/external.md +++ b/doc/administration/postgresql/external.md @@ -32,7 +32,7 @@ If you use a cloud-managed service, or provide your own PostgreSQL instance: gitlab_rails['db_password'] = 'DB password' ``` - For more information on GitLab HA setups, refer to [configuring GitLab for HA](../high_availability/gitlab.md). + For more information on GitLab multi-node setups, refer to the [reference architectures](../reference_architectures/index.md). 1. Reconfigure for the changes to take effect: diff --git a/doc/administration/postgresql/index.md b/doc/administration/postgresql/index.md index 7e0a2f3cae1..2720d8e696b 100644 --- a/doc/administration/postgresql/index.md +++ b/doc/administration/postgresql/index.md @@ -13,7 +13,7 @@ There are essentially three setups to choose from. This setup is for when you have installed GitLab using the [Omnibus GitLab **Enterprise Edition** (EE) package](https://about.gitlab.com/install/?version=ee). -All the tools that are needed like PostgreSQL, PgBouncer, Repmgr are bundled in +All the tools that are needed like PostgreSQL, PgBouncer, Patroni, and repmgr are bundled in the package, so you can it to set up the whole PostgreSQL infrastructure (primary, replica). [> Read how to set up PostgreSQL replication and failover using Omnibus GitLab](replication_and_failover.md) diff --git a/doc/administration/postgresql/pgbouncer.md b/doc/administration/postgresql/pgbouncer.md new file mode 100644 index 00000000000..9db3e017359 --- /dev/null +++ b/doc/administration/postgresql/pgbouncer.md @@ -0,0 +1,168 @@ +--- +type: reference +--- + +# Working with the bundled PgBouncer service **(PREMIUM ONLY)** + +[PgBouncer](http://www.pgbouncer.org/) is used to seamlessly migrate database +connections between servers in a failover scenario. Additionally, it can be used +in a non-fault-tolerant setup to pool connections, speeding up response time +while reducing resource usage. + +GitLab Premium includes a bundled version of PgBouncer that can be managed +through `/etc/gitlab/gitlab.rb`. + +## PgBouncer as part of a fault-tolerant GitLab installation + +This content has been moved to a [new location](replication_and_failover.md#configuring-the-pgbouncer-node). + +## PgBouncer as part of a non-fault-tolerant GitLab installation + +1. Generate PGBOUNCER_USER_PASSWORD_HASH with the command `gitlab-ctl pg-password-md5 pgbouncer` + +1. Generate SQL_USER_PASSWORD_HASH with the command `gitlab-ctl pg-password-md5 gitlab`. We'll also need to enter the plaintext SQL_USER_PASSWORD later + +1. On your database node, ensure the following is set in your `/etc/gitlab/gitlab.rb` + + ```ruby + postgresql['pgbouncer_user_password'] = 'PGBOUNCER_USER_PASSWORD_HASH' + postgresql['sql_user_password'] = 'SQL_USER_PASSWORD_HASH' + postgresql['listen_address'] = 'XX.XX.XX.Y' # Where XX.XX.XX.Y is the ip address on the node postgresql should listen on + postgresql['md5_auth_cidr_addresses'] = %w(AA.AA.AA.B/32) # Where AA.AA.AA.B is the IP address of the pgbouncer node + ``` + +1. Run `gitlab-ctl reconfigure` + + NOTE: **Note:** + If the database was already running, it will need to be restarted after reconfigure by running `gitlab-ctl restart postgresql`. + +1. On the node you are running PgBouncer on, make sure the following is set in `/etc/gitlab/gitlab.rb` + + ```ruby + pgbouncer['enable'] = true + pgbouncer['databases'] = { + gitlabhq_production: { + host: 'DATABASE_HOST', + user: 'pgbouncer', + password: 'PGBOUNCER_USER_PASSWORD_HASH' + } + } + ``` + +1. Run `gitlab-ctl reconfigure` + +1. On the node running Puma, make sure the following is set in `/etc/gitlab/gitlab.rb` + + ```ruby + gitlab_rails['db_host'] = 'PGBOUNCER_HOST' + gitlab_rails['db_port'] = '6432' + gitlab_rails['db_password'] = 'SQL_USER_PASSWORD' + ``` + +1. Run `gitlab-ctl reconfigure` + +1. At this point, your instance should connect to the database through PgBouncer. If you are having issues, see the [Troubleshooting](#troubleshooting) section + +## Enable Monitoring + +> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3786) in GitLab 12.0. + +If you enable Monitoring, it must be enabled on **all** PgBouncer servers. + +1. Create/edit `/etc/gitlab/gitlab.rb` and add the following configuration: + + ```ruby + # Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + # Replace placeholders + # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z + # with the addresses of the Consul server nodes + consul['configuration'] = { + retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + pgbouncer_exporter['listen_address'] = '0.0.0.0:9188' + ``` + +1. Run `sudo gitlab-ctl reconfigure` to compile the configuration. + +## Administrative console + +As part of Omnibus GitLab, a command is provided to automatically connect to the +PgBouncer administrative console. See the +[PgBouncer documentation](https://www.pgbouncer.org/usage.html#admin-console) +for detailed instructions on how to interact with the console. + +To start a session run the following and provide the password for the `pgbouncer` +user: + +```shell +sudo gitlab-ctl pgb-console +``` + +To get some basic information about the instance: + +```shell +pgbouncer=# show databases; show clients; show servers; + name | host | port | database | force_user | pool_size | reserve_pool | pool_mode | max_connections | current_connections +---------------------+-----------+------+---------------------+------------+-----------+--------------+-----------+-----------------+--------------------- + gitlabhq_production | 127.0.0.1 | 5432 | gitlabhq_production | | 100 | 5 | | 0 | 1 + pgbouncer | | 6432 | pgbouncer | pgbouncer | 2 | 0 | statement | 0 | 0 +(2 rows) + + type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link +| remote_pid | tls +------+-----------+---------------------+--------+-----------+-------+------------+------------+---------------------+---------------------+-----------+------ ++------------+----- + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44590 | 127.0.0.1 | 6432 | 2018-04-24 22:13:10 | 2018-04-24 22:17:10 | 0x12444c0 | +| 0 | + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44592 | 127.0.0.1 | 6432 | 2018-04-24 22:13:10 | 2018-04-24 22:17:10 | 0x12447c0 | +| 0 | + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44594 | 127.0.0.1 | 6432 | 2018-04-24 22:13:10 | 2018-04-24 22:17:10 | 0x1244940 | +| 0 | + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44706 | 127.0.0.1 | 6432 | 2018-04-24 22:14:22 | 2018-04-24 22:16:31 | 0x1244ac0 | +| 0 | + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44708 | 127.0.0.1 | 6432 | 2018-04-24 22:14:22 | 2018-04-24 22:15:15 | 0x1244c40 | +| 0 | + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44794 | 127.0.0.1 | 6432 | 2018-04-24 22:15:15 | 2018-04-24 22:15:15 | 0x1244dc0 | +| 0 | + C | gitlab | gitlabhq_production | active | 127.0.0.1 | 44798 | 127.0.0.1 | 6432 | 2018-04-24 22:15:15 | 2018-04-24 22:16:31 | 0x1244f40 | +| 0 | + C | pgbouncer | pgbouncer | active | 127.0.0.1 | 44660 | 127.0.0.1 | 6432 | 2018-04-24 22:13:51 | 2018-04-24 22:17:12 | 0x1244640 | +| 0 | +(8 rows) + + type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link | rem +ote_pid | tls +------+--------+---------------------+-------+-----------+------+------------+------------+---------------------+---------------------+-----------+------+---- +--------+----- + S | gitlab | gitlabhq_production | idle | 127.0.0.1 | 5432 | 127.0.0.1 | 35646 | 2018-04-24 22:15:15 | 2018-04-24 22:17:10 | 0x124dca0 | | + 19980 | +(1 row) +``` + +## Troubleshooting + +In case you are experiencing any issues connecting through PgBouncer, the first +place to check is always the logs: + +```shell +sudo gitlab-ctl tail pgbouncer +``` + +Additionally, you can check the output from `show databases` in the +[administrative console](#administrative-console). In the output, you would expect +to see values in the `host` field for the `gitlabhq_production` database. +Additionally, `current_connections` should be greater than 1. + +### Message: `LOG: invalid CIDR mask in address` + +See the suggested fix [in Geo documentation](../geo/replication/troubleshooting.md#message-log--invalid-cidr-mask-in-address). + +### Message: `LOG: invalid IP mask "md5": Name or service not known` + +See the suggested fix [in Geo documentation](../geo/replication/troubleshooting.md#message-log--invalid-ip-mask-md5-name-or-service-not-known). diff --git a/doc/administration/postgresql/replication_and_failover.md b/doc/administration/postgresql/replication_and_failover.md index 5f550f09e5b..bc2af167e6c 100644 --- a/doc/administration/postgresql/replication_and_failover.md +++ b/doc/administration/postgresql/replication_and_failover.md @@ -29,6 +29,11 @@ You also need to take into consideration the underlying network topology, making sure you have redundant connectivity between all Database and GitLab instances to avoid the network becoming a single point of failure. +NOTE: **Note:** +As of GitLab 13.3, PostgreSQL 12 is shipped with Omnibus GitLab. Clustering for PostgreSQL 12 is only supported with +Patroni. See the [Patroni](#patroni) section for further details. The support for repmgr will not be extended beyond +PostgreSQL 11. + ### Database node Each database node runs three services: @@ -97,7 +102,7 @@ This is why you will need: When using default setup, minimum configuration requires: -- `CONSUL_USERNAME`. Defaults to `gitlab-consul` +- `CONSUL_USERNAME`. The default user for Omnibus GitLab is `gitlab-consul` - `CONSUL_DATABASE_PASSWORD`. Password for the database user. - `CONSUL_PASSWORD_HASH`. This is a hash generated out of Consul username/password pair. Can be generated with: @@ -140,7 +145,7 @@ server nodes. We will need the following password information for the application's database user: -- `POSTGRESQL_USERNAME`. Defaults to `gitlab` +- `POSTGRESQL_USERNAME`. The default user for Omnibus GitLab is `gitlab` - `POSTGRESQL_USER_PASSWORD`. The password for the database user - `POSTGRESQL_PASSWORD_HASH`. This is a hash generated out of the username/password pair. Can be generated with: @@ -153,7 +158,7 @@ We will need the following password information for the application's database u When using default setup, minimum configuration requires: -- `PGBOUNCER_USERNAME`. Defaults to `pgbouncer` +- `PGBOUNCER_USERNAME`. The default user for Omnibus GitLab is `pgbouncer` - `PGBOUNCER_PASSWORD`. This is a password for PgBouncer service. - `PGBOUNCER_PASSWORD_HASH`. This is a hash generated out of PgBouncer username/password pair. Can be generated with: @@ -198,7 +203,7 @@ When installing the GitLab package, do not supply `EXTERNAL_URL` value. ### Configuring the Database nodes -1. Make sure to [configure the Consul nodes](../high_availability/consul.md). +1. Make sure to [configure the Consul nodes](../consul.md). 1. Make sure you collect [`CONSUL_SERVER_NODES`](#consul-information), [`PGBOUNCER_PASSWORD_HASH`](#pgbouncer-information), [`POSTGRESQL_PASSWORD_HASH`](#postgresql-information), the [number of db nodes](#postgresql-information), and the [network address](#network-information) before executing the next step. 1. On the master database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section: @@ -305,6 +310,12 @@ Select one node as a primary node. CREATE EXTENSION pg_trgm; ``` +1. Enable the `btree_gist` extension: + + ```shell + CREATE EXTENSION btree_gist; + ``` + 1. Exit the database prompt by typing `\q` and Enter. 1. Verify the cluster is initialized with one node: @@ -455,7 +466,7 @@ Check the [Troubleshooting section](#troubleshooting) before proceeding. gitlab-ctl write-pgpass --host 127.0.0.1 --database pgbouncer --user pgbouncer --hostuser gitlab-consul ``` -1. [Enable monitoring](../high_availability/pgbouncer.md#enable-monitoring) +1. [Enable monitoring](../postgresql/pgbouncer.md#enable-monitoring) #### PgBouncer Checkpoint @@ -736,9 +747,9 @@ consul['configuration'] = { After deploying the configuration follow these steps: -1. On `10.6.0.31`, our primary database +1. On `10.6.0.31`, our primary database: - Enable the `pg_trgm` extension + Enable the `pg_trgm` and `btree_gist` extensions: ```shell gitlab-psql -d gitlabhq_production @@ -746,33 +757,34 @@ After deploying the configuration follow these steps: ```shell CREATE EXTENSION pg_trgm; + CREATE EXTENSION btree_gist; ``` -1. On `10.6.0.32`, our first standby database +1. On `10.6.0.32`, our first standby database: - Make this node a standby of the primary + Make this node a standby of the primary: ```shell gitlab-ctl repmgr standby setup 10.6.0.21 ``` -1. On `10.6.0.33`, our second standby database +1. On `10.6.0.33`, our second standby database: - Make this node a standby of the primary + Make this node a standby of the primary: ```shell gitlab-ctl repmgr standby setup 10.6.0.21 ``` -1. On `10.6.0.41`, our application server +1. On `10.6.0.41`, our application server: - Set `gitlab-consul` user's PgBouncer password to `toomanysecrets` + Set `gitlab-consul` user's PgBouncer password to `toomanysecrets`: ```shell gitlab-ctl write-pgpass --host 127.0.0.1 --database pgbouncer --user pgbouncer --hostuser gitlab-consul ``` - Run database migrations + Run database migrations: ```shell gitlab-rake gitlab:db:configure @@ -783,7 +795,7 @@ After deploying the configuration follow these steps: This example uses 3 PostgreSQL servers, and 1 application node (with PgBouncer setup alongside). It differs from the [recommended setup](#example-recommended-setup) by moving the Consul servers into the same servers we use for PostgreSQL. -The trade-off is between reducing server counts, against the increased operational complexity of needing to deal with PostgreSQL [failover](#failover-procedure) and [restore](#restore-procedure) procedures in addition to [Consul outage recovery](../high_availability/consul.md#outage-recovery) on the same set of machines. +The trade-off is between reducing server counts, against the increased operational complexity of needing to deal with PostgreSQL [failover](#failover-procedure) and [restore](#restore-procedure) procedures in addition to [Consul outage recovery](../consul.md#outage-recovery) on the same set of machines. In this example we start with all servers on the same 10.6.0.0/16 private network range, they can connect to each freely other on those addresses. @@ -1075,7 +1087,7 @@ To restart either service, run `gitlab-ctl restart SERVICE` For PostgreSQL, it is usually safe to restart the master node by default. Automatic failover defaults to a 1 minute timeout. Provided the database returns before then, nothing else needs to be done. To be safe, you can stop `repmgrd` on the standby nodes first with `gitlab-ctl stop repmgrd`, then start afterwards with `gitlab-ctl start repmgrd`. -On the Consul server nodes, it is important to restart the Consul service in a controlled fashion. Read our [Consul documentation](../high_availability/consul.md#restarting-the-server-cluster) for instructions on how to restart the service. +On the Consul server nodes, it is important to [restart the Consul service](../consul.md#restart-consul) in a controlled manner. ### `gitlab-ctl repmgr-check-master` command produces errors @@ -1122,11 +1134,10 @@ postgresql['trust_auth_cidr_addresses'] = %w(123.123.123.123/32 ) ### Issues with other components -If you're running into an issue with a component not outlined here, be sure to check the troubleshooting section of their specific documentation page. +If you're running into an issue with a component not outlined here, be sure to check the troubleshooting section of their specific documentation page: -- [Consul](../high_availability/consul.md#troubleshooting) +- [Consul](../consul.md#troubleshooting-consul) - [PostgreSQL](https://docs.gitlab.com/omnibus/settings/database.html#troubleshooting) -- [GitLab application](../high_availability/gitlab.md#troubleshooting) ## Patroni @@ -1324,7 +1335,7 @@ You can switch an exiting database cluster to use Patroni instead of repmgr with NOTE: **Note:** Ensure that there is no `walsender` process running on the primary node. - `ps aux | grep walsender` must not show any running process. + `ps aux | grep walsender` must not show any running process. 1. On the primary node, [configure Patroni](#configuring-patroni-cluster). Remove `repmgr` and any other repmgr-specific configuration. Also remove any configuration that is related to PostgreSQL replication. diff --git a/doc/administration/raketasks/check.md b/doc/administration/raketasks/check.md index da5caf3966f..15014fffd01 100644 --- a/doc/administration/raketasks/check.md +++ b/doc/administration/raketasks/check.md @@ -135,3 +135,22 @@ The LDAP check Rake task will test the bind DN and password credentials (if configured) and will list a sample of LDAP users. This task is also executed as part of the `gitlab:check` task, but can run independently. See [LDAP Rake Tasks - LDAP Check](ldap.md#check) for details. + +## Troubleshooting + +The following are solutions to problems you might discover using the Rake tasks documented +above. + +### Dangling commits + +`gitlab:git:fsck` can find dangling commits. To fix them, try +[manually triggering housekeeping](../housekeeping.md#manual-housekeeping) +for the affected project(s). + +If the issue persists, try triggering `gc` via the +[Rails Console](../troubleshooting/navigating_gitlab_via_rails_console.md#starting-a-rails-console-session): + +```ruby +p = Project.find_by_path("project-name") +Projects::HousekeepingService.new(p, :gc).execute +``` diff --git a/doc/administration/raketasks/maintenance.md b/doc/administration/raketasks/maintenance.md index 19781b6a5db..553afba78e3 100644 --- a/doc/administration/raketasks/maintenance.md +++ b/doc/administration/raketasks/maintenance.md @@ -23,32 +23,39 @@ Example output: ```plaintext System information -System: Debian 7.8 -Current User: git -Using RVM: no -Ruby Version: 2.1.5p273 -Gem Version: 2.4.3 -Bundler Version: 1.7.6 -Rake Version: 10.3.2 -Redis Version: 3.2.5 -Sidekiq Version: 2.17.8 +System: Ubuntu 20.04 +Proxy: no +Current User: git +Using RVM: no +Ruby Version: 2.6.6p146 +Gem Version: 2.7.10 +Bundler Version:1.17.3 +Rake Version: 12.3.3 +Redis Version: 5.0.9 +Git Version: 2.27.0 +Sidekiq Version:5.2.9 +Go Version: unknown GitLab information -Version: 7.7.1 -Revision: 41ab9e1 -Directory: /home/git/gitlab -DB Adapter: postgresql -URL: https://gitlab.example.com -HTTP Clone URL: https://gitlab.example.com/some-project.git -SSH Clone URL: git@gitlab.example.com:some-project.git -Using LDAP: no -Using Omniauth: no +Version: 13.2.2-ee +Revision: 618883a1f9d +Directory: /opt/gitlab/embedded/service/gitlab-rails +DB Adapter: PostgreSQL +DB Version: 11.7 +URL: http://gitlab.example.com +HTTP Clone URL: http://gitlab.example.com/some-group/some-project.git +SSH Clone URL: git@gitlab.example.com:some-group/some-project.git +Elasticsearch: no +Geo: no +Using LDAP: no +Using Omniauth: yes +Omniauth Providers: GitLab Shell -Version: 2.4.1 -Repositories: /home/git/repositories/ -Hooks: /home/git/gitlab-shell/hooks/ -Git: /usr/bin/git +Version: 13.3.0 +Repository storage paths: +- default: /var/opt/gitlab/git-data/repositories +GitLab Shell path: /opt/gitlab/embedded/service/gitlab-shell ``` ## Show GitLab license information **(STARTER ONLY)** diff --git a/doc/administration/raketasks/project_import_export.md b/doc/administration/raketasks/project_import_export.md index b807e03b01f..51e0e2e46b6 100644 --- a/doc/administration/raketasks/project_import_export.md +++ b/doc/administration/raketasks/project_import_export.md @@ -46,6 +46,6 @@ Note the following: compatible as described in the [Version history](../../user/project/settings/import_export.md#version-history). - The project import option must be enabled in application settings (`/admin/application_settings/general`) under **Import sources**, which is available - under **{admin}** **Admin Area >** **{settings}** **Settings > Visibility and access controls**. + under **Admin Area > Settings > Visibility and access controls**. - The exports are stored in a temporary [shared directory](../../development/shared_files.md) and are deleted every 24 hours by a specific worker. diff --git a/doc/administration/raketasks/storage.md b/doc/administration/raketasks/storage.md index 74fd2c2ebb6..a97bff83290 100644 --- a/doc/administration/raketasks/storage.md +++ b/doc/administration/raketasks/storage.md @@ -100,7 +100,7 @@ to project IDs 50 to 100 in an Omnibus GitLab installation: sudo gitlab-rake gitlab:storage:migrate_to_hashed ID_FROM=50 ID_TO=100 ``` -You can monitor the progress in the **{admin}** **Admin Area > Monitoring > Background Jobs** page. +You can monitor the progress in the **Admin Area > Monitoring > Background Jobs** page. There is a specific queue you can watch to see how long it will take to finish: `hashed_storage:hashed_storage_project_migrate`. @@ -150,7 +150,7 @@ to project IDs 50 to 100 in an Omnibus GitLab installation: sudo gitlab-rake gitlab:storage:rollback_to_legacy ID_FROM=50 ID_TO=100 ``` -You can monitor the progress in the **{admin}** **Admin Area > Monitoring > Background Jobs** page. +You can monitor the progress in the **Admin Area > Monitoring > Background Jobs** page. On the **Queues** tab, you can watch the `hashed_storage:hashed_storage_project_rollback` queue to see how long the process will take to finish. After it reaches zero, you can confirm every project has been rolled back by running the commands bellow. diff --git a/doc/administration/raketasks/uploads/migrate.md b/doc/administration/raketasks/uploads/migrate.md index b164c4e744d..8c020e91a15 100644 --- a/doc/administration/raketasks/uploads/migrate.md +++ b/doc/administration/raketasks/uploads/migrate.md @@ -141,7 +141,15 @@ keeping in mind the task name in this case is `gitlab:uploads:migrate_to_local`. To migrate uploads from object storage to local storage: -1. Disable both `direct_upload` and `background_upload` under `uploads` settings in `gitlab.rb`. +1. Disable both `direct_upload` and `background_upload` under `uploads` settings in `gitlab.rb`: + + ```ruby + gitlab_rails['uploads_object_store_direct_upload'] = false + gitlab_rails['uploads_object_store_background_upload'] = false + ``` + + Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure). + 1. Run the Rake task: **Omnibus Installation** diff --git a/doc/administration/redis/replication_and_failover.md b/doc/administration/redis/replication_and_failover.md index ac31b909c89..ca041adb1d8 100644 --- a/doc/administration/redis/replication_and_failover.md +++ b/doc/administration/redis/replication_and_failover.md @@ -466,7 +466,7 @@ While it doesn't require a list of all Sentinel nodes, in case of a failure, it needs to access at least one of the listed. NOTE: **Note:** -The following steps should be performed in the [GitLab application server](../high_availability/gitlab.md) +The following steps should be performed in the GitLab application server which ideally should not have Redis or Sentinels on it for a HA setup. 1. SSH into the server where the GitLab application is installed. @@ -637,47 +637,63 @@ lives easier. If you want to know what happens underneath keep reading. ### Running multiple Redis clusters -GitLab supports running [separate Redis clusters for different persistent -classes](https://docs.gitlab.com/omnibus/settings/redis.html#running-with-multiple-redis-instances): -cache, queues, and shared_state. To make this work with Sentinel: +Omnibus GitLab supports running separate Redis and Sentinel instances for different +persistence classes. -1. Set the appropriate variable in `/etc/gitlab/gitlab.rb` for each instance you are using: +| Class | Purpose | +| -------------- | ------------------------------------------------ | +| `cache` | Store cached data. | +| `queues` | Store Sidekiq background jobs. | +| `shared_state` | Store session-related and other persistent data. | +| `actioncable` | Pub/Sub queue backend for ActionCable. | + +To make this work with Sentinel: + +1. [Configure the different Redis/Sentinels](#configuring-redis) instances based on your needs. +1. For each Rails application instance, edit its `/etc/gitlab/gitlab.rb` file: ```ruby gitlab_rails['redis_cache_instance'] = REDIS_CACHE_URL gitlab_rails['redis_queues_instance'] = REDIS_QUEUES_URL gitlab_rails['redis_shared_state_instance'] = REDIS_SHARED_STATE_URL - ``` - - **Note**: Redis URLs should be in the format: `redis://:PASSWORD@SENTINEL_PRIMARY_NAME` + gitlab_rails['redis_actioncable_instance'] = REDIS_ACTIONCABLE_URL - 1. PASSWORD is the plaintext password for the Redis instance - 1. SENTINEL_PRIMARY_NAME is the Sentinel primary name (e.g. `gitlab-redis-cache`) - -1. Include an array of hashes with host/port combinations, such as the following: - - ```ruby + # Configure the Sentinels gitlab_rails['redis_cache_sentinels'] = [ - { host: REDIS_CACHE_SENTINEL_HOST, port: PORT1 }, - { host: REDIS_CACHE_SENTINEL_HOST2, port: PORT2 } + { host: REDIS_CACHE_SENTINEL_HOST, port: 26379 }, + { host: REDIS_CACHE_SENTINEL_HOST2, port: 26379 } ] gitlab_rails['redis_queues_sentinels'] = [ - { host: REDIS_QUEUES_SENTINEL_HOST, port: PORT1 }, - { host: REDIS_QUEUES_SENTINEL_HOST2, port: PORT2 } + { host: REDIS_QUEUES_SENTINEL_HOST, port: 26379 }, + { host: REDIS_QUEUES_SENTINEL_HOST2, port: 26379 } ] gitlab_rails['redis_shared_state_sentinels'] = [ - { host: SHARED_STATE_SENTINEL_HOST, port: PORT1 }, - { host: SHARED_STATE_SENTINEL_HOST2, port: PORT2 } + { host: SHARED_STATE_SENTINEL_HOST, port: 26379 }, + { host: SHARED_STATE_SENTINEL_HOST2, port: 26379 } + ] + gitlab_rails['redis_actioncable_sentinels'] = [ + { host: ACTIONCABLE_SENTINEL_HOST, port: 26379 }, + { host: ACTIONCABLE_SENTINEL_HOST2, port: 26379 } ] ``` -1. Note that for each persistence class, GitLab will default to using the - configuration specified in `gitlab_rails['redis_sentinels']` unless - overridden by the settings above. -1. Be sure to include BOTH configuration options for each persistent classes. For example, - if you choose to configure a cache instance, you must specify both `gitlab_rails['redis_cache_instance']` - and `gitlab_rails['redis_cache_sentinels']` for GitLab to generate the proper configuration files. -1. Run `gitlab-ctl reconfigure` + Note that: + + - Redis URLs should be in the format: `redis://:PASSWORD@SENTINEL_PRIMARY_NAME`, where: + - `PASSWORD` is the plaintext password for the Redis instance. + - `SENTINEL_PRIMARY_NAME` is the Sentinel primary name set with `redis['master_name']`, + for example `gitlab-redis-cache`. + +1. Save the file and reconfigure GitLab for the change to take effect: + + ```shell + sudo gitlab-ctl reconfigure + ``` + +NOTE: **Note:** +For each persistence class, GitLab will default to using the +configuration specified in `gitlab_rails['redis_sentinels']` unless +overridden by the previously described settings. ### Control running services @@ -736,6 +752,5 @@ Read more: 1. [Reference architectures](../reference_architectures/index.md) 1. [Configure the database](../postgresql/replication_and_failover.md) -1. [Configure NFS](../high_availability/nfs.md) -1. [Configure the GitLab application servers](../high_availability/gitlab.md) -1. [Configure the load balancers](../high_availability/load_balancer.md) +1. [Configure NFS](../nfs.md) +1. [Configure the load balancers](../load_balancer.md) diff --git a/doc/administration/redis/replication_and_failover_external.md b/doc/administration/redis/replication_and_failover_external.md index 244b44dd76a..d530e6a8fd7 100644 --- a/doc/administration/redis/replication_and_failover_external.md +++ b/doc/administration/redis/replication_and_failover_external.md @@ -19,13 +19,7 @@ The following are the requirements for providing your own Redis instance: - Redis version 5.0 or higher is recommended, as this is what ships with Omnibus GitLab packages starting with GitLab 12.7. -- Support for Redis 3.2 is deprecated with GitLab 12.10 and will be completely - removed in GitLab 13.0. -- GitLab 12.0 and later requires Redis version 3.2 or higher. Older Redis - versions do not support an optional count argument to SPOP which is now - required for [Merge Trains](../../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md). -- In addition, if Redis 4 or later is available, GitLab makes use of certain - commands like `UNLINK` and `USAGE` which were introduced only in Redis 4. +- GitLab 13.0 and later requires Redis version 4.0 or higher. - Standalone Redis or Redis high availability with Sentinel are supported. Redis Cluster is not supported. - Managed Redis from cloud providers such as AWS ElastiCache will work. If these @@ -221,7 +215,7 @@ the correct credentials for the Sentinel nodes. While it doesn't require a list of all Sentinel nodes, in case of a failure, it needs to access at least one of listed ones. -The following steps should be performed in the [GitLab application server](../high_availability/gitlab.md) +The following steps should be performed in the GitLab application server which ideally should not have Redis or Sentinels in the same machine: 1. Edit `/home/git/gitlab/config/resque.yml` following the example in diff --git a/doc/administration/redis/standalone.md b/doc/administration/redis/standalone.md index 12e932dbc5e..ea5a7850244 100644 --- a/doc/administration/redis/standalone.md +++ b/doc/administration/redis/standalone.md @@ -15,7 +15,7 @@ is generally stable and can handle many requests, so it is an acceptable trade off to have only a single instance. See the [reference architectures](../reference_architectures/index.md) page for an overview of GitLab scaling options. -## Set up a standalone Redis instance +## Set up the standalone Redis instance The steps below are the minimum necessary to configure a Redis server with Omnibus GitLab: @@ -28,36 +28,49 @@ Omnibus GitLab: 1. Edit `/etc/gitlab/gitlab.rb` and add the contents: ```ruby - ## Enable Redis - redis['enable'] = true - - ## Disable all other services - sidekiq['enable'] = false - gitlab_workhorse['enable'] = false - puma['enable'] = false - postgresql['enable'] = false - nginx['enable'] = false - prometheus['enable'] = false - alertmanager['enable'] = false - pgbouncer_exporter['enable'] = false - gitlab_exporter['enable'] = false - gitaly['enable'] = false + ## Enable Redis and disable all other services + ## https://docs.gitlab.com/omnibus/roles/ + roles ['redis_master_role'] + ## Redis configuration redis['bind'] = '0.0.0.0' redis['port'] = 6379 - redis['password'] = 'SECRET_PASSWORD_HERE' + redis['password'] = '' - gitlab_rails['enable'] = false + ## Disable automatic database migrations + ## Only the primary GitLab application server should handle migrations + gitlab_rails['auto_migrate'] = false ``` 1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. 1. Note the Redis node's IP address or hostname, port, and - Redis password. These will be necessary when configuring the GitLab - application servers later. + Redis password. These will be necessary when [configuring the GitLab + application servers](#set-up-the-gitlab-rails-application-instance). [Advanced configuration options](https://docs.gitlab.com/omnibus/settings/redis.html) are supported and can be added if needed. +## Set up the GitLab Rails application instance + +On the instance where GitLab is installed: + +1. Edit the `/etc/gitlab/gitlab.rb` file and add the following contents: + + ```ruby + ## Disable Redis + redis['enable'] = false + + gitlab_rails['redis_host'] = 'redis.example.com' + gitlab_rails['redis_port'] = 6379 + + ## Required if Redis authentication is configured on the Redis node + gitlab_rails['redis_password'] = '' + ``` + +1. Save your changes to `/etc/gitlab/gitlab.rb`. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + ## Troubleshooting See the [Redis troubleshooting guide](troubleshooting.md). diff --git a/doc/administration/reference_architectures/10k_users.md b/doc/administration/reference_architectures/10k_users.md index 5367021af4e..fe2dad41066 100644 --- a/doc/administration/reference_architectures/10k_users.md +++ b/doc/administration/reference_architectures/10k_users.md @@ -1,76 +1,2047 @@ -# Reference architecture: up to 10,000 users +--- +reading_time: true +stage: Enablement +group: Distribution +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- -This page describes GitLab reference architecture for up to 10,000 users. -For a full list of reference architectures, see +# Reference architecture: up to 10,000 users **(PREMIUM ONLY)** + +This page describes GitLab reference architecture for up to 10,000 users. For a +full list of reference architectures, see [Available reference architectures](index.md#available-reference-architectures). > - **Supported users (approximate):** 10,000 -> - **High Availability:** True -> - **Test RPS rates:** API: 200 RPS, Web: 20 RPS, Git: 20 RPS - -| Service | Nodes | Configuration ([8](#footnotes)) | GCP | AWS | Azure | -|--------------------------------------------------------------|-------|---------------------------------|----------------|-----------------------|----------------| -| GitLab Rails ([1](#footnotes)) | 3 | 32 vCPU, 28.8GB Memory | n1-highcpu-32 | c5.9xlarge | F32s v2 | -| PostgreSQL | 3 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge | D4s v3 | -| PgBouncer | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large | F2s v2 | -| Gitaly ([2](#footnotes)) ([5](#footnotes)) ([7](#footnotes)) | X | 16 vCPU, 60GB Memory | n1-standard-16 | m5.4xlarge | D16s v3 | -| Redis ([3](#footnotes)) - Cache | 3 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge | D4s v3 | -| Redis ([3](#footnotes)) - Queues / Shared State | 3 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge | D4s v3 | -| Redis Sentinel ([3](#footnotes)) - Cache | 3 | 1 vCPU, 1.7GB Memory | g1-small | t2.small | B1MS | -| Redis Sentinel ([3](#footnotes)) - Queues / Shared State | 3 | 1 vCPU, 1.7GB Memory | g1-small | t2.small | B1MS | -| Consul | 3 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large | F2s v2 | -| Sidekiq | 4 | 4 vCPU, 15GB Memory | n1-standard-4 | m5.xlarge | D4s v3 | -| Object Storage ([4](#footnotes)) | - | - | - | - | - | -| NFS Server ([5](#footnotes)) ([7](#footnotes)) | 1 | 4 vCPU, 3.6GB Memory | n1-highcpu-4 | c5.xlarge | F4s v2 | -| Monitoring node | 1 | 4 vCPU, 3.6GB Memory | n1-highcpu-4 | c5.xlarge | F4s v2 | -| External load balancing node ([6](#footnotes)) | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large | F2s v2 | -| Internal load balancing node ([6](#footnotes)) | 1 | 2 vCPU, 1.8GB Memory | n1-highcpu-2 | c5.large | F2s v2 | - -## Footnotes - -1. In our architectures we run each GitLab Rails node using the Puma webserver - and have its number of workers set to 90% of available CPUs along with four threads. For - nodes that are running Rails with other components the worker value should be reduced - accordingly where we've found 50% achieves a good balance but this is dependent - on workload. - -1. Gitaly node requirements are dependent on customer data, specifically the number of - projects and their sizes. We recommend two nodes as an absolute minimum for HA environments - and at least four nodes should be used when supporting 50,000 or more users. - We also recommend that each Gitaly node should store no more than 5TB of data - and have the number of [`gitaly-ruby` workers](../gitaly/index.md#gitaly-ruby) - set to 20% of available CPUs. Additional nodes should be considered in conjunction - with a review of expected data size and spread based on the recommendations above. - -1. Recommended Redis setup differs depending on the size of the architecture. - For smaller architectures (less than 3,000 users) a single instance should suffice. - For medium sized installs (3,000 - 5,000) we suggest one Redis cluster for all - classes and that Redis Sentinel is hosted alongside Consul. - For larger architectures (10,000 users or more) we suggest running a separate - [Redis Cluster](../redis/replication_and_failover.md#running-multiple-redis-clusters) for the Cache class - and another for the Queues and Shared State classes respectively. We also recommend - that you run the Redis Sentinel clusters separately for each Redis Cluster. - -1. For data objects such as LFS, Uploads, Artifacts, etc. We recommend an [Object Storage service](../object_storage.md) - over NFS where possible, due to better performance and availability. - -1. NFS can be used as an alternative for both repository data (replacing Gitaly) and - object storage but this isn't typically recommended for performance reasons. Note however it is required for - [GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196). - -1. Our architectures have been tested and validated with [HAProxy](https://www.haproxy.org/) - as the load balancer. Although other load balancers with similar feature sets - could also be used, those load balancers have not been validated. - -1. We strongly recommend that any Gitaly or NFS nodes be set up with SSD disks over - HDD with a throughput of at least 8,000 IOPS for read operations and 2,000 IOPS for write - as these components have heavy I/O. These IOPS values are recommended only as a starter - as with time they may be adjusted higher or lower depending on the scale of your - environment's workload. If you're running the environment on a Cloud provider - you may need to refer to their documentation on how configure IOPS correctly. - -1. The architectures were built and tested with the [Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) - CPU platform on GCP. On different hardware you may find that adjustments, either lower - or higher, are required for your CPU or Node counts accordingly. For more information, a - [Sysbench](https://github.com/akopytov/sysbench) benchmark of the CPU can be found - [here](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks). +> - **High Availability:** Yes +> - **Test requests per second (RPS) rates:** API: 200 RPS, Web: 20 RPS, Git: 20 RPS + +| Service | Nodes | Configuration | GCP | AWS | Azure | +|--------------------------------------------|-------------|-------------------------|-----------------|-------------|----------| +| External load balancing node | 1 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| Consul | 3 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| PostgreSQL | 3 | 4 vCPU, 15GB memory | n1-standard-4 | m5.xlarge | D4s v3 | +| PgBouncer | 3 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| Internal load balancing node | 1 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| Redis - Cache | 3 | 4 vCPU, 15GB memory | n1-standard-4 | m5.xlarge | D4s v3 | +| Redis - Queues / Shared State | 3 | 4 vCPU, 15GB memory | n1-standard-4 | m5.xlarge | D4s v3 | +| Redis Sentinel - Cache | 3 | 1 vCPU, 1.7GB memory | g1-small | t2.small | B1MS | +| Redis Sentinel - Queues / Shared State | 3 | 1 vCPU, 1.7GB memory | g1-small | t2.small | B1MS | +| Gitaly | 2 (minimum) | 16 vCPU, 60GB memory | n1-standard-16 | m5.4xlarge | D16s v3 | +| Sidekiq | 4 | 4 vCPU, 15GB memory | n1-standard-4 | m5.xlarge | D4s v3 | +| GitLab Rails | 3 | 32 vCPU, 28.8GB memory | n1-highcpu-32 | c5.9xlarge | F32s v2 | +| Monitoring node | 1 | 4 vCPU, 3.6GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 | +| Object Storage | n/a | n/a | n/a | n/a | n/a | +| NFS Server | 1 | 4 vCPU, 3.6GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 | + +The Google Cloud Platform (GCP) architectures were built and tested using the +[Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) +CPU platform. On different hardware you may find that adjustments, either lower +or higher, are required for your CPU or node counts. For more information, see +our [Sysbench](https://github.com/akopytov/sysbench)-based +[CPU benchmark](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks). + +For data objects (such as LFS, Uploads, or Artifacts), an +[object storage service](#configure-the-object-storage) is recommended instead +of NFS where possible, due to better performance and availability. Since this +doesn't require a node to be set up, *Object Storage* is noted as not +applicable (n/a) in the previous table. + +## Setup components + +To set up GitLab and its components to accommodate up to 10,000 users: + +1. [Configure the external load balancing node](#configure-the-external-load-balancer) + that will handle the load balancing of the three GitLab application services nodes. +1. [Configure Consul](#configure-consul). +1. [Configure PostgreSQL](#configure-postgresql), the database for GitLab. +1. [Configure PgBouncer](#configure-pgbouncer). +1. [Configure the internal load balancing node](#configure-the-internal-load-balancer) +1. [Configure Redis](#configure-redis). +1. [Configure Gitaly](#configure-gitaly), + which provides access to the Git repositories. +1. [Configure Sidekiq](#configure-sidekiq). +1. [Configure the main GitLab Rails application](#configure-gitlab-rails) + to run Puma/Unicorn, Workhorse, GitLab Shell, and to serve all frontend requests (UI, API, Git + over HTTP/SSH). +1. [Configure Prometheus](#configure-prometheus) to monitor your GitLab environment. +1. [Configure the Object Storage](#configure-the-object-storage) + used for shared data objects. +1. [Configure NFS (Optional)](#configure-nfs-optional) + to have shared disk storage service as an alternative to Gitaly and/or Object Storage (although + not recommended). NFS is required for GitLab Pages, you can skip this step if you're not using + that feature. + +We start with all servers on the same 10.6.0.0/24 private network range, they +can connect to each other freely on those addresses. + +Here is a list and description of each machine and the assigned IP: + +- `10.6.0.10`: External Load Balancer +- `10.6.0.11`: Consul 1 +- `10.6.0.12`: Consul 2 +- `10.6.0.13`: Consul 3 +- `10.6.0.21`: PostgreSQL primary +- `10.6.0.22`: PostgreSQL secondary 1 +- `10.6.0.23`: PostgreSQL secondary 2 +- `10.6.0.31`: PgBouncer 1 +- `10.6.0.32`: PgBouncer 2 +- `10.6.0.33`: PgBouncer 3 +- `10.6.0.40`: Internal Load Balancer +- `10.6.0.51`: Redis - Cache Primary +- `10.6.0.52`: Redis - Cache Replica 1 +- `10.6.0.53`: Redis - Cache Replica 2 +- `10.6.0.71`: Sentinel - Cache 1 +- `10.6.0.72`: Sentinel - Cache 2 +- `10.6.0.73`: Sentinel - Cache 3 +- `10.6.0.61`: Redis - Queues Primary +- `10.6.0.62`: Redis - Queues Replica 1 +- `10.6.0.63`: Redis - Queues Replica 2 +- `10.6.0.81`: Sentinel - Queues 1 +- `10.6.0.82`: Sentinel - Queues 2 +- `10.6.0.83`: Sentinel - Queues 3 +- `10.6.0.91`: Gitaly 1 +- `10.6.0.92`: Gitaly 2 +- `10.6.0.101`: Sidekiq 1 +- `10.6.0.102`: Sidekiq 2 +- `10.6.0.103`: Sidekiq 3 +- `10.6.0.104`: Sidekiq 4 +- `10.6.0.111`: GitLab application 1 +- `10.6.0.112`: GitLab application 2 +- `10.6.0.113`: GitLab application 3 +- `10.6.0.121`: Prometheus + +## Configure the external load balancer + +NOTE: **Note:** +This architecture has been tested and validated with [HAProxy](https://www.haproxy.org/) +as the load balancer. Although other load balancers with similar feature sets +could also be used, those load balancers have not been validated. + +In an active/active GitLab configuration, you will need a load balancer to route +traffic to the application servers. The specifics on which load balancer to use +or the exact configuration is beyond the scope of GitLab documentation. We hope +that if you're managing multi-node systems like GitLab you have a load balancer of +choice already. Some examples including HAProxy (open-source), F5 Big-IP LTM, +and Citrix Net Scaler. This documentation will outline what ports and protocols +you need to use with GitLab. + +The next question is how you will handle SSL in your environment. +There are several different options: + +- [The application node terminates SSL](#application-node-terminates-ssl). +- [The load balancer terminates SSL without backend SSL](#load-balancer-terminates-ssl-without-backend-ssl) + and communication is not secure between the load balancer and the application node. +- [The load balancer terminates SSL with backend SSL](#load-balancer-terminates-ssl-with-backend-ssl) + and communication is *secure* between the load balancer and the application node. + +### Application node terminates SSL + +Configure your load balancer to pass connections on port 443 as `TCP` rather +than `HTTP(S)` protocol. This will pass the connection to the application node's +NGINX service untouched. NGINX will have the SSL certificate and listen on port 443. + +See the [NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https) +for details on managing SSL certificates and configuring NGINX. + +### Load balancer terminates SSL without backend SSL + +Configure your load balancer to use the `HTTP(S)` protocol rather than `TCP`. +The load balancer will then be responsible for managing SSL certificates and +terminating SSL. + +Since communication between the load balancer and GitLab will not be secure, +there is some additional configuration needed. See the +[NGINX proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#supporting-proxied-ssl) +for details. + +### Load balancer terminates SSL with backend SSL + +Configure your load balancer(s) to use the 'HTTP(S)' protocol rather than 'TCP'. +The load balancer(s) will be responsible for managing SSL certificates that +end users will see. + +Traffic will also be secure between the load balancer(s) and NGINX in this +scenario. There is no need to add configuration for proxied SSL since the +connection will be secure all the way. However, configuration will need to be +added to GitLab to configure SSL certificates. See +[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https) +for details on managing SSL certificates and configuring NGINX. + +### Ports + +The basic ports to be used are shown in the table below. + +| LB Port | Backend Port | Protocol | +| ------- | ------------ | ------------------------ | +| 80 | 80 | HTTP (*1*) | +| 443 | 443 | TCP or HTTPS (*1*) (*2*) | +| 22 | 22 | TCP | + +- (*1*): [Web terminal](../../ci/environments/index.md#web-terminals) support requires + your load balancer to correctly handle WebSocket connections. When using + HTTP or HTTPS proxying, this means your load balancer must be configured + to pass through the `Connection` and `Upgrade` hop-by-hop headers. See the + [web terminal](../integration/terminal.md) integration guide for + more details. +- (*2*): When using HTTPS protocol for port 443, you will need to add an SSL + certificate to the load balancers. If you wish to terminate SSL at the + GitLab application server instead, use TCP protocol. + +If you're using GitLab Pages with custom domain support you will need some +additional port configurations. +GitLab Pages requires a separate virtual IP address. Configure DNS to point the +`pages_external_url` from `/etc/gitlab/gitlab.rb` at the new virtual IP address. See the +[GitLab Pages documentation](../pages/index.md) for more information. + +| LB Port | Backend Port | Protocol | +| ------- | ------------- | --------- | +| 80 | Varies (*1*) | HTTP | +| 443 | Varies (*1*) | TCP (*2*) | + +- (*1*): The backend port for GitLab Pages depends on the + `gitlab_pages['external_http']` and `gitlab_pages['external_https']` + setting. See [GitLab Pages documentation](../pages/index.md) for more details. +- (*2*): Port 443 for GitLab Pages should always use the TCP protocol. Users can + configure custom domains with custom SSL, which would not be possible + if SSL was terminated at the load balancer. + +#### Alternate SSH Port + +Some organizations have policies against opening SSH port 22. In this case, +it may be helpful to configure an alternate SSH hostname that allows users +to use SSH on port 443. An alternate SSH hostname will require a new virtual IP address +compared to the other GitLab HTTP configuration above. + +Configure DNS for an alternate SSH hostname such as `altssh.gitlab.example.com`. + +| LB Port | Backend Port | Protocol | +| ------- | ------------ | -------- | +| 443 | 22 | TCP | + + + +## Configure Consul + +The following IPs will be used as an example: + +- `10.6.0.11`: Consul 1 +- `10.6.0.12`: Consul 2 +- `10.6.0.13`: Consul 3 + +NOTE: **Note:** +The configuration processes for the other servers in your reference architecture will +use the `/etc/gitlab/gitlab-secrets.json` file from your Consul server to connect +with the other servers. + +To configure Consul: + +1. SSH into the server that will host Consul. +1. [Download/install](https://about.gitlab.com/install/) the + Omnibus GitLab Enterprise Edition package using **steps 1 and 2** from the + GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + the GitLab application is running. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + roles ['consul_role'] + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + server: true, + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. +1. Go through the steps again for all the other Consul nodes, and + make sure you set up the correct IPs. + +NOTE: **Note:** +A Consul leader will be elected when the provisioning of the third Consul server is completed. +Viewing the Consul logs `sudo gitlab-ctl tail consul` will display +`...[INFO] consul: New leader elected: ...` + +You can list the current Consul members (server, client): + +```shell +sudo /opt/gitlab/embedded/bin/consul members +``` + +You can verify the GitLab services are running: + +```shell +sudo gitlab-ctl status +``` + +The output should be similar to the following: + +```plaintext +run: consul: (pid 30074) 76834s; run: log: (pid 29740) 76844s +run: logrotate: (pid 30925) 3041s; run: log: (pid 29649) 76861s +run: node-exporter: (pid 30093) 76833s; run: log: (pid 29663) 76855s +``` + + + +## Configure PostgreSQL + +In this section, you'll be guided through configuring an external PostgreSQL database +to be used with GitLab. + +### Provide your own PostgreSQL instance + +If you're hosting GitLab on a cloud provider, you can optionally use a +managed service for PostgreSQL. For example, AWS offers a managed Relational +Database Service (RDS) that runs PostgreSQL. + +If you use a cloud-managed service, or provide your own PostgreSQL: + +1. Set up PostgreSQL according to the + [database requirements document](../../install/requirements.md#database). +1. Set up a `gitlab` username with a password of your choice. The `gitlab` user + needs privileges to create the `gitlabhq_production` database. +1. Configure the GitLab application servers with the appropriate details. + This step is covered in [Configuring the GitLab Rails application](#configure-gitlab-rails). + +### Standalone PostgreSQL using Omnibus GitLab + +The following IPs will be used as an example: + +- `10.6.0.21`: PostgreSQL primary +- `10.6.0.22`: PostgreSQL secondary 1 +- `10.6.0.23`: PostgreSQL secondary 2 + +First, make sure to [install](https://about.gitlab.com/install/) +the Linux GitLab package **on each node**. Following the steps, +install the necessary dependencies from step 1, and add the +GitLab package repository from step 2. When installing GitLab +in the second step, do not supply the `EXTERNAL_URL` value. + +#### PostgreSQL primary node + +1. SSH into the PostgreSQL primary node. +1. Generate a password hash for the PostgreSQL username/password pair. This assumes you will use the default + username of `gitlab` (recommended). The command will request a password + and confirmation. Use the value that is output by this command in the next + step as the value of ``: + + ```shell + sudo gitlab-ctl pg-password-md5 gitlab + ``` + +1. Generate a password hash for the PgBouncer username/password pair. This assumes you will use the default + username of `pgbouncer` (recommended). The command will request a password + and confirmation. Use the value that is output by this command in the next + step as the value of ``: + + ```shell + sudo gitlab-ctl pg-password-md5 pgbouncer + ``` + +1. Generate a password hash for the Consul database username/password pair. This assumes you will use the default + username of `gitlab-consul` (recommended). The command will request a password + and confirmation. Use the value that is output by this command in the next + step as the value of ``: + + ```shell + sudo gitlab-ctl pg-password-md5 gitlab-consul + ``` + +1. On the primary database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section: + + ```ruby + # Disable all components except PostgreSQL and Repmgr and Consul + roles ['postgres_role'] + + # PostgreSQL configuration + postgresql['listen_address'] = '0.0.0.0' + postgresql['hot_standby'] = 'on' + postgresql['wal_level'] = 'replica' + postgresql['shared_preload_libraries'] = 'repmgr_funcs' + + # Disable automatic database migrations + gitlab_rails['auto_migrate'] = false + + # Configure the Consul agent + consul['services'] = %w(postgresql) + + # START user configuration + # Please set the real values as explained in Required Information section + # + # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value + postgresql['pgbouncer_user_password'] = '' + # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value + postgresql['sql_user_password'] = '' + # Set `max_wal_senders` to one more than the number of database nodes in the cluster. + # This is used to prevent replication from using up all of the + # available database connections. + postgresql['max_wal_senders'] = 4 + postgresql['max_replication_slots'] = 4 + + # Replace XXX.XXX.XXX.XXX/YY with Network Address + postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24) + repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + + ## Enable service discovery for Prometheus + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on for monitoring + node_exporter['listen_address'] = '0.0.0.0:9100' + postgres_exporter['listen_address'] = '0.0.0.0:9187' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + # + # END user configuration + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + + + +#### PostgreSQL secondary nodes + +1. On both the secondary nodes, add the same configuration specified above for the primary node + with an additional setting (`repmgr['master_on_initialization'] = false`) that will inform `gitlab-ctl` that they are standby nodes initially + and there's no need to attempt to register them as a primary node: + + ```ruby + # Disable all components except PostgreSQL and Repmgr and Consul + roles ['postgres_role'] + + # PostgreSQL configuration + postgresql['listen_address'] = '0.0.0.0' + postgresql['hot_standby'] = 'on' + postgresql['wal_level'] = 'replica' + postgresql['shared_preload_libraries'] = 'repmgr_funcs' + + # Disable automatic database migrations + gitlab_rails['auto_migrate'] = false + + # Configure the Consul agent + consul['services'] = %w(postgresql) + + # Specify if a node should attempt to be primary on initialization. + repmgr['master_on_initialization'] = false + + # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value + postgresql['pgbouncer_user_password'] = '' + # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value + postgresql['sql_user_password'] = '' + # Set `max_wal_senders` to one more than the number of database nodes in the cluster. + # This is used to prevent replication from using up all of the + # available database connections. + postgresql['max_wal_senders'] = 4 + postgresql['max_replication_slots'] = 4 + + # Replace with your network addresses + postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24) + repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + + ## Enable service discovery for Prometheus + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on for monitoring + node_exporter['listen_address'] = '0.0.0.0:9100' + postgres_exporter['listen_address'] = '0.0.0.0:9187' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + +Advanced [configuration options](https://docs.gitlab.com/omnibus/settings/database.html) +are supported and can be added if needed. + + + +#### PostgreSQL post-configuration + +SSH into the **primary node**: + +1. Open a database prompt: + + ```shell + gitlab-psql -d gitlabhq_production + ``` + +1. Make sure the `pg_trgm` extension is enabled (it might already be): + + ```shell + CREATE EXTENSION pg_trgm; + ``` + +1. Exit the database prompt by typing `\q` and Enter. + +1. Verify the cluster is initialized with one node: + + ```shell + gitlab-ctl repmgr cluster show + ``` + + The output should be similar to the following: + + ```plaintext + Role | Name | Upstream | Connection String + ----------+----------|----------|---------------------------------------- + * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr + ``` + +1. Note down the hostname or IP address in the connection string: `host=HOSTNAME`. We will + refer to the hostname in the next section as ``. If the value + is not an IP address, it will need to be a resolvable name (via DNS or + `/etc/hosts`) + +SSH into the **secondary node**: + +1. Set up the repmgr standby: + + ```shell + gitlab-ctl repmgr standby setup + ``` + + Do note that this will remove the existing data on the node. The command + has a wait time. + + The output should be similar to the following: + + ```console + Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data + If this is not what you want, hit Ctrl-C now to exit + To skip waiting, rerun with the -w option + Sleeping for 30 seconds + Stopping the database + Removing the data + Cloning the data + Starting the database + Registering the node with the cluster + ok: run: repmgrd: (pid 19068) 0s + ``` + +Before moving on, make sure the databases are configured correctly. Run the +following command on the **primary** node to verify that replication is working +properly and the secondary nodes appear in the cluster: + +```shell +gitlab-ctl repmgr cluster show +``` + +The output should be similar to the following: + +```plaintext +Role | Name | Upstream | Connection String +----------+---------|-----------|------------------------------------------------ +* master | MASTER | | host= user=gitlab_repmgr dbname=gitlab_repmgr + standby | STANDBY | MASTER | host= user=gitlab_repmgr dbname=gitlab_repmgr + standby | STANDBY | MASTER | host= user=gitlab_repmgr dbname=gitlab_repmgr +``` + +If the 'Role' column for any node says "FAILED", check the +[Troubleshooting section](troubleshooting.md) before proceeding. + +Also, check that the `repmgr-check-master` command works successfully on each node: + +```shell +su - gitlab-consul +gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node' +``` + +This command relies on exit codes to tell Consul whether a particular node is a master +or secondary. The most important thing here is that this command does not produce errors. +If there are errors it's most likely due to incorrect `gitlab-consul` database user permissions. +Check the [Troubleshooting section](troubleshooting.md) before proceeding. + + + +## Configure PgBouncer + +Now that the PostgreSQL servers are all set up, let's configure PgBouncer. +The following IPs will be used as an example: + +- `10.6.0.31`: PgBouncer 1 +- `10.6.0.32`: PgBouncer 2 +- `10.6.0.33`: PgBouncer 3 + +1. On each PgBouncer node, edit `/etc/gitlab/gitlab.rb`, and replace + `` and `` with the + password hashes you [set up previously](#postgresql-primary-node): + + ```ruby + # Disable all components except Pgbouncer and Consul agent + roles ['pgbouncer_role'] + + # Configure PgBouncer + pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul) + + pgbouncer['users'] = { + 'gitlab-consul': { + password: '' + }, + 'pgbouncer': { + password: '' + } + } + + # Configure Consul agent + consul['watchers'] = %w(postgresql) + consul['enable'] = true + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + + # Enable service discovery for Prometheus + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + + NOTE: **Note:** + If an error `execute[generate databases.ini]` occurs, this is due to an existing + [known issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4713). + It will be resolved when you run a second `reconfigure` after the next step. + +1. Create a `.pgpass` file so Consul is able to + reload PgBouncer. Enter the PgBouncer password twice when asked: + + ```shell + gitlab-ctl write-pgpass --host 127.0.0.1 --database pgbouncer --user pgbouncer --hostuser gitlab-consul + ``` + +1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) once again + to resolve any potential errors from the previous steps. +1. Ensure each node is talking to the current primary: + + ```shell + gitlab-ctl pgb-console # You will be prompted for PGBOUNCER_PASSWORD + ``` + +1. Once the console prompt is available, run the following queries: + + ```shell + show databases ; show clients ; + ``` + + The output should be similar to the following: + + ```plaintext + name | host | port | database | force_user | pool_size | reserve_pool | pool_mode | max_connections | current_connections + ---------------------+-------------+------+---------------------+------------+-----------+--------------+-----------+-----------------+--------------------- + gitlabhq_production | MASTER_HOST | 5432 | gitlabhq_production | | 20 | 0 | | 0 | 0 + pgbouncer | | 6432 | pgbouncer | pgbouncer | 2 | 0 | statement | 0 | 0 + (2 rows) + + type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link | remote_pid | tls + ------+-----------+---------------------+---------+----------------+-------+------------+------------+---------------------+---------------------+-----------+------+------------+----- + C | pgbouncer | pgbouncer | active | 127.0.0.1 | 56846 | 127.0.0.1 | 6432 | 2017-08-21 18:09:59 | 2017-08-21 18:10:48 | 0x22b3880 | | 0 | + (2 rows) + ``` + + + +### Configure the internal load balancer + +If you're running more than one PgBouncer node as recommended, then at this time you'll need to set +up a TCP internal load balancer to serve each correctly. + +The following IP will be used as an example: + +- `10.6.0.40`: Internal Load Balancer + +Here's how you could do it with [HAProxy](https://www.haproxy.org/): + +```plaintext +global + log /dev/log local0 + log localhost local1 notice + log stdout format raw local0 + +defaults + log global + default-server inter 10s fall 3 rise 2 + balance leastconn + +frontend internal-pgbouncer-tcp-in + bind *:6432 + mode tcp + option tcplog + + default_backend pgbouncer + +backend pgbouncer + mode tcp + option tcp-check + + server pgbouncer1 10.6.0.21:6432 check + server pgbouncer2 10.6.0.22:6432 check + server pgbouncer3 10.6.0.23:6432 check +``` + +Refer to your preferred Load Balancer's documentation for further guidance. + + + +## Configure Redis + +Using [Redis](https://redis.io/) in scalable environment is possible using a **Primary** x **Replica** +topology with a [Redis Sentinel](https://redis.io/topics/sentinel) service to watch and automatically +start the failover procedure. + +Redis requires authentication if used with Sentinel. See +[Redis Security](https://redis.io/topics/security) documentation for more +information. We recommend using a combination of a Redis password and tight +firewall rules to secure your Redis service. +You are highly encouraged to read the [Redis Sentinel](https://redis.io/topics/sentinel) documentation +before configuring Redis with GitLab to fully understand the topology and +architecture. + +The requirements for a Redis setup are the following: + +1. All Redis nodes must be able to talk to each other and accept incoming + connections over Redis (`6379`) and Sentinel (`26379`) ports (unless you + change the default ones). +1. The server that hosts the GitLab application must be able to access the + Redis nodes. +1. Protect the nodes from access from external networks + ([Internet](https://gitlab.com/gitlab-org/gitlab-foss/uploads/c4cc8cd353604bd80315f9384035ff9e/The_Internet_IT_Crowd.png)), + using a firewall. + +In this section, you'll be guided through configuring two external Redis clusters +to be used with GitLab. The following IPs will be used as an example: + +- `10.6.0.51`: Redis - Cache Primary +- `10.6.0.52`: Redis - Cache Replica 1 +- `10.6.0.53`: Redis - Cache Replica 2 +- `10.6.0.71`: Sentinel - Cache 1 +- `10.6.0.72`: Sentinel - Cache 2 +- `10.6.0.73`: Sentinel - Cache 3 +- `10.6.0.61`: Redis - Queues Primary +- `10.6.0.62`: Redis - Queues Replica 1 +- `10.6.0.63`: Redis - Queues Replica 2 +- `10.6.0.81`: Sentinel - Queues 1 +- `10.6.0.82`: Sentinel - Queues 2 +- `10.6.0.83`: Sentinel - Queues 3 + +NOTE: **Providing your own Redis instance:** +Managed Redis from cloud providers such as AWS ElastiCache will work. If these +services support high availability, be sure it is **not** the Redis Cluster type. +Redis version 5.0 or higher is required, as this is what ships with +Omnibus GitLab packages starting with GitLab 13.0. Older Redis versions +do not support an optional count argument to SPOP which is now required for +[Merge Trains](../../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md). +Note the Redis node's IP address or hostname, port, and password (if required). +These will be necessary when configuring the +[GitLab application servers](#configure-gitlab-rails) later. + +### Configure the Redis and Sentinel Cache cluster + +This is the section where we install and set up the new Redis Cache instances. + +NOTE: **Note:** +Redis nodes (both primary and replica) will need the same password defined in +`redis['password']`. At any time during a failover the Sentinels can +reconfigure a node and change its status from primary to replica and vice versa. + +#### Configure the primary Redis Cache node + +1. SSH into the **Primary** Redis server. +1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab + package you want using **steps 1 and 2** from the GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + and type (Community, Enterprise editions) of your current install. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + # Specify server role as 'redis_master_role' + roles ['redis_master_role'] + + # IP address pointing to a local IP that the other machines can reach to. + # You can also set bind to '0.0.0.0' which listen in all interfaces. + # If you really need to bind to an external accessible IP, make + # sure you add extra firewall rules to prevent unauthorized access. + redis['bind'] = '10.6.0.51' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # Set up password authentication for Redis (use the same password in all nodes). + redis['password'] = 'REDIS_PRIMARY_PASSWORD_OF_FIRST_CLUSTER' + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + + # Prevent database migrations from running on upgrade + gitlab_rails['auto_migrate'] = false + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + +NOTE: **Note:** +You can specify multiple roles like sentinel and Redis as: +`roles ['redis_sentinel_role', 'redis_master_role']`. +Read more about [roles](https://docs.gitlab.com/omnibus/roles/). + +#### Configure the replica Redis Cache nodes + +1. SSH into the **replica** Redis server. +1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab + package you want using **steps 1 and 2** from the GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + and type (Community, Enterprise editions) of your current install. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + # Specify server role as 'redis_replica_role' + roles ['redis_replica_role'] + + # IP address pointing to a local IP that the other machines can reach to. + # You can also set bind to '0.0.0.0' which listen in all interfaces. + # If you really need to bind to an external accessible IP, make + # sure you add extra firewall rules to prevent unauthorized access. + redis['bind'] = '10.6.0.52' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # The same password for Redis authentication you set up for the primary node. + redis['password'] = 'REDIS_PRIMARY_PASSWORD_OF_FIRST_CLUSTER' + + # The IP of the primary Redis node. + redis['master_ip'] = '10.6.0.51' + + # Port of primary Redis server, uncomment to change to non default. Defaults + # to `6379`. + #redis['master_port'] = 6379 + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + + # Prevent database migrations from running on upgrade + gitlab_rails['auto_migrate'] = false + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. +1. Go through the steps again for all the other replica nodes, and + make sure to set up the IPs correctly. + +NOTE: **Note:** +You can specify multiple roles like sentinel and Redis as: +`roles ['redis_sentinel_role', 'redis_master_role']`. +Read more about [roles](https://docs.gitlab.com/omnibus/roles/). + +These values don't have to be changed again in `/etc/gitlab/gitlab.rb` after +a failover, as the nodes will be managed by the [Sentinels](#configure-the-sentinel-cache-nodes), and even after a +`gitlab-ctl reconfigure`, they will get their configuration restored by +the same Sentinels. + +Advanced [configuration options](https://docs.gitlab.com/omnibus/settings/redis.html) +are supported and can be added if needed. + + + +#### Configure the Sentinel Cache nodes + +NOTE: **Note:** +If you are using an external Redis Sentinel instance, be sure +to exclude the `requirepass` parameter from the Sentinel +configuration. This parameter will cause clients to report `NOAUTH +Authentication required.`. [Redis Sentinel 3.2.x does not support +password authentication](https://github.com/antirez/redis/issues/3279). + +Now that the Redis servers are all set up, let's configure the Sentinel +servers. The following IPs will be used as an example: + +- `10.6.0.71`: Sentinel - Cache 1 +- `10.6.0.72`: Sentinel - Cache 2 +- `10.6.0.73`: Sentinel - Cache 3 + +To configure the Sentinel Cache server: + +1. SSH into the server that will host Consul/Sentinel. +1. [Download/install](https://about.gitlab.com/install/) the + Omnibus GitLab Enterprise Edition package using **steps 1 and 2** from the + GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + the GitLab application is running. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + roles ['redis_sentinel_role'] + + ## Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis-cache' + + ## The same password for Redis authentication you set up for the primary node. + redis['master_password'] = 'REDIS_PRIMARY_PASSWORD_OF_FIRST_CLUSTER' + + ## The IP of the primary Redis node. + redis['master_ip'] = '10.6.0.51' + + ## Define a port so Redis can listen for TCP requests which will allow other + ## machines to connect to it. + redis['port'] = 6379 + + ## Port of primary Redis server, uncomment to change to non default. Defaults + ## to `6379`. + #redis['master_port'] = 6379 + + ## Configure Sentinel's IP + sentinel['bind'] = '10.6.0.71' + + ## Port that Sentinel listens on, uncomment to change to non default. Defaults + ## to `26379`. + #sentinel['port'] = 26379 + + ## Quorum must reflect the amount of voting sentinels it take to start a failover. + ## Value must NOT be greater then the amount of sentinels. + ## + ## The quorum can be used to tune Sentinel in two ways: + ## 1. If a the quorum is set to a value smaller than the majority of Sentinels + ## we deploy, we are basically making Sentinel more sensible to primary failures, + ## triggering a failover as soon as even just a minority of Sentinels is no longer + ## able to talk with the primary. + ## 1. If a quorum is set to a value greater than the majority of Sentinels, we are + ## making Sentinel able to failover only when there are a very large number (larger + ## than majority) of well connected Sentinels which agree about the primary being down.s + sentinel['quorum'] = 2 + + ## Consider unresponsive server down after x amount of ms. + #sentinel['down_after_milliseconds'] = 10000 + + ## Specifies the failover timeout in milliseconds. It is used in many ways: + ## + ## - The time needed to re-start a failover after a previous failover was + ## already tried against the same primary by a given Sentinel, is two + ## times the failover timeout. + ## + ## - The time needed for a replica replicating to a wrong primary according + ## to a Sentinel current configuration, to be forced to replicate + ## with the right primary, is exactly the failover timeout (counting since + ## the moment a Sentinel detected the misconfiguration). + ## + ## - The time needed to cancel a failover that is already in progress but + ## did not produced any configuration change (REPLICAOF NO ONE yet not + ## acknowledged by the promoted replica). + ## + ## - The maximum time a failover in progress waits for all the replica to be + ## reconfigured as replicas of the new primary. However even after this time + ## the replicas will be reconfigured by the Sentinels anyway, but not with + ## the exact parallel-syncs progression as specified. + #sentinel['failover_timeout'] = 60000 + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. +1. Go through the steps again for all the other Consul/Sentinel nodes, and + make sure you set up the correct IPs. + + + +### Configure the Redis and Sentinel Queues cluster + +This is the section where we install and set up the new Redis Queues instances. + +NOTE: **Note:** +Redis nodes (both primary and replica) will need the same password defined in +`redis['password']`. At any time during a failover the Sentinels can +reconfigure a node and change its status from primary to replica and vice versa. + +#### Configure the primary Redis Queues node + +1. SSH into the **Primary** Redis server. +1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab + package you want using **steps 1 and 2** from the GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + and type (Community, Enterprise editions) of your current install. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + # Specify server role as 'redis_master_role' + roles ['redis_master_role'] + + # IP address pointing to a local IP that the other machines can reach to. + # You can also set bind to '0.0.0.0' which listen in all interfaces. + # If you really need to bind to an external accessible IP, make + # sure you add extra firewall rules to prevent unauthorized access. + redis['bind'] = '10.6.0.61' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # Set up password authentication for Redis (use the same password in all nodes). + redis['password'] = 'REDIS_PRIMARY_PASSWORD_OF_SECOND_CLUSTER' + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + ``` + +1. Only the primary GitLab application server should handle migrations. To + prevent database migrations from running on upgrade, add the following + configuration to your `/etc/gitlab/gitlab.rb` file: + + ```ruby + gitlab_rails['auto_migrate'] = false + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + +NOTE: **Note:** +You can specify multiple roles like sentinel and Redis as: +`roles ['redis_sentinel_role', 'redis_master_role']`. +Read more about [roles](https://docs.gitlab.com/omnibus/roles/). + +#### Configure the replica Redis Queues nodes + +1. SSH into the **replica** Redis Queue server. +1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab + package you want using **steps 1 and 2** from the GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + and type (Community, Enterprise editions) of your current install. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + # Specify server role as 'redis_replica_role' + roles ['redis_replica_role'] + + # IP address pointing to a local IP that the other machines can reach to. + # You can also set bind to '0.0.0.0' which listen in all interfaces. + # If you really need to bind to an external accessible IP, make + # sure you add extra firewall rules to prevent unauthorized access. + redis['bind'] = '10.6.0.62' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # The same password for Redis authentication you set up for the primary node. + redis['password'] = 'REDIS_PRIMARY_PASSWORD_OF_SECOND_CLUSTER' + + # The IP of the primary Redis node. + redis['master_ip'] = '10.6.0.61' + + # Port of primary Redis server, uncomment to change to non default. Defaults + # to `6379`. + #redis['master_port'] = 6379 + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. +1. Go through the steps again for all the other replica nodes, and + make sure to set up the IPs correctly. + +NOTE: **Note:** +You can specify multiple roles like sentinel and Redis as: +`roles ['redis_sentinel_role', 'redis_master_role']`. +Read more about [roles](https://docs.gitlab.com/omnibus/roles/). + +These values don't have to be changed again in `/etc/gitlab/gitlab.rb` after +a failover, as the nodes will be managed by the [Sentinels](#configure-the-sentinel-queues-nodes), and even after a +`gitlab-ctl reconfigure`, they will get their configuration restored by +the same Sentinels. + +Advanced [configuration options](https://docs.gitlab.com/omnibus/settings/redis.html) +are supported and can be added if needed. + + + +#### Configure the Sentinel Queues nodes + +NOTE: **Note:** +If you are using an external Redis Sentinel instance, be sure +to exclude the `requirepass` parameter from the Sentinel +configuration. This parameter will cause clients to report `NOAUTH +Authentication required.`. [Redis Sentinel 3.2.x does not support +password authentication](https://github.com/antirez/redis/issues/3279). + +Now that the Redis servers are all set up, let's configure the Sentinel +servers. The following IPs will be used as an example: + +- `10.6.0.81`: Sentinel - Queues 1 +- `10.6.0.82`: Sentinel - Queues 2 +- `10.6.0.83`: Sentinel - Queues 3 + +To configure the Sentinel Queues server: + +1. SSH into the server that will host Sentinel. +1. [Download/install](https://about.gitlab.com/install/) the + Omnibus GitLab Enterprise Edition package using **steps 1 and 2** from the + GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + the GitLab application is running. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + roles ['redis_sentinel_role'] + + ## Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis-persistent' + + ## The same password for Redis authentication you set up for the primary node. + redis['master_password'] = 'REDIS_PRIMARY_PASSWORD_OF_SECOND_CLUSTER' + + ## The IP of the primary Redis node. + redis['master_ip'] = '10.6.0.61' + + ## Define a port so Redis can listen for TCP requests which will allow other + ## machines to connect to it. + redis['port'] = 6379 + + ## Port of primary Redis server, uncomment to change to non default. Defaults + ## to `6379`. + #redis['master_port'] = 6379 + + ## Configure Sentinel's IP + sentinel['bind'] = '10.6.0.81' + + ## Port that Sentinel listens on, uncomment to change to non default. Defaults + ## to `26379`. + #sentinel['port'] = 26379 + + ## Quorum must reflect the amount of voting sentinels it take to start a failover. + ## Value must NOT be greater then the amount of sentinels. + ## + ## The quorum can be used to tune Sentinel in two ways: + ## 1. If a the quorum is set to a value smaller than the majority of Sentinels + ## we deploy, we are basically making Sentinel more sensible to primary failures, + ## triggering a failover as soon as even just a minority of Sentinels is no longer + ## able to talk with the primary. + ## 1. If a quorum is set to a value greater than the majority of Sentinels, we are + ## making Sentinel able to failover only when there are a very large number (larger + ## than majority) of well connected Sentinels which agree about the primary being down.s + sentinel['quorum'] = 2 + + ## Consider unresponsive server down after x amount of ms. + #sentinel['down_after_milliseconds'] = 10000 + + ## Specifies the failover timeout in milliseconds. It is used in many ways: + ## + ## - The time needed to re-start a failover after a previous failover was + ## already tried against the same primary by a given Sentinel, is two + ## times the failover timeout. + ## + ## - The time needed for a replica replicating to a wrong primary according + ## to a Sentinel current configuration, to be forced to replicate + ## with the right primary, is exactly the failover timeout (counting since + ## the moment a Sentinel detected the misconfiguration). + ## + ## - The time needed to cancel a failover that is already in progress but + ## did not produced any configuration change (REPLICAOF NO ONE yet not + ## acknowledged by the promoted replica). + ## + ## - The maximum time a failover in progress waits for all the replica to be + ## reconfigured as replicas of the new primary. However even after this time + ## the replicas will be reconfigured by the Sentinels anyway, but not with + ## the exact parallel-syncs progression as specified. + #sentinel['failover_timeout'] = 60000 + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +1. To prevent database migrations from running on upgrade, run: + + ```shell + sudo touch /etc/gitlab/skip-auto-reconfigure + ``` + + Only the primary GitLab application server should handle migrations. + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. +1. Go through the steps again for all the other Sentinel nodes, and + make sure you set up the correct IPs. + + + +## Configure Gitaly + +Deploying Gitaly in its own server can benefit GitLab installations that are +larger than a single machine. + +The Gitaly node requirements are dependent on customer data, specifically the number of +projects and their repository sizes. Two nodes are recommended as an absolute minimum. +Each Gitaly node should store no more than 5TB of data and have the number of +[`gitaly-ruby` workers](../gitaly/index.md#gitaly-ruby) set to 20% of available CPUs. +Additional nodes should be considered in conjunction with a review of expected +data size and spread based on the recommendations above. + +It is also strongly recommended that all Gitaly nodes be set up with SSD disks with +a throughput of at least 8,000 IOPS for read operations and 2,000 IOPS for write, +as Gitaly has heavy I/O. These IOPS values are recommended only as a starter as with +time they may be adjusted higher or lower depending on the scale of your environment's workload. +If you're running the environment on a Cloud provider, you may need to refer to +their documentation on how to configure IOPS correctly. + +Some things to note: + +- The GitLab Rails application shards repositories into [repository storages](../repository_storage_paths.md). +- A Gitaly server can host one or more storages. +- A GitLab server can use one or more Gitaly servers. +- Gitaly addresses must be specified in such a way that they resolve + correctly for ALL Gitaly clients. +- Gitaly servers must not be exposed to the public internet, as Gitaly's network + traffic is unencrypted by default. The use of a firewall is highly recommended + to restrict access to the Gitaly server. Another option is to + [use TLS](#gitaly-tls-support). + +TIP: **Tip:** +For more information about Gitaly's history and network architecture see the +[standalone Gitaly documentation](../gitaly/index.md). + +Note: **Note:** +The token referred to throughout the Gitaly documentation is +just an arbitrary password selected by the administrator. It is unrelated to +tokens created for the GitLab API or other similar web API tokens. + +Below we describe how to configure two Gitaly servers, with IPs and +domain names: + +- `10.6.0.91`: Gitaly 1 (`gitaly1.internal`) +- `10.6.0.92`: Gitaly 2 (`gitaly2.internal`) + +The secret token is assumed to be `gitalysecret` and that +your GitLab installation has three repository storages: + +- `default` on Gitaly 1 +- `storage1` on Gitaly 1 +- `storage2` on Gitaly 2 + +On each node: + +1. [Download/Install](https://about.gitlab.com/install/) the Omnibus GitLab + package you want using **steps 1 and 2** from the GitLab downloads page but + **without** providing the `EXTERNAL_URL` value. +1. Edit `/etc/gitlab/gitlab.rb` to configure storage paths, enable + the network listener and configure the token: + + + + ```ruby + # /etc/gitlab/gitlab.rb + + # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests + # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API. + # The following two values must be the same as their respective values + # of the GitLab Rails application setup + gitaly['auth_token'] = 'gitalysecret' + gitlab_shell['secret_token'] = 'shellsecret' + + # Avoid running unnecessary services on the Gitaly server + postgresql['enable'] = false + redis['enable'] = false + nginx['enable'] = false + puma['enable'] = false + unicorn['enable'] = false + sidekiq['enable'] = false + gitlab_workhorse['enable'] = false + grafana['enable'] = false + + # If you run a seperate monitoring node you can disable these services + alertmanager['enable'] = false + prometheus['enable'] = false + + # Prevent database connections during 'gitlab-ctl reconfigure' + gitlab_rails['rake_cache_clear'] = false + gitlab_rails['auto_migrate'] = false + + # Configure the gitlab-shell API callback URL. Without this, `git push` will + # fail. This can be your 'front door' GitLab URL or an internal load + # balancer. + # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from web server to Gitaly server. + gitlab_rails['internal_api_url'] = 'https://gitlab.example.com' + + # Make Gitaly accept connections on all network interfaces. You must use + # firewalls to restrict access to this address/port. + # Comment out following line if you only want to support TLS connections + gitaly['listen_addr'] = "0.0.0.0:8075" + ``` + +1. Append the following to `/etc/gitlab/gitlab.rb` for each respective server: + 1. On `gitaly1.internal`: + + ```ruby + git_data_dirs({ + 'default' => { + 'path' => '/var/opt/gitlab/git-data' + }, + 'storage1' => { + 'path' => '/mnt/gitlab/git-data' + }, + }) + ``` + + 1. On `gitaly2.internal`: + + ```ruby + git_data_dirs({ + 'storage2' => { + 'path' => '/mnt/gitlab/git-data' + }, + }) + ``` + + + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). + +### Gitaly TLS support + +Gitaly supports TLS encryption. To be able to communicate +with a Gitaly instance that listens for secure connections you will need to use `tls://` URL +scheme in the `gitaly_address` of the corresponding storage entry in the GitLab configuration. + +You will need to bring your own certificates as this isn't provided automatically. +The certificate, or its certificate authority, must be installed on all Gitaly +nodes (including the Gitaly node using the certificate) and on all client nodes +that communicate with it following the procedure described in +[GitLab custom certificate configuration](https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates). + +NOTE: **Note:** +The self-signed certificate must specify the address you use to access the +Gitaly server. If you are addressing the Gitaly server by a hostname, you can +either use the Common Name field for this, or add it as a Subject Alternative +Name. If you are addressing the Gitaly server by its IP address, you must add it +as a Subject Alternative Name to the certificate. +[gRPC does not support using an IP address as Common Name in a certificate](https://github.com/grpc/grpc/issues/2691). + +NOTE: **Note:** +It is possible to configure Gitaly servers with both an +unencrypted listening address `listen_addr` and an encrypted listening +address `tls_listen_addr` at the same time. This allows you to do a +gradual transition from unencrypted to encrypted traffic, if necessary. + +To configure Gitaly with TLS: + +1. Create the `/etc/gitlab/ssl` directory and copy your key and certificate there: + + ```shell + sudo mkdir -p /etc/gitlab/ssl + sudo chmod 755 /etc/gitlab/ssl + sudo cp key.pem cert.pem /etc/gitlab/ssl/ + sudo chmod 644 key.pem cert.pem + ``` + +1. Copy the cert to `/etc/gitlab/trusted-certs` so Gitaly will trust the cert when + calling into itself: + + ```shell + sudo cp /etc/gitlab/ssl/cert.pem /etc/gitlab/trusted-certs/ + ``` + +1. Edit `/etc/gitlab/gitlab.rb` and add: + + + + ```ruby + gitaly['tls_listen_addr'] = "0.0.0.0:9999" + gitaly['certificate_path'] = "/etc/gitlab/ssl/cert.pem" + gitaly['key_path'] = "/etc/gitlab/ssl/key.pem" + ``` + +1. Delete `gitaly['listen_addr']` to allow only encrypted connections. + +1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). + + + +## Configure Sidekiq + +Sidekiq requires connections to the Redis, PostgreSQL and Gitaly instances. +The following IPs will be used as an example: + +- `10.6.0.101`: Sidekiq 1 +- `10.6.0.102`: Sidekiq 2 +- `10.6.0.103`: Sidekiq 3 +- `10.6.0.104`: Sidekiq 4 + +To configure the Sidekiq nodes, on each one: + +1. SSH into the Sidekiq server. +1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab package +you want using steps 1 and 2 from the GitLab downloads page. +**Do not complete any other steps on the download page.** +1. Open `/etc/gitlab/gitlab.rb` with your editor: + + ```ruby + ######################################## + ##### Services Disabled ### + ######################################## + + nginx['enable'] = false + grafana['enable'] = false + prometheus['enable'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = false + puma['enable'] = false + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + gitlab_exporter['enable'] = false + + ######################################## + #### Redis ### + ######################################## + + ## Redis connection details + ## First cluster that will host the cache + gitlab_rails['redis_cache_instance'] = 'redis://:@gitlab-redis-cache' + + gitlab_rails['redis_cache_sentinels'] = [ + {host: '10.6.0.71', port: 26379}, + {host: '10.6.0.72', port: 26379}, + {host: '10.6.0.73', port: 26379}, + ] + + ## Second cluster that will host the queues, shared state, and actioncable + gitlab_rails['redis_queues_instance'] = 'redis://:@gitlab-redis-persistent' + gitlab_rails['redis_shared_state_instance'] = 'redis://:@gitlab-redis-persistent' + gitlab_rails['redis_actioncable_instance'] = 'redis://:@gitlab-redis-persistent' + + gitlab_rails['redis_queues_sentinels'] = [ + {host: '10.6.0.81', port: 26379}, + {host: '10.6.0.82', port: 26379}, + {host: '10.6.0.83', port: 26379}, + ] + gitlab_rails['redis_shared_state_sentinels'] = [ + {host: '10.6.0.81', port: 26379}, + {host: '10.6.0.82', port: 26379}, + {host: '10.6.0.83', port: 26379}, + ] + gitlab_rails['redis_actioncable_sentinels'] = [ + {host: '10.6.0.81', port: 26379}, + {host: '10.6.0.82', port: 26379}, + {host: '10.6.0.83', port: 26379}, + ] + + ####################################### + ### Gitaly ### + ####################################### + + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, + }) + gitlab_rails['gitaly_token'] = 'YOUR_TOKEN' + + ####################################### + ### Postgres ### + ####################################### + gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP + gitlab_rails['db_port'] = 6432 + gitlab_rails['db_password'] = '' + gitlab_rails['db_adapter'] = 'postgresql' + gitlab_rails['db_encoding'] = 'unicode' + gitlab_rails['auto_migrate'] = false + + ####################################### + ### Sidekiq configuration ### + ####################################### + sidekiq['listen_address'] = "0.0.0.0" + sidekiq['cluster'] = true # no need to set this after GitLab 13.0 + + ####################################### + ### Monitoring configuration ### + ####################################### + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + + # Rails Status for prometheus + gitlab_rails['monitoring_whitelist'] = ['10.6.0.121/32', '127.0.0.0/8'] + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + +TIP: **Tip:** +You can also run [multiple Sidekiq processes](../operations/extra_sidekiq_processes.md). + + + +## Configure GitLab Rails + +NOTE: **Note:** +In our architectures we run each GitLab Rails node using the Puma webserver +and have its number of workers set to 90% of available CPUs along with four threads. For +nodes that are running Rails with other components the worker value should be reduced +accordingly where we've found 50% achieves a good balance but this is dependent +on workload. + +This section describes how to configure the GitLab application (Rails) component. + +The following IPs will be used as an example: + +- `10.6.0.111`: GitLab application 1 +- `10.6.0.112`: GitLab application 2 +- `10.6.0.113`: GitLab application 3 + +On each node perform the following: + +1. Download/install Omnibus GitLab using **steps 1 and 2** from + [GitLab downloads](https://about.gitlab.com/install/). Do not complete other + steps on the download page. + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. Edit `/etc/gitlab/gitlab.rb` and use the following configuration. + To maintain uniformity of links across nodes, the `external_url` + on the application server should point to the external URL that users will use + to access GitLab. This would be the URL of the [external load balancer](#configure-the-external-load-balancer) + which will route traffic to the GitLab application server: + + ```ruby + external_url 'https://gitlab.example.com' + + # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests + # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API. + # The following two values must be the same as their respective values + # of the Gitaly setup + gitlab_rails['gitaly_token'] = 'gitalysecret' + gitlab_shell['secret_token'] = 'shellsecret' + + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, + }) + + ## Disable components that will not be on the GitLab application server + roles ['application_role'] + gitaly['enable'] = false + nginx['enable'] = true + + ## PostgreSQL connection details + # Disable PostgreSQL on the application node + postgresql['enable'] = false + gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP + gitlab_rails['db_port'] = 6432 + gitlab_rails['db_password'] = '' + gitlab_rails['auto_migrate'] = false + + ## Redis connection details + ## First cluster that will host the cache + gitlab_rails['redis_cache_instance'] = 'redis://:@gitlab-redis-cache' + + gitlab_rails['redis_cache_sentinels'] = [ + {host: '10.6.0.71', port: 26379}, + {host: '10.6.0.72', port: 26379}, + {host: '10.6.0.73', port: 26379}, + ] + + ## Second cluster that will host the queues, shared state, and actionable + gitlab_rails['redis_queues_instance'] = 'redis://:@gitlab-redis-persistent' + gitlab_rails['redis_shared_state_instance'] = 'redis://:@gitlab-redis-persistent' + gitlab_rails['redis_actioncable_instance'] = 'redis://:@gitlab-redis-persistent' + + gitlab_rails['redis_queues_sentinels'] = [ + {host: '10.6.0.81', port: 26379}, + {host: '10.6.0.82', port: 26379}, + {host: '10.6.0.83', port: 26379}, + ] + gitlab_rails['redis_shared_state_sentinels'] = [ + {host: '10.6.0.81', port: 26379}, + {host: '10.6.0.82', port: 26379}, + {host: '10.6.0.83', port: 26379}, + ] + gitlab_rails['redis_actioncable_sentinels'] = [ + {host: '10.6.0.81', port: 26379}, + {host: '10.6.0.82', port: 26379}, + {host: '10.6.0.83', port: 26379}, + ] + + # Set the network addresses that the exporters used for monitoring will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + gitlab_workhorse['prometheus_listen_addr'] = '0.0.0.0:9229' + sidekiq['listen_address'] = "0.0.0.0" + puma['listen'] = '0.0.0.0' + + # Add the monitoring node's IP address to the monitoring whitelist and allow it to + # scrape the NGINX metrics + gitlab_rails['monitoring_whitelist'] = ['10.6.0.121/32', '127.0.0.0/8'] + nginx['status']['options']['allow'] = ['10.6.0.121/32', '127.0.0.0/8'] + ``` + +1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). +1. If you're using [Gitaly with TLS support](#gitaly-tls-support), make sure the + `git_data_dirs` entry is configured with `tls` instead of `tcp`: + + ```ruby + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage1' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage2' => { 'gitaly_address' => 'tls://gitaly2.internal:9999' }, + }) + ``` + + 1. Copy the cert into `/etc/gitlab/trusted-certs`: + + ```shell + sudo cp cert.pem /etc/gitlab/trusted-certs/ + ``` + +1. If you're [using NFS](#configure-nfs-optional): + 1. If necessary, install the NFS client utility packages using the following + commands: + + ```shell + # Ubuntu/Debian + apt-get install nfs-common + + # CentOS/Red Hat + yum install nfs-utils nfs-utils-lib + ``` + + 1. Specify the necessary NFS mounts in `/etc/fstab`. + The exact contents of `/etc/fstab` will depend on how you chose + to configure your NFS server. See the [NFS documentation](../high_availability/nfs.md) + for examples and the various options. + + 1. Create the shared directories. These may be different depending on your NFS + mount locations. + + ```shell + mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data + ``` + + 1. Edit `/etc/gitlab/gitlab.rb` and use the following configuration: + + ```ruby + ## Prevent GitLab from starting if NFS data mounts are not available + high_availability['mountpoint'] = '/var/opt/gitlab/git-data' + + ## Ensure UIDs and GIDs match between servers for permissions via NFS + user['uid'] = 9000 + user['gid'] = 9000 + web_server['uid'] = 9001 + web_server['gid'] = 9001 + registry['uid'] = 9002 + registry['gid'] = 9002 + ``` + +1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). +1. Confirm the node can connect to Gitaly: + + ```shell + sudo gitlab-rake gitlab:gitaly:check + ``` + + Then, tail the logs to see the requests: + + ```shell + sudo gitlab-ctl tail gitaly + ``` + +1. Optionally, from the Gitaly servers, confirm that Gitaly can perform callbacks to the internal API: + + ```shell + sudo /opt/gitlab/embedded/service/gitlab-shell/bin/check -config /opt/gitlab/embedded/service/gitlab-shell/config.yml + ``` + +NOTE: **Note:** +When you specify `https` in the `external_url`, as in the example +above, GitLab assumes you have SSL certificates in `/etc/gitlab/ssl/`. If +certificates are not present, NGINX will fail to start. See the +[NGINX documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https) +for more information. + +### GitLab Rails post-configuration + +Initialize the GitLab database, by running the following in one of the Rails nodes: + +```shell +sudo gitlab-rake gitlab:db:configure +``` + +NOTE: **Note:** +If you encounter a `rake aborted!` error stating that PgBouncer is failing to connect to +PostgreSQL it may be that your PgBouncer node's IP address is missing from +PostgreSQL's `trust_auth_cidr_addresses` in `gitlab.rb` on your database nodes. See +[PgBouncer error `ERROR: pgbouncer cannot connect to server`](troubleshooting.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server) +in the Troubleshooting section before proceeding. + + + +## Configure Prometheus + +The Omnibus GitLab package can be used to configure a standalone Monitoring node +running [Prometheus](../monitoring/prometheus/index.md) and +[Grafana](../monitoring/performance/grafana_configuration.md). + +The following IP will be used as an example: + +- `10.6.0.121`: Prometheus + +To configure the Monitoring node: + +1. SSH into the Monitoring node. +1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab + package you want using **steps 1 and 2** from the GitLab downloads page. + Do not complete any other steps on the download page. + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + external_url 'http://gitlab.example.com' + + # Disable all other services + gitlab_rails['auto_migrate'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_exporter['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = true + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + sidekiq['enable'] = false + puma['enable'] = false + unicorn['enable'] = false + node_exporter['enable'] = false + gitlab_exporter['enable'] = false + + # Enable Prometheus + prometheus['enable'] = true + prometheus['listen_address'] = '0.0.0.0:9090' + prometheus['monitor_kubernetes'] = false + + # Enable Login form + grafana['disable_login_form'] = false + + # Enable Grafana + grafana['enable'] = true + grafana['admin_password'] = '' + + # Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + ``` + +1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). +1. In the GitLab UI, set `admin/application_settings/metrics_and_profiling` > Metrics - Grafana to `/-/grafana` to +`http[s]:///-/grafana` + + + +## Configure the object storage + +GitLab supports using an object storage service for holding numerous types of data. +It's recommended over [NFS](#configure-nfs-optional) and in general it's better +in larger setups as object storage is typically much more performant, reliable, +and scalable. + +Object storage options that GitLab has tested, or is aware of customers using include: + +- SaaS/Cloud solutions such as [Amazon S3](https://aws.amazon.com/s3/), [Google cloud storage](https://cloud.google.com/storage). +- On-premises hardware and appliances from various storage vendors. +- MinIO. There is [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation. + +For configuring GitLab to use Object Storage refer to the following guides +based on what features you intend to use: + +1. Configure [object storage for backups](../../raketasks/backup_restore.md#uploading-backups-to-a-remote-cloud-storage). +1. Configure [object storage for job artifacts](../job_artifacts.md#using-object-storage) + including [incremental logging](../job_logs.md#new-incremental-logging-architecture). +1. Configure [object storage for LFS objects](../lfs/index.md#storing-lfs-objects-in-remote-object-storage). +1. Configure [object storage for uploads](../uploads.md#using-object-storage-core-only). +1. Configure [object storage for merge request diffs](../merge_request_diffs.md#using-object-storage). +1. Configure [object storage for Container Registry](../packages/container_registry.md#use-object-storage) (optional feature). +1. Configure [object storage for Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage) (optional feature). +1. Configure [object storage for packages](../packages/index.md#using-object-storage) (optional feature). **(PREMIUM ONLY)** +1. Configure [object storage for Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature). **(PREMIUM ONLY)** +1. Configure [object storage for Pseudonymizer](../pseudonymizer.md#configuration) (optional feature). **(ULTIMATE ONLY)** +1. Configure [object storage for autoscale Runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional - for improved performance). +1. Configure [object storage for Terraform state files](../terraform_state.md#using-object-storage-core-only). + +Using separate buckets for each data type is the recommended approach for GitLab. + +A limitation of our configuration is that each use of object storage is separately configured. +[We have an issue for improving this](https://gitlab.com/gitlab-org/gitlab/-/issues/23345) +and easily using one bucket with separate folders is one improvement that this might bring. + +There is at least one specific issue with using the same bucket: +when GitLab is deployed with the Helm chart restore from backup +[will not properly function](https://docs.gitlab.com/charts/advanced/external-object-storage/#lfs-artifacts-uploads-packages-external-diffs-pseudonymizer) +unless separate buckets are used. + +One risk of using a single bucket would be if your organization decided to +migrate GitLab to the Helm deployment in the future. GitLab would run, but the situation with +backups might not be realized until the organization had a critical requirement for the backups to +work. + + + +## Configure NFS (optional) + +[Object storage](#configure-the-object-storage), along with [Gitaly](#configure-gitaly) +are recommended over NFS wherever possible for improved performance. If you intend +to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pages-requires-nfs). + +See how to [configure NFS](../high_availability/nfs.md). + + + +## Troubleshooting + +See the [troubleshooting documentation](troubleshooting.md). + + diff --git a/doc/administration/reference_architectures/1k_users.md b/doc/administration/reference_architectures/1k_users.md index def23619a5c..d3cf5f49413 100644 --- a/doc/administration/reference_architectures/1k_users.md +++ b/doc/administration/reference_architectures/1k_users.md @@ -1,86 +1,49 @@ -# Reference architecture: up to 1,000 users +--- +stage: Enablement +group: Distribution +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- -This page describes GitLab reference architecture for up to 1,000 users. -For a full list of reference architectures, see -[Available reference architectures](index.md#available-reference-architectures). - -> - **Supported users (approximate):** 1,000 -> - **High Availability:** False +# Reference architecture: up to 1,000 users **(CORE ONLY)** -| Users | Configuration([8](#footnotes)) | GCP | AWS | Azure | -|-------|------------------------------------|----------------|---------------------|------------------------| -| 500 | 4 vCPU, 3.6GB Memory | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | -| 1000 | 8 vCPU, 7.2GB Memory | `n1-highcpu-8` | `c5.2xlarge` | F8s v2 | +This page describes GitLab reference architecture for up to 1,000 users. For a +full list of reference architectures, see +[Available reference architectures](index.md#available-reference-architectures). -In addition to the above, we recommend having at least -2GB of swap on your server, even if you currently have -enough available RAM. Having swap will help reduce the chance of errors occurring -if your available memory changes. We also recommend -configuring the kernel's swappiness setting -to a low value like `10` to make the most of your RAM while still having the swap -available when needed. +If you need to serve up to 1,000 users and you don't have strict availability +requirements, a single-node solution with +[frequent backups](index.md#automated-backups-core-only) is appropriate for +many organizations . -For situations where you need to serve up to 1,000 users, a single-node -solution with [frequent backups](index.md#automated-backups-core-only) is appropriate -for many organizations. With automatic backup of the GitLab repositories, -configuration, and the database, if you don't have strict availability -requirements, this is the ideal solution. +> - **Supported users (approximate):** 1,000 +> - **High Availability:** No + +| Users | Configuration | GCP | AWS | Azure | +|--------------|-------------------------|----------------|-----------------|----------------| +| Up to 500 | 4 vCPU, 3.6GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 | +| Up to 1,000 | 8 vCPU, 7.2GB memory | n1-highcpu-8 | c5.2xlarge | F8s v2 | + +The Google Cloud Platform (GCP) architectures were built and tested using the +[Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) +CPU platform. On different hardware you may find that adjustments, either lower +or higher, are required for your CPU or node counts. For more information, see +our [Sysbench](https://github.com/akopytov/sysbench)-based +[CPU benchmark](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks). + +In addition to the stated configurations, we recommend having at least 2GB of +swap on your server, even if you currently have enough available memory. Having +swap will help reduce the chance of errors occurring if your available memory +changes. We also recommend configuring the kernel's swappiness setting to a +lower value (such as `10`) to make the most of your memory, while still having +the swap available when needed. ## Setup instructions -- For this default reference architecture, use the standard [installation instructions](../../install/README.md) to install GitLab. +For this default reference architecture, to install GitLab use the standard +[installation instructions](../../install/README.md). NOTE: **Note:** You can also optionally configure GitLab to use an [external PostgreSQL service](../postgresql/external.md) or an [external object storage service](../high_availability/object_storage.md) for added performance and reliability at a reduced complexity cost. - -## Footnotes - -1. In our architectures we run each GitLab Rails node using the Puma webserver - and have its number of workers set to 90% of available CPUs along with four threads. For - nodes that are running Rails with other components the worker value should be reduced - accordingly where we've found 50% achieves a good balance but this is dependent - on workload. - -1. Gitaly node requirements are dependent on customer data, specifically the number of - projects and their sizes. We recommend two nodes as an absolute minimum for HA environments - and at least four nodes should be used when supporting 50,000 or more users. - We also recommend that each Gitaly node should store no more than 5TB of data - and have the number of [`gitaly-ruby` workers](../gitaly/index.md#gitaly-ruby) - set to 20% of available CPUs. Additional nodes should be considered in conjunction - with a review of expected data size and spread based on the recommendations above. - -1. Recommended Redis setup differs depending on the size of the architecture. - For smaller architectures (less than 3,000 users) a single instance should suffice. - For medium sized installs (3,000 - 5,000) we suggest one Redis cluster for all - classes and that Redis Sentinel is hosted alongside Consul. - For larger architectures (10,000 users or more) we suggest running a separate - [Redis Cluster](../redis/replication_and_failover.md#running-multiple-redis-clusters) for the Cache class - and another for the Queues and Shared State classes respectively. We also recommend - that you run the Redis Sentinel clusters separately for each Redis Cluster. - -1. For data objects such as LFS, Uploads, Artifacts, etc. We recommend an [Object Storage service](../object_storage.md) - over NFS where possible, due to better performance and availability. - -1. NFS can be used as an alternative for both repository data (replacing Gitaly) and - object storage but this isn't typically recommended for performance reasons. Note however it is required for - [GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196). - -1. Our architectures have been tested and validated with [HAProxy](https://www.haproxy.org/) - as the load balancer. Although other load balancers with similar feature sets - could also be used, those load balancers have not been validated. - -1. We strongly recommend that any Gitaly or NFS nodes be set up with SSD disks over - HDD with a throughput of at least 8,000 IOPS for read operations and 2,000 IOPS for write - as these components have heavy I/O. These IOPS values are recommended only as a starter - as with time they may be adjusted higher or lower depending on the scale of your - environment's workload. If you're running the environment on a Cloud provider - you may need to refer to their documentation on how configure IOPS correctly. - -1. The architectures were built and tested with the [Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) - CPU platform on GCP. On different hardware you may find that adjustments, either lower - or higher, are required for your CPU or Node counts accordingly. For more information, a - [Sysbench](https://github.com/akopytov/sysbench) benchmark of the CPU can be found - [here](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks). diff --git a/doc/administration/reference_architectures/25k_users.md b/doc/administration/reference_architectures/25k_users.md index 17f4300eb03..1cfa2565893 100644 --- a/doc/administration/reference_architectures/25k_users.md +++ b/doc/administration/reference_architectures/25k_users.md @@ -1,76 +1,2047 @@ -# Reference architecture: up to 25,000 users +--- +reading_time: true +stage: Enablement +group: Distribution +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- -This page describes GitLab reference architecture for up to 25,000 users. -For a full list of reference architectures, see +# Reference architecture: up to 25,000 users **(PREMIUM ONLY)** + +This page describes GitLab reference architecture for up to 25,000 users. For a +full list of reference architectures, see [Available reference architectures](index.md#available-reference-architectures). > - **Supported users (approximate):** 25,000 -> - **High Availability:** True -> - **Test RPS rates:** API: 500 RPS, Web: 50 RPS, Git: 50 RPS - -| Service | Nodes | Configuration ([8](#footnotes)) | GCP | AWS | Azure | -|--------------------------------------------------------------|-------|---------------------------------|------------------|-----------------------|----------------| -| GitLab Rails ([1](#footnotes)) | 5 | 32 vCPU, 28.8GB Memory | `n1-highcpu-32` | `c5.9xlarge` | F32s v2 | -| PostgreSQL | 3 | 8 vCPU, 30GB Memory | `n1-standard-8` | `m5.2xlarge` | D8s v3 | -| PgBouncer | 3 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | F2s v2 | -| Gitaly ([2](#footnotes)) ([5](#footnotes)) ([7](#footnotes)) | X | 32 vCPU, 120GB Memory | `n1-standard-32` | `m5.8xlarge` | D32s v3 | -| Redis ([3](#footnotes)) - Cache | 3 | 4 vCPU, 15GB Memory | `n1-standard-4` | `m5.xlarge` | D4s v3 | -| Redis ([3](#footnotes)) - Queues / Shared State | 3 | 4 vCPU, 15GB Memory | `n1-standard-4` | `m5.xlarge` | D4s v3 | -| Redis Sentinel ([3](#footnotes)) - Cache | 3 | 1 vCPU, 1.7GB Memory | `g1-small` | `t2.small` | B1MS | -| Redis Sentinel ([3](#footnotes)) - Queues / Shared State | 3 | 1 vCPU, 1.7GB Memory | `g1-small` | `t2.small` | B1MS | -| Consul | 3 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | F2s v2 | -| Sidekiq | 4 | 4 vCPU, 15GB Memory | `n1-standard-4` | `m5.xlarge` | D4s v3 | -| Object Storage ([4](#footnotes)) | - | - | - | - | - | -| NFS Server ([5](#footnotes)) ([7](#footnotes)) | 1 | 4 vCPU, 3.6GB Memory | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | -| Monitoring node | 1 | 4 vCPU, 3.6GB Memory | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | -| External load balancing node ([6](#footnotes)) | 1 | 4 vCPU, 3.6GB Memory | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | -| Internal load balancing node ([6](#footnotes)) | 1 | 4 vCPU, 3.6GB Memory | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | - -## Footnotes - -1. In our architectures we run each GitLab Rails node using the Puma webserver - and have its number of workers set to 90% of available CPUs along with four threads. For - nodes that are running Rails with other components the worker value should be reduced - accordingly where we've found 50% achieves a good balance but this is dependent - on workload. - -1. Gitaly node requirements are dependent on customer data, specifically the number of - projects and their sizes. We recommend two nodes as an absolute minimum for HA environments - and at least four nodes should be used when supporting 50,000 or more users. - We also recommend that each Gitaly node should store no more than 5TB of data - and have the number of [`gitaly-ruby` workers](../gitaly/index.md#gitaly-ruby) - set to 20% of available CPUs. Additional nodes should be considered in conjunction - with a review of expected data size and spread based on the recommendations above. - -1. Recommended Redis setup differs depending on the size of the architecture. - For smaller architectures (less than 3,000 users) a single instance should suffice. - For medium sized installs (3,000 - 5,000) we suggest one Redis cluster for all - classes and that Redis Sentinel is hosted alongside Consul. - For larger architectures (10,000 users or more) we suggest running a separate - [Redis Cluster](../redis/replication_and_failover.md#running-multiple-redis-clusters) for the Cache class - and another for the Queues and Shared State classes respectively. We also recommend - that you run the Redis Sentinel clusters separately for each Redis Cluster. - -1. For data objects such as LFS, Uploads, Artifacts, etc. We recommend an [Object Storage service](../object_storage.md) - over NFS where possible, due to better performance and availability. - -1. NFS can be used as an alternative for both repository data (replacing Gitaly) and - object storage but this isn't typically recommended for performance reasons. Note however it is required for - [GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196). - -1. Our architectures have been tested and validated with [HAProxy](https://www.haproxy.org/) - as the load balancer. Although other load balancers with similar feature sets - could also be used, those load balancers have not been validated. - -1. We strongly recommend that any Gitaly or NFS nodes be set up with SSD disks over - HDD with a throughput of at least 8,000 IOPS for read operations and 2,000 IOPS for write - as these components have heavy I/O. These IOPS values are recommended only as a starter - as with time they may be adjusted higher or lower depending on the scale of your - environment's workload. If you're running the environment on a Cloud provider - you may need to refer to their documentation on how configure IOPS correctly. - -1. The architectures were built and tested with the [Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) - CPU platform on GCP. On different hardware you may find that adjustments, either lower - or higher, are required for your CPU or Node counts accordingly. For more information, a - [Sysbench](https://github.com/akopytov/sysbench) benchmark of the CPU can be found - [here](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks). +> - **High Availability:** Yes +> - **Test requests per second (RPS) rates:** API: 500 RPS, Web: 50 RPS, Git: 50 RPS + +| Service | Nodes | Configuration | GCP | AWS | Azure | +|-----------------------------------------|-------------|-------------------------|-----------------|-------------|----------| +| External load balancing node | 1 | 4 vCPU, 3.6GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 | +| Consul | 3 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| PostgreSQL | 3 | 8 vCPU, 30GB memory | n1-standard-8 | m5.2xlarge | D8s v3 | +| PgBouncer | 3 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| Internal load balancing node | 1 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| Redis - Cache | 3 | 4 vCPU, 15GB memory | n1-standard-4 | m5.xlarge | D4s v3 | +| Redis - Queues / Shared State | 3 | 4 vCPU, 15GB memory | n1-standard-4 | m5.xlarge | D4s v3 | +| Redis Sentinel - Cache | 3 | 1 vCPU, 1.7GB memory | g1-small | t2.small | B1MS | +| Redis Sentinel - Queues / Shared State | 3 | 1 vCPU, 1.7GB memory | g1-small | t2.small | B1MS | +| Gitaly | 2 (minimum) | 32 vCPU, 120GB memory | n1-standard-32 | m5.8xlarge | D32s v3 | +| Sidekiq | 4 | 4 vCPU, 15GB memory | n1-standard-4 | m5.xlarge | D4s v3 | +| GitLab Rails | 5 | 32 vCPU, 28.8GB memory | n1-highcpu-32 | c5.9xlarge | F32s v2 | +| Monitoring node | 1 | 4 vCPU, 3.6GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 | +| Object Storage | n/a | n/a | n/a | n/a | n/a | +| NFS Server | 1 | 4 vCPU, 3.6GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 | + +The Google Cloud Platform (GCP) architectures were built and tested using the +[Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) +CPU platform. On different hardware you may find that adjustments, either lower +or higher, are required for your CPU or node counts. For more information, see +our [Sysbench](https://github.com/akopytov/sysbench)-based +[CPU benchmark](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks). + +For data objects (such as LFS, Uploads, or Artifacts), an +[object storage service](#configure-the-object-storage) is recommended instead +of NFS where possible, due to better performance and availability. Since this +doesn't require a node to be set up, *Object Storage* is noted as not +applicable (n/a) in the previous table. + +## Setup components + +To set up GitLab and its components to accommodate up to 25,000 users: + +1. [Configure the external load balancing node](#configure-the-external-load-balancer) + that will handle the load balancing of the three GitLab application services nodes. +1. [Configure Consul](#configure-consul). +1. [Configure PostgreSQL](#configure-postgresql), the database for GitLab. +1. [Configure PgBouncer](#configure-pgbouncer). +1. [Configure the internal load balancing node](#configure-the-internal-load-balancer) +1. [Configure Redis](#configure-redis). +1. [Configure Gitaly](#configure-gitaly), + which provides access to the Git repositories. +1. [Configure Sidekiq](#configure-sidekiq). +1. [Configure the main GitLab Rails application](#configure-gitlab-rails) + to run Puma/Unicorn, Workhorse, GitLab Shell, and to serve all frontend requests (UI, API, Git + over HTTP/SSH). +1. [Configure Prometheus](#configure-prometheus) to monitor your GitLab environment. +1. [Configure the Object Storage](#configure-the-object-storage) + used for shared data objects. +1. [Configure NFS (Optional)](#configure-nfs-optional) + to have shared disk storage service as an alternative to Gitaly and/or Object Storage (although + not recommended). NFS is required for GitLab Pages, you can skip this step if you're not using + that feature. + +We start with all servers on the same 10.6.0.0/24 private network range, they +can connect to each other freely on those addresses. + +Here is a list and description of each machine and the assigned IP: + +- `10.6.0.10`: External Load Balancer +- `10.6.0.11`: Consul 1 +- `10.6.0.12`: Consul 2 +- `10.6.0.13`: Consul 3 +- `10.6.0.21`: PostgreSQL primary +- `10.6.0.22`: PostgreSQL secondary 1 +- `10.6.0.23`: PostgreSQL secondary 2 +- `10.6.0.31`: PgBouncer 1 +- `10.6.0.32`: PgBouncer 2 +- `10.6.0.33`: PgBouncer 3 +- `10.6.0.40`: Internal Load Balancer +- `10.6.0.51`: Redis - Cache Primary +- `10.6.0.52`: Redis - Cache Replica 1 +- `10.6.0.53`: Redis - Cache Replica 2 +- `10.6.0.71`: Sentinel - Cache 1 +- `10.6.0.72`: Sentinel - Cache 2 +- `10.6.0.73`: Sentinel - Cache 3 +- `10.6.0.61`: Redis - Queues Primary +- `10.6.0.62`: Redis - Queues Replica 1 +- `10.6.0.63`: Redis - Queues Replica 2 +- `10.6.0.81`: Sentinel - Queues 1 +- `10.6.0.82`: Sentinel - Queues 2 +- `10.6.0.83`: Sentinel - Queues 3 +- `10.6.0.91`: Gitaly 1 +- `10.6.0.92`: Gitaly 2 +- `10.6.0.101`: Sidekiq 1 +- `10.6.0.102`: Sidekiq 2 +- `10.6.0.103`: Sidekiq 3 +- `10.6.0.104`: Sidekiq 4 +- `10.6.0.111`: GitLab application 1 +- `10.6.0.112`: GitLab application 2 +- `10.6.0.113`: GitLab application 3 +- `10.6.0.121`: Prometheus + +## Configure the external load balancer + +NOTE: **Note:** +This architecture has been tested and validated with [HAProxy](https://www.haproxy.org/) +as the load balancer. Although other load balancers with similar feature sets +could also be used, those load balancers have not been validated. + +In an active/active GitLab configuration, you will need a load balancer to route +traffic to the application servers. The specifics on which load balancer to use +or the exact configuration is beyond the scope of GitLab documentation. We hope +that if you're managing multi-node systems like GitLab you have a load balancer of +choice already. Some examples including HAProxy (open-source), F5 Big-IP LTM, +and Citrix Net Scaler. This documentation will outline what ports and protocols +you need to use with GitLab. + +The next question is how you will handle SSL in your environment. +There are several different options: + +- [The application node terminates SSL](#application-node-terminates-ssl). +- [The load balancer terminates SSL without backend SSL](#load-balancer-terminates-ssl-without-backend-ssl) + and communication is not secure between the load balancer and the application node. +- [The load balancer terminates SSL with backend SSL](#load-balancer-terminates-ssl-with-backend-ssl) + and communication is *secure* between the load balancer and the application node. + +### Application node terminates SSL + +Configure your load balancer to pass connections on port 443 as `TCP` rather +than `HTTP(S)` protocol. This will pass the connection to the application node's +NGINX service untouched. NGINX will have the SSL certificate and listen on port 443. + +See the [NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https) +for details on managing SSL certificates and configuring NGINX. + +### Load balancer terminates SSL without backend SSL + +Configure your load balancer to use the `HTTP(S)` protocol rather than `TCP`. +The load balancer will then be responsible for managing SSL certificates and +terminating SSL. + +Since communication between the load balancer and GitLab will not be secure, +there is some additional configuration needed. See the +[NGINX proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#supporting-proxied-ssl) +for details. + +### Load balancer terminates SSL with backend SSL + +Configure your load balancer(s) to use the 'HTTP(S)' protocol rather than 'TCP'. +The load balancer(s) will be responsible for managing SSL certificates that +end users will see. + +Traffic will also be secure between the load balancer(s) and NGINX in this +scenario. There is no need to add configuration for proxied SSL since the +connection will be secure all the way. However, configuration will need to be +added to GitLab to configure SSL certificates. See +[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https) +for details on managing SSL certificates and configuring NGINX. + +### Ports + +The basic ports to be used are shown in the table below. + +| LB Port | Backend Port | Protocol | +| ------- | ------------ | ------------------------ | +| 80 | 80 | HTTP (*1*) | +| 443 | 443 | TCP or HTTPS (*1*) (*2*) | +| 22 | 22 | TCP | + +- (*1*): [Web terminal](../../ci/environments/index.md#web-terminals) support requires + your load balancer to correctly handle WebSocket connections. When using + HTTP or HTTPS proxying, this means your load balancer must be configured + to pass through the `Connection` and `Upgrade` hop-by-hop headers. See the + [web terminal](../integration/terminal.md) integration guide for + more details. +- (*2*): When using HTTPS protocol for port 443, you will need to add an SSL + certificate to the load balancers. If you wish to terminate SSL at the + GitLab application server instead, use TCP protocol. + +If you're using GitLab Pages with custom domain support you will need some +additional port configurations. +GitLab Pages requires a separate virtual IP address. Configure DNS to point the +`pages_external_url` from `/etc/gitlab/gitlab.rb` at the new virtual IP address. See the +[GitLab Pages documentation](../pages/index.md) for more information. + +| LB Port | Backend Port | Protocol | +| ------- | ------------- | --------- | +| 80 | Varies (*1*) | HTTP | +| 443 | Varies (*1*) | TCP (*2*) | + +- (*1*): The backend port for GitLab Pages depends on the + `gitlab_pages['external_http']` and `gitlab_pages['external_https']` + setting. See [GitLab Pages documentation](../pages/index.md) for more details. +- (*2*): Port 443 for GitLab Pages should always use the TCP protocol. Users can + configure custom domains with custom SSL, which would not be possible + if SSL was terminated at the load balancer. + +#### Alternate SSH Port + +Some organizations have policies against opening SSH port 22. In this case, +it may be helpful to configure an alternate SSH hostname that allows users +to use SSH on port 443. An alternate SSH hostname will require a new virtual IP address +compared to the other GitLab HTTP configuration above. + +Configure DNS for an alternate SSH hostname such as `altssh.gitlab.example.com`. + +| LB Port | Backend Port | Protocol | +| ------- | ------------ | -------- | +| 443 | 22 | TCP | + + + +## Configure Consul + +The following IPs will be used as an example: + +- `10.6.0.11`: Consul 1 +- `10.6.0.12`: Consul 2 +- `10.6.0.13`: Consul 3 + +NOTE: **Note:** +The configuration processes for the other servers in your reference architecture will +use the `/etc/gitlab/gitlab-secrets.json` file from your Consul server to connect +with the other servers. + +To configure Consul: + +1. SSH into the server that will host Consul. +1. [Download/install](https://about.gitlab.com/install/) the + Omnibus GitLab Enterprise Edition package using **steps 1 and 2** from the + GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + the GitLab application is running. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + roles ['consul_role'] + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + server: true, + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. +1. Go through the steps again for all the other Consul nodes, and + make sure you set up the correct IPs. + +NOTE: **Note:** +A Consul leader will be elected when the provisioning of the third Consul server is completed. +Viewing the Consul logs `sudo gitlab-ctl tail consul` will display +`...[INFO] consul: New leader elected: ...` + +You can list the current Consul members (server, client): + +```shell +sudo /opt/gitlab/embedded/bin/consul members +``` + +You can verify the GitLab services are running: + +```shell +sudo gitlab-ctl status +``` + +The output should be similar to the following: + +```plaintext +run: consul: (pid 30074) 76834s; run: log: (pid 29740) 76844s +run: logrotate: (pid 30925) 3041s; run: log: (pid 29649) 76861s +run: node-exporter: (pid 30093) 76833s; run: log: (pid 29663) 76855s +``` + + + +## Configure PostgreSQL + +In this section, you'll be guided through configuring an external PostgreSQL database +to be used with GitLab. + +### Provide your own PostgreSQL instance + +If you're hosting GitLab on a cloud provider, you can optionally use a +managed service for PostgreSQL. For example, AWS offers a managed Relational +Database Service (RDS) that runs PostgreSQL. + +If you use a cloud-managed service, or provide your own PostgreSQL: + +1. Set up PostgreSQL according to the + [database requirements document](../../install/requirements.md#database). +1. Set up a `gitlab` username with a password of your choice. The `gitlab` user + needs privileges to create the `gitlabhq_production` database. +1. Configure the GitLab application servers with the appropriate details. + This step is covered in [Configuring the GitLab Rails application](#configure-gitlab-rails). + +### Standalone PostgreSQL using Omnibus GitLab + +The following IPs will be used as an example: + +- `10.6.0.21`: PostgreSQL primary +- `10.6.0.22`: PostgreSQL secondary 1 +- `10.6.0.23`: PostgreSQL secondary 2 + +First, make sure to [install](https://about.gitlab.com/install/) +the Linux GitLab package **on each node**. Following the steps, +install the necessary dependencies from step 1, and add the +GitLab package repository from step 2. When installing GitLab +in the second step, do not supply the `EXTERNAL_URL` value. + +#### PostgreSQL primary node + +1. SSH into the PostgreSQL primary node. +1. Generate a password hash for the PostgreSQL username/password pair. This assumes you will use the default + username of `gitlab` (recommended). The command will request a password + and confirmation. Use the value that is output by this command in the next + step as the value of ``: + + ```shell + sudo gitlab-ctl pg-password-md5 gitlab + ``` + +1. Generate a password hash for the PgBouncer username/password pair. This assumes you will use the default + username of `pgbouncer` (recommended). The command will request a password + and confirmation. Use the value that is output by this command in the next + step as the value of ``: + + ```shell + sudo gitlab-ctl pg-password-md5 pgbouncer + ``` + +1. Generate a password hash for the Consul database username/password pair. This assumes you will use the default + username of `gitlab-consul` (recommended). The command will request a password + and confirmation. Use the value that is output by this command in the next + step as the value of ``: + + ```shell + sudo gitlab-ctl pg-password-md5 gitlab-consul + ``` + +1. On the primary database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section: + + ```ruby + # Disable all components except PostgreSQL and Repmgr and Consul + roles ['postgres_role'] + + # PostgreSQL configuration + postgresql['listen_address'] = '0.0.0.0' + postgresql['hot_standby'] = 'on' + postgresql['wal_level'] = 'replica' + postgresql['shared_preload_libraries'] = 'repmgr_funcs' + + # Disable automatic database migrations + gitlab_rails['auto_migrate'] = false + + # Configure the Consul agent + consul['services'] = %w(postgresql) + + # START user configuration + # Please set the real values as explained in Required Information section + # + # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value + postgresql['pgbouncer_user_password'] = '' + # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value + postgresql['sql_user_password'] = '' + # Set `max_wal_senders` to one more than the number of database nodes in the cluster. + # This is used to prevent replication from using up all of the + # available database connections. + postgresql['max_wal_senders'] = 4 + postgresql['max_replication_slots'] = 4 + + # Replace XXX.XXX.XXX.XXX/YY with Network Address + postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24) + repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + + ## Enable service discovery for Prometheus + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on for monitoring + node_exporter['listen_address'] = '0.0.0.0:9100' + postgres_exporter['listen_address'] = '0.0.0.0:9187' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + # + # END user configuration + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + + + +#### PostgreSQL secondary nodes + +1. On both the secondary nodes, add the same configuration specified above for the primary node + with an additional setting (`repmgr['master_on_initialization'] = false`) that will inform `gitlab-ctl` that they are standby nodes initially + and there's no need to attempt to register them as a primary node: + + ```ruby + # Disable all components except PostgreSQL and Repmgr and Consul + roles ['postgres_role'] + + # PostgreSQL configuration + postgresql['listen_address'] = '0.0.0.0' + postgresql['hot_standby'] = 'on' + postgresql['wal_level'] = 'replica' + postgresql['shared_preload_libraries'] = 'repmgr_funcs' + + # Disable automatic database migrations + gitlab_rails['auto_migrate'] = false + + # Configure the Consul agent + consul['services'] = %w(postgresql) + + # Specify if a node should attempt to be primary on initialization. + repmgr['master_on_initialization'] = false + + # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value + postgresql['pgbouncer_user_password'] = '' + # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value + postgresql['sql_user_password'] = '' + # Set `max_wal_senders` to one more than the number of database nodes in the cluster. + # This is used to prevent replication from using up all of the + # available database connections. + postgresql['max_wal_senders'] = 4 + postgresql['max_replication_slots'] = 4 + + # Replace with your network addresses + postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24) + repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + + ## Enable service discovery for Prometheus + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on for monitoring + node_exporter['listen_address'] = '0.0.0.0:9100' + postgres_exporter['listen_address'] = '0.0.0.0:9187' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + +Advanced [configuration options](https://docs.gitlab.com/omnibus/settings/database.html) +are supported and can be added if needed. + + + +#### PostgreSQL post-configuration + +SSH into the **primary node**: + +1. Open a database prompt: + + ```shell + gitlab-psql -d gitlabhq_production + ``` + +1. Make sure the `pg_trgm` extension is enabled (it might already be): + + ```shell + CREATE EXTENSION pg_trgm; + ``` + +1. Exit the database prompt by typing `\q` and Enter. + +1. Verify the cluster is initialized with one node: + + ```shell + gitlab-ctl repmgr cluster show + ``` + + The output should be similar to the following: + + ```plaintext + Role | Name | Upstream | Connection String + ----------+----------|----------|---------------------------------------- + * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr + ``` + +1. Note down the hostname or IP address in the connection string: `host=HOSTNAME`. We will + refer to the hostname in the next section as ``. If the value + is not an IP address, it will need to be a resolvable name (via DNS or + `/etc/hosts`) + +SSH into the **secondary node**: + +1. Set up the repmgr standby: + + ```shell + gitlab-ctl repmgr standby setup + ``` + + Do note that this will remove the existing data on the node. The command + has a wait time. + + The output should be similar to the following: + + ```console + Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data + If this is not what you want, hit Ctrl-C now to exit + To skip waiting, rerun with the -w option + Sleeping for 30 seconds + Stopping the database + Removing the data + Cloning the data + Starting the database + Registering the node with the cluster + ok: run: repmgrd: (pid 19068) 0s + ``` + +Before moving on, make sure the databases are configured correctly. Run the +following command on the **primary** node to verify that replication is working +properly and the secondary nodes appear in the cluster: + +```shell +gitlab-ctl repmgr cluster show +``` + +The output should be similar to the following: + +```plaintext +Role | Name | Upstream | Connection String +----------+---------|-----------|------------------------------------------------ +* master | MASTER | | host= user=gitlab_repmgr dbname=gitlab_repmgr + standby | STANDBY | MASTER | host= user=gitlab_repmgr dbname=gitlab_repmgr + standby | STANDBY | MASTER | host= user=gitlab_repmgr dbname=gitlab_repmgr +``` + +If the 'Role' column for any node says "FAILED", check the +[Troubleshooting section](troubleshooting.md) before proceeding. + +Also, check that the `repmgr-check-master` command works successfully on each node: + +```shell +su - gitlab-consul +gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node' +``` + +This command relies on exit codes to tell Consul whether a particular node is a master +or secondary. The most important thing here is that this command does not produce errors. +If there are errors it's most likely due to incorrect `gitlab-consul` database user permissions. +Check the [Troubleshooting section](troubleshooting.md) before proceeding. + + + +## Configure PgBouncer + +Now that the PostgreSQL servers are all set up, let's configure PgBouncer. +The following IPs will be used as an example: + +- `10.6.0.31`: PgBouncer 1 +- `10.6.0.32`: PgBouncer 2 +- `10.6.0.33`: PgBouncer 3 + +1. On each PgBouncer node, edit `/etc/gitlab/gitlab.rb`, and replace + `` and `` with the + password hashes you [set up previously](#postgresql-primary-node): + + ```ruby + # Disable all components except Pgbouncer and Consul agent + roles ['pgbouncer_role'] + + # Configure PgBouncer + pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul) + + pgbouncer['users'] = { + 'gitlab-consul': { + password: '' + }, + 'pgbouncer': { + password: '' + } + } + + # Configure Consul agent + consul['watchers'] = %w(postgresql) + consul['enable'] = true + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + + # Enable service discovery for Prometheus + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + + NOTE: **Note:** + If an error `execute[generate databases.ini]` occurs, this is due to an existing + [known issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4713). + It will be resolved when you run a second `reconfigure` after the next step. + +1. Create a `.pgpass` file so Consul is able to + reload PgBouncer. Enter the PgBouncer password twice when asked: + + ```shell + gitlab-ctl write-pgpass --host 127.0.0.1 --database pgbouncer --user pgbouncer --hostuser gitlab-consul + ``` + +1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) once again + to resolve any potential errors from the previous steps. +1. Ensure each node is talking to the current primary: + + ```shell + gitlab-ctl pgb-console # You will be prompted for PGBOUNCER_PASSWORD + ``` + +1. Once the console prompt is available, run the following queries: + + ```shell + show databases ; show clients ; + ``` + + The output should be similar to the following: + + ```plaintext + name | host | port | database | force_user | pool_size | reserve_pool | pool_mode | max_connections | current_connections + ---------------------+-------------+------+---------------------+------------+-----------+--------------+-----------+-----------------+--------------------- + gitlabhq_production | MASTER_HOST | 5432 | gitlabhq_production | | 20 | 0 | | 0 | 0 + pgbouncer | | 6432 | pgbouncer | pgbouncer | 2 | 0 | statement | 0 | 0 + (2 rows) + + type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link | remote_pid | tls + ------+-----------+---------------------+---------+----------------+-------+------------+------------+---------------------+---------------------+-----------+------+------------+----- + C | pgbouncer | pgbouncer | active | 127.0.0.1 | 56846 | 127.0.0.1 | 6432 | 2017-08-21 18:09:59 | 2017-08-21 18:10:48 | 0x22b3880 | | 0 | + (2 rows) + ``` + + + +### Configure the internal load balancer + +If you're running more than one PgBouncer node as recommended, then at this time you'll need to set +up a TCP internal load balancer to serve each correctly. + +The following IP will be used as an example: + +- `10.6.0.40`: Internal Load Balancer + +Here's how you could do it with [HAProxy](https://www.haproxy.org/): + +```plaintext +global + log /dev/log local0 + log localhost local1 notice + log stdout format raw local0 + +defaults + log global + default-server inter 10s fall 3 rise 2 + balance leastconn + +frontend internal-pgbouncer-tcp-in + bind *:6432 + mode tcp + option tcplog + + default_backend pgbouncer + +backend pgbouncer + mode tcp + option tcp-check + + server pgbouncer1 10.6.0.21:6432 check + server pgbouncer2 10.6.0.22:6432 check + server pgbouncer3 10.6.0.23:6432 check +``` + +Refer to your preferred Load Balancer's documentation for further guidance. + + + +## Configure Redis + +Using [Redis](https://redis.io/) in scalable environment is possible using a **Primary** x **Replica** +topology with a [Redis Sentinel](https://redis.io/topics/sentinel) service to watch and automatically +start the failover procedure. + +Redis requires authentication if used with Sentinel. See +[Redis Security](https://redis.io/topics/security) documentation for more +information. We recommend using a combination of a Redis password and tight +firewall rules to secure your Redis service. +You are highly encouraged to read the [Redis Sentinel](https://redis.io/topics/sentinel) documentation +before configuring Redis with GitLab to fully understand the topology and +architecture. + +The requirements for a Redis setup are the following: + +1. All Redis nodes must be able to talk to each other and accept incoming + connections over Redis (`6379`) and Sentinel (`26379`) ports (unless you + change the default ones). +1. The server that hosts the GitLab application must be able to access the + Redis nodes. +1. Protect the nodes from access from external networks + ([Internet](https://gitlab.com/gitlab-org/gitlab-foss/uploads/c4cc8cd353604bd80315f9384035ff9e/The_Internet_IT_Crowd.png)), + using a firewall. + +In this section, you'll be guided through configuring two external Redis clusters +to be used with GitLab. The following IPs will be used as an example: + +- `10.6.0.51`: Redis - Cache Primary +- `10.6.0.52`: Redis - Cache Replica 1 +- `10.6.0.53`: Redis - Cache Replica 2 +- `10.6.0.71`: Sentinel - Cache 1 +- `10.6.0.72`: Sentinel - Cache 2 +- `10.6.0.73`: Sentinel - Cache 3 +- `10.6.0.61`: Redis - Queues Primary +- `10.6.0.62`: Redis - Queues Replica 1 +- `10.6.0.63`: Redis - Queues Replica 2 +- `10.6.0.81`: Sentinel - Queues 1 +- `10.6.0.82`: Sentinel - Queues 2 +- `10.6.0.83`: Sentinel - Queues 3 + +NOTE: **Providing your own Redis instance:** +Managed Redis from cloud providers such as AWS ElastiCache will work. If these +services support high availability, be sure it is **not** the Redis Cluster type. +Redis version 5.0 or higher is required, as this is what ships with +Omnibus GitLab packages starting with GitLab 13.0. Older Redis versions +do not support an optional count argument to SPOP which is now required for +[Merge Trains](../../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md). +Note the Redis node's IP address or hostname, port, and password (if required). +These will be necessary when configuring the +[GitLab application servers](#configure-gitlab-rails) later. + +### Configure the Redis and Sentinel Cache cluster + +This is the section where we install and set up the new Redis Cache instances. + +NOTE: **Note:** +Redis nodes (both primary and replica) will need the same password defined in +`redis['password']`. At any time during a failover the Sentinels can +reconfigure a node and change its status from primary to replica and vice versa. + +#### Configure the primary Redis Cache node + +1. SSH into the **Primary** Redis server. +1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab + package you want using **steps 1 and 2** from the GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + and type (Community, Enterprise editions) of your current install. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + # Specify server role as 'redis_master_role' + roles ['redis_master_role'] + + # IP address pointing to a local IP that the other machines can reach to. + # You can also set bind to '0.0.0.0' which listen in all interfaces. + # If you really need to bind to an external accessible IP, make + # sure you add extra firewall rules to prevent unauthorized access. + redis['bind'] = '10.6.0.51' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # Set up password authentication for Redis (use the same password in all nodes). + redis['password'] = 'REDIS_PRIMARY_PASSWORD_OF_FIRST_CLUSTER' + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + + # Prevent database migrations from running on upgrade + gitlab_rails['auto_migrate'] = false + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + +NOTE: **Note:** +You can specify multiple roles like sentinel and Redis as: +`roles ['redis_sentinel_role', 'redis_master_role']`. +Read more about [roles](https://docs.gitlab.com/omnibus/roles/). + +#### Configure the replica Redis Cache nodes + +1. SSH into the **replica** Redis server. +1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab + package you want using **steps 1 and 2** from the GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + and type (Community, Enterprise editions) of your current install. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + # Specify server role as 'redis_replica_role' + roles ['redis_replica_role'] + + # IP address pointing to a local IP that the other machines can reach to. + # You can also set bind to '0.0.0.0' which listen in all interfaces. + # If you really need to bind to an external accessible IP, make + # sure you add extra firewall rules to prevent unauthorized access. + redis['bind'] = '10.6.0.52' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # The same password for Redis authentication you set up for the primary node. + redis['password'] = 'REDIS_PRIMARY_PASSWORD_OF_FIRST_CLUSTER' + + # The IP of the primary Redis node. + redis['master_ip'] = '10.6.0.51' + + # Port of primary Redis server, uncomment to change to non default. Defaults + # to `6379`. + #redis['master_port'] = 6379 + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + + # Prevent database migrations from running on upgrade + gitlab_rails['auto_migrate'] = false + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. +1. Go through the steps again for all the other replica nodes, and + make sure to set up the IPs correctly. + +NOTE: **Note:** +You can specify multiple roles like sentinel and Redis as: +`roles ['redis_sentinel_role', 'redis_master_role']`. +Read more about [roles](https://docs.gitlab.com/omnibus/roles/). + +These values don't have to be changed again in `/etc/gitlab/gitlab.rb` after +a failover, as the nodes will be managed by the [Sentinels](#configure-the-sentinel-cache-nodes), and even after a +`gitlab-ctl reconfigure`, they will get their configuration restored by +the same Sentinels. + +Advanced [configuration options](https://docs.gitlab.com/omnibus/settings/redis.html) +are supported and can be added if needed. + + + +#### Configure the Sentinel Cache nodes + +NOTE: **Note:** +If you are using an external Redis Sentinel instance, be sure +to exclude the `requirepass` parameter from the Sentinel +configuration. This parameter will cause clients to report `NOAUTH +Authentication required.`. [Redis Sentinel 3.2.x does not support +password authentication](https://github.com/antirez/redis/issues/3279). + +Now that the Redis servers are all set up, let's configure the Sentinel +servers. The following IPs will be used as an example: + +- `10.6.0.71`: Sentinel - Cache 1 +- `10.6.0.72`: Sentinel - Cache 2 +- `10.6.0.73`: Sentinel - Cache 3 + +To configure the Sentinel Cache server: + +1. SSH into the server that will host Consul/Sentinel. +1. [Download/install](https://about.gitlab.com/install/) the + Omnibus GitLab Enterprise Edition package using **steps 1 and 2** from the + GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + the GitLab application is running. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + roles ['redis_sentinel_role'] + + ## Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis-cache' + + ## The same password for Redis authentication you set up for the primary node. + redis['master_password'] = 'REDIS_PRIMARY_PASSWORD_OF_FIRST_CLUSTER' + + ## The IP of the primary Redis node. + redis['master_ip'] = '10.6.0.51' + + ## Define a port so Redis can listen for TCP requests which will allow other + ## machines to connect to it. + redis['port'] = 6379 + + ## Port of primary Redis server, uncomment to change to non default. Defaults + ## to `6379`. + #redis['master_port'] = 6379 + + ## Configure Sentinel's IP + sentinel['bind'] = '10.6.0.71' + + ## Port that Sentinel listens on, uncomment to change to non default. Defaults + ## to `26379`. + #sentinel['port'] = 26379 + + ## Quorum must reflect the amount of voting sentinels it take to start a failover. + ## Value must NOT be greater then the amount of sentinels. + ## + ## The quorum can be used to tune Sentinel in two ways: + ## 1. If a the quorum is set to a value smaller than the majority of Sentinels + ## we deploy, we are basically making Sentinel more sensible to primary failures, + ## triggering a failover as soon as even just a minority of Sentinels is no longer + ## able to talk with the primary. + ## 1. If a quorum is set to a value greater than the majority of Sentinels, we are + ## making Sentinel able to failover only when there are a very large number (larger + ## than majority) of well connected Sentinels which agree about the primary being down.s + sentinel['quorum'] = 2 + + ## Consider unresponsive server down after x amount of ms. + #sentinel['down_after_milliseconds'] = 10000 + + ## Specifies the failover timeout in milliseconds. It is used in many ways: + ## + ## - The time needed to re-start a failover after a previous failover was + ## already tried against the same primary by a given Sentinel, is two + ## times the failover timeout. + ## + ## - The time needed for a replica replicating to a wrong primary according + ## to a Sentinel current configuration, to be forced to replicate + ## with the right primary, is exactly the failover timeout (counting since + ## the moment a Sentinel detected the misconfiguration). + ## + ## - The time needed to cancel a failover that is already in progress but + ## did not produced any configuration change (REPLICAOF NO ONE yet not + ## acknowledged by the promoted replica). + ## + ## - The maximum time a failover in progress waits for all the replica to be + ## reconfigured as replicas of the new primary. However even after this time + ## the replicas will be reconfigured by the Sentinels anyway, but not with + ## the exact parallel-syncs progression as specified. + #sentinel['failover_timeout'] = 60000 + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. +1. Go through the steps again for all the other Consul/Sentinel nodes, and + make sure you set up the correct IPs. + + + +### Configure the Redis and Sentinel Queues cluster + +This is the section where we install and set up the new Redis Queues instances. + +NOTE: **Note:** +Redis nodes (both primary and replica) will need the same password defined in +`redis['password']`. At any time during a failover the Sentinels can +reconfigure a node and change its status from primary to replica and vice versa. + +#### Configure the primary Redis Queues node + +1. SSH into the **Primary** Redis server. +1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab + package you want using **steps 1 and 2** from the GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + and type (Community, Enterprise editions) of your current install. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + # Specify server role as 'redis_master_role' + roles ['redis_master_role'] + + # IP address pointing to a local IP that the other machines can reach to. + # You can also set bind to '0.0.0.0' which listen in all interfaces. + # If you really need to bind to an external accessible IP, make + # sure you add extra firewall rules to prevent unauthorized access. + redis['bind'] = '10.6.0.61' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # Set up password authentication for Redis (use the same password in all nodes). + redis['password'] = 'REDIS_PRIMARY_PASSWORD_OF_SECOND_CLUSTER' + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + ``` + +1. Only the primary GitLab application server should handle migrations. To + prevent database migrations from running on upgrade, add the following + configuration to your `/etc/gitlab/gitlab.rb` file: + + ```ruby + gitlab_rails['auto_migrate'] = false + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + +NOTE: **Note:** +You can specify multiple roles like sentinel and Redis as: +`roles ['redis_sentinel_role', 'redis_master_role']`. +Read more about [roles](https://docs.gitlab.com/omnibus/roles/). + +#### Configure the replica Redis Queues nodes + +1. SSH into the **replica** Redis Queue server. +1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab + package you want using **steps 1 and 2** from the GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + and type (Community, Enterprise editions) of your current install. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + # Specify server role as 'redis_replica_role' + roles ['redis_replica_role'] + + # IP address pointing to a local IP that the other machines can reach to. + # You can also set bind to '0.0.0.0' which listen in all interfaces. + # If you really need to bind to an external accessible IP, make + # sure you add extra firewall rules to prevent unauthorized access. + redis['bind'] = '10.6.0.62' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # The same password for Redis authentication you set up for the primary node. + redis['password'] = 'REDIS_PRIMARY_PASSWORD_OF_SECOND_CLUSTER' + + # The IP of the primary Redis node. + redis['master_ip'] = '10.6.0.61' + + # Port of primary Redis server, uncomment to change to non default. Defaults + # to `6379`. + #redis['master_port'] = 6379 + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. +1. Go through the steps again for all the other replica nodes, and + make sure to set up the IPs correctly. + +NOTE: **Note:** +You can specify multiple roles like sentinel and Redis as: +`roles ['redis_sentinel_role', 'redis_master_role']`. +Read more about [roles](https://docs.gitlab.com/omnibus/roles/). + +These values don't have to be changed again in `/etc/gitlab/gitlab.rb` after +a failover, as the nodes will be managed by the [Sentinels](#configure-the-sentinel-queues-nodes), and even after a +`gitlab-ctl reconfigure`, they will get their configuration restored by +the same Sentinels. + +Advanced [configuration options](https://docs.gitlab.com/omnibus/settings/redis.html) +are supported and can be added if needed. + + + +#### Configure the Sentinel Queues nodes + +NOTE: **Note:** +If you are using an external Redis Sentinel instance, be sure +to exclude the `requirepass` parameter from the Sentinel +configuration. This parameter will cause clients to report `NOAUTH +Authentication required.`. [Redis Sentinel 3.2.x does not support +password authentication](https://github.com/antirez/redis/issues/3279). + +Now that the Redis servers are all set up, let's configure the Sentinel +servers. The following IPs will be used as an example: + +- `10.6.0.81`: Sentinel - Queues 1 +- `10.6.0.82`: Sentinel - Queues 2 +- `10.6.0.83`: Sentinel - Queues 3 + +To configure the Sentinel Queues server: + +1. SSH into the server that will host Sentinel. +1. [Download/install](https://about.gitlab.com/install/) the + Omnibus GitLab Enterprise Edition package using **steps 1 and 2** from the + GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + the GitLab application is running. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + roles ['redis_sentinel_role'] + + ## Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis-persistent' + + ## The same password for Redis authentication you set up for the primary node. + redis['master_password'] = 'REDIS_PRIMARY_PASSWORD_OF_SECOND_CLUSTER' + + ## The IP of the primary Redis node. + redis['master_ip'] = '10.6.0.61' + + ## Define a port so Redis can listen for TCP requests which will allow other + ## machines to connect to it. + redis['port'] = 6379 + + ## Port of primary Redis server, uncomment to change to non default. Defaults + ## to `6379`. + #redis['master_port'] = 6379 + + ## Configure Sentinel's IP + sentinel['bind'] = '10.6.0.81' + + ## Port that Sentinel listens on, uncomment to change to non default. Defaults + ## to `26379`. + #sentinel['port'] = 26379 + + ## Quorum must reflect the amount of voting sentinels it take to start a failover. + ## Value must NOT be greater then the amount of sentinels. + ## + ## The quorum can be used to tune Sentinel in two ways: + ## 1. If a the quorum is set to a value smaller than the majority of Sentinels + ## we deploy, we are basically making Sentinel more sensible to primary failures, + ## triggering a failover as soon as even just a minority of Sentinels is no longer + ## able to talk with the primary. + ## 1. If a quorum is set to a value greater than the majority of Sentinels, we are + ## making Sentinel able to failover only when there are a very large number (larger + ## than majority) of well connected Sentinels which agree about the primary being down.s + sentinel['quorum'] = 2 + + ## Consider unresponsive server down after x amount of ms. + #sentinel['down_after_milliseconds'] = 10000 + + ## Specifies the failover timeout in milliseconds. It is used in many ways: + ## + ## - The time needed to re-start a failover after a previous failover was + ## already tried against the same primary by a given Sentinel, is two + ## times the failover timeout. + ## + ## - The time needed for a replica replicating to a wrong primary according + ## to a Sentinel current configuration, to be forced to replicate + ## with the right primary, is exactly the failover timeout (counting since + ## the moment a Sentinel detected the misconfiguration). + ## + ## - The time needed to cancel a failover that is already in progress but + ## did not produced any configuration change (REPLICAOF NO ONE yet not + ## acknowledged by the promoted replica). + ## + ## - The maximum time a failover in progress waits for all the replica to be + ## reconfigured as replicas of the new primary. However even after this time + ## the replicas will be reconfigured by the Sentinels anyway, but not with + ## the exact parallel-syncs progression as specified. + #sentinel['failover_timeout'] = 60000 + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +1. To prevent database migrations from running on upgrade, run: + + ```shell + sudo touch /etc/gitlab/skip-auto-reconfigure + ``` + + Only the primary GitLab application server should handle migrations. + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. +1. Go through the steps again for all the other Sentinel nodes, and + make sure you set up the correct IPs. + + + +## Configure Gitaly + +Deploying Gitaly in its own server can benefit GitLab installations that are +larger than a single machine. + +The Gitaly node requirements are dependent on customer data, specifically the number of +projects and their repository sizes. Two nodes are recommended as an absolute minimum. +Each Gitaly node should store no more than 5TB of data and have the number of +[`gitaly-ruby` workers](../gitaly/index.md#gitaly-ruby) set to 20% of available CPUs. +Additional nodes should be considered in conjunction with a review of expected +data size and spread based on the recommendations above. + +It is also strongly recommended that all Gitaly nodes be set up with SSD disks with +a throughput of at least 8,000 IOPS for read operations and 2,000 IOPS for write, +as Gitaly has heavy I/O. These IOPS values are recommended only as a starter as with +time they may be adjusted higher or lower depending on the scale of your environment's workload. +If you're running the environment on a Cloud provider, you may need to refer to +their documentation on how to configure IOPS correctly. + +Some things to note: + +- The GitLab Rails application shards repositories into [repository storages](../repository_storage_paths.md). +- A Gitaly server can host one or more storages. +- A GitLab server can use one or more Gitaly servers. +- Gitaly addresses must be specified in such a way that they resolve + correctly for ALL Gitaly clients. +- Gitaly servers must not be exposed to the public internet, as Gitaly's network + traffic is unencrypted by default. The use of a firewall is highly recommended + to restrict access to the Gitaly server. Another option is to + [use TLS](#gitaly-tls-support). + +TIP: **Tip:** +For more information about Gitaly's history and network architecture see the +[standalone Gitaly documentation](../gitaly/index.md). + +Note: **Note:** +The token referred to throughout the Gitaly documentation is +just an arbitrary password selected by the administrator. It is unrelated to +tokens created for the GitLab API or other similar web API tokens. + +Below we describe how to configure two Gitaly servers, with IPs and +domain names: + +- `10.6.0.91`: Gitaly 1 (`gitaly1.internal`) +- `10.6.0.92`: Gitaly 2 (`gitaly2.internal`) + +The secret token is assumed to be `gitalysecret` and that +your GitLab installation has three repository storages: + +- `default` on Gitaly 1 +- `storage1` on Gitaly 1 +- `storage2` on Gitaly 2 + +On each node: + +1. [Download/Install](https://about.gitlab.com/install/) the Omnibus GitLab + package you want using **steps 1 and 2** from the GitLab downloads page but + **without** providing the `EXTERNAL_URL` value. +1. Edit `/etc/gitlab/gitlab.rb` to configure storage paths, enable + the network listener and configure the token: + + + + ```ruby + # /etc/gitlab/gitlab.rb + + # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests + # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API. + # The following two values must be the same as their respective values + # of the GitLab Rails application setup + gitaly['auth_token'] = 'gitalysecret' + gitlab_shell['secret_token'] = 'shellsecret' + + # Avoid running unnecessary services on the Gitaly server + postgresql['enable'] = false + redis['enable'] = false + nginx['enable'] = false + puma['enable'] = false + unicorn['enable'] = false + sidekiq['enable'] = false + gitlab_workhorse['enable'] = false + grafana['enable'] = false + + # If you run a seperate monitoring node you can disable these services + alertmanager['enable'] = false + prometheus['enable'] = false + + # Prevent database connections during 'gitlab-ctl reconfigure' + gitlab_rails['rake_cache_clear'] = false + gitlab_rails['auto_migrate'] = false + + # Configure the gitlab-shell API callback URL. Without this, `git push` will + # fail. This can be your 'front door' GitLab URL or an internal load + # balancer. + # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from web server to Gitaly server. + gitlab_rails['internal_api_url'] = 'https://gitlab.example.com' + + # Make Gitaly accept connections on all network interfaces. You must use + # firewalls to restrict access to this address/port. + # Comment out following line if you only want to support TLS connections + gitaly['listen_addr'] = "0.0.0.0:8075" + ``` + +1. Append the following to `/etc/gitlab/gitlab.rb` for each respective server: + 1. On `gitaly1.internal`: + + ```ruby + git_data_dirs({ + 'default' => { + 'path' => '/var/opt/gitlab/git-data' + }, + 'storage1' => { + 'path' => '/mnt/gitlab/git-data' + }, + }) + ``` + + 1. On `gitaly2.internal`: + + ```ruby + git_data_dirs({ + 'storage2' => { + 'path' => '/mnt/gitlab/git-data' + }, + }) + ``` + + + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). + +### Gitaly TLS support + +Gitaly supports TLS encryption. To be able to communicate +with a Gitaly instance that listens for secure connections you will need to use `tls://` URL +scheme in the `gitaly_address` of the corresponding storage entry in the GitLab configuration. + +You will need to bring your own certificates as this isn't provided automatically. +The certificate, or its certificate authority, must be installed on all Gitaly +nodes (including the Gitaly node using the certificate) and on all client nodes +that communicate with it following the procedure described in +[GitLab custom certificate configuration](https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates). + +NOTE: **Note:** +The self-signed certificate must specify the address you use to access the +Gitaly server. If you are addressing the Gitaly server by a hostname, you can +either use the Common Name field for this, or add it as a Subject Alternative +Name. If you are addressing the Gitaly server by its IP address, you must add it +as a Subject Alternative Name to the certificate. +[gRPC does not support using an IP address as Common Name in a certificate](https://github.com/grpc/grpc/issues/2691). + +NOTE: **Note:** +It is possible to configure Gitaly servers with both an +unencrypted listening address `listen_addr` and an encrypted listening +address `tls_listen_addr` at the same time. This allows you to do a +gradual transition from unencrypted to encrypted traffic, if necessary. + +To configure Gitaly with TLS: + +1. Create the `/etc/gitlab/ssl` directory and copy your key and certificate there: + + ```shell + sudo mkdir -p /etc/gitlab/ssl + sudo chmod 755 /etc/gitlab/ssl + sudo cp key.pem cert.pem /etc/gitlab/ssl/ + sudo chmod 644 key.pem cert.pem + ``` + +1. Copy the cert to `/etc/gitlab/trusted-certs` so Gitaly will trust the cert when + calling into itself: + + ```shell + sudo cp /etc/gitlab/ssl/cert.pem /etc/gitlab/trusted-certs/ + ``` + +1. Edit `/etc/gitlab/gitlab.rb` and add: + + + + ```ruby + gitaly['tls_listen_addr'] = "0.0.0.0:9999" + gitaly['certificate_path'] = "/etc/gitlab/ssl/cert.pem" + gitaly['key_path'] = "/etc/gitlab/ssl/key.pem" + ``` + +1. Delete `gitaly['listen_addr']` to allow only encrypted connections. + +1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). + + + +## Configure Sidekiq + +Sidekiq requires connections to the Redis, PostgreSQL and Gitaly instances. +The following IPs will be used as an example: + +- `10.6.0.101`: Sidekiq 1 +- `10.6.0.102`: Sidekiq 2 +- `10.6.0.103`: Sidekiq 3 +- `10.6.0.104`: Sidekiq 4 + +To configure the Sidekiq nodes, on each one: + +1. SSH into the Sidekiq server. +1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab package +you want using steps 1 and 2 from the GitLab downloads page. +**Do not complete any other steps on the download page.** +1. Open `/etc/gitlab/gitlab.rb` with your editor: + + ```ruby + ######################################## + ##### Services Disabled ### + ######################################## + + nginx['enable'] = false + grafana['enable'] = false + prometheus['enable'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = false + puma['enable'] = false + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + gitlab_exporter['enable'] = false + + ######################################## + #### Redis ### + ######################################## + + ## Redis connection details + ## First cluster that will host the cache + gitlab_rails['redis_cache_instance'] = 'redis://:@gitlab-redis-cache' + + gitlab_rails['redis_cache_sentinels'] = [ + {host: '10.6.0.71', port: 26379}, + {host: '10.6.0.72', port: 26379}, + {host: '10.6.0.73', port: 26379}, + ] + + ## Second cluster that will host the queues, shared state, and actioncable + gitlab_rails['redis_queues_instance'] = 'redis://:@gitlab-redis-persistent' + gitlab_rails['redis_shared_state_instance'] = 'redis://:@gitlab-redis-persistent' + gitlab_rails['redis_actioncable_instance'] = 'redis://:@gitlab-redis-persistent' + + gitlab_rails['redis_queues_sentinels'] = [ + {host: '10.6.0.81', port: 26379}, + {host: '10.6.0.82', port: 26379}, + {host: '10.6.0.83', port: 26379}, + ] + gitlab_rails['redis_shared_state_sentinels'] = [ + {host: '10.6.0.81', port: 26379}, + {host: '10.6.0.82', port: 26379}, + {host: '10.6.0.83', port: 26379}, + ] + gitlab_rails['redis_actioncable_sentinels'] = [ + {host: '10.6.0.81', port: 26379}, + {host: '10.6.0.82', port: 26379}, + {host: '10.6.0.83', port: 26379}, + ] + + ####################################### + ### Gitaly ### + ####################################### + + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, + }) + gitlab_rails['gitaly_token'] = 'YOUR_TOKEN' + + ####################################### + ### Postgres ### + ####################################### + gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP + gitlab_rails['db_port'] = 6432 + gitlab_rails['db_password'] = '' + gitlab_rails['db_adapter'] = 'postgresql' + gitlab_rails['db_encoding'] = 'unicode' + gitlab_rails['auto_migrate'] = false + + ####################################### + ### Sidekiq configuration ### + ####################################### + sidekiq['listen_address'] = "0.0.0.0" + sidekiq['cluster'] = true # no need to set this after GitLab 13.0 + + ####################################### + ### Monitoring configuration ### + ####################################### + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + + # Rails Status for prometheus + gitlab_rails['monitoring_whitelist'] = ['10.6.0.121/32', '127.0.0.0/8'] + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + +TIP: **Tip:** +You can also run [multiple Sidekiq processes](../operations/extra_sidekiq_processes.md). + + + +## Configure GitLab Rails + +NOTE: **Note:** +In our architectures we run each GitLab Rails node using the Puma webserver +and have its number of workers set to 90% of available CPUs along with four threads. For +nodes that are running Rails with other components the worker value should be reduced +accordingly where we've found 50% achieves a good balance but this is dependent +on workload. + +This section describes how to configure the GitLab application (Rails) component. + +The following IPs will be used as an example: + +- `10.6.0.111`: GitLab application 1 +- `10.6.0.112`: GitLab application 2 +- `10.6.0.113`: GitLab application 3 + +On each node perform the following: + +1. Download/install Omnibus GitLab using **steps 1 and 2** from + [GitLab downloads](https://about.gitlab.com/install/). Do not complete other + steps on the download page. + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. Edit `/etc/gitlab/gitlab.rb` and use the following configuration. + To maintain uniformity of links across nodes, the `external_url` + on the application server should point to the external URL that users will use + to access GitLab. This would be the URL of the [external load balancer](#configure-the-external-load-balancer) + which will route traffic to the GitLab application server: + + ```ruby + external_url 'https://gitlab.example.com' + + # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests + # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API. + # The following two values must be the same as their respective values + # of the Gitaly setup + gitlab_rails['gitaly_token'] = 'gitalysecret' + gitlab_shell['secret_token'] = 'shellsecret' + + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, + }) + + ## Disable components that will not be on the GitLab application server + roles ['application_role'] + gitaly['enable'] = false + nginx['enable'] = true + + ## PostgreSQL connection details + # Disable PostgreSQL on the application node + postgresql['enable'] = false + gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP + gitlab_rails['db_port'] = 6432 + gitlab_rails['db_password'] = '' + gitlab_rails['auto_migrate'] = false + + ## Redis connection details + ## First cluster that will host the cache + gitlab_rails['redis_cache_instance'] = 'redis://:@gitlab-redis-cache' + + gitlab_rails['redis_cache_sentinels'] = [ + {host: '10.6.0.71', port: 26379}, + {host: '10.6.0.72', port: 26379}, + {host: '10.6.0.73', port: 26379}, + ] + + ## Second cluster that will host the queues, shared state, and actionable + gitlab_rails['redis_queues_instance'] = 'redis://:@gitlab-redis-persistent' + gitlab_rails['redis_shared_state_instance'] = 'redis://:@gitlab-redis-persistent' + gitlab_rails['redis_actioncable_instance'] = 'redis://:@gitlab-redis-persistent' + + gitlab_rails['redis_queues_sentinels'] = [ + {host: '10.6.0.81', port: 26379}, + {host: '10.6.0.82', port: 26379}, + {host: '10.6.0.83', port: 26379}, + ] + gitlab_rails['redis_shared_state_sentinels'] = [ + {host: '10.6.0.81', port: 26379}, + {host: '10.6.0.82', port: 26379}, + {host: '10.6.0.83', port: 26379}, + ] + gitlab_rails['redis_actioncable_sentinels'] = [ + {host: '10.6.0.81', port: 26379}, + {host: '10.6.0.82', port: 26379}, + {host: '10.6.0.83', port: 26379}, + ] + + # Set the network addresses that the exporters used for monitoring will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + gitlab_workhorse['prometheus_listen_addr'] = '0.0.0.0:9229' + sidekiq['listen_address'] = "0.0.0.0" + puma['listen'] = '0.0.0.0' + + # Add the monitoring node's IP address to the monitoring whitelist and allow it to + # scrape the NGINX metrics + gitlab_rails['monitoring_whitelist'] = ['10.6.0.121/32', '127.0.0.0/8'] + nginx['status']['options']['allow'] = ['10.6.0.121/32', '127.0.0.0/8'] + ``` + +1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). +1. If you're using [Gitaly with TLS support](#gitaly-tls-support), make sure the + `git_data_dirs` entry is configured with `tls` instead of `tcp`: + + ```ruby + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage1' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage2' => { 'gitaly_address' => 'tls://gitaly2.internal:9999' }, + }) + ``` + + 1. Copy the cert into `/etc/gitlab/trusted-certs`: + + ```shell + sudo cp cert.pem /etc/gitlab/trusted-certs/ + ``` + +1. If you're [using NFS](#configure-nfs-optional): + 1. If necessary, install the NFS client utility packages using the following + commands: + + ```shell + # Ubuntu/Debian + apt-get install nfs-common + + # CentOS/Red Hat + yum install nfs-utils nfs-utils-lib + ``` + + 1. Specify the necessary NFS mounts in `/etc/fstab`. + The exact contents of `/etc/fstab` will depend on how you chose + to configure your NFS server. See the [NFS documentation](../high_availability/nfs.md) + for examples and the various options. + + 1. Create the shared directories. These may be different depending on your NFS + mount locations. + + ```shell + mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data + ``` + + 1. Edit `/etc/gitlab/gitlab.rb` and use the following configuration: + + ```ruby + ## Prevent GitLab from starting if NFS data mounts are not available + high_availability['mountpoint'] = '/var/opt/gitlab/git-data' + + ## Ensure UIDs and GIDs match between servers for permissions via NFS + user['uid'] = 9000 + user['gid'] = 9000 + web_server['uid'] = 9001 + web_server['gid'] = 9001 + registry['uid'] = 9002 + registry['gid'] = 9002 + ``` + +1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). +1. Confirm the node can connect to Gitaly: + + ```shell + sudo gitlab-rake gitlab:gitaly:check + ``` + + Then, tail the logs to see the requests: + + ```shell + sudo gitlab-ctl tail gitaly + ``` + +1. Optionally, from the Gitaly servers, confirm that Gitaly can perform callbacks to the internal API: + + ```shell + sudo /opt/gitlab/embedded/service/gitlab-shell/bin/check -config /opt/gitlab/embedded/service/gitlab-shell/config.yml + ``` + +NOTE: **Note:** +When you specify `https` in the `external_url`, as in the example +above, GitLab assumes you have SSL certificates in `/etc/gitlab/ssl/`. If +certificates are not present, NGINX will fail to start. See the +[NGINX documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https) +for more information. + +### GitLab Rails post-configuration + +Initialize the GitLab database, by running the following in one of the Rails nodes: + +```shell +sudo gitlab-rake gitlab:db:configure +``` + +NOTE: **Note:** +If you encounter a `rake aborted!` error stating that PgBouncer is failing to connect to +PostgreSQL it may be that your PgBouncer node's IP address is missing from +PostgreSQL's `trust_auth_cidr_addresses` in `gitlab.rb` on your database nodes. See +[PgBouncer error `ERROR: pgbouncer cannot connect to server`](troubleshooting.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server) +in the Troubleshooting section before proceeding. + + + +## Configure Prometheus + +The Omnibus GitLab package can be used to configure a standalone Monitoring node +running [Prometheus](../monitoring/prometheus/index.md) and +[Grafana](../monitoring/performance/grafana_configuration.md). + +The following IP will be used as an example: + +- `10.6.0.121`: Prometheus + +To configure the Monitoring node: + +1. SSH into the Monitoring node. +1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab + package you want using **steps 1 and 2** from the GitLab downloads page. + Do not complete any other steps on the download page. + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + external_url 'http://gitlab.example.com' + + # Disable all other services + gitlab_rails['auto_migrate'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_exporter['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = true + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + sidekiq['enable'] = false + puma['enable'] = false + unicorn['enable'] = false + node_exporter['enable'] = false + gitlab_exporter['enable'] = false + + # Enable Prometheus + prometheus['enable'] = true + prometheus['listen_address'] = '0.0.0.0:9090' + prometheus['monitor_kubernetes'] = false + + # Enable Login form + grafana['disable_login_form'] = false + + # Enable Grafana + grafana['enable'] = true + grafana['admin_password'] = '' + + # Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + ``` + +1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). +1. In the GitLab UI, set `admin/application_settings/metrics_and_profiling` > Metrics - Grafana to `/-/grafana` to +`http[s]:///-/grafana` + + + +## Configure the object storage + +GitLab supports using an object storage service for holding numerous types of data. +It's recommended over [NFS](#configure-nfs-optional) and in general it's better +in larger setups as object storage is typically much more performant, reliable, +and scalable. + +Object storage options that GitLab has tested, or is aware of customers using include: + +- SaaS/Cloud solutions such as [Amazon S3](https://aws.amazon.com/s3/), [Google cloud storage](https://cloud.google.com/storage). +- On-premises hardware and appliances from various storage vendors. +- MinIO. There is [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation. + +For configuring GitLab to use Object Storage refer to the following guides +based on what features you intend to use: + +1. Configure [object storage for backups](../../raketasks/backup_restore.md#uploading-backups-to-a-remote-cloud-storage). +1. Configure [object storage for job artifacts](../job_artifacts.md#using-object-storage) + including [incremental logging](../job_logs.md#new-incremental-logging-architecture). +1. Configure [object storage for LFS objects](../lfs/index.md#storing-lfs-objects-in-remote-object-storage). +1. Configure [object storage for uploads](../uploads.md#using-object-storage-core-only). +1. Configure [object storage for merge request diffs](../merge_request_diffs.md#using-object-storage). +1. Configure [object storage for Container Registry](../packages/container_registry.md#use-object-storage) (optional feature). +1. Configure [object storage for Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage) (optional feature). +1. Configure [object storage for packages](../packages/index.md#using-object-storage) (optional feature). **(PREMIUM ONLY)** +1. Configure [object storage for Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature). **(PREMIUM ONLY)** +1. Configure [object storage for Pseudonymizer](../pseudonymizer.md#configuration) (optional feature). **(ULTIMATE ONLY)** +1. Configure [object storage for autoscale Runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional - for improved performance). +1. Configure [object storage for Terraform state files](../terraform_state.md#using-object-storage-core-only). + +Using separate buckets for each data type is the recommended approach for GitLab. + +A limitation of our configuration is that each use of object storage is separately configured. +[We have an issue for improving this](https://gitlab.com/gitlab-org/gitlab/-/issues/23345) +and easily using one bucket with separate folders is one improvement that this might bring. + +There is at least one specific issue with using the same bucket: +when GitLab is deployed with the Helm chart restore from backup +[will not properly function](https://docs.gitlab.com/charts/advanced/external-object-storage/#lfs-artifacts-uploads-packages-external-diffs-pseudonymizer) +unless separate buckets are used. + +One risk of using a single bucket would be if your organization decided to +migrate GitLab to the Helm deployment in the future. GitLab would run, but the situation with +backups might not be realized until the organization had a critical requirement for the backups to +work. + + + +## Configure NFS (optional) + +[Object storage](#configure-the-object-storage), along with [Gitaly](#configure-gitaly) +are recommended over NFS wherever possible for improved performance. If you intend +to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pages-requires-nfs). + +See how to [configure NFS](../high_availability/nfs.md). + + + +## Troubleshooting + +See the [troubleshooting documentation](troubleshooting.md). + + diff --git a/doc/administration/reference_architectures/2k_users.md b/doc/administration/reference_architectures/2k_users.md index d182daf45b3..a7feb78a365 100644 --- a/doc/administration/reference_architectures/2k_users.md +++ b/doc/administration/reference_architectures/2k_users.md @@ -1,27 +1,30 @@ --- reading_time: true +stage: Enablement +group: Distribution +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers --- -# Reference architecture: up to 2,000 users +# Reference architecture: up to 2,000 users **(CORE ONLY)** This page describes GitLab reference architecture for up to 2,000 users. For a full list of reference architectures, see [Available reference architectures](index.md#available-reference-architectures). > - **Supported users (approximate):** 2,000 -> - **High Availability:** False +> - **High Availability:** No > - **Test requests per second (RPS) rates:** API: 40 RPS, Web: 4 RPS, Git: 4 RPS -| Service | Nodes | Configuration | GCP | AWS | Azure | -|------------------------------------------|--------|-------------------------|-----------------|----------------|-----------| -| Load balancer | 1 | 2 vCPU, 1.8GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | -| PostgreSQL | 1 | 2 vCPU, 7.5GB memory | `n1-standard-2` | `m5.large` | `D2s v3` | -| Redis | 1 | 1 vCPU, 3.75GB memory | `n1-standard-1` | `m5.large` | `D2s v3` | -| Gitaly | 1 | 4 vCPU, 15GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` | -| GitLab Rails | 2 | 8 vCPU, 7.2GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` | -| Monitoring node | 1 | 2 vCPU, 1.8GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | -| Object storage | n/a | n/a | n/a | n/a | n/a | -| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` | +| Service | Nodes | Configuration | GCP | AWS | Azure | +|------------------------------------------|--------|-------------------------|----------------|--------------|---------| +| Load balancer | 1 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| PostgreSQL | 1 | 2 vCPU, 7.5GB memory | n1-standard-2 | m5.large | D2s v3 | +| Redis | 1 | 1 vCPU, 3.75GB memory | n1-standard-1 | m5.large | D2s v3 | +| Gitaly | 1 | 4 vCPU, 15GB memory | n1-standard-4 | m5.xlarge | D4s v3 | +| GitLab Rails | 2 | 8 vCPU, 7.2GB memory | n1-highcpu-8 | c5.2xlarge | F8s v2 | +| Monitoring node | 1 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| Object storage | n/a | n/a | n/a | n/a | n/a | +| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 | The Google Cloud Platform (GCP) architectures were built and tested using the [Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) @@ -554,7 +557,7 @@ On each node perform the following: 1. Specify the necessary NFS mounts in `/etc/fstab`. The exact contents of `/etc/fstab` will depend on how you chose - to configure your NFS server. See the [NFS documentation](../high_availability/nfs.md) + to configure your NFS server. See the [NFS documentation](../nfs.md) for examples and the various options. 1. Create the shared directories. These may be different depending on your NFS @@ -852,7 +855,7 @@ along with [Gitaly](#configure-gitaly), are recommended over using NFS whenever possible. However, if you intend to use GitLab Pages, [you must use NFS](troubleshooting.md#gitlab-pages-requires-nfs). -For information about configuring NFS, see the [NFS documentation page](../high_availability/nfs.md). +For information about configuring NFS, see the [NFS documentation page](../nfs.md).
diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md index 04cb9fa4769..2f88413de6f 100644 --- a/doc/administration/reference_architectures/3k_users.md +++ b/doc/administration/reference_architectures/3k_users.md @@ -1,49 +1,54 @@ --- reading_time: true +stage: Enablement +group: Distribution +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers --- -# Reference architecture: up to 3,000 users +# Reference architecture: up to 3,000 users **(PREMIUM ONLY)** -This page describes GitLab reference architecture for up to 3,000 users. -For a full list of reference architectures, see +This page describes GitLab reference architecture for up to 3,000 users. For a +full list of reference architectures, see [Available reference architectures](index.md#available-reference-architectures). NOTE: **Note:** -The 3,000-user reference architecture documented below is -designed to help your organization achieve a highly-available GitLab deployment. -If you do not have the expertise or need to maintain a highly-available -environment, you can have a simpler and less costly-to-operate environment by -following the [2,000-user reference architecture](2k_users.md). +This reference architecture is designed to help your organization achieve a +highly-available GitLab deployment. If you do not have the expertise or need to +maintain a highly-available environment, you can have a simpler and less +costly-to-operate environment by using the +[2,000-user reference architecture](2k_users.md). > - **Supported users (approximate):** 3,000 -> - **High Availability:** True -> - **Test RPS rates:** API: 60 RPS, Web: 6 RPS, Git: 6 RPS - -| Service | Nodes | Configuration | GCP | AWS | Azure | -|--------------------------------------------------------------|-------|---------------------------------|-----------------|-------------------------|----------------| -| External load balancing node | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | -| Redis | 3 | 2 vCPU, 7.5GB Memory | `n1-standard-2` | `m5.large` | `D2s v3` | -| Consul + Sentinel | 3 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | -| PostgreSQL | 3 | 2 vCPU, 7.5GB Memory | `n1-standard-2` | `m5.large` | `D2s v3` | -| PgBouncer | 3 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | -| Internal load balancing node | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | -| Gitaly | 2 minimum | 4 vCPU, 15GB Memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` | -| Sidekiq | 4 | 2 vCPU, 7.5GB Memory | `n1-standard-2` | `m5.large` | `D2s v3` | -| GitLab Rails | 3 | 8 vCPU, 7.2GB Memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` | -| Monitoring node | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | -| Object Storage | n/a | n/a | n/a | n/a | n/a | -| NFS Server (optional, not recommended) | 1 | 4 vCPU, 3.6GB Memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` | - -The architectures were built and tested with the [Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) -CPU platform on GCP. On different hardware you may find that adjustments, either lower -or higher, are required for your CPU or Node counts accordingly. For more information, a -[Sysbench](https://github.com/akopytov/sysbench) benchmark of the CPU can be found -[here](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks). - -For data objects such as LFS, Uploads, Artifacts, etc, an [object storage service](#configure-the-object-storage) -is recommended over NFS where possible, due to better performance and availability. -Since this doesn't require a node to be set up, it's marked as not applicable (n/a) -in the table above. +> - **High Availability:** Yes +> - **Test requests per second (RPS) rates:** API: 60 RPS, Web: 6 RPS, Git: 6 RPS + +| Service | Nodes | Configuration | GCP | AWS | Azure | +|--------------------------------------------|-------------|-----------------------|----------------|-------------|---------| +| External load balancing node | 1 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| Redis | 3 | 2 vCPU, 7.5GB memory | n1-standard-2 | m5.large | D2s v3 | +| Consul + Sentinel | 3 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| PostgreSQL | 3 | 2 vCPU, 7.5GB memory | n1-standard-2 | m5.large | D2s v3 | +| PgBouncer | 3 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| Internal load balancing node | 1 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| Gitaly | 2 (minimum) | 4 vCPU, 15GB memory | n1-standard-4 | m5.xlarge | D4s v3 | +| Sidekiq | 4 | 2 vCPU, 7.5GB memory | n1-standard-2 | m5.large | D2s v3 | +| GitLab Rails | 3 | 8 vCPU, 7.2GB memory | n1-highcpu-8 | c5.2xlarge | F8s v2 | +| Monitoring node | 1 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| Object Storage | n/a | n/a | n/a | n/a | n/a | +| NFS Server (optional, not recommended) | 1 | 4 vCPU, 3.6GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 | + +The Google Cloud Platform (GCP) architectures were built and tested using the +[Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) +CPU platform. On different hardware you may find that adjustments, either lower +or higher, are required for your CPU or node counts. For more information, see +our [Sysbench](https://github.com/akopytov/sysbench)-based +[CPU benchmark](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks). + +For data objects (such as LFS, Uploads, or Artifacts), an +[object storage service](#configure-the-object-storage) is recommended instead +of NFS where possible, due to better performance and availability. Since this +doesn't require a node to be set up, *Object Storage* is noted as not +applicable (n/a) in the previous table. ## Setup components @@ -804,10 +809,11 @@ SSH into the **primary node**: gitlab-psql -d gitlabhq_production ``` -1. Enable the `pg_trgm` extension: +1. Enable the `pg_trgm` and `btree_gist` extensions: ```shell CREATE EXTENSION pg_trgm; + CREATE EXTENSION btree_gist; ``` 1. Exit the database prompt by typing `\q` and Enter. @@ -1439,7 +1445,7 @@ On each node perform the following: 1. Specify the necessary NFS mounts in `/etc/fstab`. The exact contents of `/etc/fstab` will depend on how you chose - to configure your NFS server. See the [NFS documentation](../high_availability/nfs.md) + to configure your NFS server. See the [NFS documentation](../nfs.md) for examples and the various options. 1. Create the shared directories. These may be different depending on your NFS @@ -1748,7 +1754,7 @@ work. are recommended over NFS wherever possible for improved performance. If you intend to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pages-requires-nfs). -See how to [configure NFS](../high_availability/nfs.md). +See how to [configure NFS](../nfs.md).
diff --git a/doc/administration/reference_architectures/50k_users.md b/doc/administration/reference_architectures/50k_users.md index 2540fe68dac..565845b4bf5 100644 --- a/doc/administration/reference_architectures/50k_users.md +++ b/doc/administration/reference_architectures/50k_users.md @@ -1,76 +1,2047 @@ -# Reference architecture: up to 50,000 users +--- +reading_time: true +stage: Enablement +group: Distribution +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- -This page describes GitLab reference architecture for up to 50,000 users. -For a full list of reference architectures, see +# Reference architecture: up to 50,000 users **(PREMIUM ONLY)** + +This page describes GitLab reference architecture for up to 50,000 users. For a +full list of reference architectures, see [Available reference architectures](index.md#available-reference-architectures). > - **Supported users (approximate):** 50,000 -> - **High Availability:** True -> - **Test RPS rates:** API: 1000 RPS, Web: 100 RPS, Git: 100 RPS - -| Service | Nodes | Configuration ([8](#footnotes)) | GCP | AWS | Azure | -|--------------------------------------------------------------|-------|---------------------------------|----------------|-----------------------|----------------| -| GitLab Rails ([1](#footnotes)) | 12 | 32 vCPU, 28.8GB Memory | `n1-highcpu-32` | `c5.9xlarge` | F32s v2 | -| PostgreSQL | 3 | 16 vCPU, 60GB Memory | `n1-standard-16` | `m5.4xlarge` | D16s v3 | -| PgBouncer | 3 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | F2s v2 | -| Gitaly ([2](#footnotes)) ([5](#footnotes)) ([7](#footnotes)) | X | 64 vCPU, 240GB Memory | `n1-standard-64` | `m5.16xlarge` | D64s v3 | -| Redis ([3](#footnotes)) - Cache | 3 | 4 vCPU, 15GB Memory | `n1-standard-4` | `m5.xlarge` | D4s v3 | -| Redis ([3](#footnotes)) - Queues / Shared State | 3 | 4 vCPU, 15GB Memory | `n1-standard-4` | `m5.xlarge` | D4s v3 | -| Redis Sentinel ([3](#footnotes)) - Cache | 3 | 1 vCPU, 1.7GB Memory | `g1-small` | `t2.small` | B1MS | -| Redis Sentinel ([3](#footnotes)) - Queues / Shared State | 3 | 1 vCPU, 1.7GB Memory | `g1-small` | `t2.small` | B1MS | -| Consul | 3 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | F2s v2 | -| Sidekiq | 4 | 4 vCPU, 15GB Memory | `n1-standard-4` | `m5.xlarge` | D4s v3 | -| NFS Server ([5](#footnotes)) ([7](#footnotes)) | 1 | 4 vCPU, 3.6GB Memory | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | -| Object Storage ([4](#footnotes)) | - | - | - | - | - | -| Monitoring node | 1 | 4 vCPU, 3.6GB Memory | `n1-highcpu-4` | `c5.xlarge` | F4s v2 | -| External load balancing node ([6](#footnotes)) | 1 | 8 vCPU, 7.2GB Memory | `n1-highcpu-8` | `c5.2xlarge` | F8s v2 | -| Internal load balancing node ([6](#footnotes)) | 1 | 8 vCPU, 7.2GB Memory | `n1-highcpu-8` | `c5.2xlarge` | F8s v2 | - -## Footnotes - -1. In our architectures we run each GitLab Rails node using the Puma webserver - and have its number of workers set to 90% of available CPUs along with four threads. For - nodes that are running Rails with other components the worker value should be reduced - accordingly where we've found 50% achieves a good balance but this is dependent - on workload. - -1. Gitaly node requirements are dependent on customer data, specifically the number of - projects and their sizes. We recommend two nodes as an absolute minimum for HA environments - and at least four nodes should be used when supporting 50,000 or more users. - We also recommend that each Gitaly node should store no more than 5TB of data - and have the number of [`gitaly-ruby` workers](../gitaly/index.md#gitaly-ruby) - set to 20% of available CPUs. Additional nodes should be considered in conjunction - with a review of expected data size and spread based on the recommendations above. - -1. Recommended Redis setup differs depending on the size of the architecture. - For smaller architectures (less than 3,000 users) a single instance should suffice. - For medium sized installs (3,000 - 5,000) we suggest one Redis cluster for all - classes and that Redis Sentinel is hosted alongside Consul. - For larger architectures (10,000 users or more) we suggest running a separate - [Redis Cluster](../redis/replication_and_failover.md#running-multiple-redis-clusters) for the Cache class - and another for the Queues and Shared State classes respectively. We also recommend - that you run the Redis Sentinel clusters separately for each Redis Cluster. - -1. For data objects such as LFS, Uploads, Artifacts, etc. We recommend an [Object Storage service](../object_storage.md) - over NFS where possible, due to better performance and availability. - -1. NFS can be used as an alternative for both repository data (replacing Gitaly) and - object storage but this isn't typically recommended for performance reasons. Note however it is required for - [GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196). - -1. Our architectures have been tested and validated with [HAProxy](https://www.haproxy.org/) - as the load balancer. Although other load balancers with similar feature sets - could also be used, those load balancers have not been validated. - -1. We strongly recommend that any Gitaly or NFS nodes be set up with SSD disks over - HDD with a throughput of at least 8,000 IOPS for read operations and 2,000 IOPS for write - as these components have heavy I/O. These IOPS values are recommended only as a starter - as with time they may be adjusted higher or lower depending on the scale of your - environment's workload. If you're running the environment on a Cloud provider - you may need to refer to their documentation on how configure IOPS correctly. - -1. The architectures were built and tested with the [Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) - CPU platform on GCP. On different hardware you may find that adjustments, either lower - or higher, are required for your CPU or Node counts accordingly. For more information, a - [Sysbench](https://github.com/akopytov/sysbench) benchmark of the CPU can be found - [here](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks). +> - **High Availability:** Yes +> - **Test requests per second (RPS) rates:** API: 1000 RPS, Web: 100 RPS, Git: 100 RPS + +| Service | Nodes | Configuration | GCP | AWS | Azure | +|-----------------------------------------|-------------|-------------------------|-----------------|--------------|----------| +| External load balancing node | 1 | 8 vCPU, 7.2GB memory | n1-highcpu-8 | c5.2xlarge | F8s v2 | +| Consul | 3 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| PostgreSQL | 3 | 16 vCPU, 60GB memory | n1-standard-16 | m5.4xlarge | D16s v3 | +| PgBouncer | 3 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| Internal load balancing node | 1 | 8 vCPU, 7.2GB memory | n1-highcpu-8 | c5.2xlarge | F8s v2 | +| Redis - Cache | 3 | 4 vCPU, 15GB memory | n1-standard-4 | m5.xlarge | D4s v3 | +| Redis - Queues / Shared State | 3 | 4 vCPU, 15GB memory | n1-standard-4 | m5.xlarge | D4s v3 | +| Redis Sentinel - Cache | 3 | 1 vCPU, 1.7GB memory | g1-small | t2.small | B1MS | +| Redis Sentinel - Queues / Shared State | 3 | 1 vCPU, 1.7GB memory | g1-small | t2.small | B1MS | +| Gitaly | 2 (minimum) | 64 vCPU, 240GB memory | n1-standard-64 | m5.16xlarge | D64s v3 | +| Sidekiq | 4 | 4 vCPU, 15GB memory | n1-standard-4 | m5.xlarge | D4s v3 | +| GitLab Rails | 12 | 32 vCPU, 28.8GB memory | n1-highcpu-32 | c5.9xlarge | F32s v2 | +| Monitoring node | 1 | 4 vCPU, 3.6GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 | +| Object Storage | n/a | n/a | n/a | n/a | n/a | +| NFS Server | 1 | 4 vCPU, 3.6GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 | + +The Google Cloud Platform (GCP) architectures were built and tested using the +[Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) +CPU platform. On different hardware you may find that adjustments, either lower +or higher, are required for your CPU or node counts. For more information, see +our [Sysbench](https://github.com/akopytov/sysbench)-based +[CPU benchmark](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks). + +For data objects (such as LFS, Uploads, or Artifacts), an +[object storage service](#configure-the-object-storage) is recommended instead +of NFS where possible, due to better performance and availability. Since this +doesn't require a node to be set up, *Object Storage* is noted as not +applicable (n/a) in the previous table. + +## Setup components + +To set up GitLab and its components to accommodate up to 50,000 users: + +1. [Configure the external load balancing node](#configure-the-external-load-balancer) + that will handle the load balancing of the three GitLab application services nodes. +1. [Configure Consul](#configure-consul). +1. [Configure PostgreSQL](#configure-postgresql), the database for GitLab. +1. [Configure PgBouncer](#configure-pgbouncer). +1. [Configure the internal load balancing node](#configure-the-internal-load-balancer) +1. [Configure Redis](#configure-redis). +1. [Configure Gitaly](#configure-gitaly), + which provides access to the Git repositories. +1. [Configure Sidekiq](#configure-sidekiq). +1. [Configure the main GitLab Rails application](#configure-gitlab-rails) + to run Puma/Unicorn, Workhorse, GitLab Shell, and to serve all frontend requests (UI, API, Git + over HTTP/SSH). +1. [Configure Prometheus](#configure-prometheus) to monitor your GitLab environment. +1. [Configure the Object Storage](#configure-the-object-storage) + used for shared data objects. +1. [Configure NFS (Optional)](#configure-nfs-optional) + to have shared disk storage service as an alternative to Gitaly and/or Object Storage (although + not recommended). NFS is required for GitLab Pages, you can skip this step if you're not using + that feature. + +We start with all servers on the same 10.6.0.0/24 private network range, they +can connect to each other freely on those addresses. + +Here is a list and description of each machine and the assigned IP: + +- `10.6.0.10`: External Load Balancer +- `10.6.0.11`: Consul 1 +- `10.6.0.12`: Consul 2 +- `10.6.0.13`: Consul 3 +- `10.6.0.21`: PostgreSQL primary +- `10.6.0.22`: PostgreSQL secondary 1 +- `10.6.0.23`: PostgreSQL secondary 2 +- `10.6.0.31`: PgBouncer 1 +- `10.6.0.32`: PgBouncer 2 +- `10.6.0.33`: PgBouncer 3 +- `10.6.0.40`: Internal Load Balancer +- `10.6.0.51`: Redis - Cache Primary +- `10.6.0.52`: Redis - Cache Replica 1 +- `10.6.0.53`: Redis - Cache Replica 2 +- `10.6.0.71`: Sentinel - Cache 1 +- `10.6.0.72`: Sentinel - Cache 2 +- `10.6.0.73`: Sentinel - Cache 3 +- `10.6.0.61`: Redis - Queues Primary +- `10.6.0.62`: Redis - Queues Replica 1 +- `10.6.0.63`: Redis - Queues Replica 2 +- `10.6.0.81`: Sentinel - Queues 1 +- `10.6.0.82`: Sentinel - Queues 2 +- `10.6.0.83`: Sentinel - Queues 3 +- `10.6.0.91`: Gitaly 1 +- `10.6.0.92`: Gitaly 2 +- `10.6.0.101`: Sidekiq 1 +- `10.6.0.102`: Sidekiq 2 +- `10.6.0.103`: Sidekiq 3 +- `10.6.0.104`: Sidekiq 4 +- `10.6.0.111`: GitLab application 1 +- `10.6.0.112`: GitLab application 2 +- `10.6.0.113`: GitLab application 3 +- `10.6.0.121`: Prometheus + +## Configure the external load balancer + +NOTE: **Note:** +This architecture has been tested and validated with [HAProxy](https://www.haproxy.org/) +as the load balancer. Although other load balancers with similar feature sets +could also be used, those load balancers have not been validated. + +In an active/active GitLab configuration, you will need a load balancer to route +traffic to the application servers. The specifics on which load balancer to use +or the exact configuration is beyond the scope of GitLab documentation. We hope +that if you're managing multi-node systems like GitLab you have a load balancer of +choice already. Some examples including HAProxy (open-source), F5 Big-IP LTM, +and Citrix Net Scaler. This documentation will outline what ports and protocols +you need to use with GitLab. + +The next question is how you will handle SSL in your environment. +There are several different options: + +- [The application node terminates SSL](#application-node-terminates-ssl). +- [The load balancer terminates SSL without backend SSL](#load-balancer-terminates-ssl-without-backend-ssl) + and communication is not secure between the load balancer and the application node. +- [The load balancer terminates SSL with backend SSL](#load-balancer-terminates-ssl-with-backend-ssl) + and communication is *secure* between the load balancer and the application node. + +### Application node terminates SSL + +Configure your load balancer to pass connections on port 443 as `TCP` rather +than `HTTP(S)` protocol. This will pass the connection to the application node's +NGINX service untouched. NGINX will have the SSL certificate and listen on port 443. + +See the [NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https) +for details on managing SSL certificates and configuring NGINX. + +### Load balancer terminates SSL without backend SSL + +Configure your load balancer to use the `HTTP(S)` protocol rather than `TCP`. +The load balancer will then be responsible for managing SSL certificates and +terminating SSL. + +Since communication between the load balancer and GitLab will not be secure, +there is some additional configuration needed. See the +[NGINX proxied SSL documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#supporting-proxied-ssl) +for details. + +### Load balancer terminates SSL with backend SSL + +Configure your load balancer(s) to use the 'HTTP(S)' protocol rather than 'TCP'. +The load balancer(s) will be responsible for managing SSL certificates that +end users will see. + +Traffic will also be secure between the load balancer(s) and NGINX in this +scenario. There is no need to add configuration for proxied SSL since the +connection will be secure all the way. However, configuration will need to be +added to GitLab to configure SSL certificates. See +[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https) +for details on managing SSL certificates and configuring NGINX. + +### Ports + +The basic ports to be used are shown in the table below. + +| LB Port | Backend Port | Protocol | +| ------- | ------------ | ------------------------ | +| 80 | 80 | HTTP (*1*) | +| 443 | 443 | TCP or HTTPS (*1*) (*2*) | +| 22 | 22 | TCP | + +- (*1*): [Web terminal](../../ci/environments/index.md#web-terminals) support requires + your load balancer to correctly handle WebSocket connections. When using + HTTP or HTTPS proxying, this means your load balancer must be configured + to pass through the `Connection` and `Upgrade` hop-by-hop headers. See the + [web terminal](../integration/terminal.md) integration guide for + more details. +- (*2*): When using HTTPS protocol for port 443, you will need to add an SSL + certificate to the load balancers. If you wish to terminate SSL at the + GitLab application server instead, use TCP protocol. + +If you're using GitLab Pages with custom domain support you will need some +additional port configurations. +GitLab Pages requires a separate virtual IP address. Configure DNS to point the +`pages_external_url` from `/etc/gitlab/gitlab.rb` at the new virtual IP address. See the +[GitLab Pages documentation](../pages/index.md) for more information. + +| LB Port | Backend Port | Protocol | +| ------- | ------------- | --------- | +| 80 | Varies (*1*) | HTTP | +| 443 | Varies (*1*) | TCP (*2*) | + +- (*1*): The backend port for GitLab Pages depends on the + `gitlab_pages['external_http']` and `gitlab_pages['external_https']` + setting. See [GitLab Pages documentation](../pages/index.md) for more details. +- (*2*): Port 443 for GitLab Pages should always use the TCP protocol. Users can + configure custom domains with custom SSL, which would not be possible + if SSL was terminated at the load balancer. + +#### Alternate SSH Port + +Some organizations have policies against opening SSH port 22. In this case, +it may be helpful to configure an alternate SSH hostname that allows users +to use SSH on port 443. An alternate SSH hostname will require a new virtual IP address +compared to the other GitLab HTTP configuration above. + +Configure DNS for an alternate SSH hostname such as `altssh.gitlab.example.com`. + +| LB Port | Backend Port | Protocol | +| ------- | ------------ | -------- | +| 443 | 22 | TCP | + + + +## Configure Consul + +The following IPs will be used as an example: + +- `10.6.0.11`: Consul 1 +- `10.6.0.12`: Consul 2 +- `10.6.0.13`: Consul 3 + +NOTE: **Note:** +The configuration processes for the other servers in your reference architecture will +use the `/etc/gitlab/gitlab-secrets.json` file from your Consul server to connect +with the other servers. + +To configure Consul: + +1. SSH into the server that will host Consul. +1. [Download/install](https://about.gitlab.com/install/) the + Omnibus GitLab Enterprise Edition package using **steps 1 and 2** from the + GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + the GitLab application is running. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + roles ['consul_role'] + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + server: true, + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. +1. Go through the steps again for all the other Consul nodes, and + make sure you set up the correct IPs. + +NOTE: **Note:** +A Consul leader will be elected when the provisioning of the third Consul server is completed. +Viewing the Consul logs `sudo gitlab-ctl tail consul` will display +`...[INFO] consul: New leader elected: ...` + +You can list the current Consul members (server, client): + +```shell +sudo /opt/gitlab/embedded/bin/consul members +``` + +You can verify the GitLab services are running: + +```shell +sudo gitlab-ctl status +``` + +The output should be similar to the following: + +```plaintext +run: consul: (pid 30074) 76834s; run: log: (pid 29740) 76844s +run: logrotate: (pid 30925) 3041s; run: log: (pid 29649) 76861s +run: node-exporter: (pid 30093) 76833s; run: log: (pid 29663) 76855s +``` + + + +## Configure PostgreSQL + +In this section, you'll be guided through configuring an external PostgreSQL database +to be used with GitLab. + +### Provide your own PostgreSQL instance + +If you're hosting GitLab on a cloud provider, you can optionally use a +managed service for PostgreSQL. For example, AWS offers a managed Relational +Database Service (RDS) that runs PostgreSQL. + +If you use a cloud-managed service, or provide your own PostgreSQL: + +1. Set up PostgreSQL according to the + [database requirements document](../../install/requirements.md#database). +1. Set up a `gitlab` username with a password of your choice. The `gitlab` user + needs privileges to create the `gitlabhq_production` database. +1. Configure the GitLab application servers with the appropriate details. + This step is covered in [Configuring the GitLab Rails application](#configure-gitlab-rails). + +### Standalone PostgreSQL using Omnibus GitLab + +The following IPs will be used as an example: + +- `10.6.0.21`: PostgreSQL primary +- `10.6.0.22`: PostgreSQL secondary 1 +- `10.6.0.23`: PostgreSQL secondary 2 + +First, make sure to [install](https://about.gitlab.com/install/) +the Linux GitLab package **on each node**. Following the steps, +install the necessary dependencies from step 1, and add the +GitLab package repository from step 2. When installing GitLab +in the second step, do not supply the `EXTERNAL_URL` value. + +#### PostgreSQL primary node + +1. SSH into the PostgreSQL primary node. +1. Generate a password hash for the PostgreSQL username/password pair. This assumes you will use the default + username of `gitlab` (recommended). The command will request a password + and confirmation. Use the value that is output by this command in the next + step as the value of ``: + + ```shell + sudo gitlab-ctl pg-password-md5 gitlab + ``` + +1. Generate a password hash for the PgBouncer username/password pair. This assumes you will use the default + username of `pgbouncer` (recommended). The command will request a password + and confirmation. Use the value that is output by this command in the next + step as the value of ``: + + ```shell + sudo gitlab-ctl pg-password-md5 pgbouncer + ``` + +1. Generate a password hash for the Consul database username/password pair. This assumes you will use the default + username of `gitlab-consul` (recommended). The command will request a password + and confirmation. Use the value that is output by this command in the next + step as the value of ``: + + ```shell + sudo gitlab-ctl pg-password-md5 gitlab-consul + ``` + +1. On the primary database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section: + + ```ruby + # Disable all components except PostgreSQL and Repmgr and Consul + roles ['postgres_role'] + + # PostgreSQL configuration + postgresql['listen_address'] = '0.0.0.0' + postgresql['hot_standby'] = 'on' + postgresql['wal_level'] = 'replica' + postgresql['shared_preload_libraries'] = 'repmgr_funcs' + + # Disable automatic database migrations + gitlab_rails['auto_migrate'] = false + + # Configure the Consul agent + consul['services'] = %w(postgresql) + + # START user configuration + # Please set the real values as explained in Required Information section + # + # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value + postgresql['pgbouncer_user_password'] = '' + # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value + postgresql['sql_user_password'] = '' + # Set `max_wal_senders` to one more than the number of database nodes in the cluster. + # This is used to prevent replication from using up all of the + # available database connections. + postgresql['max_wal_senders'] = 4 + postgresql['max_replication_slots'] = 4 + + # Replace XXX.XXX.XXX.XXX/YY with Network Address + postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24) + repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + + ## Enable service discovery for Prometheus + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on for monitoring + node_exporter['listen_address'] = '0.0.0.0:9100' + postgres_exporter['listen_address'] = '0.0.0.0:9187' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + # + # END user configuration + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + + + +#### PostgreSQL secondary nodes + +1. On both the secondary nodes, add the same configuration specified above for the primary node + with an additional setting (`repmgr['master_on_initialization'] = false`) that will inform `gitlab-ctl` that they are standby nodes initially + and there's no need to attempt to register them as a primary node: + + ```ruby + # Disable all components except PostgreSQL and Repmgr and Consul + roles ['postgres_role'] + + # PostgreSQL configuration + postgresql['listen_address'] = '0.0.0.0' + postgresql['hot_standby'] = 'on' + postgresql['wal_level'] = 'replica' + postgresql['shared_preload_libraries'] = 'repmgr_funcs' + + # Disable automatic database migrations + gitlab_rails['auto_migrate'] = false + + # Configure the Consul agent + consul['services'] = %w(postgresql) + + # Specify if a node should attempt to be primary on initialization. + repmgr['master_on_initialization'] = false + + # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value + postgresql['pgbouncer_user_password'] = '' + # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value + postgresql['sql_user_password'] = '' + # Set `max_wal_senders` to one more than the number of database nodes in the cluster. + # This is used to prevent replication from using up all of the + # available database connections. + postgresql['max_wal_senders'] = 4 + postgresql['max_replication_slots'] = 4 + + # Replace with your network addresses + postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24) + repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) + + ## Enable service discovery for Prometheus + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on for monitoring + node_exporter['listen_address'] = '0.0.0.0:9100' + postgres_exporter['listen_address'] = '0.0.0.0:9187' + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + +Advanced [configuration options](https://docs.gitlab.com/omnibus/settings/database.html) +are supported and can be added if needed. + + + +#### PostgreSQL post-configuration + +SSH into the **primary node**: + +1. Open a database prompt: + + ```shell + gitlab-psql -d gitlabhq_production + ``` + +1. Make sure the `pg_trgm` extension is enabled (it might already be): + + ```shell + CREATE EXTENSION pg_trgm; + ``` + +1. Exit the database prompt by typing `\q` and Enter. + +1. Verify the cluster is initialized with one node: + + ```shell + gitlab-ctl repmgr cluster show + ``` + + The output should be similar to the following: + + ```plaintext + Role | Name | Upstream | Connection String + ----------+----------|----------|---------------------------------------- + * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr + ``` + +1. Note down the hostname or IP address in the connection string: `host=HOSTNAME`. We will + refer to the hostname in the next section as ``. If the value + is not an IP address, it will need to be a resolvable name (via DNS or + `/etc/hosts`) + +SSH into the **secondary node**: + +1. Set up the repmgr standby: + + ```shell + gitlab-ctl repmgr standby setup + ``` + + Do note that this will remove the existing data on the node. The command + has a wait time. + + The output should be similar to the following: + + ```console + Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data + If this is not what you want, hit Ctrl-C now to exit + To skip waiting, rerun with the -w option + Sleeping for 30 seconds + Stopping the database + Removing the data + Cloning the data + Starting the database + Registering the node with the cluster + ok: run: repmgrd: (pid 19068) 0s + ``` + +Before moving on, make sure the databases are configured correctly. Run the +following command on the **primary** node to verify that replication is working +properly and the secondary nodes appear in the cluster: + +```shell +gitlab-ctl repmgr cluster show +``` + +The output should be similar to the following: + +```plaintext +Role | Name | Upstream | Connection String +----------+---------|-----------|------------------------------------------------ +* master | MASTER | | host= user=gitlab_repmgr dbname=gitlab_repmgr + standby | STANDBY | MASTER | host= user=gitlab_repmgr dbname=gitlab_repmgr + standby | STANDBY | MASTER | host= user=gitlab_repmgr dbname=gitlab_repmgr +``` + +If the 'Role' column for any node says "FAILED", check the +[Troubleshooting section](troubleshooting.md) before proceeding. + +Also, check that the `repmgr-check-master` command works successfully on each node: + +```shell +su - gitlab-consul +gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node' +``` + +This command relies on exit codes to tell Consul whether a particular node is a master +or secondary. The most important thing here is that this command does not produce errors. +If there are errors it's most likely due to incorrect `gitlab-consul` database user permissions. +Check the [Troubleshooting section](troubleshooting.md) before proceeding. + + + +## Configure PgBouncer + +Now that the PostgreSQL servers are all set up, let's configure PgBouncer. +The following IPs will be used as an example: + +- `10.6.0.31`: PgBouncer 1 +- `10.6.0.32`: PgBouncer 2 +- `10.6.0.33`: PgBouncer 3 + +1. On each PgBouncer node, edit `/etc/gitlab/gitlab.rb`, and replace + `` and `` with the + password hashes you [set up previously](#postgresql-primary-node): + + ```ruby + # Disable all components except Pgbouncer and Consul agent + roles ['pgbouncer_role'] + + # Configure PgBouncer + pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul) + + pgbouncer['users'] = { + 'gitlab-consul': { + password: '' + }, + 'pgbouncer': { + password: '' + } + } + + # Configure Consul agent + consul['watchers'] = %w(postgresql) + consul['enable'] = true + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + + # Enable service discovery for Prometheus + consul['monitoring_service_discovery'] = true + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + + NOTE: **Note:** + If an error `execute[generate databases.ini]` occurs, this is due to an existing + [known issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4713). + It will be resolved when you run a second `reconfigure` after the next step. + +1. Create a `.pgpass` file so Consul is able to + reload PgBouncer. Enter the PgBouncer password twice when asked: + + ```shell + gitlab-ctl write-pgpass --host 127.0.0.1 --database pgbouncer --user pgbouncer --hostuser gitlab-consul + ``` + +1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) once again + to resolve any potential errors from the previous steps. +1. Ensure each node is talking to the current primary: + + ```shell + gitlab-ctl pgb-console # You will be prompted for PGBOUNCER_PASSWORD + ``` + +1. Once the console prompt is available, run the following queries: + + ```shell + show databases ; show clients ; + ``` + + The output should be similar to the following: + + ```plaintext + name | host | port | database | force_user | pool_size | reserve_pool | pool_mode | max_connections | current_connections + ---------------------+-------------+------+---------------------+------------+-----------+--------------+-----------+-----------------+--------------------- + gitlabhq_production | MASTER_HOST | 5432 | gitlabhq_production | | 20 | 0 | | 0 | 0 + pgbouncer | | 6432 | pgbouncer | pgbouncer | 2 | 0 | statement | 0 | 0 + (2 rows) + + type | user | database | state | addr | port | local_addr | local_port | connect_time | request_time | ptr | link | remote_pid | tls + ------+-----------+---------------------+---------+----------------+-------+------------+------------+---------------------+---------------------+-----------+------+------------+----- + C | pgbouncer | pgbouncer | active | 127.0.0.1 | 56846 | 127.0.0.1 | 6432 | 2017-08-21 18:09:59 | 2017-08-21 18:10:48 | 0x22b3880 | | 0 | + (2 rows) + ``` + + + +### Configure the internal load balancer + +If you're running more than one PgBouncer node as recommended, then at this time you'll need to set +up a TCP internal load balancer to serve each correctly. + +The following IP will be used as an example: + +- `10.6.0.40`: Internal Load Balancer + +Here's how you could do it with [HAProxy](https://www.haproxy.org/): + +```plaintext +global + log /dev/log local0 + log localhost local1 notice + log stdout format raw local0 + +defaults + log global + default-server inter 10s fall 3 rise 2 + balance leastconn + +frontend internal-pgbouncer-tcp-in + bind *:6432 + mode tcp + option tcplog + + default_backend pgbouncer + +backend pgbouncer + mode tcp + option tcp-check + + server pgbouncer1 10.6.0.21:6432 check + server pgbouncer2 10.6.0.22:6432 check + server pgbouncer3 10.6.0.23:6432 check +``` + +Refer to your preferred Load Balancer's documentation for further guidance. + + + +## Configure Redis + +Using [Redis](https://redis.io/) in scalable environment is possible using a **Primary** x **Replica** +topology with a [Redis Sentinel](https://redis.io/topics/sentinel) service to watch and automatically +start the failover procedure. + +Redis requires authentication if used with Sentinel. See +[Redis Security](https://redis.io/topics/security) documentation for more +information. We recommend using a combination of a Redis password and tight +firewall rules to secure your Redis service. +You are highly encouraged to read the [Redis Sentinel](https://redis.io/topics/sentinel) documentation +before configuring Redis with GitLab to fully understand the topology and +architecture. + +The requirements for a Redis setup are the following: + +1. All Redis nodes must be able to talk to each other and accept incoming + connections over Redis (`6379`) and Sentinel (`26379`) ports (unless you + change the default ones). +1. The server that hosts the GitLab application must be able to access the + Redis nodes. +1. Protect the nodes from access from external networks + ([Internet](https://gitlab.com/gitlab-org/gitlab-foss/uploads/c4cc8cd353604bd80315f9384035ff9e/The_Internet_IT_Crowd.png)), + using a firewall. + +In this section, you'll be guided through configuring two external Redis clusters +to be used with GitLab. The following IPs will be used as an example: + +- `10.6.0.51`: Redis - Cache Primary +- `10.6.0.52`: Redis - Cache Replica 1 +- `10.6.0.53`: Redis - Cache Replica 2 +- `10.6.0.71`: Sentinel - Cache 1 +- `10.6.0.72`: Sentinel - Cache 2 +- `10.6.0.73`: Sentinel - Cache 3 +- `10.6.0.61`: Redis - Queues Primary +- `10.6.0.62`: Redis - Queues Replica 1 +- `10.6.0.63`: Redis - Queues Replica 2 +- `10.6.0.81`: Sentinel - Queues 1 +- `10.6.0.82`: Sentinel - Queues 2 +- `10.6.0.83`: Sentinel - Queues 3 + +NOTE: **Providing your own Redis instance:** +Managed Redis from cloud providers such as AWS ElastiCache will work. If these +services support high availability, be sure it is **not** the Redis Cluster type. +Redis version 5.0 or higher is required, as this is what ships with +Omnibus GitLab packages starting with GitLab 13.0. Older Redis versions +do not support an optional count argument to SPOP which is now required for +[Merge Trains](../../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md). +Note the Redis node's IP address or hostname, port, and password (if required). +These will be necessary when configuring the +[GitLab application servers](#configure-gitlab-rails) later. + +### Configure the Redis and Sentinel Cache cluster + +This is the section where we install and set up the new Redis Cache instances. + +NOTE: **Note:** +Redis nodes (both primary and replica) will need the same password defined in +`redis['password']`. At any time during a failover the Sentinels can +reconfigure a node and change its status from primary to replica and vice versa. + +#### Configure the primary Redis Cache node + +1. SSH into the **Primary** Redis server. +1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab + package you want using **steps 1 and 2** from the GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + and type (Community, Enterprise editions) of your current install. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + # Specify server role as 'redis_master_role' + roles ['redis_master_role'] + + # IP address pointing to a local IP that the other machines can reach to. + # You can also set bind to '0.0.0.0' which listen in all interfaces. + # If you really need to bind to an external accessible IP, make + # sure you add extra firewall rules to prevent unauthorized access. + redis['bind'] = '10.6.0.51' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # Set up password authentication for Redis (use the same password in all nodes). + redis['password'] = 'REDIS_PRIMARY_PASSWORD_OF_FIRST_CLUSTER' + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + + # Prevent database migrations from running on upgrade + gitlab_rails['auto_migrate'] = false + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + +NOTE: **Note:** +You can specify multiple roles like sentinel and Redis as: +`roles ['redis_sentinel_role', 'redis_master_role']`. +Read more about [roles](https://docs.gitlab.com/omnibus/roles/). + +#### Configure the replica Redis Cache nodes + +1. SSH into the **replica** Redis server. +1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab + package you want using **steps 1 and 2** from the GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + and type (Community, Enterprise editions) of your current install. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + # Specify server role as 'redis_replica_role' + roles ['redis_replica_role'] + + # IP address pointing to a local IP that the other machines can reach to. + # You can also set bind to '0.0.0.0' which listen in all interfaces. + # If you really need to bind to an external accessible IP, make + # sure you add extra firewall rules to prevent unauthorized access. + redis['bind'] = '10.6.0.52' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # The same password for Redis authentication you set up for the primary node. + redis['password'] = 'REDIS_PRIMARY_PASSWORD_OF_FIRST_CLUSTER' + + # The IP of the primary Redis node. + redis['master_ip'] = '10.6.0.51' + + # Port of primary Redis server, uncomment to change to non default. Defaults + # to `6379`. + #redis['master_port'] = 6379 + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + + # Prevent database migrations from running on upgrade + gitlab_rails['auto_migrate'] = false + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. +1. Go through the steps again for all the other replica nodes, and + make sure to set up the IPs correctly. + +NOTE: **Note:** +You can specify multiple roles like sentinel and Redis as: +`roles ['redis_sentinel_role', 'redis_master_role']`. +Read more about [roles](https://docs.gitlab.com/omnibus/roles/). + +These values don't have to be changed again in `/etc/gitlab/gitlab.rb` after +a failover, as the nodes will be managed by the [Sentinels](#configure-the-sentinel-cache-nodes), and even after a +`gitlab-ctl reconfigure`, they will get their configuration restored by +the same Sentinels. + +Advanced [configuration options](https://docs.gitlab.com/omnibus/settings/redis.html) +are supported and can be added if needed. + + + +#### Configure the Sentinel Cache nodes + +NOTE: **Note:** +If you are using an external Redis Sentinel instance, be sure +to exclude the `requirepass` parameter from the Sentinel +configuration. This parameter will cause clients to report `NOAUTH +Authentication required.`. [Redis Sentinel 3.2.x does not support +password authentication](https://github.com/antirez/redis/issues/3279). + +Now that the Redis servers are all set up, let's configure the Sentinel +servers. The following IPs will be used as an example: + +- `10.6.0.71`: Sentinel - Cache 1 +- `10.6.0.72`: Sentinel - Cache 2 +- `10.6.0.73`: Sentinel - Cache 3 + +To configure the Sentinel Cache server: + +1. SSH into the server that will host Consul/Sentinel. +1. [Download/install](https://about.gitlab.com/install/) the + Omnibus GitLab Enterprise Edition package using **steps 1 and 2** from the + GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + the GitLab application is running. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + roles ['redis_sentinel_role'] + + ## Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis-cache' + + ## The same password for Redis authentication you set up for the primary node. + redis['master_password'] = 'REDIS_PRIMARY_PASSWORD_OF_FIRST_CLUSTER' + + ## The IP of the primary Redis node. + redis['master_ip'] = '10.6.0.51' + + ## Define a port so Redis can listen for TCP requests which will allow other + ## machines to connect to it. + redis['port'] = 6379 + + ## Port of primary Redis server, uncomment to change to non default. Defaults + ## to `6379`. + #redis['master_port'] = 6379 + + ## Configure Sentinel's IP + sentinel['bind'] = '10.6.0.71' + + ## Port that Sentinel listens on, uncomment to change to non default. Defaults + ## to `26379`. + #sentinel['port'] = 26379 + + ## Quorum must reflect the amount of voting sentinels it take to start a failover. + ## Value must NOT be greater then the amount of sentinels. + ## + ## The quorum can be used to tune Sentinel in two ways: + ## 1. If a the quorum is set to a value smaller than the majority of Sentinels + ## we deploy, we are basically making Sentinel more sensible to primary failures, + ## triggering a failover as soon as even just a minority of Sentinels is no longer + ## able to talk with the primary. + ## 1. If a quorum is set to a value greater than the majority of Sentinels, we are + ## making Sentinel able to failover only when there are a very large number (larger + ## than majority) of well connected Sentinels which agree about the primary being down.s + sentinel['quorum'] = 2 + + ## Consider unresponsive server down after x amount of ms. + #sentinel['down_after_milliseconds'] = 10000 + + ## Specifies the failover timeout in milliseconds. It is used in many ways: + ## + ## - The time needed to re-start a failover after a previous failover was + ## already tried against the same primary by a given Sentinel, is two + ## times the failover timeout. + ## + ## - The time needed for a replica replicating to a wrong primary according + ## to a Sentinel current configuration, to be forced to replicate + ## with the right primary, is exactly the failover timeout (counting since + ## the moment a Sentinel detected the misconfiguration). + ## + ## - The time needed to cancel a failover that is already in progress but + ## did not produced any configuration change (REPLICAOF NO ONE yet not + ## acknowledged by the promoted replica). + ## + ## - The maximum time a failover in progress waits for all the replica to be + ## reconfigured as replicas of the new primary. However even after this time + ## the replicas will be reconfigured by the Sentinels anyway, but not with + ## the exact parallel-syncs progression as specified. + #sentinel['failover_timeout'] = 60000 + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. +1. Go through the steps again for all the other Consul/Sentinel nodes, and + make sure you set up the correct IPs. + + + +### Configure the Redis and Sentinel Queues cluster + +This is the section where we install and set up the new Redis Queues instances. + +NOTE: **Note:** +Redis nodes (both primary and replica) will need the same password defined in +`redis['password']`. At any time during a failover the Sentinels can +reconfigure a node and change its status from primary to replica and vice versa. + +#### Configure the primary Redis Queues node + +1. SSH into the **Primary** Redis server. +1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab + package you want using **steps 1 and 2** from the GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + and type (Community, Enterprise editions) of your current install. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + # Specify server role as 'redis_master_role' + roles ['redis_master_role'] + + # IP address pointing to a local IP that the other machines can reach to. + # You can also set bind to '0.0.0.0' which listen in all interfaces. + # If you really need to bind to an external accessible IP, make + # sure you add extra firewall rules to prevent unauthorized access. + redis['bind'] = '10.6.0.61' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # Set up password authentication for Redis (use the same password in all nodes). + redis['password'] = 'REDIS_PRIMARY_PASSWORD_OF_SECOND_CLUSTER' + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + ``` + +1. Only the primary GitLab application server should handle migrations. To + prevent database migrations from running on upgrade, add the following + configuration to your `/etc/gitlab/gitlab.rb` file: + + ```ruby + gitlab_rails['auto_migrate'] = false + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + +NOTE: **Note:** +You can specify multiple roles like sentinel and Redis as: +`roles ['redis_sentinel_role', 'redis_master_role']`. +Read more about [roles](https://docs.gitlab.com/omnibus/roles/). + +#### Configure the replica Redis Queues nodes + +1. SSH into the **replica** Redis Queue server. +1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab + package you want using **steps 1 and 2** from the GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + and type (Community, Enterprise editions) of your current install. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + # Specify server role as 'redis_replica_role' + roles ['redis_replica_role'] + + # IP address pointing to a local IP that the other machines can reach to. + # You can also set bind to '0.0.0.0' which listen in all interfaces. + # If you really need to bind to an external accessible IP, make + # sure you add extra firewall rules to prevent unauthorized access. + redis['bind'] = '10.6.0.62' + + # Define a port so Redis can listen for TCP requests which will allow other + # machines to connect to it. + redis['port'] = 6379 + + # The same password for Redis authentication you set up for the primary node. + redis['password'] = 'REDIS_PRIMARY_PASSWORD_OF_SECOND_CLUSTER' + + # The IP of the primary Redis node. + redis['master_ip'] = '10.6.0.61' + + # Port of primary Redis server, uncomment to change to non default. Defaults + # to `6379`. + #redis['master_port'] = 6379 + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. +1. Go through the steps again for all the other replica nodes, and + make sure to set up the IPs correctly. + +NOTE: **Note:** +You can specify multiple roles like sentinel and Redis as: +`roles ['redis_sentinel_role', 'redis_master_role']`. +Read more about [roles](https://docs.gitlab.com/omnibus/roles/). + +These values don't have to be changed again in `/etc/gitlab/gitlab.rb` after +a failover, as the nodes will be managed by the [Sentinels](#configure-the-sentinel-queues-nodes), and even after a +`gitlab-ctl reconfigure`, they will get their configuration restored by +the same Sentinels. + +Advanced [configuration options](https://docs.gitlab.com/omnibus/settings/redis.html) +are supported and can be added if needed. + + + +#### Configure the Sentinel Queues nodes + +NOTE: **Note:** +If you are using an external Redis Sentinel instance, be sure +to exclude the `requirepass` parameter from the Sentinel +configuration. This parameter will cause clients to report `NOAUTH +Authentication required.`. [Redis Sentinel 3.2.x does not support +password authentication](https://github.com/antirez/redis/issues/3279). + +Now that the Redis servers are all set up, let's configure the Sentinel +servers. The following IPs will be used as an example: + +- `10.6.0.81`: Sentinel - Queues 1 +- `10.6.0.82`: Sentinel - Queues 2 +- `10.6.0.83`: Sentinel - Queues 3 + +To configure the Sentinel Queues server: + +1. SSH into the server that will host Sentinel. +1. [Download/install](https://about.gitlab.com/install/) the + Omnibus GitLab Enterprise Edition package using **steps 1 and 2** from the + GitLab downloads page. + - Make sure you select the correct Omnibus package, with the same version + the GitLab application is running. + - Do not complete any other steps on the download page. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + roles ['redis_sentinel_role'] + + ## Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis-persistent' + + ## The same password for Redis authentication you set up for the primary node. + redis['master_password'] = 'REDIS_PRIMARY_PASSWORD_OF_SECOND_CLUSTER' + + ## The IP of the primary Redis node. + redis['master_ip'] = '10.6.0.61' + + ## Define a port so Redis can listen for TCP requests which will allow other + ## machines to connect to it. + redis['port'] = 6379 + + ## Port of primary Redis server, uncomment to change to non default. Defaults + ## to `6379`. + #redis['master_port'] = 6379 + + ## Configure Sentinel's IP + sentinel['bind'] = '10.6.0.81' + + ## Port that Sentinel listens on, uncomment to change to non default. Defaults + ## to `26379`. + #sentinel['port'] = 26379 + + ## Quorum must reflect the amount of voting sentinels it take to start a failover. + ## Value must NOT be greater then the amount of sentinels. + ## + ## The quorum can be used to tune Sentinel in two ways: + ## 1. If a the quorum is set to a value smaller than the majority of Sentinels + ## we deploy, we are basically making Sentinel more sensible to primary failures, + ## triggering a failover as soon as even just a minority of Sentinels is no longer + ## able to talk with the primary. + ## 1. If a quorum is set to a value greater than the majority of Sentinels, we are + ## making Sentinel able to failover only when there are a very large number (larger + ## than majority) of well connected Sentinels which agree about the primary being down.s + sentinel['quorum'] = 2 + + ## Consider unresponsive server down after x amount of ms. + #sentinel['down_after_milliseconds'] = 10000 + + ## Specifies the failover timeout in milliseconds. It is used in many ways: + ## + ## - The time needed to re-start a failover after a previous failover was + ## already tried against the same primary by a given Sentinel, is two + ## times the failover timeout. + ## + ## - The time needed for a replica replicating to a wrong primary according + ## to a Sentinel current configuration, to be forced to replicate + ## with the right primary, is exactly the failover timeout (counting since + ## the moment a Sentinel detected the misconfiguration). + ## + ## - The time needed to cancel a failover that is already in progress but + ## did not produced any configuration change (REPLICAOF NO ONE yet not + ## acknowledged by the promoted replica). + ## + ## - The maximum time a failover in progress waits for all the replica to be + ## reconfigured as replicas of the new primary. However even after this time + ## the replicas will be reconfigured by the Sentinels anyway, but not with + ## the exact parallel-syncs progression as specified. + #sentinel['failover_timeout'] = 60000 + + ## Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + ## The IPs of the Consul server nodes + ## You can also use FQDNs and intermix them with IPs + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + redis_exporter['listen_address'] = '0.0.0.0:9121' + + # Disable auto migrations + gitlab_rails['auto_migrate'] = false + ``` + +1. To prevent database migrations from running on upgrade, run: + + ```shell + sudo touch /etc/gitlab/skip-auto-reconfigure + ``` + + Only the primary GitLab application server should handle migrations. + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. +1. Go through the steps again for all the other Sentinel nodes, and + make sure you set up the correct IPs. + + + +## Configure Gitaly + +Deploying Gitaly in its own server can benefit GitLab installations that are +larger than a single machine. + +The Gitaly node requirements are dependent on customer data, specifically the number of +projects and their repository sizes. Two nodes are recommended as an absolute minimum. +Each Gitaly node should store no more than 5TB of data and have the number of +[`gitaly-ruby` workers](../gitaly/index.md#gitaly-ruby) set to 20% of available CPUs. +Additional nodes should be considered in conjunction with a review of expected +data size and spread based on the recommendations above. + +It is also strongly recommended that all Gitaly nodes be set up with SSD disks with +a throughput of at least 8,000 IOPS for read operations and 2,000 IOPS for write, +as Gitaly has heavy I/O. These IOPS values are recommended only as a starter as with +time they may be adjusted higher or lower depending on the scale of your environment's workload. +If you're running the environment on a Cloud provider, you may need to refer to +their documentation on how to configure IOPS correctly. + +Some things to note: + +- The GitLab Rails application shards repositories into [repository storages](../repository_storage_paths.md). +- A Gitaly server can host one or more storages. +- A GitLab server can use one or more Gitaly servers. +- Gitaly addresses must be specified in such a way that they resolve + correctly for ALL Gitaly clients. +- Gitaly servers must not be exposed to the public internet, as Gitaly's network + traffic is unencrypted by default. The use of a firewall is highly recommended + to restrict access to the Gitaly server. Another option is to + [use TLS](#gitaly-tls-support). + +TIP: **Tip:** +For more information about Gitaly's history and network architecture see the +[standalone Gitaly documentation](../gitaly/index.md). + +Note: **Note:** +The token referred to throughout the Gitaly documentation is +just an arbitrary password selected by the administrator. It is unrelated to +tokens created for the GitLab API or other similar web API tokens. + +Below we describe how to configure two Gitaly servers, with IPs and +domain names: + +- `10.6.0.91`: Gitaly 1 (`gitaly1.internal`) +- `10.6.0.92`: Gitaly 2 (`gitaly2.internal`) + +The secret token is assumed to be `gitalysecret` and that +your GitLab installation has three repository storages: + +- `default` on Gitaly 1 +- `storage1` on Gitaly 1 +- `storage2` on Gitaly 2 + +On each node: + +1. [Download/Install](https://about.gitlab.com/install/) the Omnibus GitLab + package you want using **steps 1 and 2** from the GitLab downloads page but + **without** providing the `EXTERNAL_URL` value. +1. Edit `/etc/gitlab/gitlab.rb` to configure storage paths, enable + the network listener and configure the token: + + + + ```ruby + # /etc/gitlab/gitlab.rb + + # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests + # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API. + # The following two values must be the same as their respective values + # of the GitLab Rails application setup + gitaly['auth_token'] = 'gitalysecret' + gitlab_shell['secret_token'] = 'shellsecret' + + # Avoid running unnecessary services on the Gitaly server + postgresql['enable'] = false + redis['enable'] = false + nginx['enable'] = false + puma['enable'] = false + unicorn['enable'] = false + sidekiq['enable'] = false + gitlab_workhorse['enable'] = false + grafana['enable'] = false + + # If you run a seperate monitoring node you can disable these services + alertmanager['enable'] = false + prometheus['enable'] = false + + # Prevent database connections during 'gitlab-ctl reconfigure' + gitlab_rails['rake_cache_clear'] = false + gitlab_rails['auto_migrate'] = false + + # Configure the gitlab-shell API callback URL. Without this, `git push` will + # fail. This can be your 'front door' GitLab URL or an internal load + # balancer. + # Don't forget to copy `/etc/gitlab/gitlab-secrets.json` from web server to Gitaly server. + gitlab_rails['internal_api_url'] = 'https://gitlab.example.com' + + # Make Gitaly accept connections on all network interfaces. You must use + # firewalls to restrict access to this address/port. + # Comment out following line if you only want to support TLS connections + gitaly['listen_addr'] = "0.0.0.0:8075" + ``` + +1. Append the following to `/etc/gitlab/gitlab.rb` for each respective server: + 1. On `gitaly1.internal`: + + ```ruby + git_data_dirs({ + 'default' => { + 'path' => '/var/opt/gitlab/git-data' + }, + 'storage1' => { + 'path' => '/mnt/gitlab/git-data' + }, + }) + ``` + + 1. On `gitaly2.internal`: + + ```ruby + git_data_dirs({ + 'storage2' => { + 'path' => '/mnt/gitlab/git-data' + }, + }) + ``` + + + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). + +### Gitaly TLS support + +Gitaly supports TLS encryption. To be able to communicate +with a Gitaly instance that listens for secure connections you will need to use `tls://` URL +scheme in the `gitaly_address` of the corresponding storage entry in the GitLab configuration. + +You will need to bring your own certificates as this isn't provided automatically. +The certificate, or its certificate authority, must be installed on all Gitaly +nodes (including the Gitaly node using the certificate) and on all client nodes +that communicate with it following the procedure described in +[GitLab custom certificate configuration](https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates). + +NOTE: **Note:** +The self-signed certificate must specify the address you use to access the +Gitaly server. If you are addressing the Gitaly server by a hostname, you can +either use the Common Name field for this, or add it as a Subject Alternative +Name. If you are addressing the Gitaly server by its IP address, you must add it +as a Subject Alternative Name to the certificate. +[gRPC does not support using an IP address as Common Name in a certificate](https://github.com/grpc/grpc/issues/2691). + +NOTE: **Note:** +It is possible to configure Gitaly servers with both an +unencrypted listening address `listen_addr` and an encrypted listening +address `tls_listen_addr` at the same time. This allows you to do a +gradual transition from unencrypted to encrypted traffic, if necessary. + +To configure Gitaly with TLS: + +1. Create the `/etc/gitlab/ssl` directory and copy your key and certificate there: + + ```shell + sudo mkdir -p /etc/gitlab/ssl + sudo chmod 755 /etc/gitlab/ssl + sudo cp key.pem cert.pem /etc/gitlab/ssl/ + sudo chmod 644 key.pem cert.pem + ``` + +1. Copy the cert to `/etc/gitlab/trusted-certs` so Gitaly will trust the cert when + calling into itself: + + ```shell + sudo cp /etc/gitlab/ssl/cert.pem /etc/gitlab/trusted-certs/ + ``` + +1. Edit `/etc/gitlab/gitlab.rb` and add: + + + + ```ruby + gitaly['tls_listen_addr'] = "0.0.0.0:9999" + gitaly['certificate_path'] = "/etc/gitlab/ssl/cert.pem" + gitaly['key_path'] = "/etc/gitlab/ssl/key.pem" + ``` + +1. Delete `gitaly['listen_addr']` to allow only encrypted connections. + +1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). + + + +## Configure Sidekiq + +Sidekiq requires connections to the Redis, PostgreSQL and Gitaly instances. +The following IPs will be used as an example: + +- `10.6.0.101`: Sidekiq 1 +- `10.6.0.102`: Sidekiq 2 +- `10.6.0.103`: Sidekiq 3 +- `10.6.0.104`: Sidekiq 4 + +To configure the Sidekiq nodes, on each one: + +1. SSH into the Sidekiq server. +1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab package +you want using steps 1 and 2 from the GitLab downloads page. +**Do not complete any other steps on the download page.** +1. Open `/etc/gitlab/gitlab.rb` with your editor: + + ```ruby + ######################################## + ##### Services Disabled ### + ######################################## + + nginx['enable'] = false + grafana['enable'] = false + prometheus['enable'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = false + puma['enable'] = false + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + gitlab_exporter['enable'] = false + + ######################################## + #### Redis ### + ######################################## + + ## Redis connection details + ## First cluster that will host the cache + gitlab_rails['redis_cache_instance'] = 'redis://:@gitlab-redis-cache' + + gitlab_rails['redis_cache_sentinels'] = [ + {host: '10.6.0.71', port: 26379}, + {host: '10.6.0.72', port: 26379}, + {host: '10.6.0.73', port: 26379}, + ] + + ## Second cluster that will host the queues, shared state, and actioncable + gitlab_rails['redis_queues_instance'] = 'redis://:@gitlab-redis-persistent' + gitlab_rails['redis_shared_state_instance'] = 'redis://:@gitlab-redis-persistent' + gitlab_rails['redis_actioncable_instance'] = 'redis://:@gitlab-redis-persistent' + + gitlab_rails['redis_queues_sentinels'] = [ + {host: '10.6.0.81', port: 26379}, + {host: '10.6.0.82', port: 26379}, + {host: '10.6.0.83', port: 26379}, + ] + gitlab_rails['redis_shared_state_sentinels'] = [ + {host: '10.6.0.81', port: 26379}, + {host: '10.6.0.82', port: 26379}, + {host: '10.6.0.83', port: 26379}, + ] + gitlab_rails['redis_actioncable_sentinels'] = [ + {host: '10.6.0.81', port: 26379}, + {host: '10.6.0.82', port: 26379}, + {host: '10.6.0.83', port: 26379}, + ] + + ####################################### + ### Gitaly ### + ####################################### + + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, + }) + gitlab_rails['gitaly_token'] = 'YOUR_TOKEN' + + ####################################### + ### Postgres ### + ####################################### + gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP + gitlab_rails['db_port'] = 6432 + gitlab_rails['db_password'] = '' + gitlab_rails['db_adapter'] = 'postgresql' + gitlab_rails['db_encoding'] = 'unicode' + gitlab_rails['auto_migrate'] = false + + ####################################### + ### Sidekiq configuration ### + ####################################### + sidekiq['listen_address'] = "0.0.0.0" + sidekiq['cluster'] = true # no need to set this after GitLab 13.0 + + ####################################### + ### Monitoring configuration ### + ####################################### + consul['enable'] = true + consul['monitoring_service_discovery'] = true + + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + + # Set the network addresses that the exporters will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + + # Rails Status for prometheus + gitlab_rails['monitoring_whitelist'] = ['10.6.0.121/32', '127.0.0.0/8'] + ``` + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + +TIP: **Tip:** +You can also run [multiple Sidekiq processes](../operations/extra_sidekiq_processes.md). + + + +## Configure GitLab Rails + +NOTE: **Note:** +In our architectures we run each GitLab Rails node using the Puma webserver +and have its number of workers set to 90% of available CPUs along with four threads. For +nodes that are running Rails with other components the worker value should be reduced +accordingly where we've found 50% achieves a good balance but this is dependent +on workload. + +This section describes how to configure the GitLab application (Rails) component. + +The following IPs will be used as an example: + +- `10.6.0.111`: GitLab application 1 +- `10.6.0.112`: GitLab application 2 +- `10.6.0.113`: GitLab application 3 + +On each node perform the following: + +1. Download/install Omnibus GitLab using **steps 1 and 2** from + [GitLab downloads](https://about.gitlab.com/install/). Do not complete other + steps on the download page. + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. Edit `/etc/gitlab/gitlab.rb` and use the following configuration. + To maintain uniformity of links across nodes, the `external_url` + on the application server should point to the external URL that users will use + to access GitLab. This would be the URL of the [external load balancer](#configure-the-external-load-balancer) + which will route traffic to the GitLab application server: + + ```ruby + external_url 'https://gitlab.example.com' + + # Gitaly and GitLab use two shared secrets for authentication, one to authenticate gRPC requests + # to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API. + # The following two values must be the same as their respective values + # of the Gitaly setup + gitlab_rails['gitaly_token'] = 'gitalysecret' + gitlab_shell['secret_token'] = 'shellsecret' + + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage1' => { 'gitaly_address' => 'tcp://gitaly1.internal:8075' }, + 'storage2' => { 'gitaly_address' => 'tcp://gitaly2.internal:8075' }, + }) + + ## Disable components that will not be on the GitLab application server + roles ['application_role'] + gitaly['enable'] = false + nginx['enable'] = true + + ## PostgreSQL connection details + # Disable PostgreSQL on the application node + postgresql['enable'] = false + gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP + gitlab_rails['db_port'] = 6432 + gitlab_rails['db_password'] = '' + gitlab_rails['auto_migrate'] = false + + ## Redis connection details + ## First cluster that will host the cache + gitlab_rails['redis_cache_instance'] = 'redis://:@gitlab-redis-cache' + + gitlab_rails['redis_cache_sentinels'] = [ + {host: '10.6.0.71', port: 26379}, + {host: '10.6.0.72', port: 26379}, + {host: '10.6.0.73', port: 26379}, + ] + + ## Second cluster that will host the queues, shared state, and actionable + gitlab_rails['redis_queues_instance'] = 'redis://:@gitlab-redis-persistent' + gitlab_rails['redis_shared_state_instance'] = 'redis://:@gitlab-redis-persistent' + gitlab_rails['redis_actioncable_instance'] = 'redis://:@gitlab-redis-persistent' + + gitlab_rails['redis_queues_sentinels'] = [ + {host: '10.6.0.81', port: 26379}, + {host: '10.6.0.82', port: 26379}, + {host: '10.6.0.83', port: 26379}, + ] + gitlab_rails['redis_shared_state_sentinels'] = [ + {host: '10.6.0.81', port: 26379}, + {host: '10.6.0.82', port: 26379}, + {host: '10.6.0.83', port: 26379}, + ] + gitlab_rails['redis_actioncable_sentinels'] = [ + {host: '10.6.0.81', port: 26379}, + {host: '10.6.0.82', port: 26379}, + {host: '10.6.0.83', port: 26379}, + ] + + # Set the network addresses that the exporters used for monitoring will listen on + node_exporter['listen_address'] = '0.0.0.0:9100' + gitlab_workhorse['prometheus_listen_addr'] = '0.0.0.0:9229' + sidekiq['listen_address'] = "0.0.0.0" + puma['listen'] = '0.0.0.0' + + # Add the monitoring node's IP address to the monitoring whitelist and allow it to + # scrape the NGINX metrics + gitlab_rails['monitoring_whitelist'] = ['10.6.0.121/32', '127.0.0.0/8'] + nginx['status']['options']['allow'] = ['10.6.0.121/32', '127.0.0.0/8'] + ``` + +1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). +1. If you're using [Gitaly with TLS support](#gitaly-tls-support), make sure the + `git_data_dirs` entry is configured with `tls` instead of `tcp`: + + ```ruby + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage1' => { 'gitaly_address' => 'tls://gitaly1.internal:9999' }, + 'storage2' => { 'gitaly_address' => 'tls://gitaly2.internal:9999' }, + }) + ``` + + 1. Copy the cert into `/etc/gitlab/trusted-certs`: + + ```shell + sudo cp cert.pem /etc/gitlab/trusted-certs/ + ``` + +1. If you're [using NFS](#configure-nfs-optional): + 1. If necessary, install the NFS client utility packages using the following + commands: + + ```shell + # Ubuntu/Debian + apt-get install nfs-common + + # CentOS/Red Hat + yum install nfs-utils nfs-utils-lib + ``` + + 1. Specify the necessary NFS mounts in `/etc/fstab`. + The exact contents of `/etc/fstab` will depend on how you chose + to configure your NFS server. See the [NFS documentation](../high_availability/nfs.md) + for examples and the various options. + + 1. Create the shared directories. These may be different depending on your NFS + mount locations. + + ```shell + mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data + ``` + + 1. Edit `/etc/gitlab/gitlab.rb` and use the following configuration: + + ```ruby + ## Prevent GitLab from starting if NFS data mounts are not available + high_availability['mountpoint'] = '/var/opt/gitlab/git-data' + + ## Ensure UIDs and GIDs match between servers for permissions via NFS + user['uid'] = 9000 + user['gid'] = 9000 + web_server['uid'] = 9001 + web_server['gid'] = 9001 + registry['uid'] = 9002 + registry['gid'] = 9002 + ``` + +1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). +1. Confirm the node can connect to Gitaly: + + ```shell + sudo gitlab-rake gitlab:gitaly:check + ``` + + Then, tail the logs to see the requests: + + ```shell + sudo gitlab-ctl tail gitaly + ``` + +1. Optionally, from the Gitaly servers, confirm that Gitaly can perform callbacks to the internal API: + + ```shell + sudo /opt/gitlab/embedded/service/gitlab-shell/bin/check -config /opt/gitlab/embedded/service/gitlab-shell/config.yml + ``` + +NOTE: **Note:** +When you specify `https` in the `external_url`, as in the example +above, GitLab assumes you have SSL certificates in `/etc/gitlab/ssl/`. If +certificates are not present, NGINX will fail to start. See the +[NGINX documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https) +for more information. + +### GitLab Rails post-configuration + +Initialize the GitLab database, by running the following in one of the Rails nodes: + +```shell +sudo gitlab-rake gitlab:db:configure +``` + +NOTE: **Note:** +If you encounter a `rake aborted!` error stating that PgBouncer is failing to connect to +PostgreSQL it may be that your PgBouncer node's IP address is missing from +PostgreSQL's `trust_auth_cidr_addresses` in `gitlab.rb` on your database nodes. See +[PgBouncer error `ERROR: pgbouncer cannot connect to server`](troubleshooting.md#pgbouncer-error-error-pgbouncer-cannot-connect-to-server) +in the Troubleshooting section before proceeding. + + + +## Configure Prometheus + +The Omnibus GitLab package can be used to configure a standalone Monitoring node +running [Prometheus](../monitoring/prometheus/index.md) and +[Grafana](../monitoring/performance/grafana_configuration.md). + +The following IP will be used as an example: + +- `10.6.0.121`: Prometheus + +To configure the Monitoring node: + +1. SSH into the Monitoring node. +1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab + package you want using **steps 1 and 2** from the GitLab downloads page. + Do not complete any other steps on the download page. + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + +1. Edit `/etc/gitlab/gitlab.rb` and add the contents: + + ```ruby + external_url 'http://gitlab.example.com' + + # Disable all other services + gitlab_rails['auto_migrate'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_exporter['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = true + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + sidekiq['enable'] = false + puma['enable'] = false + unicorn['enable'] = false + node_exporter['enable'] = false + gitlab_exporter['enable'] = false + + # Enable Prometheus + prometheus['enable'] = true + prometheus['listen_address'] = '0.0.0.0:9090' + prometheus['monitor_kubernetes'] = false + + # Enable Login form + grafana['disable_login_form'] = false + + # Enable Grafana + grafana['enable'] = true + grafana['admin_password'] = '' + + # Enable service discovery for Prometheus + consul['enable'] = true + consul['monitoring_service_discovery'] = true + consul['configuration'] = { + retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) + } + ``` + +1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). +1. In the GitLab UI, set `admin/application_settings/metrics_and_profiling` > Metrics - Grafana to `/-/grafana` to +`http[s]:///-/grafana` + + + +## Configure the object storage + +GitLab supports using an object storage service for holding numerous types of data. +It's recommended over [NFS](#configure-nfs-optional) and in general it's better +in larger setups as object storage is typically much more performant, reliable, +and scalable. + +Object storage options that GitLab has tested, or is aware of customers using include: + +- SaaS/Cloud solutions such as [Amazon S3](https://aws.amazon.com/s3/), [Google cloud storage](https://cloud.google.com/storage). +- On-premises hardware and appliances from various storage vendors. +- MinIO. There is [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation. + +For configuring GitLab to use Object Storage refer to the following guides +based on what features you intend to use: + +1. Configure [object storage for backups](../../raketasks/backup_restore.md#uploading-backups-to-a-remote-cloud-storage). +1. Configure [object storage for job artifacts](../job_artifacts.md#using-object-storage) + including [incremental logging](../job_logs.md#new-incremental-logging-architecture). +1. Configure [object storage for LFS objects](../lfs/index.md#storing-lfs-objects-in-remote-object-storage). +1. Configure [object storage for uploads](../uploads.md#using-object-storage-core-only). +1. Configure [object storage for merge request diffs](../merge_request_diffs.md#using-object-storage). +1. Configure [object storage for Container Registry](../packages/container_registry.md#use-object-storage) (optional feature). +1. Configure [object storage for Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage) (optional feature). +1. Configure [object storage for packages](../packages/index.md#using-object-storage) (optional feature). **(PREMIUM ONLY)** +1. Configure [object storage for Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature). **(PREMIUM ONLY)** +1. Configure [object storage for Pseudonymizer](../pseudonymizer.md#configuration) (optional feature). **(ULTIMATE ONLY)** +1. Configure [object storage for autoscale Runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional - for improved performance). +1. Configure [object storage for Terraform state files](../terraform_state.md#using-object-storage-core-only). + +Using separate buckets for each data type is the recommended approach for GitLab. + +A limitation of our configuration is that each use of object storage is separately configured. +[We have an issue for improving this](https://gitlab.com/gitlab-org/gitlab/-/issues/23345) +and easily using one bucket with separate folders is one improvement that this might bring. + +There is at least one specific issue with using the same bucket: +when GitLab is deployed with the Helm chart restore from backup +[will not properly function](https://docs.gitlab.com/charts/advanced/external-object-storage/#lfs-artifacts-uploads-packages-external-diffs-pseudonymizer) +unless separate buckets are used. + +One risk of using a single bucket would be if your organization decided to +migrate GitLab to the Helm deployment in the future. GitLab would run, but the situation with +backups might not be realized until the organization had a critical requirement for the backups to +work. + + + +## Configure NFS (optional) + +[Object storage](#configure-the-object-storage), along with [Gitaly](#configure-gitaly) +are recommended over NFS wherever possible for improved performance. If you intend +to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pages-requires-nfs). + +See how to [configure NFS](../high_availability/nfs.md). + + + +## Troubleshooting + +See the [troubleshooting documentation](troubleshooting.md). + + diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md index 0b4114bca6e..14685ffa53d 100644 --- a/doc/administration/reference_architectures/5k_users.md +++ b/doc/administration/reference_architectures/5k_users.md @@ -1,49 +1,54 @@ --- reading_time: true +stage: Enablement +group: Distribution +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers --- -# Reference architecture: up to 5,000 users +# Reference architecture: up to 5,000 users **(PREMIUM ONLY)** -This page describes GitLab reference architecture for up to 5,000 users. -For a full list of reference architectures, see +This page describes GitLab reference architecture for up to 5,000 users. For a +full list of reference architectures, see [Available reference architectures](index.md#available-reference-architectures). NOTE: **Note:** -The 5,000-user reference architecture documented below is -designed to help your organization achieve a highly-available GitLab deployment. -If you do not have the expertise or need to maintain a highly-available -environment, you can have a simpler and less costly-to-operate environment by -following the [2,000-user reference architecture](2k_users.md). +This reference architecture is designed to help your organization achieve a +highly-available GitLab deployment. If you do not have the expertise or need to +maintain a highly-available environment, you can have a simpler and less +costly-to-operate environment by using the +[2,000-user reference architecture](2k_users.md). > - **Supported users (approximate):** 5,000 -> - **High Availability:** True -> - **Test RPS rates:** API: 100 RPS, Web: 10 RPS, Git: 10 RPS - -| Service | Nodes | Configuration | GCP | AWS | Azure | -|--------------------------------------------------------------|-------|---------------------------------|-----------------|-----------------------|----------------| -| External load balancing node | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | -| Redis | 3 | 2 vCPU, 7.5GB Memory | `n1-standard-2` | `m5.large` | `D2s v3` | -| Consul + Sentinel | 3 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | -| PostgreSQL | 3 | 2 vCPU, 7.5GB Memory | `n1-standard-2` | `m5.large` | `D2s v3` | -| PgBouncer | 3 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | -| Internal load balancing node | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | -| Gitaly | 2 minimum | 8 vCPU, 30GB Memory | `n1-standard-8` | `m5.2xlarge` | `D8s v3` | -| Sidekiq | 4 | 2 vCPU, 7.5GB Memory | `n1-standard-2` | `m5.large` | `D2s v3` | -| GitLab Rails | 3 | 16 vCPU, 14.4GB Memory | `n1-highcpu-16` | `c5.4xlarge` | `F16s v2` | -| Monitoring node | 1 | 2 vCPU, 1.8GB Memory | `n1-highcpu-2` | `c5.large` | `F2s v2` | -| Object Storage | n/a | n/a | n/a | n/a | n/a | -| NFS Server (optional, not recommended) | 1 | 4 vCPU, 3.6GB Memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` | - -The architectures were built and tested with the [Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) -CPU platform on GCP. On different hardware you may find that adjustments, either lower -or higher, are required for your CPU or Node counts accordingly. For more information, a -[Sysbench](https://github.com/akopytov/sysbench) benchmark of the CPU can be found -[here](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks). - -For data objects such as LFS, Uploads, Artifacts, etc, an [object storage service](#configure-the-object-storage) -is recommended over NFS where possible, due to better performance and availability. -Since this doesn't require a node to be set up, it's marked as not applicable (n/a) -in the table above. +> - **High Availability:** Yes +> - **Test requests per second (RPS) rates:** API: 100 RPS, Web: 10 RPS, Git: 10 RPS + +| Service | Nodes | Configuration | GCP | AWS | Azure | +|--------------------------------------------|-------------|-------------------------|----------------|-------------|----------| +| External load balancing node | 1 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| Redis | 3 | 2 vCPU, 7.5GB memory | n1-standard-2 | m5.large | D2s v3 | +| Consul + Sentinel | 3 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| PostgreSQL | 3 | 2 vCPU, 7.5GB memory | n1-standard-2 | m5.large | D2s v3 | +| PgBouncer | 3 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| Internal load balancing node | 1 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| Gitaly | 2 (minimum) | 8 vCPU, 30GB memory | n1-standard-8 | m5.2xlarge | D8s v3 | +| Sidekiq | 4 | 2 vCPU, 7.5GB memory | n1-standard-2 | m5.large | D2s v3 | +| GitLab Rails | 3 | 16 vCPU, 14.4GB memory | n1-highcpu-16 | c5.4xlarge | F16s v2 | +| Monitoring node | 1 | 2 vCPU, 1.8GB memory | n1-highcpu-2 | c5.large | F2s v2 | +| Object Storage | n/a | n/a | n/a | n/a | n/a | +| NFS Server (optional, not recommended) | 1 | 4 vCPU, 3.6GB memory | n1-highcpu-4 | c5.xlarge | F4s v2 | + +The Google Cloud Platform (GCP) architectures were built and tested using the +[Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) +CPU platform. On different hardware you may find that adjustments, either lower +or higher, are required for your CPU or node counts. For more information, see +our [Sysbench](https://github.com/akopytov/sysbench)-based +[CPU benchmark](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks). + +For data objects (such as LFS, Uploads, or Artifacts), an +[object storage service](#configure-the-object-storage) is recommended instead +of NFS where possible, due to better performance and availability. Since this +doesn't require a node to be set up, *Object Storage* is noted as not +applicable (n/a) in the previous table. ## Setup components @@ -1439,7 +1444,7 @@ On each node perform the following: 1. Specify the necessary NFS mounts in `/etc/fstab`. The exact contents of `/etc/fstab` will depend on how you chose - to configure your NFS server. See the [NFS documentation](../high_availability/nfs.md) + to configure your NFS server. See the [NFS documentation](../nfs.md) for examples and the various options. 1. Create the shared directories. These may be different depending on your NFS @@ -1748,7 +1753,7 @@ work. are recommended over NFS wherever possible for improved performance. If you intend to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pages-requires-nfs). -See how to [configure NFS](../high_availability/nfs.md). +See how to [configure NFS](../nfs.md).
diff --git a/doc/administration/reference_architectures/img/reference-architectures.png b/doc/administration/reference_architectures/img/reference-architectures.png index e15609e78e1..0f8e663b57b 100644 Binary files a/doc/administration/reference_architectures/img/reference-architectures.png and b/doc/administration/reference_architectures/img/reference-architectures.png differ diff --git a/doc/administration/reference_architectures/index.md b/doc/administration/reference_architectures/index.md index 8fde71a66bf..4f7be2413dd 100644 --- a/doc/administration/reference_architectures/index.md +++ b/doc/administration/reference_architectures/index.md @@ -1,36 +1,45 @@ --- type: reference, concepts +stage: Enablement +group: Distribution +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers --- -# Reference architectures - +# Reference architectures You can set up GitLab on a single server or scale it up to serve many users. -This page details the recommended Reference Architectures that were built and verified by GitLab's Quality and Support teams. +This page details the recommended Reference Architectures that were built and +verified by GitLab's Quality and Support teams. -Below is a chart representing each architecture tier and the number of users they can handle. As your number of users grow with time, it’s recommended that you scale GitLab accordingly. +Below is a chart representing each architecture tier and the number of users +they can handle. As your number of users grow with time, it’s recommended that +you scale GitLab accordingly. ![Reference Architectures](img/reference-architectures.png) -Testing on these reference architectures were performed with [GitLab's Performance Tool](https://gitlab.com/gitlab-org/quality/performance) -at specific coded workloads, and the throughputs used for testing were calculated based on sample customer data. -After selecting the reference architecture that matches your scale, refer to -[Configure GitLab to Scale](#configure-gitlab-to-scale) to see the components -involved, and how to configure them. +Testing on these reference architectures were performed with +[GitLab's Performance Tool](https://gitlab.com/gitlab-org/quality/performance) +at specific coded workloads, and the throughputs used for testing were +calculated based on sample customer data. Select the +[reference architecture](#available-reference-architectures) that matches your scale. -Each endpoint type is tested with the following number of requests per second (RPS) per 1000 users: +Each endpoint type is tested with the following number of requests per second (RPS) +per 1,000 users: - API: 20 RPS - Web: 2 RPS - Git: 2 RPS -For GitLab instances with less than 2,000 users, it's recommended that you use the [default setup](#automated-backups-core-only) -by [installing GitLab](../../install/README.md) on a single machine to minimize maintenance and resource costs. +For GitLab instances with less than 2,000 users, it's recommended that you use +the [default setup](#automated-backups-core-only) by +[installing GitLab](../../install/README.md) on a single machine to minimize +maintenance and resource costs. -If your organization has more than 2,000 users, the recommendation is to scale GitLab's components to multiple -machine nodes. The machine nodes are grouped by component(s). The addition of these -nodes increases the performance and scalability of to your GitLab instance. +If your organization has more than 2,000 users, the recommendation is to scale +GitLab's components to multiple machine nodes. The machine nodes are grouped by +components. The addition of these nodes increases the performance and +scalability of to your GitLab instance. When scaling GitLab, there are several factors to consider: @@ -39,12 +48,13 @@ When scaling GitLab, there are several factors to consider: - The application nodes connects to a shared file server and PostgreSQL and Redis services on the backend. NOTE: **Note:** -Depending on your workflow, the following recommended -reference architectures may need to be adapted accordingly. Your workload -is influenced by factors including how active your users are, -how much automation you use, mirroring, and repository/change size. Additionally the -displayed memory values are provided by [GCP machine types](https://cloud.google.com/compute/docs/machine-types). -For different cloud vendors, attempt to select options that best match the provided architecture. +Depending on your workflow, the following recommended reference architectures +may need to be adapted accordingly. Your workload is influenced by factors +including how active your users are, how much automation you use, mirroring, +and repository/change size. Additionally the displayed memory values are +provided by [GCP machine types](https://cloud.google.com/compute/docs/machine-types). +For different cloud vendors, attempt to select options that best match the +provided architecture. ## Available reference architectures @@ -60,14 +70,14 @@ The following reference architectures are available: ## Availability Components -GitLab comes with the following components for your use, listed from -least to most complex: +GitLab comes with the following components for your use, listed from least to +most complex: -1. [Automated backups](#automated-backups-core-only) -1. [Traffic load balancer](#traffic-load-balancer-starter-only) -1. [Zero downtime updates](#zero-downtime-updates-starter-only) -1. [Automated database failover](#automated-database-failover-premium-only) -1. [Instance level replication with GitLab Geo](#instance-level-replication-with-gitlab-geo-premium-only) +- [Automated backups](#automated-backups-core-only) +- [Traffic load balancer](#traffic-load-balancer-starter-only) +- [Zero downtime updates](#zero-downtime-updates-starter-only) +- [Automated database failover](#automated-database-failover-premium-only) +- [Instance level replication with GitLab Geo](#instance-level-replication-with-gitlab-geo-premium-only) As you implement these components, begin with a single server and then do backups. Only after completing the first server should you proceed to the next. @@ -115,7 +125,8 @@ to the default installation: > - Supported tiers: [GitLab Starter, Premium, and Ultimate](https://about.gitlab.com/pricing/) GitLab supports [zero-downtime updates](https://docs.gitlab.com/omnibus/update/#zero-downtime-updates). -Although you can perform zero-downtime updates with a single GitLab node, the recommendation is to separate GitLab into several application nodes. +Single GitLab nodes can be updated with only a [few minutes of downtime](https://docs.gitlab.com/omnibus/update/README.html#single-node-deployment). +To avoid this, we recommend to separate GitLab into several application nodes. As long as at least one of each component is online and capable of handling the instance's usage load, your team's productivity will not be interrupted during the update. ### Automated database failover **(PREMIUM ONLY)** @@ -140,40 +151,7 @@ is recommended. instance to other geographical locations as a read-only fully operational instance that can also be promoted in case of disaster. -## Configure GitLab to scale - -NOTE: **Note:** -From GitLab 13.0, using NFS for Git repositories is deprecated. In GitLab 14.0, support for NFS for Git repositories is scheduled to be removed. Upgrade to [Gitaly Cluster](../gitaly/praefect.md) as soon as possible. - -The following components are the ones you need to configure in order to scale -GitLab. They are listed in the order you'll typically configure them if they are -required by your [reference architecture](#reference-architectures) of choice. - -Most of them are bundled in the GitLab deb/rpm package (called Omnibus GitLab), -but depending on your system architecture, you may require some components which are -not included in it. If required, those should be configured before -setting up components provided by GitLab. Advice on how to select the right -solution for your organization is provided in the configuration instructions -column. - -| Component | Description | Configuration instructions | Bundled with Omnibus GitLab | -|-----------|-------------|----------------------------| -| Load balancer(s) ([6](#footnotes)) | Handles load balancing, typically when you have multiple GitLab application services nodes | [Load balancer configuration](../high_availability/load_balancer.md) ([6](#footnotes)) | No | -| Object storage service ([4](#footnotes)) | Recommended store for shared data objects | [Object Storage configuration](../object_storage.md) | No | -| NFS ([5](#footnotes)) ([7](#footnotes)) | Shared disk storage service. Can be used as an alternative Object Storage. Required for GitLab Pages | [NFS configuration](../high_availability/nfs.md) | No | -| [Consul](../../development/architecture.md#consul) ([3](#footnotes)) | Service discovery and health checks/failover | [Consul configuration](../high_availability/consul.md) **(PREMIUM ONLY)** | Yes | -| [PostgreSQL](../../development/architecture.md#postgresql) | Database | [PostgreSQL configuration](https://docs.gitlab.com/omnibus/settings/database.html) | Yes | -| [PgBouncer](../../development/architecture.md#pgbouncer) | Database connection pooler | [PgBouncer configuration](../high_availability/pgbouncer.md#running-pgbouncer-as-part-of-a-non-ha-gitlab-installation) **(PREMIUM ONLY)** | Yes | -| Repmgr | PostgreSQL cluster management and failover | [PostgreSQL and Repmgr configuration](../postgresql/replication_and_failover.md) | Yes | -| Patroni | An alternative PostgreSQL cluster management and failover | [PostgreSQL and Patroni configuration](../postgresql/replication_and_failover.md#patroni) | Yes | -| [Redis](../../development/architecture.md#redis) ([3](#footnotes)) | Key/value store for fast data lookup and caching | [Redis configuration](../high_availability/redis.md) | Yes | -| Redis Sentinel | Redis | [Redis Sentinel configuration](../high_availability/redis.md) | Yes | -| [Gitaly](../../development/architecture.md#gitaly) ([2](#footnotes)) ([7](#footnotes)) | Provides access to Git repositories | [Gitaly configuration](../gitaly/index.md#run-gitaly-on-its-own-server) | Yes | -| [Sidekiq](../../development/architecture.md#sidekiq) | Asynchronous/background jobs | [Sidekiq configuration](../high_availability/sidekiq.md) | Yes | -| [GitLab application services](../../development/architecture.md#unicorn)([1](#footnotes)) | Puma/Unicorn, Workhorse, GitLab Shell - serves front-end requests (UI, API, Git over HTTP/SSH) | [GitLab app scaling configuration](../high_availability/gitlab.md) | Yes | -| [Prometheus](../../development/architecture.md#prometheus) and [Grafana](../../development/architecture.md#grafana) | GitLab environment monitoring | [Monitoring node for scaling](../high_availability/monitoring_node.md) | Yes | - -### Configuring select components with Cloud Native Helm +## Configuring select components with Cloud Native Helm We also provide [Helm charts](https://docs.gitlab.com/charts/) as a Cloud Native installation method for GitLab. For the reference architectures, select components can be set up in this @@ -191,50 +169,3 @@ specs, only translated into Kubernetes resources. For example, if you were to set up a 50k installation with the Rails nodes being run in Helm, then the same amount of resources as given for Omnibus should be given to the Kubernetes cluster with the Rails nodes broken down into a number of smaller Pods across that cluster. - -## Footnotes - -1. In our architectures we run each GitLab Rails node using the Puma webserver - and have its number of workers set to 90% of available CPUs along with four threads. For - nodes that are running Rails with other components the worker value should be reduced - accordingly where we've found 50% achieves a good balance but this is dependent - on workload. - -1. Gitaly node requirements are dependent on customer data, specifically the number of - projects and their sizes. We recommend that each Gitaly node should store no more than 5TB of data - and have the number of [`gitaly-ruby` workers](../gitaly/index.md#gitaly-ruby) - set to 20% of available CPUs. Additional nodes should be considered in conjunction - with a review of expected data size and spread based on the recommendations above. - -1. Recommended Redis setup differs depending on the size of the architecture. - For smaller architectures (less than 3,000 users) a single instance should suffice. - For medium sized installs (3,000 - 5,000) we suggest one Redis cluster for all - classes and that Redis Sentinel is hosted alongside Consul. - For larger architectures (10,000 users or more) we suggest running a separate - [Redis Cluster](../redis/replication_and_failover.md#running-multiple-redis-clusters) for the Cache class - and another for the Queues and Shared State classes respectively. We also recommend - that you run the Redis Sentinel clusters separately for each Redis Cluster. - -1. For data objects such as LFS, Uploads, Artifacts, etc. We recommend an [Object Storage service](../object_storage.md) - over NFS where possible, due to better performance. - -1. NFS can be used as an alternative for object storage but this isn't typically - recommended for performance reasons. Note however it is required for [GitLab - Pages](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196). - -1. Our architectures have been tested and validated with [HAProxy](https://www.haproxy.org/) - as the load balancer. Although other load balancers with similar feature sets - could also be used, those load balancers have not been validated. - -1. We strongly recommend that any Gitaly or NFS nodes be set up with SSD disks over - HDD with a throughput of at least 8,000 IOPS for read operations and 2,000 IOPS for write - as these components have heavy I/O. These IOPS values are recommended only as a starter - as with time they may be adjusted higher or lower depending on the scale of your - environment's workload. If you're running the environment on a Cloud provider - you may need to refer to their documentation on how configure IOPS correctly. - -1. The architectures were built and tested with the [Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms) - CPU platform on GCP. On different hardware you may find that adjustments, either lower - or higher, are required for your CPU or Node counts accordingly. For more information, a - [Sysbench](https://github.com/akopytov/sysbench) benchmark of the CPU can be found - [here](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks). diff --git a/doc/administration/reference_architectures/troubleshooting.md b/doc/administration/reference_architectures/troubleshooting.md index 35bdb65c810..db2e9b89ba2 100644 --- a/doc/administration/reference_architectures/troubleshooting.md +++ b/doc/administration/reference_architectures/troubleshooting.md @@ -1,3 +1,9 @@ +--- +stage: Enablement +group: Distribution +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- + # Troubleshooting a reference architecture setup This page serves as the troubleshooting documentation if you followed one of @@ -17,7 +23,7 @@ with the Fog library that GitLab uses. Symptoms include: ### GitLab Pages requires NFS If you intend to use [GitLab Pages](../../user/project/pages/index.md), this currently requires -[NFS](../high_availability/nfs.md). There is [work in progress](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196) +[NFS](../nfs.md). There is [work in progress](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196) to remove this dependency. In the future, GitLab Pages may use [object storage](https://gitlab.com/gitlab-org/gitlab/-/issues/208135). @@ -524,7 +530,7 @@ To restart either service, run `gitlab-ctl restart SERVICE` For PostgreSQL, it is usually safe to restart the master node by default. Automatic failover defaults to a 1 minute timeout. Provided the database returns before then, nothing else needs to be done. To be safe, you can stop `repmgrd` on the standby nodes first with `gitlab-ctl stop repmgrd`, then start afterwards with `gitlab-ctl start repmgrd`. -On the Consul server nodes, it is important to restart the Consul service in a controlled fashion. Read our [Consul documentation](../high_availability/consul.md#restarting-the-server-cluster) for instructions on how to restart the service. +On the Consul server nodes, it is important to restart the Consul service in a controlled fashion. Read our [Consul documentation](../consul.md#restart-consul) for instructions on how to restart the service. ### `gitlab-ctl repmgr-check-master` command produces errors diff --git a/doc/administration/reply_by_email.md b/doc/administration/reply_by_email.md index 6d7069dd461..62645ad17a1 100644 --- a/doc/administration/reply_by_email.md +++ b/doc/administration/reply_by_email.md @@ -1,5 +1,13 @@ +--- +stage: Plan +group: Certify +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- + # Reply by email +> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/1173) in GitLab 8.0. + GitLab can be set up to allow users to comment on issues and merge requests by replying to notification emails. diff --git a/doc/administration/reply_by_email_postfix_setup.md b/doc/administration/reply_by_email_postfix_setup.md index 86854a2a7b6..f950134889d 100644 --- a/doc/administration/reply_by_email_postfix_setup.md +++ b/doc/administration/reply_by_email_postfix_setup.md @@ -306,7 +306,7 @@ Courier, which we will install later to add IMAP authentication, requires mailbo ```shell Trying 123.123.123.123... - Connected to mail.example.gitlab.com. + Connected to mail.gitlab.example.com. Escape character is '^]'. - OK [CAPABILITY IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA IDLE ACL ACL2=UNION] Courier-IMAP ready. Copyright 1998-2011 Double Precision, Inc. See COPYING for distribution information. ``` diff --git a/doc/administration/repository_checks.md b/doc/administration/repository_checks.md index 6d9ab723d2f..7d79840b56d 100644 --- a/doc/administration/repository_checks.md +++ b/doc/administration/repository_checks.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Editor +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference +--- + # Repository checks > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3232) in GitLab 8.7. diff --git a/doc/administration/repository_storage_paths.md b/doc/administration/repository_storage_paths.md index 5520eeace0a..16e17458e10 100644 --- a/doc/administration/repository_storage_paths.md +++ b/doc/administration/repository_storage_paths.md @@ -68,7 +68,7 @@ the example below, we add two more mount points that are named `nfs_1` and `nfs_ respectively. NOTE: **Note:** -This example uses NFS. We do not recommend using EFS for storage as it may impact GitLab's performance. See the [relevant documentation](high_availability/nfs.md#avoid-using-awss-elastic-file-system-efs) for more details. +This example uses NFS. We do not recommend using EFS for storage as it may impact GitLab's performance. See the [relevant documentation](nfs.md#avoid-using-awss-elastic-file-system-efs) for more details. **For installations from source** @@ -89,7 +89,7 @@ This example uses NFS. We do not recommend using EFS for storage as it may impac 1. [Restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect. ->**Note:** +NOTE: **Note:** The [`gitlab_shell: repos_path` entry](https://gitlab.com/gitlab-org/gitlab-foss/-/blob/8-9-stable/config/gitlab.yml.example#L457) in `gitlab.yml` will be deprecated and replaced by `repositories: storages` in the future, so if you are upgrading from a version prior to 8.10, make sure to add the configuration diff --git a/doc/administration/server_hooks.md b/doc/administration/server_hooks.md index 2fea000b799..ab808fc28d8 100644 --- a/doc/administration/server_hooks.md +++ b/doc/administration/server_hooks.md @@ -163,13 +163,13 @@ them as they can change. The following server hooks have been re-implemented in Go: - `pre-receive`, with the Go implementation used by default. To use the Ruby implementation instead, - [disable](../operations/feature_flags.md#enable-or-disable-feature-flag-strategies) the - `:gitaly_go_preceive_hook` feature flag. + [disable](feature_flags.md#enable-or-disable-the-feature) the `:gitaly_go_preceive_hook` feature + flag. - `update`, with the Go implementation used by default. To use the Ruby implementation instead, - [disable](../operations/feature_flags.md#enable-or-disable-feature-flag-strategies) the - `:gitaly_go_update_hook` feature flag. + [disable](feature_flags.md#enable-or-disable-the-feature) the `:gitaly_go_update_hook` feature + flag. - `post-receive`, however the Ruby implementation is used by default. To use the Go implementation - instead, [enable](../operations/feature_flags.md#enable-or-disable-feature-flag-strategies) the + instead, [enable](feature_flags.md#enable-or-disable-the-feature) the `:gitaly_go_postreceive_hook` feature flag. ## Custom error messages diff --git a/doc/administration/sidekiq.md b/doc/administration/sidekiq.md new file mode 100644 index 00000000000..23e870dbb82 --- /dev/null +++ b/doc/administration/sidekiq.md @@ -0,0 +1,188 @@ +--- +type: reference +--- + +# Configuring Sidekiq + +This section discusses how to configure an external Sidekiq instance using the +bundled Sidekiq in the GitLab package. + +Sidekiq requires connection to the Redis, PostgreSQL and Gitaly instance. +To configure the Sidekiq node: + +1. SSH into the Sidekiq server. +1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab package +you want using steps 1 and 2 from the GitLab downloads page. +**Do not complete any other steps on the download page.** +1. Open `/etc/gitlab/gitlab.rb` with your editor. +1. Generate the Sidekiq configuration: + + ```ruby + sidekiq['listen_address'] = "10.10.1.48" + + ## Optional: Enable extra Sidekiq processes + sidekiq_cluster['enable'] = true + sidekiq_cluster['enable'] = true + "elastic_indexer" + ] + ``` + +1. Setup Sidekiq's connection to Redis: + + ```ruby + ## Must be the same in every sentinel node + redis['master_name'] = 'gitlab-redis' + + ## The same password for Redis authentication you set up for the master node. + redis['master_password'] = 'YOUR_PASSOWORD' + + ## A list of sentinels with `host` and `port` + gitlab_rails['redis_sentinels'] = [ + {'host' => '10.10.1.34', 'port' => 26379}, + {'host' => '10.10.1.35', 'port' => 26379}, + {'host' => '10.10.1.36', 'port' => 26379}, + ] + ``` + +1. Set up Sidekiq's connection to Gitaly: + + ```ruby + git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly:8075' }, + }) + gitlab_rails['gitaly_token'] = 'YOUR_TOKEN' + ``` + +1. Set up Sidekiq's connection to PostgreSQL: + + ```ruby + gitlab_rails['db_host'] = '10.10.1.30' + gitlab_rails['db_password'] = 'YOUR_PASSOWORD' + gitlab_rails['db_port'] = '5432' + gitlab_rails['db_adapter'] = 'postgresql' + gitlab_rails['db_encoding'] = 'unicode' + gitlab_rails['auto_migrate'] = false + ``` + + Remember to add the Sidekiq nodes to PostgreSQL's trusted addresses: + + ```ruby + postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.10.1.30/32 10.10.1.31/32 10.10.1.32/32 10.10.1.33/32 10.10.1.38/32) + ``` + +1. Disable other services: + + ```ruby + nginx['enable'] = false + grafana['enable'] = false + prometheus['enable'] = false + gitlab_rails['auto_migrate'] = false + alertmanager['enable'] = false + gitaly['enable'] = false + gitlab_monitor['enable'] = false + gitlab_workhorse['enable'] = false + nginx['enable'] = false + postgres_exporter['enable'] = false + postgresql['enable'] = false + redis['enable'] = false + redis_exporter['enable'] = false + puma['enable'] = false + gitlab_exporter['enable'] = false + ``` + +1. Run `gitlab-ctl reconfigure`. + +NOTE: **Note:** +You will need to restart the Sidekiq nodes after an update has occurred and database +migrations performed. + +## Example configuration + +Here's what the ending `/etc/gitlab/gitlab.rb` would look like: + +```ruby +######################################## +##### Services Disabled ### +######################################## + +nginx['enable'] = false +grafana['enable'] = false +prometheus['enable'] = false +gitlab_rails['auto_migrate'] = false +alertmanager['enable'] = false +gitaly['enable'] = false +gitlab_monitor['enable'] = false +gitlab_workhorse['enable'] = false +nginx['enable'] = false +postgres_exporter['enable'] = false +postgresql['enable'] = false +redis['enable'] = false +redis_exporter['enable'] = false +puma['enable'] = false +gitlab_exporter['enable'] = false + +######################################## +#### Redis ### +######################################## + +## Must be the same in every sentinel node +redis['master_name'] = 'gitlab-redis' + +## The same password for Redis authentication you set up for the master node. +redis['master_password'] = 'YOUR_PASSOWORD' + +## A list of sentinels with `host` and `port` +gitlab_rails['redis_sentinels'] = [ + {'host' => '10.10.1.34', 'port' => 26379}, + {'host' => '10.10.1.35', 'port' => 26379}, + {'host' => '10.10.1.36', 'port' => 26379}, + ] + +####################################### +### Gitaly ### +####################################### + +git_data_dirs({ + 'default' => { 'gitaly_address' => 'tcp://gitaly:8075' }, +}) +gitlab_rails['gitaly_token'] = 'YOUR_TOKEN' + +####################################### +### Postgres ### +####################################### +gitlab_rails['db_host'] = '10.10.1.30' +gitlab_rails['db_password'] = 'YOUR_PASSOWORD' +gitlab_rails['db_port'] = '5432' +gitlab_rails['db_adapter'] = 'postgresql' +gitlab_rails['db_encoding'] = 'unicode' +gitlab_rails['auto_migrate'] = false + +####################################### +### Sidekiq configuration ### +####################################### +sidekiq['listen_address'] = "10.10.1.48" + +####################################### +### Monitoring configuration ### +####################################### +consul['enable'] = true +consul['monitoring_service_discovery'] = true + +consul['configuration'] = { + bind_addr: '10.10.1.48', + retry_join: %w(10.10.1.34 10.10.1.35 10.10.1.36) +} + +# Set the network addresses that the exporters will listen on +node_exporter['listen_address'] = '10.10.1.48:9100' + +# Rails Status for prometheus +gitlab_rails['monitoring_whitelist'] = ['10.10.1.42', '127.0.0.1'] +``` + +## Further reading + +Related Sidekiq configuration: + +1. [Extra Sidekiq processes](operations/extra_sidekiq_processes.md) +1. [Using the GitLab-Sidekiq chart](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/) diff --git a/doc/administration/smime_signing_email.md b/doc/administration/smime_signing_email.md index 304b65917c1..b1e7e349978 100644 --- a/doc/administration/smime_signing_email.md +++ b/doc/administration/smime_signing_email.md @@ -3,7 +3,7 @@ Notification emails sent by GitLab can be signed with S/MIME for improved security. -> **Note:** +NOTE: **Note:** Please be aware that S/MIME certificates and TLS/SSL certificates are not the same and are used for different purposes: TLS creates a secure channel, whereas S/MIME signs and/or encrypts the message itself diff --git a/doc/administration/snippets/index.md b/doc/administration/snippets/index.md index cf3d8bec1a6..95de3b8c183 100644 --- a/doc/administration/snippets/index.md +++ b/doc/administration/snippets/index.md @@ -1,5 +1,8 @@ --- type: reference, howto +stage: Create +group: Editor +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" --- # Snippets settings **(CORE ONLY)** @@ -10,15 +13,15 @@ Adjust the snippets' settings of your GitLab instance. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31133) in GitLab 12.6. -You can set a content size max limit in snippets. This limit can prevent -abuses of the feature. The default content size limit is **52428800 Bytes** (50MB). +You can set a maximum content size limit for snippets. This limit can prevent +abuse of the feature. The default value is **52428800 Bytes** (50 MB). ### How does it work? -The content size limit will be applied when a snippet is created or -updated. Nevertheless, in order not to break any existing snippet, -the limit will only be enforced in stored snippets when the content -is updated. +The content size limit will be applied when a snippet is created or updated. + +In order not to break any existing snippets, the limit doesn't have any +effect on them until a snippet is edited again and the content changes. ### Snippets size limit configuration @@ -27,7 +30,7 @@ In order to configure this setting, use either the Rails console or the [Application settings API](../../api/settings.md). NOTE: **IMPORTANT:** -The value of the limit **must** be in Bytes. +The value of the limit **must** be in bytes. #### Through the Rails console diff --git a/doc/administration/static_objects_external_storage.md b/doc/administration/static_objects_external_storage.md index 973f4304115..34c7c8947fc 100644 --- a/doc/administration/static_objects_external_storage.md +++ b/doc/administration/static_objects_external_storage.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Editor +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference +--- + # Static objects external storage > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31025) in GitLab 12.3. @@ -52,10 +59,10 @@ sequenceDiagram ## Set up external storage -While this procedure uses [CloudFlare Workers](https://workers.cloudflare.com) for external storage, +While this procedure uses [Cloudflare Workers](https://workers.cloudflare.com) for external storage, other CDNs or Function as a Service (FaaS) systems should work using the same principles. -1. Choose a CloudFlare Worker domain if you haven't done so already. +1. Choose a Cloudflare Worker domain if you haven't done so already. 1. In the following script, set the following values for the first two constants: - `ORIGIN_HOSTNAME`: the hostname of your GitLab installation. diff --git a/doc/administration/terraform_state.md b/doc/administration/terraform_state.md index 8d3ddc4e306..76e54acce16 100644 --- a/doc/administration/terraform_state.md +++ b/doc/administration/terraform_state.md @@ -26,7 +26,6 @@ below. `/etc/gitlab/gitlab.rb` and add the following line: ```ruby - gitlab_rails['terraform_state_enabled'] = true gitlab_rails['terraform_state_storage_path'] = "/mnt/storage/terraform_state" ``` @@ -76,7 +75,6 @@ See [the available connection settings for different providers](object_storage.m the values you want: ```ruby - gitlab_rails['terraform_state_enabled'] = true gitlab_rails['terraform_state_object_store_enabled'] = true gitlab_rails['terraform_state_object_store_remote_directory'] = "terraform" gitlab_rails['terraform_state_object_store_connection'] = { diff --git a/doc/administration/troubleshooting/debug.md b/doc/administration/troubleshooting/debug.md index 55fd6462bc3..5daf34c1011 100644 --- a/doc/administration/troubleshooting/debug.md +++ b/doc/administration/troubleshooting/debug.md @@ -7,6 +7,10 @@ in production. Troubleshooting and debugging your GitLab instance often requires a [Rails console](https://guides.rubyonrails.org/command_line.html#rails-console). +See also: + +- [GitLab Rails Console Cheat Sheet](gitlab_rails_cheat_sheet.md). +- [Navigating GitLab via Rails console](navigating_gitlab_via_rails_console.md). **For Omnibus installations** @@ -73,7 +77,7 @@ sudo gitlab-rails runner "RAILS_COMMAND" # Example with a two-line Ruby script sudo gitlab-rails runner "user = User.first; puts user.username" -# Example with a ruby script file +# Example with a ruby script file (make sure to use the full path) sudo gitlab-rails runner /path/to/script.rb ``` @@ -85,7 +89,7 @@ sudo -u git -H bundle exec rails runner -e production "RAILS_COMMAND" # Example with a two-line Ruby script sudo -u git -H bundle exec rails runner -e production "user = User.first; puts user.username" -# Example with a ruby script file +# Example with a ruby script file (make sure to use the full path) sudo -u git -H bundle exec rails runner -e production /path/to/script.rb ``` diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md index 8e9749fb239..22d699b424b 100644 --- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md +++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md @@ -167,7 +167,7 @@ user = User.find_by_username('root') # Find the project, update the xxx-changeme values from above project = Project.find_by_full_path('group-changeme/project-changeme') -# Delete the project +# Immediately delete the project ::Projects::DestroyService.new(project, user, {}).execute ``` @@ -248,7 +248,8 @@ end A Projects Wiki can be recreated by -**Note:** This is a destructive operation, the Wiki will be empty +NOTE: **Note:** +This is a destructive operation, the Wiki will be empty. ```ruby p = Project.find_by_full_path('/') ### enter your projects path @@ -689,10 +690,10 @@ end As a GitLab administrator, you may need to reduce disk space consumption. A common culprit is Docker Registry images that are no longer in use. To find the storage broken down by each project, run the following in the -GitLab Rails console: +[GitLab Rails console](../troubleshooting/navigating_gitlab_via_rails_console.md): ```ruby -projects_and_size = [] +projects_and_size = [["project_id", "creator_id", "registry_size_bytes", "project path"]] # You need to specify the projects that you want to look through. You can get these in any manner. projects = Project.last(100) @@ -707,17 +708,21 @@ projects.each do |p| end if project_total_size > 0 - projects_and_size << [p.full_path,project_total_size] + projects_and_size << [p.project_id, p.creator.id, project_total_size, p.full_path] end end # projects_and_size is filled out now # maybe print it as comma separated output? projects_and_size.each do |ps| - puts "%s,%s" % ps + puts "%s,%s,%s,%s" % ps end ``` +### Run the Cleanup policy now + +Find this content in the [Container Registry troubleshooting docs](../packages/container_registry.md#run-the-cleanup-policy-now). + ## Sidekiq This content has been moved to the [Troubleshooting Sidekiq docs](./sidekiq.md). @@ -831,19 +836,19 @@ Geo::JobArtifactRegistry.synced.missing_on_primary.pluck(:artifact_id) #### Get the number of verification failed repositories ```ruby -Geo::ProjectRegistryFinder.new.count_verification_failed_repositories +Geo::ProjectRegistry.verification_failed('repository').count ``` #### Find the verification failed repositories ```ruby -Geo::ProjectRegistry.verification_failed_repos +Geo::ProjectRegistry.verification_failed('repository') ``` ### Find repositories that failed to sync ```ruby -Geo::ProjectRegistryFinder.new.find_failed_project_registries('repository') +Geo::ProjectRegistry.sync_failed('repository') ``` ### Resync repositories diff --git a/doc/administration/troubleshooting/group_saml_scim.md b/doc/administration/troubleshooting/group_saml_scim.md index e2ce72d5a16..7492688ded0 100644 --- a/doc/administration/troubleshooting/group_saml_scim.md +++ b/doc/administration/troubleshooting/group_saml_scim.md @@ -2,7 +2,7 @@ type: reference --- -# Group SAML and SCIM troubleshooting **(SILVER ONLY)** +# Troubleshooting Group SAML and SCIM **(SILVER ONLY)** These are notes and screenshots regarding Group SAML and SCIM that the GitLab Support Team sometimes uses while troubleshooting, but which do not fit into the official documentation. GitLab is making this public, so that anyone can make use of the Support team’s collected knowledge. diff --git a/doc/administration/troubleshooting/img/network_monitor_xid.png b/doc/administration/troubleshooting/img/network_monitor_xid.png new file mode 100644 index 00000000000..5392f77327f Binary files /dev/null and b/doc/administration/troubleshooting/img/network_monitor_xid.png differ diff --git a/doc/administration/troubleshooting/postgresql.md b/doc/administration/troubleshooting/postgresql.md index 36c1f20818a..b7e33e4501d 100644 --- a/doc/administration/troubleshooting/postgresql.md +++ b/doc/administration/troubleshooting/postgresql.md @@ -57,7 +57,7 @@ This section is for links to information elsewhere in the GitLab documentation. - [GitLab database requirements](../../install/requirements.md#database) including - Support for MySQL was removed in GitLab 12.1; [migrate to PostgreSQL](../../update/mysql_to_postgresql.md) - required extension `pg_trgm` - - required extension `postgres_fdw` for Geo + - required extension `btree_gist` - Errors like this in the `production/sidekiq` log; see: [Set default_transaction_isolation into read committed](https://docs.gitlab.com/omnibus/settings/database.html#set-default_transaction_isolation-into-read-committed): @@ -84,7 +84,7 @@ This section is for links to information elsewhere in the GitLab documentation. PANIC: could not write to file ‘pg_xlog/xlogtemp.123’: No space left on device ``` -- [Checking Geo configuration](../geo/replication/troubleshooting.md#checking-configuration) including +- [Checking Geo configuration](../geo/replication/troubleshooting.md) including - reconfiguring hosts/ports - checking and fixing user/password mappings diff --git a/doc/administration/troubleshooting/sidekiq.md b/doc/administration/troubleshooting/sidekiq.md index 566e2686735..9125ddf545f 100644 --- a/doc/administration/troubleshooting/sidekiq.md +++ b/doc/administration/troubleshooting/sidekiq.md @@ -7,16 +7,18 @@ may be filling up. Users will notice when this happens because new branches may not show up and merge requests may not be updated. The following are some troubleshooting steps that will help you diagnose the bottleneck. -> **Note:** GitLab administrators/users should consider working through these -> debug steps with GitLab Support so the backtraces can be analyzed by our team. -> It may reveal a bug or necessary improvement in GitLab. -> -> **Note:** In any of the backtraces, be wary of suspecting cases where every -> thread appears to be waiting in the database, Redis, or waiting to acquire -> a mutex. This **may** mean there's contention in the database, for example, -> but look for one thread that is different than the rest. This other thread -> may be using all available CPU, or have a Ruby Global Interpreter Lock, -> preventing other threads from continuing. +NOTE **Note:** +GitLab administrators/users should consider working through these +debug steps with GitLab Support so the backtraces can be analyzed by our team. +It may reveal a bug or necessary improvement in GitLab. + +NOTE: **Note:** +In any of the backtraces, be wary of suspecting cases where every +thread appears to be waiting in the database, Redis, or waiting to acquire +a mutex. This **may** mean there's contention in the database, for example, +but look for one thread that is different than the rest. This other thread +may be using all available CPU, or have a Ruby Global Interpreter Lock, +preventing other threads from continuing. ## Log arguments to Sidekiq jobs diff --git a/doc/administration/troubleshooting/tracing_correlation_id.md b/doc/administration/troubleshooting/tracing_correlation_id.md new file mode 100644 index 00000000000..31f537beae5 --- /dev/null +++ b/doc/administration/troubleshooting/tracing_correlation_id.md @@ -0,0 +1,126 @@ +--- +type: reference +--- + +# Finding relevant log entries with a correlation ID + +Since GitLab 11.6, a unique request tracking ID, known as the "correlation ID" has been +logged by the GitLab instance for most requests. Each individual request to GitLab gets +its own correlation ID, which then gets logged in each GitLab component's logs for that +request. This makes it easier to trace behavior in a +distributed system. Without this ID it can be difficult or +impossible to match correlating log entries. + +## Identify the correlation ID for a request + +The correlation ID is logged in structured logs under the key `correlation_id` +and in all response headers GitLab sends under the header `x-request-id`. +You can find your correlation ID by searching in either place. + +### Getting the correlation ID in your browser + +You can use your browser's developer tools to monitor and inspect network +activity with the site that you're visiting. See the links below for network monitoring +documenation for some popular browsers. + +- [Network Monitor - Firefox Developer Tools](https://developer.mozilla.org/en-US/docs/Tools/Network_Monitor) +- [Inspect Network Activity In Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/network/) +- [Safari Web Development Tools](https://developer.apple.com/safari/tools/) +- [Microsoft Edge Network panel](https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide/network#request-details) + +To locate a relevant request and view its correlation ID: + +1. Enable persistent logging in your network monitor. Some actions in GitLab will redirect you quickly after you submit a form, so this will help capture all relevant activity. +1. To help isolate the requests you are looking for, you can filter for `document` requests. +1. Click the request of interest to view further detail. +1. Go to the **Headers** section and look for **Response Headers**. There you should find an `x-request-id` header with a +value that was randomly generated by GitLab for the request. + +See the following example: + +![Firefox's network monitor showing an request id header](img/network_monitor_xid.png) + +### Getting the correlation ID from your logs + +Another approach to finding the correct correlation ID is to search or watch +your logs and find the `correlation_id` value for the log entry that you're +watching for. + +For example, let's say that you want learn what's happening or breaking when +you reproduce an action in GitLab. You could tail the GitLab logs, filtering +to requests by your user, and then watch the requests until you see what you're +interested in. + +### Getting the correlation ID from curl + +If you're using `curl` then you can use the verbose option to show request and response headers, as well as other debug info. + +```shell +➜ ~ curl --verbose https://gitlab.example.com/api/v4/projects +# look for a line that looks like this +< x-request-id: 4rAMkV3gof4 +``` + +#### Using jq + +This example uses [jq](https://stedolan.github.io/jq/) to filter results and +display values we most likely care about. + +```shell +sudo gitlab-ctl tail gitlab-rails/production_json.log | jq 'select(.username == "bob") | "User: \(.username), \(.method) \(.path), \(.controller)#\(.action), ID: \(.correlation_id)"' +``` + +```plaintext +"User: bob, GET /root/linux, ProjectsController#show, ID: U7k7fh6NpW3" +"User: bob, GET /root/linux/commits/master/signatures, Projects::CommitsController#signatures, ID: XPIHpctzEg1" +"User: bob, GET /root/linux/blob/master/README, Projects::BlobController#show, ID: LOt9hgi1TV4" +``` + +#### Using grep + +This example uses only `grep` and `tr`, which are more likely to be installed than `jq`. + +```shell +sudo gitlab-ctl tail gitlab-rails/production_json.log | grep '"username":"bob"' | tr ',' '\n' | egrep 'method|path|correlation_id' +``` + +```plaintext +{"method":"GET" +"path":"/root/linux" +"username":"bob" +"correlation_id":"U7k7fh6NpW3"} +{"method":"GET" +"path":"/root/linux/commits/master/signatures" +"username":"bob" +"correlation_id":"XPIHpctzEg1"} +{"method":"GET" +"path":"/root/linux/blob/master/README" +"username":"bob" +"correlation_id":"LOt9hgi1TV4"} +``` + +## Searching your logs for the correlation ID + +Once you have the correlation ID you can start searching for relevant log +entries. You can filter the lines by the correlation ID itself. +Combining a `find` and `grep` should be sufficient to find the entries you are looking for. + +```shell +# find -type f -mtime -0 exec grep '' '{}' '+' +find /var/log/gitlab -type f -mtime 0 -exec grep 'LOt9hgi1TV4' '{}' '+' +``` + +```plaintext +/var/log/gitlab/gitlab-workhorse/current:{"correlation_id":"LOt9hgi1TV4","duration_ms":2478,"host":"gitlab.domain.tld","level":"info","method":"GET","msg":"access","proto":"HTTP/1.1","referrer":"https://gitlab.domain.tld/root/linux","remote_addr":"68.0.116.160:0","remote_ip":"[filtered]","status":200,"system":"http","time":"2019-09-17T22:17:19Z","uri":"/root/linux/blob/master/README?format=json\u0026viewer=rich","user_agent":"Mozilla/5.0 (Mac) Gecko Firefox/69.0","written_bytes":1743} +/var/log/gitlab/gitaly/current:{"correlation_id":"LOt9hgi1TV4","grpc.code":"OK","grpc.meta.auth_version":"v2","grpc.meta.client_name":"gitlab-web","grpc.method":"FindCommits","grpc.request.deadline":"2019-09-17T22:17:47Z","grpc.request.fullMethod":"/gitaly.CommitService/FindCommits","grpc.request.glProjectPath":"root/linux","grpc.request.glRepository":"project-1","grpc.request.repoPath":"@hashed/6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b.git","grpc.request.repoStorage":"default","grpc.request.topLevelGroup":"@hashed","grpc.service":"gitaly.CommitService","grpc.start_time":"2019-09-17T22:17:17Z","grpc.time_ms":2319.161,"level":"info","msg":"finished streaming call with code OK","peer.address":"@","span.kind":"server","system":"grpc","time":"2019-09-17T22:17:19Z"} +/var/log/gitlab/gitlab-rails/production_json.log:{"method":"GET","path":"/root/linux/blob/master/README","format":"json","controller":"Projects::BlobController","action":"show","status":200,"duration":2448.77,"view":0.49,"db":21.63,"time":"2019-09-17T22:17:19.800Z","params":[{"key":"viewer","value":"rich"},{"key":"namespace_id","value":"root"},{"key":"project_id","value":"linux"},{"key":"id","value":"master/README"}],"remote_ip":"[filtered]","user_id":2,"username":"bob","ua":"Mozilla/5.0 (Mac) Gecko Firefox/69.0","queue_duration":3.38,"gitaly_calls":1,"gitaly_duration":0.77,"rugged_calls":4,"rugged_duration_ms":28.74,"correlation_id":"LOt9hgi1TV4"} +``` + +### Searching in distributed architectures + +If you have done some horizontal scaling in your GitLab infrastructure, then +you will need to search across _all_ of your GitLab nodes. You can do this with +some sort of log aggregation software like Loki, ELK, Splunk, or others. + +You can use a tool like Ansible or PSSH (parellel SSH) that can execute identical commands across your servers in +parallel, or craft your own solution. diff --git a/doc/administration/wikis/index.md b/doc/administration/wikis/index.md new file mode 100644 index 00000000000..077b4f064dc --- /dev/null +++ b/doc/administration/wikis/index.md @@ -0,0 +1,75 @@ +--- +type: reference, howto +stage: Create +group: Knowledge +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- + +# Wiki settings **(CORE ONLY)** + +Adjust the wiki settings of your GitLab instance. + +## Wiki page content size limit + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31176) in GitLab 13.2. + +You can set a maximum content size limit for wiki pages. This limit can prevent +abuse of the feature. The default value is **52428800 Bytes** (50 MB). + +### How does it work? + +The content size limit will be applied when a wiki page is created or updated +through the GitLab UI or API. Local changes pushed via Git will not be validated. + +In order not to break any existing wiki pages, the limit doesn't have any +effect on them until a wiki page is edited again and the content changes. + +### Wiki page content size limit configuration + +This setting is not available through the [Admin Area settings](../../user/admin_area/settings/index.md). +In order to configure this setting, use either the Rails console +or the [Application settings API](../../api/settings.md). + +NOTE: **Note:** +The value of the limit **must** be in bytes. The minimum value is 1024 bytes. + +#### Through the Rails console + +The steps to configure this setting through the Rails console are: + +1. Start the Rails console: + + ```shell + # For Omnibus installations + sudo gitlab-rails console + + # For installations from source + sudo -u git -H bundle exec rails console -e production + ``` + +1. Update the wiki page maximum content size: + + ```ruby + ApplicationSetting.first.update!(wiki_page_max_content_bytes: 50.megabytes) + ``` + +To retrieve the current value, start the Rails console and run: + + ```ruby + Gitlab::CurrentSettings.wiki_page_max_content_bytes + ``` + +#### Through the API + +The process to set the wiki page size limit through the Application Settings API is +exactly the same as you would do to [update any other setting](../../api/settings.md#change-application-settings). + +```shell +curl --request PUT --header "PRIVATE-TOKEN: " https://gitlab.example.com/api/v4/application/settings?wiki_page_max_content_bytes=52428800 +``` + +You can also use the API to [retrieve the current value](../../api/settings.md#get-current-application-settings). + +```shell +curl --header "PRIVATE-TOKEN: " https://gitlab.example.com/api/v4/application/settings +``` diff --git a/doc/api/README.md b/doc/api/README.md index b07f14b5a7a..82cce57f47b 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -156,7 +156,7 @@ for example, without needing to explicitly pass an access token. With a few API endpoints you can use a [GitLab CI/CD job token](../user/project/new_ci_build_permissions_model.md#job-token) to authenticate with the API: -- [Get job artifacts](jobs.md#get-job-artifacts) +- [Get job artifacts](job_artifacts.md#get-job-artifacts) - [Pipeline triggers](pipeline_triggers.md) - [Release creation](releases/index.md#create-a-release) @@ -218,6 +218,7 @@ Only available to [administrators](../user/permissions.md). All API requests support performing an API call as if you were another user, provided you are authenticated as an administrator with an OAuth or Personal Access Token that has the `sudo` scope. +The API requests are executed with the permissions of the impersonated user. You need to pass the `sudo` parameter either via query string or a header with an ID/username of the user you want to perform the operation as. If passed as a header, the @@ -337,10 +338,10 @@ In the example below, we list 50 [namespaces](namespaces.md) per page. curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/namespaces?per_page=50" ``` -#### Pagination Link header +#### Pagination `Link` header -[Link headers](https://www.w3.org/wiki/LinkHeader) are sent back with each -response. They have `rel` set to prev/next/first/last and contain the relevant +[`Link` headers](https://www.w3.org/wiki/LinkHeader) are sent back with each +response. They have `rel` set to `prev`/`next`/`first`/`last` and contain the relevant URL. Please use these links instead of generating your own URLs. In the cURL example below, we limit the output to 3 items per page (`per_page=3`) @@ -423,12 +424,14 @@ Status: 200 OK ``` CAUTION: **Deprecation:** -The `Links` Header will be removed in GitLab 14.0 to be aligned with the [W3C `Link` specification](https://www.w3.org/wiki/LinkHeader) +The `Links` header will be removed in GitLab 14.0 to be aligned with the [W3C `Link` specification](https://www.w3.org/wiki/LinkHeader). +The `Link` header was [added in GitLab 13.1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33714) +and should be used instead. The link to the next page contains an additional filter `id_after=42` which excludes records we have retrieved already. Note the type of filter depends on the `order_by` option used and we may have more than one additional filter. -When the end of the collection has been reached and there are no additional records to retrieve, the `Links` header is absent and the resulting array is empty. +When the end of the collection has been reached and there are no additional records to retrieve, the `Link` header is absent and the resulting array is empty. We recommend using only the given link to retrieve the next page instead of building your own URL. Apart from the headers shown, we don't expose additional pagination headers. @@ -544,7 +547,7 @@ https://gitlab.example.com/api/v4/projects/import ### Array of hashes -`variables` is a parameter of type `array` containing hash key/value pairs `[{ 'key' => 'UPLOAD_TO_S3', 'value' => 'true' }]`: +`variables` is a parameter of type `array` containing hash key/value pairs `[{ 'key': 'UPLOAD_TO_S3', 'value': 'true' }]`: ```shell curl --globoff --request POST --header "PRIVATE-TOKEN: " \ diff --git a/doc/api/access_requests.md b/doc/api/access_requests.md index 53198d05b46..c133a362788 100644 --- a/doc/api/access_requests.md +++ b/doc/api/access_requests.md @@ -1,6 +1,13 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Group and project access requests API - >**Note:** This feature was introduced in GitLab 8.11 +> Introduced in GitLab 8.11. ## Valid access levels diff --git a/doc/api/admin_sidekiq_queues.md b/doc/api/admin_sidekiq_queues.md index 32d336e79fe..5c841ae4076 100644 --- a/doc/api/admin_sidekiq_queues.md +++ b/doc/api/admin_sidekiq_queues.md @@ -1,6 +1,6 @@ # Admin Sidekiq queues API -> **Note:** This feature was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25998) in GitLab 12.9 +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25998) in GitLab 12.9 Delete jobs from a Sidekiq queue that match the given [metadata](../development/logging.md#logging-context-metadata-through-rails-or-grape-requests). diff --git a/doc/api/api_resources.md b/doc/api/api_resources.md index e93dfed3b1f..886f2e990f0 100644 --- a/doc/api/api_resources.md +++ b/doc/api/api_resources.md @@ -46,7 +46,7 @@ The following API resources are available in the project context: | [Merge requests](merge_requests.md) | `/projects/:id/merge_requests` (also available for groups and standalone) | | [Notes](notes.md) (comments) | `/projects/:id/issues/.../notes`, `/projects/:id/snippets/.../notes`, `/projects/:id/merge_requests/.../notes` (also available for groups) | | [Notification settings](notification_settings.md) | `/projects/:id/notification_settings` (also available for groups and standalone) | -| [Packages](packages.md) **(PREMIUM)** | `/projects/:id/packages` | +| [Packages](packages.md) | `/projects/:id/packages` | | [Pages domains](pages_domains.md) | `/projects/:id/pages` (also available standalone) | | [Pipelines](pipelines.md) | `/projects/:id/pipelines` | | [Pipeline schedules](pipeline_schedules.md) | `/projects/:id/pipeline_schedules` | @@ -140,6 +140,7 @@ The following API resources are available outside of project and group contexts | [Namespaces](namespaces.md) | `/namespaces` | | [Notification settings](notification_settings.md) | `/notification_settings` (also available for groups and projects) | | [Pages domains](pages_domains.md) | `/pages/domains` (also available for projects) | +| [Personal access tokens](personal_access_tokens.md) | `/personal_access_tokens` | | [Projects](projects.md) | `/users/:id/projects` (also available for projects) | | [Project repository storage moves](project_repository_storage_moves.md) **(CORE ONLY)** | `/project_repository_storage_moves` | | [Runners](runners.md) | `/runners` (also available for projects) | diff --git a/doc/api/branches.md b/doc/api/branches.md index 7a64f62189e..fbb5368cabc 100644 --- a/doc/api/branches.md +++ b/doc/api/branches.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Branches API This API operates on [repository branches](../user/project/repository/branches/index.md). diff --git a/doc/api/commits.md b/doc/api/commits.md index 9be4ce4fcdb..da95e9a943f 100644 --- a/doc/api/commits.md +++ b/doc/api/commits.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Commits API ## List repository commits @@ -292,9 +299,10 @@ Parameters: | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | | `sha` | string | yes | The commit hash | | `branch` | string | yes | The name of the branch | +| `dry_run` | boolean | no | Does not commit any changes. Default is false. [Introduced in GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/231032) | ```shell curl --request POST --header "PRIVATE-TOKEN: " --form "branch=master" "https://gitlab.example.com/api/v4/projects/5/repository/commits/master/cherry_pick" @@ -338,6 +346,19 @@ indicates that the commit already exists in the target branch. The other possible error code is `conflict`, which indicates that there was a merge conflict. +When `dry_run` is enabled, the server will attempt to apply the cherry-pick _but +not actually commit any resulting changes_. If the cherry-pick applies cleanly, +the API will respond with `200 OK`: + +```json +{ + "dry_run": "success" +} +``` + +In the event of a failure, you'll see an error identical to a failure without +dry run. + ## Revert a commit > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22919) in GitLab 11.5. @@ -355,6 +376,7 @@ Parameters: | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) | | `sha` | string | yes | Commit SHA to revert | | `branch` | string | yes | Target branch name | +| `dry_run` | boolean | no | Does not commit any changes. Default is false. [Introduced in GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/231032) | ```shell curl --request POST --header "PRIVATE-TOKEN: " --form "branch=master" "https://gitlab.example.com/api/v4/projects/5/repository/commits/a738f717824ff53aebad8b090c1b79a14f2bd9e8/revert" @@ -393,6 +415,19 @@ In this case, the revert failed because the attempted revert generated a merge conflict. The other possible error code is `empty`, which indicates that the changeset was empty, likely due to the change having already been reverted. +When `dry_run` is enabled, the server will attempt to apply the revert _but not +actually commit any resulting changes_. If the revert applies cleanly, the API +will respond with `200 OK`: + +```json +{ + "dry_run": "success" +} +``` + +In the event of a failure, you'll see an error identical to a failure without +dry run. + ## Get the diff of a commit Get the diff of a commit in a project. diff --git a/doc/api/discussions.md b/doc/api/discussions.md index aa1a691a8f8..b9feef843b1 100644 --- a/doc/api/discussions.md +++ b/doc/api/discussions.md @@ -1,7 +1,8 @@ --- -stage: Plan -group: Project Management +stage: Create +group: Source Code info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +type: reference, api --- # Discussions API diff --git a/doc/api/environments.md b/doc/api/environments.md index 2287ec9aad2..8b900ad2fd3 100644 --- a/doc/api/environments.md +++ b/doc/api/environments.md @@ -34,7 +34,7 @@ Example response: "id": 1, "name": "review/fix-foo", "slug": "review-fix-foo-dfjre3", - "external_url": "https://review-fix-foo-dfjre3.example.gitlab.com", + "external_url": "https://review-fix-foo-dfjre3.gitlab.example.com", "state": "available" } ] @@ -62,7 +62,7 @@ Example of response "id": 1, "name": "review/fix-foo", "slug": "review-fix-foo-dfjre3", - "external_url": "https://review-fix-foo-dfjre3.example.gitlab.com" + "external_url": "https://review-fix-foo-dfjre3.gitlab.example.com", "state": "available", "last_deployment": { "id": 100, @@ -78,7 +78,7 @@ Example of response "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", "web_url": "http://localhost:3000/root" - } + }, "deployable": { "id": 710, "status": "success", @@ -107,7 +107,7 @@ Example of response "twitter": "", "website_url": "", "organization": null - } + }, "commit": { "id": "416d8ea11849050d3d1f5104cf8cf51053e790ab", "short_id": "416d8ea1", @@ -164,7 +164,7 @@ POST /projects/:id/environments | `external_url` | string | no | Place to link to for this environment | ```shell -curl --data "name=deploy&external_url=https://deploy.example.gitlab.com" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/environments" +curl --data "name=deploy&external_url=https://deploy.gitlab.example.com" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/environments" ``` Example response: @@ -174,7 +174,7 @@ Example response: "id": 1, "name": "deploy", "slug": "deploy", - "external_url": "https://deploy.example.gitlab.com", + "external_url": "https://deploy.gitlab.example.com", "state": "available" } ``` @@ -197,7 +197,7 @@ PUT /projects/:id/environments/:environments_id | `external_url` | string | no | The new `external_url` | ```shell -curl --request PUT --data "name=staging&external_url=https://staging.example.gitlab.com" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/environments/1" +curl --request PUT --data "name=staging&external_url=https://staging.gitlab.example.com" --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/environments/1" ``` Example response: @@ -207,7 +207,7 @@ Example response: "id": 1, "name": "staging", "slug": "staging", - "external_url": "https://staging.example.gitlab.com", + "external_url": "https://staging.gitlab.example.com", "state": "available" } ``` @@ -253,7 +253,7 @@ Example response: "id": 1, "name": "deploy", "slug": "deploy", - "external_url": "https://deploy.example.gitlab.com", + "external_url": "https://deploy.gitlab.example.com", "state": "stopped" } ``` diff --git a/doc/api/epic_links.md b/doc/api/epic_links.md index 1d54bfe01e3..a2477123ce4 100644 --- a/doc/api/epic_links.md +++ b/doc/api/epic_links.md @@ -1,7 +1,6 @@ # Epic Links API **(ULTIMATE)** ->**Note:** -> This endpoint was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9188) in GitLab 11.8. +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9188) in GitLab 11.8. Manages parent-child [epic relationships](../user/group/epics/index.md#multi-level-child-epics-ultimate). diff --git a/doc/api/epics.md b/doc/api/epics.md index fcdbb8cea71..45bf406dec2 100644 --- a/doc/api/epics.md +++ b/doc/api/epics.md @@ -92,7 +92,7 @@ Example response: "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "state": "opened", "confidential": "false", - "web_url": "http://localhost:3001/groups/test/-/epics/4", + "web_url": "http://gitlab.example.com/groups/test/-/epics/4", "reference": "&4", "references": { "short": "&4", @@ -105,7 +105,7 @@ Example response: "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", - "web_url": "http://localhost:3001/kam" + "web_url": "http://gitlab.example.com/kam" }, "start_date": null, "start_date_is_fixed": false, @@ -123,7 +123,12 @@ Example response: "closed_at": "2018-08-18T12:22:05.239Z", "labels": [], "upvotes": 4, - "downvotes": 0 + "downvotes": 0, + "_links":{ + "self": "http://gitlab.example.com/api/v4/groups/7/epics/4", + "epic_issues": "http://gitlab.example.com/api/v4/groups/7/epics/4/issues", + "group":"http://gitlab.example.com/api/v4/groups/7" + } }, { "id": 50, @@ -133,7 +138,7 @@ Example response: "title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "state": "opened", - "web_url": "http://localhost:3001/groups/test/sample/-/epics/4", + "web_url": "http://gitlab.example.com/groups/test/sample/-/epics/35", "reference": "&4", "references": { "short": "&4", @@ -146,7 +151,7 @@ Example response: "username": "kam", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/018729e129a6f31c80a6327a30196823?s=80&d=identicon", - "web_url": "http://localhost:3001/kam" + "web_url": "http://gitlab.example.com/kam" }, "start_date": null, "start_date_is_fixed": false, @@ -164,7 +169,12 @@ Example response: "closed_at": "2018-08-18T12:22:05.239Z", "labels": [], "upvotes": 4, - "downvotes": 0 + "downvotes": 0, + "_links":{ + "self": "http://gitlab.example.com/api/v4/groups/17/epics/35", + "epic_issues": "http://gitlab.example.com/api/v4/groups/17/epics/35/issues", + "group":"http://gitlab.example.com/api/v4/groups/17" + } } ] ``` @@ -196,7 +206,7 @@ Example response: "title": "Ea cupiditate dolores ut vero consequatur quasi veniam voluptatem et non.", "description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.", "state": "opened", - "web_url": "http://localhost:3001/groups/test/-/epics/5", + "web_url": "http://gitlab.example.com/groups/test/-/epics/5", "reference": "&5", "references": { "short": "&5", @@ -209,7 +219,7 @@ Example response: "username": "arnita", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", - "web_url": "http://localhost:3001/arnita" + "web_url": "http://gitlab.example.com/arnita" }, "start_date": null, "start_date_is_fixed": false, @@ -228,7 +238,12 @@ Example response: "labels": [], "upvotes": 4, "downvotes": 0, - "subscribed": true + "subscribed": true, + "_links":{ + "self": "http://gitlab.example.com/api/v4/groups/7/epics/5", + "epic_issues": "http://gitlab.example.com/api/v4/groups/7/epics/5/issues", + "group":"http://gitlab.example.com/api/v4/groups/7" + } } ``` @@ -273,7 +288,7 @@ Example response: "description": "Epic description", "state": "opened", "confidential": "false", - "web_url": "http://localhost:3001/groups/test/-/epics/6", + "web_url": "http://gitlab.example.com/groups/test/-/epics/6", "reference": "&6", "references": { "short": "&6", @@ -304,7 +319,12 @@ Example response: "closed_at": "2018-08-18T12:22:05.239Z", "labels": [], "upvotes": 4, - "downvotes": 0 + "downvotes": 0, + "_links":{ + "self": "http://gitlab.example.com/api/v4/groups/7/epics/6", + "epic_issues": "http://gitlab.example.com/api/v4/groups/7/epics/6/issues", + "group":"http://gitlab.example.com/api/v4/groups/7" + } } ``` @@ -350,7 +370,7 @@ Example response: "description": "Epic description", "state": "opened", "confidential": "false", - "web_url": "http://localhost:3001/groups/test/-/epics/6", + "web_url": "http://gitlab.example.com/groups/test/-/epics/6", "reference": "&6", "references": { "short": "&6", @@ -456,9 +476,9 @@ Example response: "username": "arnita", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/a2f5c6fcef64c9c69cb8779cb292be1b?s=80&d=identicon", - "web_url": "http://localhost:3001/arnita" + "web_url": "http://gitlab.example.com/arnita" }, - "web_url": "http://localhost:3001/groups/test/-/epics/5", + "web_url": "http://gitlab.example.com/groups/test/-/epics/5", "reference": "&5", "references": { "short": "&5", diff --git a/doc/api/error_tracking.md b/doc/api/error_tracking.md index 658480ce6fa..5bb5016d0fd 100644 --- a/doc/api/error_tracking.md +++ b/doc/api/error_tracking.md @@ -10,7 +10,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w ## Error Tracking project settings -The project settings API allows you to retrieve the Error Tracking settings for a project. Only for project maintainers. +The project settings API allows you to retrieve the [Error Tracking](../operations/error_tracking.md) +settings for a project. Only for project maintainers. ### Get Error Tracking settings diff --git a/doc/api/events.md b/doc/api/events.md index 99bb6d5af2b..3f4f11b9786 100644 --- a/doc/api/events.md +++ b/doc/api/events.md @@ -80,6 +80,7 @@ Example response: ```json [ { + "id": 1, "title":null, "project_id":1, "action_name":"opened", @@ -99,6 +100,7 @@ Example response: "author_username":"user3" }, { + "id": 2, "title":null, "project_id":1, "action_name":"opened", @@ -152,6 +154,7 @@ Example response: ```json [ { + "id": 3, "title": null, "project_id": 15, "action_name": "closed", @@ -170,6 +173,7 @@ Example response: "author_username": "root" }, { + "id": 4, "title": null, "project_id": 15, "action_name": "pushed", @@ -197,6 +201,7 @@ Example response: "target_title": null }, { + "id": 5, "title": null, "project_id": 15, "action_name": "closed", @@ -215,6 +220,7 @@ Example response: "author_username": "root" }, { + "id": 7, "title": null, "project_id": 15, "action_name": "commented on", @@ -255,7 +261,8 @@ Example response: ## List a Project's visible events ->**Note:** This endpoint has been around longer than the others. Documentation was formerly located in the [Projects API pages](projects.md). +NOTE: **Note:** +This endpoint has been around longer than the others. Documentation was formerly located in the [Projects API pages](projects.md). Get a list of visible events for a particular project. @@ -285,6 +292,7 @@ Example response: ```json [ { + "id": 8 "title":null, "project_id":1, "action_name":"opened", @@ -305,6 +313,7 @@ Example response: "author_username":"user3" }, { + "id": 9, "title":null, "project_id":1, "action_name":"opened", @@ -325,6 +334,7 @@ Example response: "author_username":"ted" }, { + "id": 10, "title": null, "project_id": 1, "action_name": "commented on", diff --git a/doc/api/feature_flags.md b/doc/api/feature_flags.md index 99303e23c37..479f82914a9 100644 --- a/doc/api/feature_flags.md +++ b/doc/api/feature_flags.md @@ -45,6 +45,7 @@ Example response: { "name":"merge_train", "description":"This feature is about merge train", + "active": true, "version": "new_version_flag", "created_at":"2019-11-04T08:13:51.423Z", "updated_at":"2019-11-04T08:13:51.423Z", @@ -68,6 +69,7 @@ Example response: { "name":"new_live_trace", "description":"This is a new live trace feature", + "active": true, "version": "new_version_flag", "created_at":"2019-11-04T08:13:10.507Z", "updated_at":"2019-11-04T08:13:10.507Z", @@ -94,13 +96,13 @@ Example response: Gets a single feature flag. ```plaintext -GET /projects/:id/feature_flags/:name +GET /projects/:id/feature_flags/:feature_flag_name ``` | Attribute | Type | Required | Description | | ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------| | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). | -| `name` | string | yes | The name of the feature flag. | +| `feature_flag_name` | string | yes | The name of the feature flag. | ```shell curl --header "PRIVATE-TOKEN: " https://gitlab.example.com/api/v4/projects/1/feature_flags/awesome_feature @@ -112,6 +114,7 @@ Example response: { "name": "awesome_feature", "description": null, + "active": true, "version": "new_version_flag", "created_at": "2020-05-13T19:56:33.119Z", "updated_at": "2020-05-13T19:56:33.119Z", @@ -146,6 +149,7 @@ POST /projects/:id/feature_flags | `name` | string | yes | The name of the feature flag. | | `version` | string | yes | The version of the feature flag. Must be `new_version_flag`. Omit or set to `legacy_flag` to create a [Legacy Feature Flag](feature_flags_legacy.md). | | `description` | string | no | The description of the feature flag. | +| `active` | boolean | no | The active state of the flag. Defaults to true. [Supported](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38350) in GitLab 13.3 and later. | | `strategies` | JSON | no | The feature flag [strategies](../operations/feature_flags.md#feature-flag-strategies). | | `strategies:name` | JSON | no | The strategy name. | | `strategies:parameters` | JSON | no | The strategy parameters. | @@ -171,6 +175,7 @@ Example response: { "name": "awesome_feature", "description": null, + "active": true, "version": "new_version_flag", "created_at": "2020-05-13T19:56:33.119Z", "updated_at": "2020-05-13T19:56:33.119Z", @@ -196,14 +201,16 @@ Example response: Updates a feature flag. ```plaintext -PUT /projects/:id/feature_flags/:name +PUT /projects/:id/feature_flags/:feature_flag_name ``` | Attribute | Type | Required | Description | | ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------| | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). | -| `name` | string | yes | The name of the feature flag. | +| `feature_flag_name` | string | yes | The current name of the feature flag. | | `description` | string | no | The description of the feature flag. | +| `active` | boolean | no | The active state of the flag. [Supported](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38350) in GitLab 13.3 and later. | +| `name` | string | no | The new name of the feature flag. [Supported](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38350) in GitLab 13.3 and later. | | `strategies` | JSON | no | The feature flag [strategies](../operations/feature_flags.md#feature-flag-strategies). | | `strategies:id` | JSON | no | The feature flag strategy id. | | `strategies:name` | JSON | no | The strategy name. | @@ -229,6 +236,7 @@ Example response: { "name": "awesome_feature", "description": null, + "active": true, "version": "new_version_flag", "created_at": "2020-05-13T20:10:32.891Z", "updated_at": "2020-05-13T20:10:32.891Z", @@ -268,13 +276,13 @@ Example response: Deletes a feature flag. ```plaintext -DELETE /projects/:id/feature_flags/:name +DELETE /projects/:id/feature_flags/:feature_flag_name ``` | Attribute | Type | Required | Description | | ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------| | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). | -| `name` | string | yes | The name of the feature flag. | +| `feature_flag_name` | string | yes | The name of the feature flag. | ```shell curl --header "PRIVATE-TOKEN: " --request DELETE "https://gitlab.example.com/api/v4/projects/1/feature_flags/awesome_feature" diff --git a/doc/api/feature_flags_legacy.md b/doc/api/feature_flags_legacy.md index 7e4fc47a1de..175261b3a7b 100644 --- a/doc/api/feature_flags_legacy.md +++ b/doc/api/feature_flags_legacy.md @@ -44,6 +44,7 @@ Example response: { "name":"merge_train", "description":"This feature is about merge train", + "active": true, "created_at":"2019-11-04T08:13:51.423Z", "updated_at":"2019-11-04T08:13:51.423Z", "scopes":[ @@ -97,6 +98,7 @@ Example response: { "name":"new_live_trace", "description":"This is a new live trace feature", + "active": true, "created_at":"2019-11-04T08:13:10.507Z", "updated_at":"2019-11-04T08:13:10.507Z", "scopes":[ @@ -163,6 +165,7 @@ POST /projects/:id/feature_flags | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). | | `name` | string | yes | The name of the feature flag. | | `description` | string | no | The description of the feature flag. | +| `active` | boolean | no | The active state of the flag. Defaults to true. [Supported](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38350) in GitLab 13.3 and later. | | `scopes` | JSON | no | The feature flag specs of the feature flag. | | `scopes:environment_scope` | string | no | The environment spec. | | `scopes:active` | boolean | no | Whether the spec is active. | @@ -187,6 +190,7 @@ Example response: { "name":"awesome_feature", "description":null, + "active": true, "created_at":"2019-11-04T08:32:27.288Z", "updated_at":"2019-11-04T08:32:27.288Z", "scopes":[ @@ -247,6 +251,7 @@ Example response: { "name":"new_live_trace", "description":"This is a new live trace feature", + "active": true, "created_at":"2019-11-04T08:13:10.507Z", "updated_at":"2019-11-04T08:13:10.507Z", "scopes":[ diff --git a/doc/api/geo_nodes.md b/doc/api/geo_nodes.md index 402170fba37..ba970d2cdb1 100644 --- a/doc/api/geo_nodes.md +++ b/doc/api/geo_nodes.md @@ -325,9 +325,11 @@ Example response: "design_repositories_failed_count": nil, "design_repositories_synced_in_percentage": "0.00%", "projects_count": 41, + "repositories_count": 41, "repositories_failed_count": nil, "repositories_synced_count": nil, "repositories_synced_in_percentage": "0.00%", + "wikis_count": 41, "wikis_failed_count": nil, "wikis_synced_count": nil, "wikis_synced_in_percentage": "0.00%", @@ -402,9 +404,11 @@ Example response: "design_repositories_failed_count": nil, "design_repositories_synced_in_percentage": "0.00%", "projects_count": 41, + "repositories_count": 41, "repositories_failed_count": 1, "repositories_synced_count": 40, "repositories_synced_in_percentage": "97.56%", + "wikis_count": 41, "wikis_failed_count": 0, "wikis_synced_count": 41, "wikis_synced_in_percentage": "100.00%", @@ -448,9 +452,6 @@ Example response: ] ``` -NOTE: **Note:** -In GitLab 12.0, deprecated fields `wikis_count` and `repositories_count` were removed. Use `projects_count` instead. - ## Retrieve status about a specific Geo node ```plaintext @@ -495,9 +496,11 @@ Example response: "design_repositories_failed_count": nil, "design_repositories_synced_in_percentage": "0.00%", "projects_count": 41, + "repositories_count": 41, "repositories_failed_count": 1, "repositories_synced_count": 40, "repositories_synced_in_percentage": "97.56%", + "wikis_count": 41, "wikis_failed_count": 0, "wikis_synced_count": 41, "wikis_synced_in_percentage": "100.00%", @@ -517,9 +520,6 @@ Example response: Note: The `health_status` parameter can only be in an "Healthy" or "Unhealthy" state, while the `health` parameter can be empty, "Healthy", or contain the actual error message. -NOTE: **Note:** -In GitLab 12.0, deprecated fields `wikis_count` and `repositories_count` were removed. Use `projects_count` instead. - ## Retrieve project sync or verification failures that occurred on the current node This only works on a secondary node. diff --git a/doc/api/graphql/audit_report.md b/doc/api/graphql/audit_report.md new file mode 100644 index 00000000000..36c3f44ff89 --- /dev/null +++ b/doc/api/graphql/audit_report.md @@ -0,0 +1,116 @@ +# Set up an Audit Report with GraphQL + +This page describes how you can use the GraphiQL explorer to set up an audit report +for a specific subset of users. + +You can run the same query directly via a HTTP endpoint, using `cURL`. For more information, see our +guidance on getting started from the [command line](getting_started.md#command-line). + +The [example users query](#set-up-the-graphiql-explorer) looks for a subset of users in +a GitLab instance either by username or +[Global ID](../../development/api_graphql_styleguide.md#global-ids). +The query includes: + +- [`pageInfo`](#pageinfo) +- [`nodes`](#nodes) + +## pageInfo + +This contains the data needed to implement pagination. GitLab uses cursor-based +[pagination](getting_started.md#pagination). For more information, see +[Pagination](https://graphql.org/learn/pagination/) in the GraphQL documentation. + +## nodes + +In a GraphQL query, `nodes` is used to represent a collection of [`nodes` on a graph](https://en.wikipedia.org/wiki/Vertex_(graph_theory)). +In this case, the collection of nodes is a collection of `User` objects. For each one, +we output: + +- Their user's `id`. +- The `membership` fragment, which represents a Project or Group membership belonging + to that user. Outputting a fragment is denoted with the `...memberships` notation. + +The GitLab GraphQL API is extensive and a large amount of data for a wide variety of entities can be output. +See the official [reference documentation](reference/index.md) for the most up-to-date information. + +## Set up the GraphiQL explorer + +This procedure presents a substantive example that you can copy and paste into GraphiQL +explorer. GraphiQL explorer is available for: + +- GitLab.com users at [https://gitlab.com/-/graphql-explorer](https://gitlab.com/-/graphql-explorer). +- Self-managed users at `https://gitlab.example.com/-/graphql-explorer`. + +1. Copy the following code excerpt: + + ```graphql + { + users(usernames: ["user1", "user2", "user3"]) { + pageInfo { + endCursor + startCursor + hasNextPage + } + nodes { + id + ...memberships + } + } + } + + fragment membership on MemberInterface { + createdAt + updatedAt + accessLevel { + integerValue + stringValue + } + createdBy { + id + } + } + + fragment memberships on User { + groupMemberships { + nodes { + ...membership + group { + id + name + } + } + } + + projectMemberships { + nodes { + ...membership + project { + id + name + } + } + } + } + ``` + +1. Open the [GraphiQL explorer tool](https://gitlab.com/-/graphql-explorer). +1. Paste the `query` listed above into the left window of your GraphiQL explorer tool. +1. Click Play to get the result shown here: + +![GraphiQL explorer search for boards](img/user_query_example_v13_2.png) + +NOTE: **Note:** +[The GraphQL API returns a GlobalID, rather than a standard ID.](getting_started.md#queries-and-mutations) It also expects a GlobalID as an input rather than +a single integer. + +This GraphQL query returns the groups and projects that the user has been *explicitly* made a member of. +Since the GraphiQL explorer uses the session token to authorize access to resources, +the output is limited to the projects and groups accessible to the currently signed-in user. + +If you've signed in as an instance administrator, you would have access to all records, regardless of ownership. + +For more information on: + +- GraphQL specific entities, such as Fragments and Interfaces, see the official + [GraphQL documentation](https://graphql.org/learn/). +- Individual attributes, see the [GraphQL API Resources](reference/index.md). diff --git a/doc/api/graphql/getting_started.md b/doc/api/graphql/getting_started.md index bf8a2120734..12665f68f25 100644 --- a/doc/api/graphql/getting_started.md +++ b/doc/api/graphql/getting_started.md @@ -59,8 +59,9 @@ The GitLab GraphQL API can be used to perform: - [Mutations](#mutations) for creating, updating, and deleting data. NOTE: **Note:** -In the GitLab GraphQL API, `id` generally refers to a global ID, -which is an object identifier in the format of `gid://gitlab/Issue/123`. +In the GitLab GraphQL API, `id` refers to a +[Global ID](https://graphql.org/learn/global-object-identification/), +which is an object identifier in the format of `"gid://gitlab/Issue/123"`. [GitLab's GraphQL Schema](reference/index.md) outlines which objects and fields are available for clients to query and their corresponding data types. diff --git a/doc/api/graphql/img/sample_issue_boards_v13_2.png b/doc/api/graphql/img/sample_issue_boards_v13_2.png new file mode 100644 index 00000000000..5afe5f5151a Binary files /dev/null and b/doc/api/graphql/img/sample_issue_boards_v13_2.png differ diff --git a/doc/api/graphql/img/user_query_example_v13_2.png b/doc/api/graphql/img/user_query_example_v13_2.png new file mode 100644 index 00000000000..270cf5da7fd Binary files /dev/null and b/doc/api/graphql/img/user_query_example_v13_2.png differ diff --git a/doc/api/graphql/index.md b/doc/api/graphql/index.md index d653c4e0f47..c513dea239a 100644 --- a/doc/api/graphql/index.md +++ b/doc/api/graphql/index.md @@ -14,7 +14,15 @@ For those new to the GitLab GraphQL API, see - Get an [introduction to GraphQL from graphql.org](https://graphql.org/). - GitLab supports a wide range of resources, listed in the [GraphQL API Reference](reference/index.md). -#### GraphiQL +### Examples + +To work with sample queries that pull data from public projects on GitLab.com, +see the menu options in the left-hand +documentation menu, under API > GraphQL at `https://docs.gitlab.com/ee/api/graphql/`. + +The [Getting started](getting_started.md) page includes different methods to customize GraphQL queries. + +### GraphiQL Explore the GraphQL API using the interactive [GraphiQL explorer](https://gitlab.com/-/graphql-explorer), or on your self-managed GitLab instance on diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql index 2ed6bec104d..1d920894eec 100644 --- a/doc/api/graphql/reference/gitlab_schema.graphql +++ b/doc/api/graphql/reference/gitlab_schema.graphql @@ -209,6 +209,11 @@ type AlertManagementAlert implements Noteable { """ details: JSON + """ + The URL of the alert detail page + """ + detailsUrl: String! + """ All discussions on this noteable """ @@ -294,6 +299,16 @@ type AlertManagementAlert implements Noteable { last: Int ): NoteConnection! + """ + The alert condition for Prometheus + """ + prometheusAlert: PrometheusAlert + + """ + Runbook for the alert as defined in alert details + """ + runbook: String + """ Service the alert came from """ @@ -319,6 +334,61 @@ type AlertManagementAlert implements Noteable { """ title: String + """ + Todos of the current user for the alert + """ + todos( + """ + The action to be filtered + """ + action: [TodoActionEnum!] + + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + The ID of an author + """ + authorId: [ID!] + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + The ID of a group + """ + groupId: [ID!] + + """ + Returns the last _n_ elements from the list. + """ + last: Int + + """ + The ID of a project + """ + projectId: [ID!] + + """ + The state of the todo + """ + state: [TodoStateEnum!] + + """ + The type of the todo + """ + type: [TodoTargetEnum!] + ): TodoConnection + """ Timestamp the alert was last updated """ @@ -873,6 +943,11 @@ type Blob implements Entry { """ type: EntryType! + """ + Web path of the blob + """ + webPath: String + """ Web URL of the blob """ @@ -927,6 +1002,51 @@ enum BlobViewersType { Represents a project or group board """ type Board { + """ + The board assignee. + """ + assignee: User + + """ + Epics associated with board issues. + """ + epics( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Filters applied when selecting issues on the board + """ + issueFilters: BoardEpicIssueInput + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): EpicConnection + + """ + Whether or not backlog list is hidden. + """ + hideBacklogList: Boolean + + """ + Whether or not closed list is hidden. + """ + hideClosedList: Boolean + """ ID (global ID) of the board """ @@ -951,19 +1071,29 @@ type Board { """ first: Int + """ + Find a list by its global ID + """ + id: ID + """ Returns the last _n_ elements from the list. """ last: Int ): BoardListConnection + """ + The board milestone. + """ + milestone: Milestone + """ Name of the board """ name: String """ - Weight of the board + Weight of the board. """ weight: Int } @@ -1003,6 +1133,58 @@ type BoardEdge { node: Board } +input BoardEpicIssueInput { + """ + Filter by assignee username + """ + assigneeUsername: [String] + + """ + Filter by author username + """ + authorUsername: String + + """ + Filter by epic ID + """ + epicId: String + + """ + Filter by label name + """ + labelName: [String] + + """ + Filter by milestone title + """ + milestoneTitle: String + + """ + Filter by reaction emoji + """ + myReactionEmoji: String + + """ + List of negated params. Warning: this argument is experimental and a subject to change in future + """ + not: NegatedBoardEpicIssueInput + + """ + Filter by release tag + """ + releaseTag: String + + """ + Filter by weight + """ + weight: String +} + +""" +Identifier of Board +""" +scalar BoardID + """ Represents a list for an issue board """ @@ -1022,6 +1204,36 @@ type BoardList { """ id: ID! + """ + Board issues + """ + issues( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): IssueConnection + + """ + Count of issues in the list + """ + issuesCount: Int + """ Label of the list """ @@ -1061,6 +1273,11 @@ type BoardList { Title of the list """ title: String! + + """ + Total weight of all issues in the list + """ + totalWeight: Int } """ @@ -1083,6 +1300,51 @@ type BoardListConnection { pageInfo: PageInfo! } +""" +Autogenerated input type of BoardListCreate +""" +input BoardListCreateInput { + """ + Create the backlog list + """ + backlog: Boolean + + """ + The Global ID of the issue board to mutate + """ + boardId: BoardID! + + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + ID of an existing label + """ + labelId: LabelID +} + +""" +Autogenerated return type of BoardListCreate +""" +type BoardListCreatePayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Errors encountered during execution of the mutation. + """ + errors: [String!]! + + """ + List of the issue board + """ + list: BoardList +} + """ An edge in a connection. """ @@ -1160,45 +1422,283 @@ type Branch { name: String! } -type Commit { +type CiGroup { """ - Author of the commit + Jobs in group """ - author: User + jobs( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): CiJobConnection """ - Commit authors gravatar + Name of the job group """ - authorGravatar: String + name: String """ - Commit authors name + Size of the group """ - authorName: String + size: Int +} +""" +The connection type for CiGroup. +""" +type CiGroupConnection { """ - Timestamp of when the commit was authored + A list of edges. """ - authoredDate: Time + edges: [CiGroupEdge] """ - Description of the commit message + A list of nodes. """ - description: String + nodes: [CiGroup] """ - ID (global ID) of the commit + Information to aid in pagination. """ - id: ID! + pageInfo: PageInfo! +} +""" +An edge in a connection. +""" +type CiGroupEdge { """ - Latest pipeline of the commit. Deprecated in 12.5: Use `pipelines` + A cursor for use in pagination. """ - latestPipeline( - """ - Filter pipelines by the ref they are run for - """ - ref: String + cursor: String! + + """ + The item at the end of the edge. + """ + node: CiGroup +} + +type CiJob { + """ + Name of the job + """ + name: String + + """ + Builds that must complete before the jobs run + """ + needs( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): CiJobConnection +} + +""" +The connection type for CiJob. +""" +type CiJobConnection { + """ + A list of edges. + """ + edges: [CiJobEdge] + + """ + A list of nodes. + """ + nodes: [CiJob] + + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! +} + +""" +An edge in a connection. +""" +type CiJobEdge { + """ + A cursor for use in pagination. + """ + cursor: String! + + """ + The item at the end of the edge. + """ + node: CiJob +} + +type CiStage { + """ + Group of jobs for the stage + """ + groups( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): CiGroupConnection + + """ + Name of the stage + """ + name: String +} + +""" +The connection type for CiStage. +""" +type CiStageConnection { + """ + A list of edges. + """ + edges: [CiStageEdge] + + """ + A list of nodes. + """ + nodes: [CiStage] + + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! +} + +""" +An edge in a connection. +""" +type CiStageEdge { + """ + A cursor for use in pagination. + """ + cursor: String! + + """ + The item at the end of the edge. + """ + node: CiStage +} + +type ClusterAgent { + """ + Timestamp the cluster agent was created + """ + createdAt: Time + + """ + ID of the cluster agent + """ + id: ID! + + """ + Name of the cluster agent + """ + name: String + + """ + The project this cluster agent is associated with + """ + project: Project + + """ + Timestamp the cluster agent was updated + """ + updatedAt: Time +} + +type Commit { + """ + Author of the commit + """ + author: User + + """ + Commit authors gravatar + """ + authorGravatar: String + + """ + Commit authors name + """ + authorName: String + + """ + Timestamp of when the commit was authored + """ + authoredDate: Time + + """ + Description of the commit message + """ + description: String + + """ + The GitLab Flavored Markdown rendering of `description` + """ + descriptionHtml: String + + """ + ID (global ID) of the commit + """ + id: ID! + + """ + Latest pipeline of the commit. Deprecated in 12.5: Use `pipelines` + """ + latestPipeline( + """ + Filter pipelines by the ref they are run for + """ + ref: String """ Filter pipelines by the sha of the commit they are run for @@ -1276,6 +1776,11 @@ type Commit { """ titleHtml: String + """ + Web path of the commit + """ + webPath: String! + """ Web URL of the commit """ @@ -1456,6 +1961,46 @@ type ComplianceFrameworkEdge { node: ComplianceFramework } +""" +Autogenerated input type of ConfigureSast +""" +input ConfigureSastInput { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Payload containing SAST variable values (https://docs.gitlab.com/ee/user/application_security/sast/#available-variables). + """ + configuration: JSON! + + """ + Full path of the project. + """ + projectPath: ID! +} + +""" +Autogenerated return type of ConfigureSast +""" +type ConfigureSastPayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Errors encountered during execution of the mutation. + """ + errors: [String!]! + + """ + JSON containing the status of MR creation. + """ + result: JSON +} + """ A tag expiration policy designed to keep only the images that matter most """ @@ -1742,6 +2287,46 @@ type CreateBranchPayload { errors: [String!]! } +""" +Autogenerated input type of CreateClusterAgent +""" +input CreateClusterAgentInput { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Name of the cluster agent + """ + name: String! + + """ + Full path of the associated project for this cluster agent + """ + projectPath: ID! +} + +""" +Autogenerated return type of CreateClusterAgent +""" +type CreateClusterAgentPayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Cluster agent created after mutation + """ + clusterAgent: ClusterAgent + + """ + Errors encountered during execution of the mutation. + """ + errors: [String!]! +} + """ Autogenerated input type of CreateDiffNote """ @@ -1944,7 +2529,12 @@ input CreateIterationInput { """ The target group for the iteration """ - groupPath: ID! + groupPath: ID + + """ + The target project for the iteration + """ + projectPath: ID """ The start date of the iteration @@ -2071,6 +2661,11 @@ type CreateRequirementPayload { Autogenerated input type of CreateSnippet """ input CreateSnippetInput { + """ + Actions to perform over the snippet repository and blobs + """ + blobActions: [SnippetBlobActionInputType!] + """ A unique identifier for the client performing the mutation. """ @@ -2091,11 +2686,6 @@ input CreateSnippetInput { """ fileName: String - """ - The snippet files to create - """ - files: [SnippetFileInputType!] - """ The project full path the snippet is associated with """ @@ -2137,6 +2727,46 @@ type CreateSnippetPayload { snippet: Snippet } +""" +Autogenerated input type of DastOnDemandScanCreate +""" +input DastOnDemandScanCreateInput { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + ID of the site profile to be used for the scan. + """ + dastSiteProfileId: DastSiteProfileID! + + """ + The project the site profile belongs to. + """ + fullPath: ID! +} + +""" +Autogenerated return type of DastOnDemandScanCreate +""" +type DastOnDemandScanCreatePayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Errors encountered during execution of the mutation. + """ + errors: [String!]! + + """ + URL of the pipeline that was created. + """ + pipelineUrl: String +} + enum DastScanTypeEnum { """ Passive DAST scan. This scan will not make active attacks against the target site. @@ -2144,6 +2774,171 @@ enum DastScanTypeEnum { PASSIVE } +""" +Represents a DAST scanner profile. +""" +type DastScannerProfile { + """ + ID of the DAST scanner profile + """ + id: ID! + + """ + Name of the DAST scanner profile + """ + profileName: String + + """ + The maximum number of seconds allowed for the spider to traverse the site + """ + spiderTimeout: Int + + """ + The maximum number of seconds allowed for the site under test to respond to a request + """ + targetTimeout: Int +} + +""" +The connection type for DastScannerProfile. +""" +type DastScannerProfileConnection { + """ + A list of edges. + """ + edges: [DastScannerProfileEdge] + + """ + A list of nodes. + """ + nodes: [DastScannerProfile] + + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! +} + +""" +Autogenerated input type of DastScannerProfileCreate +""" +input DastScannerProfileCreateInput { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + The project the scanner profile belongs to. + """ + fullPath: ID! + + """ + The name of the scanner profile. + """ + profileName: String! + + """ + The maximum number of seconds allowed for the spider to traverse the site. + """ + spiderTimeout: Int + + """ + The maximum number of seconds allowed for the site under test to respond to a request. + """ + targetTimeout: Int +} + +""" +Autogenerated return type of DastScannerProfileCreate +""" +type DastScannerProfileCreatePayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Errors encountered during execution of the mutation. + """ + errors: [String!]! + + """ + ID of the scanner profile. + """ + id: ID +} + +""" +An edge in a connection. +""" +type DastScannerProfileEdge { + """ + A cursor for use in pagination. + """ + cursor: String! + + """ + The item at the end of the edge. + """ + node: DastScannerProfile +} + +""" +Represents a DAST Site Profile. +""" +type DastSiteProfile { + """ + Relative web path to the edit page of a site profile + """ + editPath: String + + """ + ID of the site profile + """ + id: DastSiteProfileID! + + """ + The name of the site profile + """ + profileName: String + + """ + The URL of the target to be scanned + """ + targetUrl: String + + """ + Permissions for the current user on the resource + """ + userPermissions: DastSiteProfilePermissions! + + """ + The current validation status of the site profile + """ + validationStatus: DastSiteProfileValidationStatusEnum +} + +""" +The connection type for DastSiteProfile. +""" +type DastSiteProfileConnection { + """ + A list of edges. + """ + edges: [DastSiteProfileEdge] + + """ + A list of nodes. + """ + nodes: [DastSiteProfile] + + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! +} + """ Autogenerated input type of DastSiteProfileCreate """ @@ -2186,7 +2981,144 @@ type DastSiteProfileCreatePayload { """ ID of the site profile. """ - id: ID + id: DastSiteProfileID +} + +""" +Autogenerated input type of DastSiteProfileDelete +""" +input DastSiteProfileDeleteInput { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + The project the site profile belongs to. + """ + fullPath: ID! + + """ + ID of the site profile to be deleted. + """ + id: DastSiteProfileID! +} + +""" +Autogenerated return type of DastSiteProfileDelete +""" +type DastSiteProfileDeletePayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Errors encountered during execution of the mutation. + """ + errors: [String!]! +} + +""" +An edge in a connection. +""" +type DastSiteProfileEdge { + """ + A cursor for use in pagination. + """ + cursor: String! + + """ + The item at the end of the edge. + """ + node: DastSiteProfile +} + +""" +Identifier of DastSiteProfile +""" +scalar DastSiteProfileID + +""" +Check permissions for the current user on site profile +""" +type DastSiteProfilePermissions { + """ + Indicates the user can perform `create_on_demand_dast_scan` on this resource + """ + createOnDemandDastScan: Boolean! +} + +""" +Autogenerated input type of DastSiteProfileUpdate +""" +input DastSiteProfileUpdateInput { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + The project the site profile belongs to. + """ + fullPath: ID! + + """ + ID of the site profile to be updated. + """ + id: DastSiteProfileID! + + """ + The name of the site profile. + """ + profileName: String! + + """ + The URL of the target to be scanned. + """ + targetUrl: String +} + +""" +Autogenerated return type of DastSiteProfileUpdate +""" +type DastSiteProfileUpdatePayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Errors encountered during execution of the mutation. + """ + errors: [String!]! + + """ + ID of the site profile. + """ + id: DastSiteProfileID +} + +enum DastSiteProfileValidationStatusEnum { + """ + Site validation process finished but failed + """ + FAILED_VALIDATION + + """ + Site validation process is in progress + """ + INPROGRESS_VALIDATION + + """ + Site validation process finished successfully + """ + PASSED_VALIDATION + + """ + Site validation process has not started + """ + PENDING_VALIDATION } """ @@ -2757,11 +3689,61 @@ type DesignManagementDeletePayload { Errors encountered during execution of the mutation. """ errors: [String!]! - - """ - The new version in which the designs are deleted - """ - version: DesignVersion + + """ + The new version in which the designs are deleted + """ + version: DesignVersion +} + +""" +Identifier of DesignManagement::Design +""" +scalar DesignManagementDesignID + +""" +Autogenerated input type of DesignManagementMove +""" +input DesignManagementMoveInput { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + ID of the design to move + """ + id: DesignManagementDesignID! + + """ + ID of the immediately following design + """ + next: DesignManagementDesignID + + """ + ID of the immediately preceding design + """ + previous: DesignManagementDesignID +} + +""" +Autogenerated return type of DesignManagementMove +""" +type DesignManagementMovePayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + The current state of the collection + """ + designCollection: DesignCollection + + """ + Errors encountered during execution of the mutation. + """ + errors: [String!]! } """ @@ -3523,6 +4505,11 @@ type Environment { """ id: ID! + """ + The most severe open alert for the environment. If multiple alerts have equal severity, the most recent is returned. + """ + latestOpenedMostSevereAlert: AlertManagementAlert + """ Metrics dashboard schema for the environment """ @@ -3643,6 +4630,11 @@ type Epic implements Noteable { """ last: Int + """ + Filter epics by milestone title, computed from epic's issues + """ + milestoneTitle: String + """ Search query for epic title or description """ @@ -3991,7 +4983,7 @@ input EpicAddIssueInput { issueIid: String! """ - The project the issue belongs to + The full path of the project the issue belongs to """ projectPath: ID! } @@ -4046,7 +5038,7 @@ Counts of descendent epics. """ type EpicDescendantCount { """ - Number of closed sub-epics + Number of closed child epics """ closedEpics: Int @@ -4056,7 +5048,7 @@ type EpicDescendantCount { closedIssues: Int """ - Number of opened sub-epics + Number of opened child epics """ openedEpics: Int @@ -4150,6 +5142,11 @@ type EpicIssue implements Noteable { """ author: User! + """ + Indicates the issue is blocked + """ + blocked: Boolean! + """ Timestamp of when the issue was closed """ @@ -4360,6 +5357,11 @@ type EpicIssue implements Noteable { """ state: IssueState! + """ + Indicates whether an issue is published to the status page + """ + statusPagePublishedIncident: Boolean + """ Indicates the currently logged in user is subscribed to the issue """ @@ -4390,6 +5392,11 @@ type EpicIssue implements Noteable { """ totalTimeSpent: Int! + """ + Type of the issue + """ + type: IssueType + """ Timestamp of when the issue was last updated """ @@ -4925,6 +5932,11 @@ type Group { """ labelName: [String!] + """ + Filter epics by milestone title, computed from epic's issues + """ + milestoneTitle: String + """ Search query for epic title or description """ @@ -5002,6 +6014,11 @@ type Group { """ last: Int + """ + Filter epics by milestone title, computed from epic's issues + """ + milestoneTitle: String + """ Search query for epic title or description """ @@ -5049,6 +6066,11 @@ type Group { """ id: ID! + """ + Status of the temporary storage increase + """ + isTemporaryStorageIncreaseEnabled: Boolean! + """ Issues of the group """ @@ -5064,7 +6086,7 @@ type Group { assigneeId: String """ - Username of a user assigned to the issues + Username of a user assigned to the issue """ assigneeUsername: String @@ -5108,6 +6130,11 @@ type Group { """ iids: [String!] + """ + Include issues belonging to subgroups. + """ + includeSubgroups: Boolean = false + """ Iterations applied to the issue """ @@ -5124,7 +6151,7 @@ type Group { last: Int """ - Milestones applied to this issue + Milestone applied to this issue """ milestoneTitle: [String] @@ -5143,6 +6170,11 @@ type Group { """ state: IssuableState + """ + Filter issues by the given issue types + """ + types: [IssueType!] + """ Issues updated after this date """ @@ -5267,7 +6299,7 @@ type Group { mentionsDisabled: Boolean """ - Find milestones + Milestones of the group """ milestones( """ @@ -5292,7 +6324,12 @@ type Group { first: Int """ - Return also milestones in all subgroups and subprojects + Array of global milestone IDs, e.g., "gid://gitlab/Milestone/1" + """ + ids: [ID!] + + """ + Also return milestones in all subgroups and subprojects """ includeDescendants: Boolean @@ -5514,7 +6551,43 @@ type Group { ): VulnerabilityConnection """ - Number of vulnerabilities per severity level, per day, for the projects in the group and its subgroups + Number of vulnerabilities per day for the projects in the group and its subgroups + """ + vulnerabilitiesCountByDay( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Last day for which to fetch vulnerability history + """ + endDate: ISO8601Date! + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + + """ + First day for which to fetch vulnerability history + """ + startDate: ISO8601Date! + ): VulnerabilitiesCountByDayConnection + + """ + Number of vulnerabilities per severity level, per day, for the projects in the + group and its subgroups. Deprecated in 13.3: Use `vulnerabilitiesCountByDay` """ vulnerabilitiesCountByDayAndSeverity( """ @@ -5546,7 +6619,12 @@ type Group { First day for which to fetch vulnerability history """ startDate: ISO8601Date! - ): VulnerabilitiesCountByDayAndSeverityConnection + ): VulnerabilitiesCountByDayAndSeverityConnection @deprecated(reason: "Use `vulnerabilitiesCountByDay`. Deprecated in 13.3") + + """ + Represents vulnerable project counts for each grade + """ + vulnerabilityGrades: [VulnerableProjectsByGrade!]! """ Vulnerability scanners reported on the project vulnerabilties of the group and its subgroups @@ -5701,6 +6779,11 @@ type InstanceSecurityDashboard { last: Int ): ProjectConnection! + """ + Represents vulnerable project counts for each grade + """ + vulnerabilityGrades: [VulnerableProjectsByGrade!]! + """ Vulnerability scanners reported on the vulnerabilties from projects selected in Instance Security Dashboard """ @@ -5731,6 +6814,7 @@ type InstanceSecurityDashboard { State of a GitLab issue or merge request """ enum IssuableState { + all closed locked opened @@ -5767,6 +6851,11 @@ type Issue implements Noteable { """ author: User! + """ + Indicates the issue is blocked + """ + blocked: Boolean! + """ Timestamp of when the issue was closed """ @@ -5967,6 +7056,11 @@ type Issue implements Noteable { """ state: IssueState! + """ + Indicates whether an issue is published to the status page + """ + statusPagePublishedIncident: Boolean + """ Indicates the currently logged in user is subscribed to the issue """ @@ -5997,6 +7091,11 @@ type Issue implements Noteable { """ totalTimeSpent: Int! + """ + Type of the issue + """ + type: IssueType + """ Timestamp of when the issue was last updated """ @@ -6073,6 +7172,71 @@ type IssueEdge { node: Issue } +""" +Autogenerated input type of IssueMoveList +""" +input IssueMoveListInput { + """ + Global ID of the board that the issue is in + """ + boardId: ID! + + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + ID of the board list that the issue will be moved from + """ + fromListId: ID + + """ + IID of the issue to mutate + """ + iid: String! + + """ + ID of issue after which the current issue will be positioned at + """ + moveAfterId: ID + + """ + ID of issue before which the current issue will be positioned at + """ + moveBeforeId: ID + + """ + Project the issue to mutate is in + """ + projectPath: ID! + + """ + ID of the board list that the issue will be moved to + """ + toListId: ID +} + +""" +Autogenerated return type of IssueMoveList +""" +type IssueMoveListPayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Errors encountered during execution of the mutation. + """ + errors: [String!]! + + """ + The issue after mutation + """ + issue: Issue +} + """ Check permissions for the current user on a issue """ @@ -6118,6 +7282,56 @@ type IssuePermissions { updateIssue: Boolean! } +""" +Autogenerated input type of IssueSetAssignees +""" +input IssueSetAssigneesInput { + """ + The usernames to assign to the resource. Replaces existing assignees by default. + """ + assigneeUsernames: [String!]! + + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + The IID of the issue to mutate + """ + iid: String! + + """ + The operation to perform. Defaults to REPLACE. + """ + operationMode: MutationOperationMode + + """ + The project the issue to mutate is in + """ + projectPath: ID! +} + +""" +Autogenerated return type of IssueSetAssignees +""" +type IssueSetAssigneesPayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Errors encountered during execution of the mutation. + """ + errors: [String!]! + + """ + The issue after mutation + """ + issue: Issue +} + """ Autogenerated input type of IssueSetConfidential """ @@ -6133,7 +7347,7 @@ input IssueSetConfidentialInput { confidential: Boolean! """ - The iid of the issue to mutate + The IID of the issue to mutate """ iid: String! @@ -6178,7 +7392,7 @@ input IssueSetDueDateInput { dueDate: Time! """ - The iid of the issue to mutate + The IID of the issue to mutate """ iid: String! @@ -6208,6 +7422,51 @@ type IssueSetDueDatePayload { issue: Issue } +""" +Autogenerated input type of IssueSetEpic +""" +input IssueSetEpicInput { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Global ID of the epic to be assigned to the issue, epic will be removed if absent or set to null + """ + epicId: ID + + """ + The IID of the issue to mutate + """ + iid: String! + + """ + The project the issue to mutate is in + """ + projectPath: ID! +} + +""" +Autogenerated return type of IssueSetEpic +""" +type IssueSetEpicPayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Errors encountered during execution of the mutation. + """ + errors: [String!]! + + """ + The issue after mutation + """ + issue: Issue +} + """ Autogenerated input type of IssueSetIteration """ @@ -6218,7 +7477,7 @@ input IssueSetIterationInput { clientMutationId: String """ - The iid of the issue to mutate + The IID of the issue to mutate """ iid: String! @@ -6263,25 +7522,70 @@ input IssueSetLockedInput { clientMutationId: String """ - The iid of the issue to mutate + The IID of the issue to mutate """ iid: String! """ Whether or not to lock discussion on the issue """ - locked: Boolean! + locked: Boolean! + + """ + The project the issue to mutate is in + """ + projectPath: ID! +} + +""" +Autogenerated return type of IssueSetLocked +""" +type IssueSetLockedPayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Errors encountered during execution of the mutation. + """ + errors: [String!]! + + """ + The issue after mutation + """ + issue: Issue +} + +""" +Autogenerated input type of IssueSetSubscription +""" +input IssueSetSubscriptionInput { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + The IID of the issue to mutate + """ + iid: String! """ The project the issue to mutate is in """ projectPath: ID! + + """ + The desired state of the subscription + """ + subscribedState: Boolean! } """ -Autogenerated return type of IssueSetLocked +Autogenerated return type of IssueSetSubscription """ -type IssueSetLockedPayload { +type IssueSetSubscriptionPayload { """ A unique identifier for the client performing the mutation. """ @@ -6308,7 +7612,7 @@ input IssueSetWeightInput { clientMutationId: String """ - The iid of the issue to mutate + The IID of the issue to mutate """ iid: String! @@ -6427,11 +7731,47 @@ enum IssueSort { State of a GitLab issue """ enum IssueState { + all closed locked opened } +""" +Represents total number of issues for the represented statuses. +""" +type IssueStatusCountsType { + """ + Number of issues with status ALL for the project + """ + all: Int + + """ + Number of issues with status CLOSED for the project + """ + closed: Int + + """ + Number of issues with status OPENED for the project + """ + opened: Int +} + +""" +Issue type +""" +enum IssueType { + """ + Incident issue type + """ + INCIDENT + + """ + Issue issue type + """ + ISSUE +} + """ Represents an iteration object. """ @@ -6446,6 +7786,11 @@ type Iteration { """ description: String + """ + The GitLab Flavored Markdown rendering of `description` + """ + descriptionHtml: String + """ Timestamp of the iteration due date """ @@ -6461,6 +7806,16 @@ type Iteration { """ iid: ID! + """ + Web path of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts + """ + scopedPath: String + + """ + Web URL of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts + """ + scopedUrl: String + """ Timestamp of the iteration start date """ @@ -6527,6 +7882,11 @@ type IterationEdge { node: Iteration } +""" +Identifier of Iteration +""" +scalar IterationID + """ State of a GitLab iteration """ @@ -6910,6 +8270,11 @@ type LabelEdge { node: Label } +""" +Identifier of Label +""" +scalar LabelID + """ List limit metric setting """ @@ -6987,6 +8352,31 @@ type MergeRequest implements Noteable { """ allowCollaboration: Boolean + """ + Users who approved the merge request + """ + approvedBy( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): UserConnection + """ Assignees of the merge request """ @@ -7017,6 +8407,11 @@ type MergeRequest implements Noteable { """ author: User + """ + Number of commits in the merge request + """ + commitCount: Int + """ Timestamp of when the merge request was created """ @@ -7432,6 +8827,11 @@ type MergeRequest implements Noteable { The connection type for MergeRequest. """ type MergeRequestConnection { + """ + Total count of collection + """ + count: Int! + """ A list of edges. """ @@ -7462,6 +8862,11 @@ input MergeRequestCreateInput { """ description: String + """ + Labels of the merge request + """ + labels: [String!] + """ Project full path the merge request is associated with """ @@ -7568,7 +8973,7 @@ Autogenerated input type of MergeRequestSetAssignees """ input MergeRequestSetAssigneesInput { """ - The usernames to assign to the merge request. Replaces existing assignees by default. + The usernames to assign to the resource. Replaces existing assignees by default. """ assigneeUsernames: [String!]! @@ -7847,6 +9252,7 @@ type MergeRequestSetWipPayload { State of a GitLab merge request """ enum MergeRequestState { + all closed locked merged @@ -8134,6 +9540,11 @@ type MilestoneEdge { node: Milestone } +""" +Identifier of Milestone +""" +scalar MilestoneID + enum MilestoneStateEnum { active closed @@ -8178,11 +9589,14 @@ type Mutation { awardEmojiAdd(input: AwardEmojiAddInput!): AwardEmojiAddPayload awardEmojiRemove(input: AwardEmojiRemoveInput!): AwardEmojiRemovePayload awardEmojiToggle(input: AwardEmojiToggleInput!): AwardEmojiTogglePayload + boardListCreate(input: BoardListCreateInput!): BoardListCreatePayload boardListUpdateLimitMetrics(input: BoardListUpdateLimitMetricsInput!): BoardListUpdateLimitMetricsPayload commitCreate(input: CommitCreateInput!): CommitCreatePayload + configureSast(input: ConfigureSastInput!): ConfigureSastPayload createAlertIssue(input: CreateAlertIssueInput!): CreateAlertIssuePayload createAnnotation(input: CreateAnnotationInput!): CreateAnnotationPayload createBranch(input: CreateBranchInput!): CreateBranchPayload + createClusterAgent(input: CreateClusterAgentInput!): CreateClusterAgentPayload createDiffNote(input: CreateDiffNoteInput!): CreateDiffNotePayload createEpic(input: CreateEpicInput!): CreateEpicPayload createImageDiffNote(input: CreateImageDiffNoteInput!): CreateImageDiffNotePayload @@ -8190,9 +9604,14 @@ type Mutation { createNote(input: CreateNoteInput!): CreateNotePayload createRequirement(input: CreateRequirementInput!): CreateRequirementPayload createSnippet(input: CreateSnippetInput!): CreateSnippetPayload + dastOnDemandScanCreate(input: DastOnDemandScanCreateInput!): DastOnDemandScanCreatePayload + dastScannerProfileCreate(input: DastScannerProfileCreateInput!): DastScannerProfileCreatePayload dastSiteProfileCreate(input: DastSiteProfileCreateInput!): DastSiteProfileCreatePayload + dastSiteProfileDelete(input: DastSiteProfileDeleteInput!): DastSiteProfileDeletePayload + dastSiteProfileUpdate(input: DastSiteProfileUpdateInput!): DastSiteProfileUpdatePayload deleteAnnotation(input: DeleteAnnotationInput!): DeleteAnnotationPayload designManagementDelete(input: DesignManagementDeleteInput!): DesignManagementDeletePayload + designManagementMove(input: DesignManagementMoveInput!): DesignManagementMovePayload designManagementUpload(input: DesignManagementUploadInput!): DesignManagementUploadPayload destroyNote(input: DestroyNoteInput!): DestroyNotePayload destroySnippet(input: DestroySnippetInput!): DestroySnippetPayload @@ -8205,10 +9624,14 @@ type Mutation { epicAddIssue(input: EpicAddIssueInput!): EpicAddIssuePayload epicSetSubscription(input: EpicSetSubscriptionInput!): EpicSetSubscriptionPayload epicTreeReorder(input: EpicTreeReorderInput!): EpicTreeReorderPayload + issueMoveList(input: IssueMoveListInput!): IssueMoveListPayload + issueSetAssignees(input: IssueSetAssigneesInput!): IssueSetAssigneesPayload issueSetConfidential(input: IssueSetConfidentialInput!): IssueSetConfidentialPayload issueSetDueDate(input: IssueSetDueDateInput!): IssueSetDueDatePayload + issueSetEpic(input: IssueSetEpicInput!): IssueSetEpicPayload issueSetIteration(input: IssueSetIterationInput!): IssueSetIterationPayload issueSetLocked(input: IssueSetLockedInput!): IssueSetLockedPayload + issueSetSubscription(input: IssueSetSubscriptionInput!): IssueSetSubscriptionPayload issueSetWeight(input: IssueSetWeightInput!): IssueSetWeightPayload jiraImportStart(input: JiraImportStartInput!): JiraImportStartPayload jiraImportUsers(input: JiraImportUsersInput!): JiraImportUsersPayload @@ -8225,6 +9648,7 @@ type Mutation { Update attributes of a merge request """ mergeRequestUpdate(input: MergeRequestUpdateInput!): MergeRequestUpdatePayload + namespaceIncreaseStorageTemporarily(input: NamespaceIncreaseStorageTemporarilyInput!): NamespaceIncreaseStorageTemporarilyPayload removeAwardEmoji(input: RemoveAwardEmojiInput!): RemoveAwardEmojiPayload @deprecated(reason: "Use awardEmojiRemove. Deprecated in 13.2") removeProjectFromSecurityDashboard(input: RemoveProjectFromSecurityDashboardInput!): RemoveProjectFromSecurityDashboardPayload runDastScan(input: RunDASTScanInput!): RunDASTScanPayload @@ -8234,6 +9658,8 @@ type Mutation { todosMarkAllDone(input: TodosMarkAllDoneInput!): TodosMarkAllDonePayload toggleAwardEmoji(input: ToggleAwardEmojiInput!): ToggleAwardEmojiPayload @deprecated(reason: "Use awardEmojiToggle. Deprecated in 13.2") updateAlertStatus(input: UpdateAlertStatusInput!): UpdateAlertStatusPayload + updateBoard(input: UpdateBoardInput!): UpdateBoardPayload + updateBoardList(input: UpdateBoardListInput!): UpdateBoardListPayload updateContainerExpirationPolicy(input: UpdateContainerExpirationPolicyInput!): UpdateContainerExpirationPolicyPayload updateEpic(input: UpdateEpicInput!): UpdateEpicPayload @@ -8301,6 +9727,11 @@ type Namespace { """ id: ID! + """ + Status of the temporary storage increase + """ + isTemporaryStorageIncreaseEnabled: Boolean! + """ Indicates if Large File Storage (LFS) is enabled for namespace """ @@ -8412,6 +9843,83 @@ type NamespaceEdge { node: Namespace } +""" +Autogenerated input type of NamespaceIncreaseStorageTemporarily +""" +input NamespaceIncreaseStorageTemporarilyInput { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + The global id of the namespace to mutate + """ + id: ID! +} + +""" +Autogenerated return type of NamespaceIncreaseStorageTemporarily +""" +type NamespaceIncreaseStorageTemporarilyPayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Errors encountered during execution of the mutation. + """ + errors: [String!]! + + """ + The namespace after mutation + """ + namespace: Namespace +} + +input NegatedBoardEpicIssueInput { + """ + Filter by assignee username + """ + assigneeUsername: [String] + + """ + Filter by author username + """ + authorUsername: String + + """ + Filter by epic ID + """ + epicId: String + + """ + Filter by label name + """ + labelName: [String] + + """ + Filter by milestone title + """ + milestoneTitle: String + + """ + Filter by reaction emoji + """ + myReactionEmoji: String + + """ + Filter by release tag + """ + releaseTag: String + + """ + Filter by weight + """ + weight: String +} + type Note implements ResolvableInterface { """ User who wrote this note @@ -8831,6 +10339,13 @@ type Pipeline { """ committedAt: Time + """ + Config source of the pipeline (UNKNOWN_SOURCE, REPOSITORY_SOURCE, + AUTO_DEVOPS_SOURCE, WEBIDE_SOURCE, REMOTE_SOURCE, EXTERNAL_PROJECT_SOURCE, + BRIDGE_SOURCE, PARAMETER_SOURCE) + """ + configSource: PipelineConfigSourceEnum + """ Coverage percentage """ @@ -8876,6 +10391,31 @@ type Pipeline { """ sha: String! + """ + Stages of the pipeline + """ + stages( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): CiStageConnection + """ Timestamp when the pipeline was started """ @@ -8892,16 +10432,37 @@ type Pipeline { """ updatedAt: Time! + """ + Pipeline user + """ + user: User + """ Permissions for the current user on the resource """ userPermissions: PipelinePermissions! } +enum PipelineConfigSourceEnum { + AUTO_DEVOPS_SOURCE + BRIDGE_SOURCE + EXTERNAL_PROJECT_SOURCE + PARAMETER_SOURCE + REMOTE_SOURCE + REPOSITORY_SOURCE + UNKNOWN_SOURCE + WEBIDE_SOURCE +} + """ The connection type for Pipeline. """ type PipelineConnection { + """ + Total count of collection + """ + count: Int! + """ A list of edges. """ @@ -9057,29 +10618,99 @@ type Project { archived: Boolean """ - Indicates if issues referenced by merge requests and commits within the default branch are closed automatically + Indicates if issues referenced by merge requests and commits within the default branch are closed automatically + """ + autocloseReferencedIssues: Boolean + + """ + URL to avatar image file of the project + """ + avatarUrl: String + + """ + A single board of the project + """ + board( + """ + Find a board by its ID + """ + id: ID + ): Board + + """ + Boards of the project + """ + boards( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Find a board by its ID + """ + id: ID + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): BoardConnection + + """ + Compliance frameworks associated with the project + """ + complianceFrameworks( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): ComplianceFrameworkConnection + + """ + The container expiration policy of the project """ - autocloseReferencedIssues: Boolean + containerExpirationPolicy: ContainerExpirationPolicy """ - URL to avatar image file of the project + Indicates if the project stores Docker container images in a container registry """ - avatarUrl: String + containerRegistryEnabled: Boolean """ - A single board of the project + Timestamp of the project creation """ - board( - """ - Find a board by its ID - """ - id: ID - ): Board + createdAt: Time """ - Boards of the project + The DAST scanner profiles associated with the project """ - boards( + dastScannerProfiles( """ Returns the elements in the list that come after the specified cursor. """ @@ -9095,21 +10726,16 @@ type Project { """ first: Int - """ - Find a board by its ID - """ - id: ID - """ Returns the last _n_ elements from the list. """ last: Int - ): BoardConnection + ): DastScannerProfileConnection """ - Compliance frameworks associated with the project + DAST Site Profiles associated with the project """ - complianceFrameworks( + dastSiteProfiles( """ Returns the elements in the list that come after the specified cursor. """ @@ -9129,32 +10755,37 @@ type Project { Returns the last _n_ elements from the list. """ last: Int - ): ComplianceFrameworkConnection + ): DastSiteProfileConnection """ - The container expiration policy of the project + Short description of the project """ - containerExpirationPolicy: ContainerExpirationPolicy + description: String """ - Indicates if the project stores Docker container images in a container registry + The GitLab Flavored Markdown rendering of `description` """ - containerRegistryEnabled: Boolean + descriptionHtml: String """ - Timestamp of the project creation + A single environment of the project """ - createdAt: Time + environment( + """ + Name of the environment + """ + name: String - """ - Short description of the project - """ - description: String + """ + Search query for environment name + """ + search: String - """ - The GitLab Flavored Markdown rendering of `description` - """ - descriptionHtml: String + """ + States of environments that should be included in result + """ + states: [String!] + ): Environment """ Environments of the project @@ -9241,7 +10872,7 @@ type Project { assigneeId: String """ - Username of a user assigned to the issues + Username of a user assigned to the issue """ assigneeUsername: String @@ -9286,7 +10917,7 @@ type Project { labelName: [String] """ - Milestones applied to this issue + Milestone applied to this issue """ milestoneTitle: [String] @@ -9305,6 +10936,11 @@ type Project { """ state: IssuableState + """ + Filter issues by the given issue types + """ + types: [IssueType!] + """ Issues updated after this date """ @@ -9316,6 +10952,81 @@ type Project { updatedBefore: Time ): Issue + """ + Counts of issues by status for the project + """ + issueStatusCounts( + """ + ID of a user assigned to the issues, "none" and "any" values supported + """ + assigneeId: String + + """ + Username of a user assigned to the issue + """ + assigneeUsername: String + + """ + Issues closed after this date + """ + closedAfter: Time + + """ + Issues closed before this date + """ + closedBefore: Time + + """ + Issues created after this date + """ + createdAfter: Time + + """ + Issues created before this date + """ + createdBefore: Time + + """ + IID of the issue. For example, "1" + """ + iid: String + + """ + List of IIDs of issues. For example, [1, 2] + """ + iids: [String!] + + """ + Labels applied to this issue + """ + labelName: [String] + + """ + Milestone applied to this issue + """ + milestoneTitle: [String] + + """ + Search query for issue title or description + """ + search: String + + """ + Filter issues by the given issue types + """ + types: [IssueType!] + + """ + Issues updated after this date + """ + updatedAfter: Time + + """ + Issues updated before this date + """ + updatedBefore: Time + ): IssueStatusCountsType + """ Issues of the project """ @@ -9331,7 +11042,7 @@ type Project { assigneeId: String """ - Username of a user assigned to the issues + Username of a user assigned to the issue """ assigneeUsername: String @@ -9391,7 +11102,7 @@ type Project { last: Int """ - Milestones applied to this issue + Milestone applied to this issue """ milestoneTitle: [String] @@ -9410,6 +11121,11 @@ type Project { """ state: IssuableState + """ + Filter issues by the given issue types + """ + types: [IssueType!] + """ Issues updated after this date """ @@ -9426,6 +11142,68 @@ type Project { """ issuesEnabled: Boolean + """ + Find iterations + """ + iterations( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + List items within a time frame where items.end_date is between startDate and + endDate parameters (startDate parameter must be present) + """ + endDate: Time + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + The ID of the Iteration to look up + """ + id: ID + + """ + The internal ID of the Iteration to look up + """ + iid: ID + + """ + Whether to include ancestor iterations. Defaults to true + """ + includeAncestors: Boolean + + """ + Returns the last _n_ elements from the list. + """ + last: Int + + """ + List items within a time frame where items.start_date is between startDate + and endDate parameters (endDate parameter must be present) + """ + startDate: Time + + """ + Filter iterations by state + """ + state: IterationState + + """ + Fuzzy search by title + """ + title: String + ): IterationConnection + """ Status of Jira import background job of the project """ @@ -9555,6 +11333,16 @@ type Project { """ last: Int + """ + Merge requests merged after this date + """ + mergedAfter: Time + + """ + Merge requests merged before this date + """ + mergedBefore: Time + """ Array of source branch names. All resolved merge requests will have one of these branches as their source. """ @@ -9566,22 +11354,74 @@ type Project { state: MergeRequestState """ - Array of target branch names. All resolved merge requests will have one of these branches as their target. + Array of target branch names. All resolved merge requests will have one of these branches as their target. + """ + targetBranches: [String!] + ): MergeRequestConnection + + """ + Indicates if Merge Requests are enabled for the current user + """ + mergeRequestsEnabled: Boolean + + """ + Indicates if no merge commits should be created and all merges should instead + be fast-forwarded, which means that merging is only allowed if the branch + could be fast-forwarded. + """ + mergeRequestsFfOnlyEnabled: Boolean + + """ + Milestones of the project + """ + milestones( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + List items within a time frame where items.end_date is between startDate and + endDate parameters (startDate parameter must be present) + """ + endDate: Time + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Array of global milestone IDs, e.g., "gid://gitlab/Milestone/1" + """ + ids: [ID!] + + """ + Also return milestones in the project's parent group and its ancestors + """ + includeAncestors: Boolean + + """ + Returns the last _n_ elements from the list. + """ + last: Int + + """ + List items within a time frame where items.start_date is between startDate + and endDate parameters (endDate parameter must be present) """ - targetBranches: [String!] - ): MergeRequestConnection - - """ - Indicates if Merge Requests are enabled for the current user - """ - mergeRequestsEnabled: Boolean + startDate: Time - """ - Indicates if no merge commits should be created and all merges should instead - be fast-forwarded, which means that merging is only allowed if the branch - could be fast-forwarded. - """ - mergeRequestsFfOnlyEnabled: Boolean + """ + Filter milestones by state + """ + state: MilestoneStateEnum + ): MilestoneConnection """ Name of the project (without namespace) @@ -9884,6 +11724,11 @@ type Project { """ sastCiConfiguration: SastCiConfiguration + """ + Path to project's security dashboard + """ + securityDashboardPath: String + """ Information about security analyzers used in the project """ @@ -10505,6 +12350,21 @@ type ProjectStatistics { wikiSize: Float } +""" +The alert condition for Prometheus +""" +type PrometheusAlert { + """ + The human-readable text of the alert condition + """ + humanizedText: String! + + """ + ID of the alert condition + """ + id: ID! +} + type Query { """ Get information about current user @@ -10551,11 +12411,31 @@ type Query { """ instanceSecurityDashboard: InstanceSecurityDashboard + """ + Find an iteration + """ + iteration( + """ + Find an iteration by its ID + """ + id: IterationID! + ): Iteration + """ Metadata about GitLab """ metadata: Metadata + """ + Find a milestone + """ + milestone( + """ + Find a milestone by its ID + """ + id: MilestoneID! + ): Milestone + """ Find a namespace """ @@ -10772,7 +12652,44 @@ type Query { ): VulnerabilityConnection """ - Number of vulnerabilities per severity level, per day, for the projects on the current user's instance security dashboard + Number of vulnerabilities per day for the projects on the current user's instance security dashboard + """ + vulnerabilitiesCountByDay( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Last day for which to fetch vulnerability history + """ + endDate: ISO8601Date! + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + + """ + First day for which to fetch vulnerability history + """ + startDate: ISO8601Date! + ): VulnerabilitiesCountByDayConnection + + """ + Number of vulnerabilities per severity level, per day, for the projects on the + current user's instance security dashboard. Deprecated in 13.3: Use + `vulnerabilitiesCountByDay` """ vulnerabilitiesCountByDayAndSeverity( """ @@ -10804,7 +12721,7 @@ type Query { First day for which to fetch vulnerability history """ startDate: ISO8601Date! - ): VulnerabilitiesCountByDayAndSeverityConnection + ): VulnerabilitiesCountByDayAndSeverityConnection @deprecated(reason: "Use `vulnerabilitiesCountByDay`. Deprecated in 13.3") } """ @@ -11832,6 +13749,11 @@ type SastCiConfigurationEntity { last: Int ): SastCiConfigurationOptionsEntityConnection + """ + Size of the UI component. + """ + size: SastUiComponentSize + """ Type of the field value. """ @@ -11928,6 +13850,15 @@ type SastCiConfigurationOptionsEntityEdge { node: SastCiConfigurationOptionsEntity } +""" +Size of UI component in SAST configuration page +""" +enum SastUiComponentSize { + LARGE + MEDIUM + SMALL +} + """ Represents a resource scanned by a security scan """ @@ -12063,6 +13994,7 @@ The type of the security scanner. """ enum SecurityScannerType { CONTAINER_SCANNING + COVERAGE_FUZZING DAST DEPENDENCY_SCANNING SAST @@ -12636,9 +14568,9 @@ type Snippet implements Noteable { author: User """ - Snippet blob + Snippet blob. Deprecated in 13.3: Use `blobs` """ - blob: SnippetBlob! + blob: SnippetBlob! @deprecated(reason: "Use `blobs`. Deprecated in 13.3") """ Snippet blobs @@ -12831,6 +14763,41 @@ type SnippetBlob { size: Int! } +""" +Type of a snippet blob input action +""" +enum SnippetBlobActionEnum { + create + delete + move + update +} + +""" +Represents an action to perform over a snippet file +""" +input SnippetBlobActionInputType { + """ + Type of input action + """ + action: SnippetBlobActionEnum! + + """ + Snippet file content + """ + content: String + + """ + Path of the snippet file + """ + filePath: String! + + """ + Previous path of the snippet file + """ + previousPath: String +} + """ Represents how the blob content should be displayed """ @@ -12906,41 +14873,6 @@ type SnippetEdge { node: Snippet } -""" -Type of a snippet file input action -""" -enum SnippetFileInputActionEnum { - create - delete - move - update -} - -""" -Represents an action to perform over a snippet file -""" -input SnippetFileInputType { - """ - Type of input action - """ - action: SnippetFileInputActionEnum! - - """ - Snippet file content - """ - content: String - - """ - Path of the snippet file - """ - filePath: String! - - """ - Previous path of the snippet file - """ - previousPath: String -} - type SnippetPermissions { """ Indicates the user can perform `admin_snippet` on this resource @@ -13663,6 +15595,11 @@ type TreeEntry implements Entry { """ type: EntryType! + """ + Web path for the tree entry (directory) + """ + webPath: String + """ Web URL for the tree entry (directory) """ @@ -13676,78 +15613,173 @@ type TreeEntryConnection { """ A list of edges. """ - edges: [TreeEntryEdge] + edges: [TreeEntryEdge] + + """ + A list of nodes. + """ + nodes: [TreeEntry] + + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! +} + +""" +An edge in a connection. +""" +type TreeEntryEdge { + """ + A cursor for use in pagination. + """ + cursor: String! + + """ + The item at the end of the edge. + """ + node: TreeEntry +} + +enum TypeEnum { + personal + project +} + +""" +A regexp containing patterns sourced from user input +""" +scalar UntrustedRegexp + +""" +Autogenerated input type of UpdateAlertStatus +""" +input UpdateAlertStatusInput { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + The iid of the alert to mutate + """ + iid: String! + + """ + The project the alert to mutate is in + """ + projectPath: ID! + + """ + The status to set the alert + """ + status: AlertManagementStatus! +} + +""" +Autogenerated return type of UpdateAlertStatus +""" +type UpdateAlertStatusPayload { + """ + The alert after mutation + """ + alert: AlertManagementAlert + + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Errors encountered during execution of the mutation. + """ + errors: [String!]! + + """ + The issue created after mutation + """ + issue: Issue + + """ + The todo after mutation + """ + todo: Todo +} + +""" +Autogenerated input type of UpdateBoard +""" +input UpdateBoardInput { + """ + The id of user to be assigned to the board. + """ + assigneeId: ID + + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Whether or not backlog list is hidden. + """ + hideBacklogList: Boolean """ - A list of nodes. + Whether or not closed list is hidden. """ - nodes: [TreeEntry] + hideClosedList: Boolean """ - Information to aid in pagination. + The board global id. """ - pageInfo: PageInfo! -} + id: ID! -""" -An edge in a connection. -""" -type TreeEntryEdge { """ - A cursor for use in pagination. + The id of milestone to be assigned to the board. """ - cursor: String! + milestoneId: ID """ - The item at the end of the edge. + Name of the board """ - node: TreeEntry -} + name: String -enum TypeEnum { - personal - project + """ + The weight value to be assigned to the board. + """ + weight: Int } """ -A regexp containing patterns sourced from user input -""" -scalar UntrustedRegexp - -""" -Autogenerated input type of UpdateAlertStatus +Autogenerated input type of UpdateBoardList """ -input UpdateAlertStatusInput { +input UpdateBoardListInput { """ A unique identifier for the client performing the mutation. """ clientMutationId: String """ - The iid of the alert to mutate + Indicates if list is collapsed for this user """ - iid: String! + collapsed: Boolean """ - The project the alert to mutate is in + Global ID of the list. """ - projectPath: ID! + listId: ID! """ - The status to set the alert + Position of list within the board """ - status: AlertManagementStatus! + position: Int } """ -Autogenerated return type of UpdateAlertStatus +Autogenerated return type of UpdateBoardList """ -type UpdateAlertStatusPayload { - """ - The alert after mutation - """ - alert: AlertManagementAlert - +type UpdateBoardListPayload { """ A unique identifier for the client performing the mutation. """ @@ -13759,14 +15791,29 @@ type UpdateAlertStatusPayload { errors: [String!]! """ - The issue created after mutation + Mutated list """ - issue: Issue + list: BoardList +} + +""" +Autogenerated return type of UpdateBoard +""" +type UpdateBoardPayload { + """ + The board after mutation. + """ + board: Board """ - The todo after mutation + A unique identifier for the client performing the mutation. """ - todo: Todo + clientMutationId: String + + """ + Errors encountered during execution of the mutation. + """ + errors: [String!]! } """ @@ -13995,6 +16042,11 @@ type UpdateImageDiffNotePayload { Autogenerated input type of UpdateIssue """ input UpdateIssueInput { + """ + The IDs of labels to be added to the issue. + """ + addLabelIds: [ID!] + """ A unique identifier for the client performing the mutation. """ @@ -14021,15 +16073,30 @@ input UpdateIssueInput { healthStatus: HealthStatus """ - The iid of the issue to mutate + The IID of the issue to mutate """ iid: String! + """ + Indicates discussion is locked on the issue + """ + locked: Boolean + + """ + The ID of the milestone to be assigned, milestone will be removed if set to null. + """ + milestoneId: ID + """ The project the issue to mutate is in """ projectPath: ID! + """ + The IDs of labels to be removed from the issue. + """ + removeLabelIds: [ID!] + """ Title of the issue """ @@ -14123,13 +16190,18 @@ input UpdateNoteInput { """ Content of the note """ - body: String! + body: String """ A unique identifier for the client performing the mutation. """ clientMutationId: String + """ + The confidentiality flag of a note. Default is false. + """ + confidential: Boolean + """ The global id of the note to update """ @@ -14210,6 +16282,11 @@ type UpdateRequirementPayload { Autogenerated input type of UpdateSnippet """ input UpdateSnippetInput { + """ + Actions to perform over the snippet repository and blobs + """ + blobActions: [SnippetBlobActionInputType!] + """ A unique identifier for the client performing the mutation. """ @@ -14230,11 +16307,6 @@ input UpdateSnippetInput { """ fileName: String - """ - The snippet files to update - """ - files: [SnippetFileInputType!] - """ The global id of the snippet to update """ @@ -14308,6 +16380,16 @@ type User { """ last: Int + """ + Merge requests merged after this date + """ + mergedAfter: Time + + """ + Merge requests merged before this date + """ + mergedBefore: Time + """ The global ID of the project the authored merge requests should be in. Incompatible with projectPath. """ @@ -14368,6 +16450,16 @@ type User { """ last: Int + """ + Merge requests merged after this date + """ + mergedAfter: Time + + """ + Merge requests merged before this date + """ + mergedBefore: Time + """ The global ID of the project the authored merge requests should be in. Incompatible with projectPath. """ @@ -14399,6 +16491,11 @@ type User { """ avatarUrl: String + """ + User email + """ + email: String + """ Group memberships of the user """ @@ -14504,6 +16601,11 @@ type User { """ state: UserState! + """ + User status + """ + status: UserStatus + """ Todos of the user """ @@ -14569,6 +16671,11 @@ type User { """ username: String! + """ + Web path of the user + """ + webPath: String! + """ Web URL of the user """ @@ -14637,6 +16744,23 @@ enum UserState { deactivated } +type UserStatus { + """ + String representation of emoji + """ + emoji: String + + """ + User status message + """ + message: String + + """ + HTML of the user status message + """ + messageHtml: String +} + enum VisibilityLevelsEnum { internal private @@ -14649,6 +16773,51 @@ enum VisibilityScopesEnum { public } +""" +Represents the count of vulnerabilities by severity on a particular day +""" +type VulnerabilitiesCountByDay { + """ + Total number of vulnerabilities on a particular day with critical severity + """ + critical: Int! + + """ + Date for the count + """ + date: ISO8601Date! + + """ + Total number of vulnerabilities on a particular day with high severity + """ + high: Int! + + """ + Total number of vulnerabilities on a particular day with info severity + """ + info: Int! + + """ + Total number of vulnerabilities on a particular day with low severity + """ + low: Int! + + """ + Total number of vulnerabilities on a particular day with medium severity + """ + medium: Int! + + """ + Total number of vulnerabilities on a particular day + """ + total: Int! + + """ + Total number of vulnerabilities on a particular day with unknown severity + """ + unknown: Int! +} + """ Represents the number of vulnerabilities for a particular severity on a particular day """ @@ -14704,6 +16873,41 @@ type VulnerabilitiesCountByDayAndSeverityEdge { node: VulnerabilitiesCountByDayAndSeverity } +""" +The connection type for VulnerabilitiesCountByDay. +""" +type VulnerabilitiesCountByDayConnection { + """ + A list of edges. + """ + edges: [VulnerabilitiesCountByDayEdge] + + """ + A list of nodes. + """ + nodes: [VulnerabilitiesCountByDay] + + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! +} + +""" +An edge in a connection. +""" +type VulnerabilitiesCountByDayEdge { + """ + A cursor for use in pagination. + """ + cursor: String! + + """ + The item at the end of the edge. + """ + node: VulnerabilitiesCountByDay +} + """ Represents a vulnerability. """ @@ -14775,6 +16979,11 @@ type Vulnerability { """ reportType: VulnerabilityReportType + """ + Indicates whether the vulnerability is fixed on the default branch or not + """ + resolvedOnDefaultBranch: Boolean! + """ Scanner metadata for the vulnerability. """ @@ -14846,6 +17055,17 @@ type VulnerabilityEdge { node: Vulnerability } +""" +The grade of the vulnerable project +""" +enum VulnerabilityGrade { + A + B + C + D + F +} + """ Represents a vulnerability identifier. """ @@ -14937,7 +17157,7 @@ enum VulnerabilityIssueLinkType { """ Represents a vulnerability location. The fields with data will depend on the vulnerability report type """ -union VulnerabilityLocation = VulnerabilityLocationContainerScanning | VulnerabilityLocationDast | VulnerabilityLocationDependencyScanning | VulnerabilityLocationSast | VulnerabilityLocationSecretDetection +union VulnerabilityLocation = VulnerabilityLocationContainerScanning | VulnerabilityLocationCoverageFuzzing | VulnerabilityLocationDast | VulnerabilityLocationDependencyScanning | VulnerabilityLocationSast | VulnerabilityLocationSecretDetection """ Represents the location of a vulnerability found by a container security scan @@ -14959,6 +17179,36 @@ type VulnerabilityLocationContainerScanning { operatingSystem: String } +""" +Represents the location of a vulnerability found by a Coverage Fuzzing scan +""" +type VulnerabilityLocationCoverageFuzzing { + """ + Number of the last relevant line in the vulnerable file + """ + endLine: String + + """ + Path to the vulnerable file + """ + file: String + + """ + Number of the first relevant line in the vulnerable file + """ + startLine: String + + """ + Class containing the vulnerability + """ + vulnerableClass: String + + """ + Method containing the vulnerability + """ + vulnerableMethod: String +} + """ Represents the location of a vulnerability found by a DAST scan """ @@ -15256,4 +17506,44 @@ type VulnerablePackage { The name of the vulnerable package """ name: String +} + +""" +Represents vulnerability letter grades with associated projects +""" +type VulnerableProjectsByGrade { + """ + Number of projects within this grade + """ + count: Int! + + """ + Grade based on the highest severity vulnerability present + """ + grade: VulnerabilityGrade! + + """ + Projects within this grade + """ + projects( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): ProjectConnection! } \ No newline at end of file diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json index 80aaa4aa949..7ee37fb4d43 100644 --- a/doc/api/graphql/reference/gitlab_schema.json +++ b/doc/api/graphql/reference/gitlab_schema.json @@ -577,6 +577,24 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "detailsUrl", + "description": "The URL of the alert detail page", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "discussions", "description": "All discussions on this noteable", @@ -801,6 +819,34 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "prometheusAlert", + "description": "The alert condition for Prometheus", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "PrometheusAlert", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "runbook", + "description": "Runbook for the alert as defined in alert details", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "service", "description": "Service the alert came from", @@ -871,6 +917,167 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "todos", + "description": "Todos of the current user for the alert", + "args": [ + { + "name": "action", + "description": "The action to be filtered", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "TodoActionEnum", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "authorId", + "description": "The ID of an author", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "projectId", + "description": "The ID of a project", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "groupId", + "description": "The ID of a group", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "state", + "description": "The state of the todo", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "TodoStateEnum", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "type", + "description": "The type of the todo", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "TodoTargetEnum", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "TodoConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "updatedAt", "description": "Timestamp the alert was last updated", @@ -2300,6 +2507,20 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "webPath", + "description": "Web path of the blob", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "webUrl", "description": "Web URL of the blob", @@ -2472,6 +2693,111 @@ "name": "Board", "description": "Represents a project or group board", "fields": [ + { + "name": "assignee", + "description": "The board assignee.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "epics", + "description": "Epics associated with board issues.", + "args": [ + { + "name": "issueFilters", + "description": "Filters applied when selecting issues on the board", + "type": { + "kind": "INPUT_OBJECT", + "name": "BoardEpicIssueInput", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EpicConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "hideBacklogList", + "description": "Whether or not backlog list is hidden.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "hideClosedList", + "description": "Whether or not closed list is hidden.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "id", "description": "ID (global ID) of the board", @@ -2494,6 +2820,16 @@ "name": "lists", "description": "Lists of the board", "args": [ + { + "name": "id", + "description": "Find a list by its global ID", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", @@ -2543,6 +2879,20 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "milestone", + "description": "The board milestone.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "Milestone", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "name", "description": "Name of the board", @@ -2559,7 +2909,7 @@ }, { "name": "weight", - "description": "Weight of the board", + "description": "Weight of the board.", "args": [ ], @@ -2691,6 +3041,125 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "BoardEpicIssueInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "labelName", + "description": "Filter by label name", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "milestoneTitle", + "description": "Filter by milestone title", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "assigneeUsername", + "description": "Filter by assignee username", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "authorUsername", + "description": "Filter by author username", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "releaseTag", + "description": "Filter by release tag", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "epicId", + "description": "Filter by epic ID", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "myReactionEmoji", + "description": "Filter by reaction emoji", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "weight", + "description": "Filter by weight", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "not", + "description": "List of negated params. Warning: this argument is experimental and a subject to change in future", + "type": { + "kind": "INPUT_OBJECT", + "name": "NegatedBoardEpicIssueInput", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "BoardID", + "description": "Identifier of Board", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "BoardList", @@ -2742,6 +3211,73 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "issues", + "description": "Board issues", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "IssueConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "issuesCount", + "description": "Count of issues in the list", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "label", "description": "Label of the list", @@ -2861,6 +3397,20 @@ }, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "totalWeight", + "description": "Total weight of all issues in the list", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null } ], "inputFields": null, @@ -2937,97 +3487,219 @@ "enumValues": null, "possibleTypes": null }, - { - "kind": "OBJECT", - "name": "BoardListEdge", - "description": "An edge in a connection.", - "fields": [ - { - "name": "cursor", - "description": "A cursor for use in pagination.", - "args": [ - - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "node", - "description": "The item at the end of the edge.", - "args": [ - - ], - "type": { - "kind": "OBJECT", - "name": "BoardList", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ - - ], - "enumValues": null, - "possibleTypes": null - }, { "kind": "INPUT_OBJECT", - "name": "BoardListUpdateLimitMetricsInput", - "description": "Autogenerated input type of BoardListUpdateLimitMetrics", + "name": "BoardListCreateInput", + "description": "Autogenerated input type of BoardListCreate", "fields": null, "inputFields": [ { - "name": "listId", - "description": "The global ID of the list.", + "name": "boardId", + "description": "The Global ID of the issue board to mutate", "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", - "name": "ID", + "name": "BoardID", "ofType": null } }, "defaultValue": null }, { - "name": "limitMetric", - "description": "The new limit metric type for the list.", - "type": { - "kind": "ENUM", - "name": "ListLimitMetric", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "maxIssueCount", - "description": "The new maximum issue count limit.", + "name": "backlog", + "description": "Create the backlog list", "type": { "kind": "SCALAR", - "name": "Int", + "name": "Boolean", "ofType": null }, "defaultValue": null }, { - "name": "maxIssueWeight", - "description": "The new maximum issue weight limit.", + "name": "labelId", + "description": "ID of an existing label", "type": { "kind": "SCALAR", - "name": "Int", + "name": "LabelID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "BoardListCreatePayload", + "description": "Autogenerated return type of BoardListCreate", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "list", + "description": "List of the issue board", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "BoardList", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "BoardListEdge", + "description": "An edge in a connection.", + "fields": [ + { + "name": "cursor", + "description": "A cursor for use in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": "The item at the end of the edge.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "BoardList", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "BoardListUpdateLimitMetricsInput", + "description": "Autogenerated input type of BoardListUpdateLimitMetrics", + "fields": null, + "inputFields": [ + { + "name": "listId", + "description": "The global ID of the list.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "limitMetric", + "description": "The new limit metric type for the list.", + "type": { + "kind": "ENUM", + "name": "ListLimitMetric", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "maxIssueCount", + "description": "The new maximum issue count limit.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "maxIssueWeight", + "description": "The new maximum issue weight limit.", + "type": { + "kind": "SCALAR", + "name": "Int", "ofType": null }, "defaultValue": null @@ -3171,26 +3843,65 @@ }, { "kind": "OBJECT", - "name": "Commit", + "name": "CiGroup", "description": null, "fields": [ { - "name": "author", - "description": "Author of the commit", + "name": "jobs", + "description": "Jobs in group", "args": [ - + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } ], "type": { "kind": "OBJECT", - "name": "User", + "name": "CiJobConnection", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "authorGravatar", - "description": "Commit authors gravatar", + "name": "name", + "description": "Name of the job group", "args": [ ], @@ -3203,50 +3914,102 @@ "deprecationReason": null }, { - "name": "authorName", - "description": "Commit authors name", + "name": "size", + "description": "Size of the group", "args": [ ], "type": { "kind": "SCALAR", - "name": "String", + "name": "Int", "ofType": null }, "isDeprecated": false, "deprecationReason": null - }, + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CiGroupConnection", + "description": "The connection type for CiGroup.", + "fields": [ { - "name": "authoredDate", - "description": "Timestamp of when the commit was authored", + "name": "edges", + "description": "A list of edges.", "args": [ ], "type": { - "kind": "SCALAR", - "name": "Time", - "ofType": null + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CiGroupEdge", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "description", - "description": "Description of the commit message", + "name": "nodes", + "description": "A list of nodes.", "args": [ ], "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CiGroup", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "id", - "description": "ID (global ID) of the commit", + "name": "pageInfo", + "description": "Information to aid in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CiGroupEdge", + "description": "An edge in a connection.", + "fields": [ + { + "name": "cursor", + "description": "A cursor for use in pagination.", "args": [ ], @@ -3255,7 +4018,7 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "ID", + "name": "String", "ofType": null } }, @@ -3263,51 +4026,35 @@ "deprecationReason": null }, { - "name": "latestPipeline", - "description": "Latest pipeline of the commit. Deprecated in 12.5: Use `pipelines`", + "name": "node", + "description": "The item at the end of the edge.", "args": [ - { - "name": "status", - "description": "Filter pipelines by their status", - "type": { - "kind": "ENUM", - "name": "PipelineStatusEnum", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "ref", - "description": "Filter pipelines by the ref they are run for", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "sha", - "description": "Filter pipelines by the sha of the commit they are run for", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - } + ], "type": { "kind": "OBJECT", - "name": "Pipeline", + "name": "CiGroup", "ofType": null }, - "isDeprecated": true, - "deprecationReason": "Use `pipelines`. Deprecated in 12.5" - }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CiJob", + "description": null, + "fields": [ { - "name": "message", - "description": "Raw commit message", + "name": "name", + "description": "Name of the job", "args": [ ], @@ -3320,39 +4067,9 @@ "deprecationReason": null }, { - "name": "pipelines", - "description": "Pipelines of the commit ordered latest first", + "name": "needs", + "description": "Builds that must complete before the jobs run", "args": [ - { - "name": "status", - "description": "Filter pipelines by their status", - "type": { - "kind": "ENUM", - "name": "PipelineStatusEnum", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "ref", - "description": "Filter pipelines by the ref they are run for", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "sha", - "description": "Filter pipelines by the sha of the commit they are run for", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", @@ -3396,24 +4113,37 @@ ], "type": { "kind": "OBJECT", - "name": "PipelineConnection", + "name": "CiJobConnection", "ofType": null }, "isDeprecated": false, "deprecationReason": null - }, + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CiJobConnection", + "description": "The connection type for CiJob.", + "fields": [ { - "name": "sha", - "description": "SHA1 ID of the commit", + "name": "edges", + "description": "A list of edges.", "args": [ ], "type": { - "kind": "NON_NULL", + "kind": "LIST", "name": null, "ofType": { - "kind": "SCALAR", - "name": "String", + "kind": "OBJECT", + "name": "CiJobEdge", "ofType": null } }, @@ -3421,50 +4151,26 @@ "deprecationReason": null }, { - "name": "signatureHtml", - "description": "Rendered HTML of the commit signature", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "title", - "description": "Title of the commit message", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "titleHtml", - "description": "The GitLab Flavored Markdown rendering of `title`", + "name": "nodes", + "description": "A list of nodes.", "args": [ ], "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CiJob", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "webUrl", - "description": "Web URL of the commit", + "name": "pageInfo", + "description": "Information to aid in pagination.", "args": [ ], @@ -3472,8 +4178,8 @@ "kind": "NON_NULL", "name": null, "ofType": { - "kind": "SCALAR", - "name": "String", + "kind": "OBJECT", + "name": "PageInfo", "ofType": null } }, @@ -3489,28 +4195,16 @@ "possibleTypes": null }, { - "kind": "INPUT_OBJECT", - "name": "CommitAction", - "description": null, - "fields": null, - "inputFields": [ - { - "name": "action", - "description": "The action to perform, create, delete, move, update, chmod", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "CommitActionMode", - "ofType": null - } - }, - "defaultValue": null - }, + "kind": "OBJECT", + "name": "CiJobEdge", + "description": "An edge in a connection.", + "fields": [ { - "name": "filePath", - "description": "Full path to the file", + "name": "cursor", + "description": "A cursor for use in pagination.", + "args": [ + + ], "type": { "kind": "NON_NULL", "name": null, @@ -3520,298 +4214,99 @@ "ofType": null } }, - "defaultValue": null + "isDeprecated": false, + "deprecationReason": null }, { - "name": "content", - "description": "Content of the file", + "name": "node", + "description": "The item at the end of the edge.", + "args": [ + + ], "type": { - "kind": "SCALAR", - "name": "String", + "kind": "OBJECT", + "name": "CiJob", "ofType": null }, - "defaultValue": null - }, - { - "name": "previousPath", - "description": "Original full path to the file being moved", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "lastCommitId", - "description": "Last known file commit ID", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "executeFilemode", - "description": "Enables/disables the execute flag on the file", - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "encoding", - "description": "Encoding of the file. Default is text", - "type": { - "kind": "ENUM", - "name": "CommitEncoding", - "ofType": null - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "CommitActionMode", - "description": "Mode of a commit action", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "CREATE", - "description": "Create command", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "DELETE", - "description": "Delete command", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "MOVE", - "description": "Move command", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "UPDATE", - "description": "Update command", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "CHMOD", - "description": "Chmod command", "isDeprecated": false, "deprecationReason": null } ], - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "CommitCreateInput", - "description": "Autogenerated input type of CommitCreate", - "fields": null, - "inputFields": [ - { - "name": "projectPath", - "description": "Project full path the branch is associated with", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "branch", - "description": "Name of the branch", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "message", - "description": "Raw commit message", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "actions", - "description": "Array of action hashes to commit as a batch", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "CommitAction", - "ofType": null - } - } - } - }, - "defaultValue": null - }, - { - "name": "clientMutationId", - "description": "A unique identifier for the client performing the mutation.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - } + "inputFields": null, + "interfaces": [ + ], - "interfaces": null, "enumValues": null, "possibleTypes": null }, { "kind": "OBJECT", - "name": "CommitCreatePayload", - "description": "Autogenerated return type of CommitCreate", + "name": "CiStage", + "description": null, "fields": [ { - "name": "clientMutationId", - "description": "A unique identifier for the client performing the mutation.", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "commit", - "description": "The commit after mutation", + "name": "groups", + "description": "Group of jobs for the stage", "args": [ - + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } ], "type": { "kind": "OBJECT", - "name": "Commit", + "name": "CiGroupConnection", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, - { - "name": "errors", - "description": "Errors encountered during execution of the mutation.", - "args": [ - - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ - - ], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "CommitEncoding", - "description": null, - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "TEXT", - "description": "Text encoding", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "BASE64", - "description": "Base64 encoding", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "ComplianceFramework", - "description": "Represents a ComplianceFramework associated with a Project", - "fields": [ { "name": "name", - "description": "Name of the compliance framework", + "description": "Name of the stage", "args": [ ], "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "ProjectSettingEnum", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null }, "isDeprecated": false, "deprecationReason": null @@ -3826,8 +4321,8 @@ }, { "kind": "OBJECT", - "name": "ComplianceFrameworkConnection", - "description": "The connection type for ComplianceFramework.", + "name": "CiStageConnection", + "description": "The connection type for CiStage.", "fields": [ { "name": "edges", @@ -3840,7 +4335,7 @@ "name": null, "ofType": { "kind": "OBJECT", - "name": "ComplianceFrameworkEdge", + "name": "CiStageEdge", "ofType": null } }, @@ -3858,7 +4353,7 @@ "name": null, "ofType": { "kind": "OBJECT", - "name": "ComplianceFramework", + "name": "CiStage", "ofType": null } }, @@ -3893,7 +4388,7 @@ }, { "kind": "OBJECT", - "name": "ComplianceFrameworkEdge", + "name": "CiStageEdge", "description": "An edge in a connection.", "fields": [ { @@ -3922,7 +4417,7 @@ ], "type": { "kind": "OBJECT", - "name": "ComplianceFramework", + "name": "CiStage", "ofType": null }, "isDeprecated": false, @@ -3938,30 +4433,26 @@ }, { "kind": "OBJECT", - "name": "ContainerExpirationPolicy", - "description": "A tag expiration policy designed to keep only the images that matter most", + "name": "ClusterAgent", + "description": null, "fields": [ { - "name": "cadence", - "description": "This container expiration policy schedule", + "name": "createdAt", + "description": "Timestamp the cluster agent was created", "args": [ ], "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "ContainerExpirationPolicyCadenceEnum", - "ofType": null - } + "kind": "SCALAR", + "name": "Time", + "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "createdAt", - "description": "Timestamp of when the container expiration policy was created", + "name": "id", + "description": "ID of the cluster agent", "args": [ ], @@ -3970,7 +4461,7 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "Time", + "name": "ID", "ofType": null } }, @@ -3978,265 +4469,308 @@ "deprecationReason": null }, { - "name": "enabled", - "description": "Indicates whether this container expiration policy is enabled", + "name": "name", + "description": "Name of the cluster agent", "args": [ ], "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "keepN", - "description": "Number of tags to retain", + "name": "project", + "description": "The project this cluster agent is associated with", "args": [ ], "type": { - "kind": "ENUM", - "name": "ContainerExpirationPolicyKeepEnum", + "kind": "OBJECT", + "name": "Project", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "nameRegex", - "description": "Tags with names matching this regex pattern will expire", + "name": "updatedAt", + "description": "Timestamp the cluster agent was updated", "args": [ ], "type": { "kind": "SCALAR", - "name": "UntrustedRegexp", + "name": "Time", "ofType": null }, "isDeprecated": false, "deprecationReason": null - }, + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Commit", + "description": null, + "fields": [ { - "name": "nameRegexKeep", - "description": "Tags with names matching this regex pattern will be preserved", + "name": "author", + "description": "Author of the commit", "args": [ ], "type": { - "kind": "SCALAR", - "name": "UntrustedRegexp", + "kind": "OBJECT", + "name": "User", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "nextRunAt", - "description": "Next time that this container expiration policy will get executed", + "name": "authorGravatar", + "description": "Commit authors gravatar", "args": [ ], "type": { "kind": "SCALAR", - "name": "Time", + "name": "String", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "olderThan", - "description": "Tags older that this will expire", + "name": "authorName", + "description": "Commit authors name", "args": [ ], "type": { - "kind": "ENUM", - "name": "ContainerExpirationPolicyOlderThanEnum", + "kind": "SCALAR", + "name": "String", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "updatedAt", - "description": "Timestamp of when the container expiration policy was updated", + "name": "authoredDate", + "description": "Timestamp of when the commit was authored", "args": [ ], "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Time", - "ofType": null - } + "kind": "SCALAR", + "name": "Time", + "ofType": null }, "isDeprecated": false, "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ - - ], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "ContainerExpirationPolicyCadenceEnum", - "description": null, - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ + }, { - "name": "EVERY_DAY", - "description": "Every day", + "name": "description", + "description": "Description of the commit message", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, "isDeprecated": false, "deprecationReason": null }, { - "name": "EVERY_WEEK", - "description": "Every week", + "name": "descriptionHtml", + "description": "The GitLab Flavored Markdown rendering of `description`", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, "isDeprecated": false, "deprecationReason": null }, { - "name": "EVERY_TWO_WEEKS", - "description": "Every two weeks", + "name": "id", + "description": "ID (global ID) of the commit", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, "isDeprecated": false, "deprecationReason": null }, { - "name": "EVERY_MONTH", - "description": "Every month", + "name": "latestPipeline", + "description": "Latest pipeline of the commit. Deprecated in 12.5: Use `pipelines`", + "args": [ + { + "name": "status", + "description": "Filter pipelines by their status", + "type": { + "kind": "ENUM", + "name": "PipelineStatusEnum", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "ref", + "description": "Filter pipelines by the ref they are run for", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "sha", + "description": "Filter pipelines by the sha of the commit they are run for", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "Pipeline", + "ofType": null + }, + "isDeprecated": true, + "deprecationReason": "Use `pipelines`. Deprecated in 12.5" + }, + { + "name": "message", + "description": "Raw commit message", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, "isDeprecated": false, "deprecationReason": null }, { - "name": "EVERY_THREE_MONTHS", - "description": "Every three months", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "ContainerExpirationPolicyKeepEnum", - "description": null, - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "ONE_TAG", - "description": "1 tag per image name", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FIVE_TAGS", - "description": "5 tags per image name", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "TEN_TAGS", - "description": "10 tags per image name", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "TWENTY_FIVE_TAGS", - "description": "25 tags per image name", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FIFTY_TAGS", - "description": "50 tags per image name", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ONE_HUNDRED_TAGS", - "description": "100 tags per image name", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "ContainerExpirationPolicyOlderThanEnum", - "description": null, - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "SEVEN_DAYS", - "description": "7 days until tags are automatically removed", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FOURTEEN_DAYS", - "description": "14 days until tags are automatically removed", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "THIRTY_DAYS", - "description": "30 days until tags are automatically removed", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "NINETY_DAYS", - "description": "90 days until tags are automatically removed", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "CreateAlertIssueInput", - "description": "Autogenerated input type of CreateAlertIssue", - "fields": null, - "inputFields": [ - { - "name": "projectPath", - "description": "The project the alert to mutate is in", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null + "name": "pipelines", + "description": "Pipelines of the commit ordered latest first", + "args": [ + { + "name": "status", + "description": "Filter pipelines by their status", + "type": { + "kind": "ENUM", + "name": "PipelineStatusEnum", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "ref", + "description": "Filter pipelines by the ref they are run for", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "sha", + "description": "Filter pipelines by the sha of the commit they are run for", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null } + ], + "type": { + "kind": "OBJECT", + "name": "PipelineConnection", + "ofType": null }, - "defaultValue": null + "isDeprecated": false, + "deprecationReason": null }, { - "name": "iid", - "description": "The iid of the alert to mutate", + "name": "sha", + "description": "SHA1 ID of the commit", + "args": [ + + ], "type": { "kind": "NON_NULL", "name": null, @@ -4246,45 +4780,40 @@ "ofType": null } }, - "defaultValue": null + "isDeprecated": false, + "deprecationReason": null }, { - "name": "clientMutationId", - "description": "A unique identifier for the client performing the mutation.", + "name": "signatureHtml", + "description": "Rendered HTML of the commit signature", + "args": [ + + ], "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "CreateAlertIssuePayload", - "description": "Autogenerated return type of CreateAlertIssue", - "fields": [ + "isDeprecated": false, + "deprecationReason": null + }, { - "name": "alert", - "description": "The alert after mutation", + "name": "title", + "description": "Title of the commit message", "args": [ ], "type": { - "kind": "OBJECT", - "name": "AlertManagementAlert", + "kind": "SCALAR", + "name": "String", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "clientMutationId", - "description": "A unique identifier for the client performing the mutation.", + "name": "titleHtml", + "description": "The GitLab Flavored Markdown rendering of `title`", "args": [ ], @@ -4297,8 +4826,8 @@ "deprecationReason": null }, { - "name": "errors", - "description": "Errors encountered during execution of the mutation.", + "name": "webPath", + "description": "Web path of the commit", "args": [ ], @@ -4306,46 +4835,28 @@ "kind": "NON_NULL", "name": null, "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "issue", - "description": "The issue created after mutation", - "args": [ - - ], - "type": { - "kind": "OBJECT", - "name": "Issue", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "todo", - "description": "The todo after mutation", + "name": "webUrl", + "description": "Web URL of the commit", "args": [ ], "type": { - "kind": "OBJECT", - "name": "Todo", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null @@ -4360,88 +4871,84 @@ }, { "kind": "INPUT_OBJECT", - "name": "CreateAnnotationInput", - "description": "Autogenerated input type of CreateAnnotation", + "name": "CommitAction", + "description": null, "fields": null, "inputFields": [ { - "name": "environmentId", - "description": "The global id of the environment to add an annotation to", - "type": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "clusterId", - "description": "The global id of the cluster to add an annotation to", + "name": "action", + "description": "The action to perform, create, delete, move, update, chmod", "type": { - "kind": "SCALAR", - "name": "ID", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "CommitActionMode", + "ofType": null + } }, "defaultValue": null }, { - "name": "startingAt", - "description": "Timestamp indicating starting moment to which the annotation relates", + "name": "filePath", + "description": "Full path to the file", "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", - "name": "Time", + "name": "String", "ofType": null } }, "defaultValue": null }, { - "name": "endingAt", - "description": "Timestamp indicating ending moment to which the annotation relates", + "name": "content", + "description": "Content of the file", "type": { "kind": "SCALAR", - "name": "Time", + "name": "String", "ofType": null }, "defaultValue": null }, { - "name": "dashboardPath", - "description": "The path to a file defining the dashboard on which the annotation should be added", + "name": "previousPath", + "description": "Original full path to the file being moved", "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null }, "defaultValue": null }, { - "name": "description", - "description": "The description of the annotation", + "name": "lastCommitId", + "description": "Last known file commit ID", "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null }, "defaultValue": null }, { - "name": "clientMutationId", - "description": "A unique identifier for the client performing the mutation.", + "name": "executeFilemode", + "description": "Enables/disables the execute flag on the file", "type": { "kind": "SCALAR", - "name": "String", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "encoding", + "description": "Encoding of the file. Default is text", + "type": { + "kind": "ENUM", + "name": "CommitEncoding", "ofType": null }, "defaultValue": null @@ -4452,76 +4959,50 @@ "possibleTypes": null }, { - "kind": "OBJECT", - "name": "CreateAnnotationPayload", - "description": "Autogenerated return type of CreateAnnotation", - "fields": [ + "kind": "ENUM", + "name": "CommitActionMode", + "description": "Mode of a commit action", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ { - "name": "annotation", - "description": "The created annotation", - "args": [ - - ], - "type": { - "kind": "OBJECT", - "name": "MetricsDashboardAnnotation", - "ofType": null - }, + "name": "CREATE", + "description": "Create command", "isDeprecated": false, "deprecationReason": null }, { - "name": "clientMutationId", - "description": "A unique identifier for the client performing the mutation.", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, + "name": "DELETE", + "description": "Delete command", "isDeprecated": false, "deprecationReason": null }, { - "name": "errors", - "description": "Errors encountered during execution of the mutation.", - "args": [ - - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - } - }, + "name": "MOVE", + "description": "Move command", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "UPDATE", + "description": "Update command", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "CHMOD", + "description": "Chmod command", "isDeprecated": false, "deprecationReason": null } ], - "inputFields": null, - "interfaces": [ - - ], - "enumValues": null, "possibleTypes": null }, { "kind": "INPUT_OBJECT", - "name": "CreateBranchInput", - "description": "Autogenerated input type of CreateBranch", + "name": "CommitCreateInput", + "description": "Autogenerated input type of CommitCreate", "fields": null, "inputFields": [ { @@ -4539,7 +5020,7 @@ "defaultValue": null }, { - "name": "name", + "name": "branch", "description": "Name of the branch", "type": { "kind": "NON_NULL", @@ -4553,8 +5034,8 @@ "defaultValue": null }, { - "name": "ref", - "description": "Branch name or commit SHA to create branch from", + "name": "message", + "description": "Raw commit message", "type": { "kind": "NON_NULL", "name": null, @@ -4566,6 +5047,28 @@ }, "defaultValue": null }, + { + "name": "actions", + "description": "Array of action hashes to commit as a batch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CommitAction", + "ofType": null + } + } + } + }, + "defaultValue": null + }, { "name": "clientMutationId", "description": "A unique identifier for the client performing the mutation.", @@ -4583,32 +5086,32 @@ }, { "kind": "OBJECT", - "name": "CreateBranchPayload", - "description": "Autogenerated return type of CreateBranch", + "name": "CommitCreatePayload", + "description": "Autogenerated return type of CommitCreate", "fields": [ { - "name": "branch", - "description": "Branch after mutation", + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", "args": [ ], "type": { - "kind": "OBJECT", - "name": "Branch", + "kind": "SCALAR", + "name": "String", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "clientMutationId", - "description": "A unique identifier for the client performing the mutation.", + "name": "commit", + "description": "The commit after mutation", "args": [ ], "type": { - "kind": "SCALAR", - "name": "String", + "kind": "OBJECT", + "name": "Commit", "ofType": null }, "isDeprecated": false, @@ -4649,100 +5152,36 @@ "possibleTypes": null }, { - "kind": "INPUT_OBJECT", - "name": "CreateDiffNoteInput", - "description": "Autogenerated input type of CreateDiffNote", + "kind": "ENUM", + "name": "CommitEncoding", + "description": null, "fields": null, - "inputFields": [ + "inputFields": null, + "interfaces": null, + "enumValues": [ { - "name": "noteableId", - "description": "The global id of the resource to add a note to", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - }, - "defaultValue": null + "name": "TEXT", + "description": "Text encoding", + "isDeprecated": false, + "deprecationReason": null }, { - "name": "body", - "description": "Content of the note", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "confidential", - "description": "The confidentiality flag of a note. Default is false.", - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "position", - "description": "The position of this note on a diff", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "DiffPositionInput", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "clientMutationId", - "description": "A unique identifier for the client performing the mutation.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null + "name": "BASE64", + "description": "Base64 encoding", + "isDeprecated": false, + "deprecationReason": null } ], - "interfaces": null, - "enumValues": null, "possibleTypes": null }, { "kind": "OBJECT", - "name": "CreateDiffNotePayload", - "description": "Autogenerated return type of CreateDiffNote", + "name": "ComplianceFramework", + "description": "Represents a ComplianceFramework associated with a Project", "fields": [ { - "name": "clientMutationId", - "description": "A unique identifier for the client performing the mutation.", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "errors", - "description": "Errors encountered during execution of the mutation.", + "name": "name", + "description": "Name of the compliance framework", "args": [ ], @@ -4750,35 +5189,13 @@ "kind": "NON_NULL", "name": null, "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } + "kind": "ENUM", + "name": "ProjectSettingEnum", + "ofType": null } }, "isDeprecated": false, "deprecationReason": null - }, - { - "name": "note", - "description": "The note after mutation", - "args": [ - - ], - "type": { - "kind": "OBJECT", - "name": "Note", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null } ], "inputFields": null, @@ -4789,204 +5206,108 @@ "possibleTypes": null }, { - "kind": "INPUT_OBJECT", - "name": "CreateEpicInput", - "description": "Autogenerated input type of CreateEpic", - "fields": null, - "inputFields": [ + "kind": "OBJECT", + "name": "ComplianceFrameworkConnection", + "description": "The connection type for ComplianceFramework.", + "fields": [ { - "name": "groupPath", - "description": "The group the epic to mutate is in", + "name": "edges", + "description": "A list of edges.", + "args": [ + + ], "type": { - "kind": "NON_NULL", + "kind": "LIST", "name": null, "ofType": { - "kind": "SCALAR", - "name": "ID", + "kind": "OBJECT", + "name": "ComplianceFrameworkEdge", "ofType": null } }, - "defaultValue": null - }, - { - "name": "title", - "description": "The title of the epic", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "description", - "description": "The description of the epic", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "confidential", - "description": "Indicates if the epic is confidential. Will be ignored if `confidential_epics` feature flag is disabled", - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "startDateFixed", - "description": "The start date of the epic", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "dueDateFixed", - "description": "The end date of the epic", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "startDateIsFixed", - "description": "Indicates start date should be sourced from start_date_fixed field not the issue milestones", - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "dueDateIsFixed", - "description": "Indicates end date should be sourced from due_date_fixed field not the issue milestones", - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": null + "isDeprecated": false, + "deprecationReason": null }, { - "name": "addLabelIds", - "description": "The IDs of labels to be added to the epic.", + "name": "nodes", + "description": "A list of nodes.", + "args": [ + + ], "type": { "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } + "kind": "OBJECT", + "name": "ComplianceFramework", + "ofType": null } }, - "defaultValue": null + "isDeprecated": false, + "deprecationReason": null }, { - "name": "removeLabelIds", - "description": "The IDs of labels to be removed from the epic.", + "name": "pageInfo", + "description": "Information to aid in pagination.", + "args": [ + + ], "type": { - "kind": "LIST", + "kind": "NON_NULL", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null } }, - "defaultValue": null - }, - { - "name": "clientMutationId", - "description": "A unique identifier for the client performing the mutation.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null + "isDeprecated": false, + "deprecationReason": null } ], - "interfaces": null, + "inputFields": null, + "interfaces": [ + + ], "enumValues": null, "possibleTypes": null }, { "kind": "OBJECT", - "name": "CreateEpicPayload", - "description": "Autogenerated return type of CreateEpic", + "name": "ComplianceFrameworkEdge", + "description": "An edge in a connection.", "fields": [ { - "name": "clientMutationId", - "description": "A unique identifier for the client performing the mutation.", + "name": "cursor", + "description": "A cursor for use in pagination.", "args": [ ], "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "epic", - "description": "The created epic", + "name": "node", + "description": "The item at the end of the edge.", "args": [ ], "type": { "kind": "OBJECT", - "name": "Epic", + "name": "ComplianceFramework", "ofType": null }, "isDeprecated": false, "deprecationReason": null - }, - { - "name": "errors", - "description": "Errors encountered during execution of the mutation.", - "args": [ - - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null } ], "inputFields": null, @@ -4998,13 +5319,13 @@ }, { "kind": "INPUT_OBJECT", - "name": "CreateImageDiffNoteInput", - "description": "Autogenerated input type of CreateImageDiffNote", + "name": "ConfigureSastInput", + "description": "Autogenerated input type of ConfigureSast", "fields": null, "inputFields": [ { - "name": "noteableId", - "description": "The global id of the resource to add a note to", + "name": "projectPath", + "description": "Full path of the project.", "type": { "kind": "NON_NULL", "name": null, @@ -5017,38 +5338,14 @@ "defaultValue": null }, { - "name": "body", - "description": "Content of the note", + "name": "configuration", + "description": "Payload containing SAST variable values (https://docs.gitlab.com/ee/user/application_security/sast/#available-variables).", "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "confidential", - "description": "The confidentiality flag of a note. Default is false.", - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "position", - "description": "The position of this note on a diff", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "DiffImagePositionInput", + "name": "JSON", "ofType": null } }, @@ -5071,8 +5368,8 @@ }, { "kind": "OBJECT", - "name": "CreateImageDiffNotePayload", - "description": "Autogenerated return type of CreateImageDiffNote", + "name": "ConfigureSastPayload", + "description": "Autogenerated return type of ConfigureSast", "fields": [ { "name": "clientMutationId", @@ -5115,14 +5412,14 @@ "deprecationReason": null }, { - "name": "note", - "description": "The note after mutation", + "name": "result", + "description": "JSON containing the status of MR creation.", "args": [ ], "type": { - "kind": "OBJECT", - "name": "Note", + "kind": "SCALAR", + "name": "JSON", "ofType": null }, "isDeprecated": false, @@ -5137,135 +5434,148 @@ "possibleTypes": null }, { - "kind": "INPUT_OBJECT", - "name": "CreateIterationInput", - "description": "Autogenerated input type of CreateIteration", - "fields": null, - "inputFields": [ + "kind": "OBJECT", + "name": "ContainerExpirationPolicy", + "description": "A tag expiration policy designed to keep only the images that matter most", + "fields": [ { - "name": "groupPath", - "description": "The target group for the iteration", + "name": "cadence", + "description": "This container expiration policy schedule", + "args": [ + + ], "type": { "kind": "NON_NULL", "name": null, "ofType": { - "kind": "SCALAR", - "name": "ID", + "kind": "ENUM", + "name": "ContainerExpirationPolicyCadenceEnum", "ofType": null } }, - "defaultValue": null + "isDeprecated": false, + "deprecationReason": null }, { - "name": "title", - "description": "The title of the iteration", + "name": "createdAt", + "description": "Timestamp of when the container expiration policy was created", + "args": [ + + ], "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + } }, - "defaultValue": null + "isDeprecated": false, + "deprecationReason": null }, { - "name": "description", - "description": "The description of the iteration", + "name": "enabled", + "description": "Indicates whether this container expiration policy is enabled", + "args": [ + + ], "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } }, - "defaultValue": null + "isDeprecated": false, + "deprecationReason": null }, { - "name": "startDate", - "description": "The start date of the iteration", + "name": "keepN", + "description": "Number of tags to retain", + "args": [ + + ], "type": { - "kind": "SCALAR", - "name": "String", + "kind": "ENUM", + "name": "ContainerExpirationPolicyKeepEnum", "ofType": null }, - "defaultValue": null + "isDeprecated": false, + "deprecationReason": null }, { - "name": "dueDate", - "description": "The end date of the iteration", + "name": "nameRegex", + "description": "Tags with names matching this regex pattern will expire", + "args": [ + + ], "type": { "kind": "SCALAR", - "name": "String", + "name": "UntrustedRegexp", "ofType": null }, - "defaultValue": null + "isDeprecated": false, + "deprecationReason": null }, { - "name": "clientMutationId", - "description": "A unique identifier for the client performing the mutation.", + "name": "nameRegexKeep", + "description": "Tags with names matching this regex pattern will be preserved", + "args": [ + + ], "type": { "kind": "SCALAR", - "name": "String", + "name": "UntrustedRegexp", "ofType": null }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "CreateIterationPayload", - "description": "Autogenerated return type of CreateIteration", - "fields": [ + "isDeprecated": false, + "deprecationReason": null + }, { - "name": "clientMutationId", - "description": "A unique identifier for the client performing the mutation.", + "name": "nextRunAt", + "description": "Next time that this container expiration policy will get executed", "args": [ ], "type": { "kind": "SCALAR", - "name": "String", + "name": "Time", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "errors", - "description": "Errors encountered during execution of the mutation.", + "name": "olderThan", + "description": "Tags older that this will expire", "args": [ ], "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - } + "kind": "ENUM", + "name": "ContainerExpirationPolicyOlderThanEnum", + "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "iteration", - "description": "The created iteration", + "name": "updatedAt", + "description": "Timestamp of when the container expiration policy was updated", "args": [ ], "type": { - "kind": "OBJECT", - "name": "Iteration", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null @@ -5279,14 +5589,137 @@ "possibleTypes": null }, { - "kind": "INPUT_OBJECT", - "name": "CreateNoteInput", - "description": "Autogenerated input type of CreateNote", + "kind": "ENUM", + "name": "ContainerExpirationPolicyCadenceEnum", + "description": null, "fields": null, - "inputFields": [ + "inputFields": null, + "interfaces": null, + "enumValues": [ { - "name": "noteableId", - "description": "The global id of the resource to add a note to", + "name": "EVERY_DAY", + "description": "Every day", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EVERY_WEEK", + "description": "Every week", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EVERY_TWO_WEEKS", + "description": "Every two weeks", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EVERY_MONTH", + "description": "Every month", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EVERY_THREE_MONTHS", + "description": "Every three months", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "ContainerExpirationPolicyKeepEnum", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "ONE_TAG", + "description": "1 tag per image name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "FIVE_TAGS", + "description": "5 tags per image name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "TEN_TAGS", + "description": "10 tags per image name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "TWENTY_FIVE_TAGS", + "description": "25 tags per image name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "FIFTY_TAGS", + "description": "50 tags per image name", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "ONE_HUNDRED_TAGS", + "description": "100 tags per image name", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "ContainerExpirationPolicyOlderThanEnum", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "SEVEN_DAYS", + "description": "7 days until tags are automatically removed", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "FOURTEEN_DAYS", + "description": "14 days until tags are automatically removed", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "THIRTY_DAYS", + "description": "30 days until tags are automatically removed", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "NINETY_DAYS", + "description": "90 days until tags are automatically removed", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "CreateAlertIssueInput", + "description": "Autogenerated input type of CreateAlertIssue", + "fields": null, + "inputFields": [ + { + "name": "projectPath", + "description": "The project the alert to mutate is in", "type": { "kind": "NON_NULL", "name": null, @@ -5299,8 +5732,8 @@ "defaultValue": null }, { - "name": "body", - "description": "Content of the note", + "name": "iid", + "description": "The iid of the alert to mutate", "type": { "kind": "NON_NULL", "name": null, @@ -5312,26 +5745,6 @@ }, "defaultValue": null }, - { - "name": "confidential", - "description": "The confidentiality flag of a note. Default is false.", - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "discussionId", - "description": "The global id of the discussion this note is in reply to", - "type": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - }, - "defaultValue": null - }, { "name": "clientMutationId", "description": "A unique identifier for the client performing the mutation.", @@ -5349,9 +5762,23 @@ }, { "kind": "OBJECT", - "name": "CreateNotePayload", - "description": "Autogenerated return type of CreateNote", + "name": "CreateAlertIssuePayload", + "description": "Autogenerated return type of CreateAlertIssue", "fields": [ + { + "name": "alert", + "description": "The alert after mutation", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "AlertManagementAlert", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "clientMutationId", "description": "A unique identifier for the client performing the mutation.", @@ -5393,14 +5820,28 @@ "deprecationReason": null }, { - "name": "note", - "description": "The note after mutation", + "name": "issue", + "description": "The issue created after mutation", "args": [ ], "type": { "kind": "OBJECT", - "name": "Note", + "name": "Issue", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "todo", + "description": "The todo after mutation", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "Todo", "ofType": null }, "isDeprecated": false, @@ -5416,13 +5857,57 @@ }, { "kind": "INPUT_OBJECT", - "name": "CreateRequirementInput", - "description": "Autogenerated input type of CreateRequirement", + "name": "CreateAnnotationInput", + "description": "Autogenerated input type of CreateAnnotation", "fields": null, "inputFields": [ { - "name": "title", - "description": "Title of the requirement", + "name": "environmentId", + "description": "The global id of the environment to add an annotation to", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "clusterId", + "description": "The global id of the cluster to add an annotation to", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "startingAt", + "description": "Timestamp indicating starting moment to which the annotation relates", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "endingAt", + "description": "Timestamp indicating ending moment to which the annotation relates", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "dashboardPath", + "description": "The path to a file defining the dashboard on which the annotation should be added", "type": { "kind": "NON_NULL", "name": null, @@ -5435,14 +5920,14 @@ "defaultValue": null }, { - "name": "projectPath", - "description": "The project full path the requirement is associated with", + "name": "description", + "description": "The description of the annotation", "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", - "name": "ID", + "name": "String", "ofType": null } }, @@ -5465,9 +5950,23 @@ }, { "kind": "OBJECT", - "name": "CreateRequirementPayload", - "description": "Autogenerated return type of CreateRequirement", + "name": "CreateAnnotationPayload", + "description": "Autogenerated return type of CreateAnnotation", "fields": [ + { + "name": "annotation", + "description": "The created annotation", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "MetricsDashboardAnnotation", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "clientMutationId", "description": "A unique identifier for the client performing the mutation.", @@ -5507,20 +6006,6 @@ }, "isDeprecated": false, "deprecationReason": null - }, - { - "name": "requirement", - "description": "The requirement after mutation", - "args": [ - - ], - "type": { - "kind": "OBJECT", - "name": "Requirement", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null } ], "inputFields": null, @@ -5532,110 +6017,48 @@ }, { "kind": "INPUT_OBJECT", - "name": "CreateSnippetInput", - "description": "Autogenerated input type of CreateSnippet", + "name": "CreateBranchInput", + "description": "Autogenerated input type of CreateBranch", "fields": null, "inputFields": [ { - "name": "title", - "description": "Title of the snippet", + "name": "projectPath", + "description": "Project full path the branch is associated with", "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", - "name": "String", + "name": "ID", "ofType": null } }, "defaultValue": null }, { - "name": "fileName", - "description": "File name of the snippet", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "content", - "description": "Content of the snippet", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "description", - "description": "Description of the snippet", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "visibilityLevel", - "description": "The visibility level of the snippet", + "name": "name", + "description": "Name of the branch", "type": { "kind": "NON_NULL", "name": null, "ofType": { - "kind": "ENUM", - "name": "VisibilityLevelsEnum", + "kind": "SCALAR", + "name": "String", "ofType": null } }, "defaultValue": null }, { - "name": "projectPath", - "description": "The project full path the snippet is associated with", - "type": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "uploadedFiles", - "description": "The paths to files uploaded in the snippet description", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - }, - "defaultValue": null - }, - { - "name": "files", - "description": "The snippet files to create", + "name": "ref", + "description": "Branch name or commit SHA to create branch from", "type": { - "kind": "LIST", + "kind": "NON_NULL", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "SnippetFileInputType", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null @@ -5657,9 +6080,23 @@ }, { "kind": "OBJECT", - "name": "CreateSnippetPayload", - "description": "Autogenerated return type of CreateSnippet", + "name": "CreateBranchPayload", + "description": "Autogenerated return type of CreateBranch", "fields": [ + { + "name": "branch", + "description": "Branch after mutation", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "Branch", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "clientMutationId", "description": "A unique identifier for the client performing the mutation.", @@ -5699,20 +6136,6 @@ }, "isDeprecated": false, "deprecationReason": null - }, - { - "name": "snippet", - "description": "The snippet after mutation", - "args": [ - - ], - "type": { - "kind": "OBJECT", - "name": "Snippet", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null } ], "inputFields": null, @@ -5722,32 +6145,15 @@ "enumValues": null, "possibleTypes": null }, - { - "kind": "ENUM", - "name": "DastScanTypeEnum", - "description": null, - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "PASSIVE", - "description": "Passive DAST scan. This scan will not make active attacks against the target site.", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, { "kind": "INPUT_OBJECT", - "name": "DastSiteProfileCreateInput", - "description": "Autogenerated input type of DastSiteProfileCreate", + "name": "CreateClusterAgentInput", + "description": "Autogenerated input type of CreateClusterAgent", "fields": null, "inputFields": [ { - "name": "fullPath", - "description": "The project the site profile belongs to.", + "name": "projectPath", + "description": "Full path of the associated project for this cluster agent", "type": { "kind": "NON_NULL", "name": null, @@ -5760,8 +6166,8 @@ "defaultValue": null }, { - "name": "profileName", - "description": "The name of the site profile.", + "name": "name", + "description": "Name of the cluster agent", "type": { "kind": "NON_NULL", "name": null, @@ -5773,16 +6179,6 @@ }, "defaultValue": null }, - { - "name": "targetUrl", - "description": "The URL of the target to be scanned.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, { "name": "clientMutationId", "description": "A unique identifier for the client performing the mutation.", @@ -5800,8 +6196,8 @@ }, { "kind": "OBJECT", - "name": "DastSiteProfileCreatePayload", - "description": "Autogenerated return type of DastSiteProfileCreate", + "name": "CreateClusterAgentPayload", + "description": "Autogenerated return type of CreateClusterAgent", "fields": [ { "name": "clientMutationId", @@ -5817,6 +6213,20 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "clusterAgent", + "description": "Cluster agent created after mutation", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "ClusterAgent", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "errors", "description": "Errors encountered during execution of the mutation.", @@ -5842,20 +6252,6 @@ }, "isDeprecated": false, "deprecationReason": null - }, - { - "name": "id", - "description": "ID of the site profile.", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null } ], "inputFields": null, @@ -5867,13 +6263,13 @@ }, { "kind": "INPUT_OBJECT", - "name": "DeleteAnnotationInput", - "description": "Autogenerated input type of DeleteAnnotation", + "name": "CreateDiffNoteInput", + "description": "Autogenerated input type of CreateDiffNote", "fields": null, "inputFields": [ { - "name": "id", - "description": "The global id of the annotation to delete", + "name": "noteableId", + "description": "The global id of the resource to add a note to", "type": { "kind": "NON_NULL", "name": null, @@ -5885,6 +6281,44 @@ }, "defaultValue": null }, + { + "name": "body", + "description": "Content of the note", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "confidential", + "description": "The confidentiality flag of a note. Default is false.", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "position", + "description": "The position of this note on a diff", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "DiffPositionInput", + "ofType": null + } + }, + "defaultValue": null + }, { "name": "clientMutationId", "description": "A unique identifier for the client performing the mutation.", @@ -5902,8 +6336,8 @@ }, { "kind": "OBJECT", - "name": "DeleteAnnotationPayload", - "description": "Autogenerated return type of DeleteAnnotation", + "name": "CreateDiffNotePayload", + "description": "Autogenerated return type of CreateDiffNote", "fields": [ { "name": "clientMutationId", @@ -5944,9 +6378,2166 @@ }, "isDeprecated": false, "deprecationReason": null - } - ], - "inputFields": null, + }, + { + "name": "note", + "description": "The note after mutation", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "Note", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "CreateEpicInput", + "description": "Autogenerated input type of CreateEpic", + "fields": null, + "inputFields": [ + { + "name": "groupPath", + "description": "The group the epic to mutate is in", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "title", + "description": "The title of the epic", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "description", + "description": "The description of the epic", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "confidential", + "description": "Indicates if the epic is confidential. Will be ignored if `confidential_epics` feature flag is disabled", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "startDateFixed", + "description": "The start date of the epic", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "dueDateFixed", + "description": "The end date of the epic", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "startDateIsFixed", + "description": "Indicates start date should be sourced from start_date_fixed field not the issue milestones", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "dueDateIsFixed", + "description": "Indicates end date should be sourced from due_date_fixed field not the issue milestones", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "addLabelIds", + "description": "The IDs of labels to be added to the epic.", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "removeLabelIds", + "description": "The IDs of labels to be removed from the epic.", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CreateEpicPayload", + "description": "Autogenerated return type of CreateEpic", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "epic", + "description": "The created epic", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "Epic", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "CreateImageDiffNoteInput", + "description": "Autogenerated input type of CreateImageDiffNote", + "fields": null, + "inputFields": [ + { + "name": "noteableId", + "description": "The global id of the resource to add a note to", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "body", + "description": "Content of the note", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "confidential", + "description": "The confidentiality flag of a note. Default is false.", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "position", + "description": "The position of this note on a diff", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "DiffImagePositionInput", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CreateImageDiffNotePayload", + "description": "Autogenerated return type of CreateImageDiffNote", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "note", + "description": "The note after mutation", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "Note", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "CreateIterationInput", + "description": "Autogenerated input type of CreateIteration", + "fields": null, + "inputFields": [ + { + "name": "groupPath", + "description": "The target group for the iteration", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "projectPath", + "description": "The target project for the iteration", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "title", + "description": "The title of the iteration", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "description", + "description": "The description of the iteration", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "startDate", + "description": "The start date of the iteration", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "dueDate", + "description": "The end date of the iteration", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CreateIterationPayload", + "description": "Autogenerated return type of CreateIteration", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "iteration", + "description": "The created iteration", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "Iteration", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "CreateNoteInput", + "description": "Autogenerated input type of CreateNote", + "fields": null, + "inputFields": [ + { + "name": "noteableId", + "description": "The global id of the resource to add a note to", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "body", + "description": "Content of the note", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "confidential", + "description": "The confidentiality flag of a note. Default is false.", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "discussionId", + "description": "The global id of the discussion this note is in reply to", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CreateNotePayload", + "description": "Autogenerated return type of CreateNote", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "note", + "description": "The note after mutation", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "Note", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "CreateRequirementInput", + "description": "Autogenerated input type of CreateRequirement", + "fields": null, + "inputFields": [ + { + "name": "title", + "description": "Title of the requirement", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "projectPath", + "description": "The project full path the requirement is associated with", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CreateRequirementPayload", + "description": "Autogenerated return type of CreateRequirement", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "requirement", + "description": "The requirement after mutation", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "Requirement", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "CreateSnippetInput", + "description": "Autogenerated input type of CreateSnippet", + "fields": null, + "inputFields": [ + { + "name": "title", + "description": "Title of the snippet", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "fileName", + "description": "File name of the snippet", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "content", + "description": "Content of the snippet", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "description", + "description": "Description of the snippet", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "visibilityLevel", + "description": "The visibility level of the snippet", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "VisibilityLevelsEnum", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "projectPath", + "description": "The project full path the snippet is associated with", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "uploadedFiles", + "description": "The paths to files uploaded in the snippet description", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "blobActions", + "description": "Actions to perform over the snippet repository and blobs", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "SnippetBlobActionInputType", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CreateSnippetPayload", + "description": "Autogenerated return type of CreateSnippet", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "snippet", + "description": "The snippet after mutation", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "Snippet", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "DastOnDemandScanCreateInput", + "description": "Autogenerated input type of DastOnDemandScanCreate", + "fields": null, + "inputFields": [ + { + "name": "fullPath", + "description": "The project the site profile belongs to.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "dastSiteProfileId", + "description": "ID of the site profile to be used for the scan.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "DastSiteProfileID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "DastOnDemandScanCreatePayload", + "description": "Autogenerated return type of DastOnDemandScanCreate", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pipelineUrl", + "description": "URL of the pipeline that was created.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "DastScanTypeEnum", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "PASSIVE", + "description": "Passive DAST scan. This scan will not make active attacks against the target site.", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "DastScannerProfile", + "description": "Represents a DAST scanner profile.", + "fields": [ + { + "name": "id", + "description": "ID of the DAST scanner profile", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "profileName", + "description": "Name of the DAST scanner profile", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "spiderTimeout", + "description": "The maximum number of seconds allowed for the spider to traverse the site", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "targetTimeout", + "description": "The maximum number of seconds allowed for the site under test to respond to a request", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "DastScannerProfileConnection", + "description": "The connection type for DastScannerProfile.", + "fields": [ + { + "name": "edges", + "description": "A list of edges.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "DastScannerProfileEdge", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": "A list of nodes.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "DastScannerProfile", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": "Information to aid in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "DastScannerProfileCreateInput", + "description": "Autogenerated input type of DastScannerProfileCreate", + "fields": null, + "inputFields": [ + { + "name": "fullPath", + "description": "The project the scanner profile belongs to.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "profileName", + "description": "The name of the scanner profile.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "spiderTimeout", + "description": "The maximum number of seconds allowed for the spider to traverse the site.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "targetTimeout", + "description": "The maximum number of seconds allowed for the site under test to respond to a request.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "DastScannerProfileCreatePayload", + "description": "Autogenerated return type of DastScannerProfileCreate", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "ID of the scanner profile.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "DastScannerProfileEdge", + "description": "An edge in a connection.", + "fields": [ + { + "name": "cursor", + "description": "A cursor for use in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": "The item at the end of the edge.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "DastScannerProfile", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "DastSiteProfile", + "description": "Represents a DAST Site Profile.", + "fields": [ + { + "name": "editPath", + "description": "Relative web path to the edit page of a site profile", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "ID of the site profile", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "DastSiteProfileID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "profileName", + "description": "The name of the site profile", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "targetUrl", + "description": "The URL of the target to be scanned", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "userPermissions", + "description": "Permissions for the current user on the resource", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "DastSiteProfilePermissions", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "validationStatus", + "description": "The current validation status of the site profile", + "args": [ + + ], + "type": { + "kind": "ENUM", + "name": "DastSiteProfileValidationStatusEnum", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "DastSiteProfileConnection", + "description": "The connection type for DastSiteProfile.", + "fields": [ + { + "name": "edges", + "description": "A list of edges.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "DastSiteProfileEdge", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": "A list of nodes.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "DastSiteProfile", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": "Information to aid in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "DastSiteProfileCreateInput", + "description": "Autogenerated input type of DastSiteProfileCreate", + "fields": null, + "inputFields": [ + { + "name": "fullPath", + "description": "The project the site profile belongs to.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "profileName", + "description": "The name of the site profile.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "targetUrl", + "description": "The URL of the target to be scanned.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "DastSiteProfileCreatePayload", + "description": "Autogenerated return type of DastSiteProfileCreate", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "ID of the site profile.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "DastSiteProfileID", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "DastSiteProfileDeleteInput", + "description": "Autogenerated input type of DastSiteProfileDelete", + "fields": null, + "inputFields": [ + { + "name": "fullPath", + "description": "The project the site profile belongs to.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "id", + "description": "ID of the site profile to be deleted.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "DastSiteProfileID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "DastSiteProfileDeletePayload", + "description": "Autogenerated return type of DastSiteProfileDelete", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "DastSiteProfileEdge", + "description": "An edge in a connection.", + "fields": [ + { + "name": "cursor", + "description": "A cursor for use in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": "The item at the end of the edge.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "DastSiteProfile", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "DastSiteProfileID", + "description": "Identifier of DastSiteProfile", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "DastSiteProfilePermissions", + "description": "Check permissions for the current user on site profile", + "fields": [ + { + "name": "createOnDemandDastScan", + "description": "Indicates the user can perform `create_on_demand_dast_scan` on this resource", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "DastSiteProfileUpdateInput", + "description": "Autogenerated input type of DastSiteProfileUpdate", + "fields": null, + "inputFields": [ + { + "name": "fullPath", + "description": "The project the site profile belongs to.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "id", + "description": "ID of the site profile to be updated.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "DastSiteProfileID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "profileName", + "description": "The name of the site profile.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "targetUrl", + "description": "The URL of the target to be scanned.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "DastSiteProfileUpdatePayload", + "description": "Autogenerated return type of DastSiteProfileUpdate", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "ID of the site profile.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "DastSiteProfileID", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "DastSiteProfileValidationStatusEnum", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "PENDING_VALIDATION", + "description": "Site validation process has not started", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "INPROGRESS_VALIDATION", + "description": "Site validation process is in progress", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "PASSED_VALIDATION", + "description": "Site validation process finished successfully", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "FAILED_VALIDATION", + "description": "Site validation process finished but failed", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "DeleteAnnotationInput", + "description": "Autogenerated input type of DeleteAnnotation", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": "The global id of the annotation to delete", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "DeleteAnnotationPayload", + "description": "Autogenerated return type of DeleteAnnotation", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, "interfaces": [ ], @@ -7575,6 +10166,138 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "SCALAR", + "name": "DesignManagementDesignID", + "description": "Identifier of DesignManagement::Design", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "DesignManagementMoveInput", + "description": "Autogenerated input type of DesignManagementMove", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": "ID of the design to move", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "DesignManagementDesignID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "previous", + "description": "ID of the immediately preceding design", + "type": { + "kind": "SCALAR", + "name": "DesignManagementDesignID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "next", + "description": "ID of the immediately following design", + "type": { + "kind": "SCALAR", + "name": "DesignManagementDesignID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "DesignManagementMovePayload", + "description": "Autogenerated return type of DesignManagementMove", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "designCollection", + "description": "The current state of the collection", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "DesignCollection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", "name": "DesignManagementUploadInput", @@ -9878,6 +12601,20 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "latestOpenedMostSevereAlert", + "description": "The most severe open alert for the environment. If multiple alerts have equal severity, the most recent is returned.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "AlertManagementAlert", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "metricsDashboard", "description": "Metrics dashboard schema for the environment", @@ -10194,6 +12931,16 @@ }, "defaultValue": null }, + { + "name": "milestoneTitle", + "description": "Filter epics by milestone title, computed from epic's issues", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, { "name": "iidStartsWith", "description": "Filter epics by iid for autocomplete", @@ -11115,7 +13862,7 @@ }, { "name": "projectPath", - "description": "The project the issue belongs to", + "description": "The full path of the project the issue belongs to", "type": { "kind": "NON_NULL", "name": null, @@ -11311,7 +14058,7 @@ "fields": [ { "name": "closedEpics", - "description": "Number of closed sub-epics", + "description": "Number of closed child epics", "args": [ ], @@ -11339,7 +14086,7 @@ }, { "name": "openedEpics", - "description": "Number of opened sub-epics", + "description": "Number of opened child epics", "args": [ ], @@ -11590,6 +14337,24 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "blocked", + "description": "Indicates the issue is blocked", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "closedAt", "description": "Timestamp of when the issue was closed", @@ -12145,6 +14910,20 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "statusPagePublishedIncident", + "description": "Indicates whether an issue is published to the status page", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "subscribed", "description": "Indicates the currently logged in user is subscribed to the issue", @@ -12249,6 +15028,20 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "type", + "description": "Type of the issue", + "args": [ + + ], + "type": { + "kind": "ENUM", + "name": "IssueType", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "updatedAt", "description": "Timestamp of when the issue was last updated", @@ -13011,8 +15804,492 @@ "deprecationReason": null }, { - "name": "errors", - "description": "Errors encountered during execution of the mutation.", + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "Float", + "description": "Represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point).", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "GeoNode", + "description": null, + "fields": [ + { + "name": "containerRepositoriesMaxCapacity", + "description": "The maximum concurrency of container repository sync for this secondary node", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "enabled", + "description": "Indicates whether this Geo node is enabled", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "filesMaxCapacity", + "description": "The maximum concurrency of LFS/attachment backfill for this secondary node", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "ID of this GeoNode", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "internalUrl", + "description": "The URL defined on the primary node that secondary nodes should use to contact it", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "minimumReverificationInterval", + "description": "The interval (in days) in which the repository verification is valid. Once expired, it will be reverified", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": "The unique identifier for this Geo node", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "packageFileRegistries", + "description": "Package file registries of the GeoNode. Available only when feature flag `geo_self_service_framework` is enabled", + "args": [ + { + "name": "ids", + "description": "Filters registries by their ID", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "PackageFileRegistryConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "primary", + "description": "Indicates whether this Geo node is the primary", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "reposMaxCapacity", + "description": "The maximum concurrency of repository backfill for this secondary node", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "selectiveSyncNamespaces", + "description": "The namespaces that should be synced, if `selective_sync_type` == `namespaces`", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "NamespaceConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "selectiveSyncShards", + "description": "The repository storages whose projects should be synced, if `selective_sync_type` == `shards`", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "selectiveSyncType", + "description": "Indicates if syncing is limited to only specific groups, or shards", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "syncObjectStorage", + "description": "Indicates if this secondary node will replicate blobs in Object Storage", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "url", + "description": "The user-facing URL for this Geo node", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "verificationMaxCapacity", + "description": "The maximum concurrency of repository verification for this secondary node", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "GrafanaIntegration", + "description": null, + "fields": [ + { + "name": "createdAt", + "description": "Timestamp of the issue's creation", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "enabled", + "description": "Indicates whether Grafana integration is enabled", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "grafanaUrl", + "description": "URL for the Grafana host for the Grafana integration", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "Internal ID of the Grafana integration", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "token", + "description": "API token for the Grafana integration. Deprecated in 12.7: Plain text token has been masked for security reasons", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": true, + "deprecationReason": "Plain text token has been masked for security reasons. Deprecated in 12.7" + }, + { + "name": "updatedAt", + "description": "Timestamp of the issue's last activity", "args": [ ], @@ -13020,17 +16297,9 @@ "kind": "NON_NULL", "name": null, "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } + "kind": "SCALAR", + "name": "Time", + "ofType": null } }, "isDeprecated": false, @@ -13044,84 +16313,128 @@ "enumValues": null, "possibleTypes": null }, - { - "kind": "SCALAR", - "name": "Float", - "description": "Represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point).", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, { "kind": "OBJECT", - "name": "GeoNode", + "name": "Group", "description": null, "fields": [ { - "name": "containerRepositoriesMaxCapacity", - "description": "The maximum concurrency of container repository sync for this secondary node", + "name": "autoDevopsEnabled", + "description": "Indicates whether Auto DevOps is enabled for all projects within this group", "args": [ ], "type": { "kind": "SCALAR", - "name": "Int", + "name": "Boolean", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "enabled", - "description": "Indicates whether this Geo node is enabled", + "name": "avatarUrl", + "description": "Avatar URL of the group", "args": [ ], "type": { "kind": "SCALAR", - "name": "Boolean", + "name": "String", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "filesMaxCapacity", - "description": "The maximum concurrency of LFS/attachment backfill for this secondary node", + "name": "board", + "description": "A single board of the group", "args": [ - + { + "name": "id", + "description": "Find a board by its ID", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + } ], "type": { - "kind": "SCALAR", - "name": "Int", + "kind": "OBJECT", + "name": "Board", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "id", - "description": "ID of this GeoNode", + "name": "boards", + "description": "Boards of the group", "args": [ - + { + "name": "id", + "description": "Find a board by its ID", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } ], "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } + "kind": "OBJECT", + "name": "BoardConnection", + "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "internalUrl", - "description": "The URL defined on the primary node that secondary nodes should use to contact it", + "name": "description", + "description": "Description of the namespace", "args": [ ], @@ -13134,40 +16447,70 @@ "deprecationReason": null }, { - "name": "minimumReverificationInterval", - "description": "The interval (in days) in which the repository verification is valid. Once expired, it will be reverified", + "name": "descriptionHtml", + "description": "The GitLab Flavored Markdown rendering of `description`", "args": [ ], "type": { "kind": "SCALAR", - "name": "Int", + "name": "String", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "name", - "description": "The unique identifier for this Geo node", + "name": "emailsDisabled", + "description": "Indicates if a group has email notifications disabled", "args": [ ], "type": { "kind": "SCALAR", - "name": "String", + "name": "Boolean", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "packageFileRegistries", - "description": "Package file registries of the GeoNode. Available only when feature flag `geo_self_service_framework` is enabled", + "name": "epic", + "description": "Find a single epic", "args": [ { - "name": "ids", - "description": "Filters registries by their ID", + "name": "startDate", + "description": "List items within a time frame where items.start_date is between startDate and endDate parameters (endDate parameter must be present)", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "endDate", + "description": "List items within a time frame where items.end_date is between startDate and endDate parameters (startDate parameter must be present)", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "iid", + "description": "IID of the epic, e.g., \"1\"", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "iids", + "description": "List of IIDs of epics, e.g., [1, 2]", "type": { "kind": "LIST", "name": null, @@ -13184,8 +16527,18 @@ "defaultValue": null }, { - "name": "after", - "description": "Returns the elements in the list that come after the specified cursor.", + "name": "state", + "description": "Filter epics by state", + "type": { + "kind": "ENUM", + "name": "EpicState", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "search", + "description": "Search query for epic title or description", "type": { "kind": "SCALAR", "name": "String", @@ -13194,8 +16547,18 @@ "defaultValue": null }, { - "name": "before", - "description": "Returns the elements in the list that come before the specified cursor.", + "name": "sort", + "description": "List epics by sort order", + "type": { + "kind": "ENUM", + "name": "EpicSort", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "authorUsername", + "description": "Filter epics by author", "type": { "kind": "SCALAR", "name": "String", @@ -13204,21 +16567,39 @@ "defaultValue": null }, { - "name": "first", - "description": "Returns the first _n_ elements from the list.", + "name": "labelName", + "description": "Filter epics by labels", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "milestoneTitle", + "description": "Filter epics by milestone title, computed from epic's issues", "type": { "kind": "SCALAR", - "name": "Int", + "name": "String", "ofType": null }, "defaultValue": null }, { - "name": "last", - "description": "Returns the last _n_ elements from the list.", + "name": "iidStartsWith", + "description": "Filter epics by iid for autocomplete", "type": { "kind": "SCALAR", - "name": "Int", + "name": "String", "ofType": null }, "defaultValue": null @@ -13226,44 +16607,142 @@ ], "type": { "kind": "OBJECT", - "name": "PackageFileRegistryConnection", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "primary", - "description": "Indicates whether this Geo node is the primary", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "reposMaxCapacity", - "description": "The maximum concurrency of repository backfill for this secondary node", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "Int", + "name": "Epic", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "selectiveSyncNamespaces", - "description": "The namespaces that should be synced, if `selective_sync_type` == `namespaces`", + "name": "epics", + "description": "Find epics", "args": [ + { + "name": "startDate", + "description": "List items within a time frame where items.start_date is between startDate and endDate parameters (endDate parameter must be present)", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "endDate", + "description": "List items within a time frame where items.end_date is between startDate and endDate parameters (startDate parameter must be present)", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "iid", + "description": "IID of the epic, e.g., \"1\"", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "iids", + "description": "List of IIDs of epics, e.g., [1, 2]", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "state", + "description": "Filter epics by state", + "type": { + "kind": "ENUM", + "name": "EpicState", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "search", + "description": "Search query for epic title or description", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "sort", + "description": "List epics by sort order", + "type": { + "kind": "ENUM", + "name": "EpicSort", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "authorUsername", + "description": "Filter epics by author", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "labelName", + "description": "Filter epics by labels", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "milestoneTitle", + "description": "Filter epics by milestone title, computed from epic's issues", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "iidStartsWith", + "description": "Filter epics by iid for autocomplete", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", @@ -13307,142 +16786,29 @@ ], "type": { "kind": "OBJECT", - "name": "NamespaceConnection", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "selectiveSyncShards", - "description": "The repository storages whose projects should be synced, if `selective_sync_type` == `shards`", - "args": [ - - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "selectiveSyncType", - "description": "Indicates if syncing is limited to only specific groups, or shards", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "syncObjectStorage", - "description": "Indicates if this secondary node will replicate blobs in Object Storage", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "url", - "description": "The user-facing URL for this Geo node", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "verificationMaxCapacity", - "description": "The maximum concurrency of repository verification for this secondary node", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "Int", + "name": "EpicConnection", "ofType": null }, "isDeprecated": false, "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ - - ], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "GrafanaIntegration", - "description": null, - "fields": [ - { - "name": "createdAt", - "description": "Timestamp of the issue's creation", - "args": [ - - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Time", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null }, { - "name": "enabled", - "description": "Indicates whether Grafana integration is enabled", + "name": "epicsEnabled", + "description": "Indicates if Epics are enabled for namespace", "args": [ ], "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } + "kind": "SCALAR", + "name": "Boolean", + "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "grafanaUrl", - "description": "URL for the Grafana host for the Grafana integration", + "name": "fullName", + "description": "Full name of the namespace", "args": [ ], @@ -13459,8 +16825,8 @@ "deprecationReason": null }, { - "name": "id", - "description": "Internal ID of the Grafana integration", + "name": "fullPath", + "description": "Full path of the namespace", "args": [ ], @@ -13477,26 +16843,22 @@ "deprecationReason": null }, { - "name": "token", - "description": "API token for the Grafana integration. Deprecated in 12.7: Plain text token has been masked for security reasons", + "name": "groupTimelogsEnabled", + "description": "Indicates if Group timelogs are enabled for namespace", "args": [ ], "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "Boolean", + "ofType": null }, - "isDeprecated": true, - "deprecationReason": "Plain text token has been masked for security reasons. Deprecated in 12.7" + "isDeprecated": false, + "deprecationReason": null }, { - "name": "updatedAt", - "description": "Timestamp of the issue's last activity", + "name": "id", + "description": "ID of the namespace", "args": [ ], @@ -13505,91 +16867,243 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "Time", + "name": "ID", "ofType": null } }, "isDeprecated": false, "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ - - ], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Group", - "description": null, - "fields": [ - { - "name": "autoDevopsEnabled", - "description": "Indicates whether Auto DevOps is enabled for all projects within this group", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null }, { - "name": "avatarUrl", - "description": "Avatar URL of the group", + "name": "isTemporaryStorageIncreaseEnabled", + "description": "Status of the temporary storage increase", "args": [ ], "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "board", - "description": "A single board of the group", + "name": "issues", + "description": "Issues of the group", "args": [ { - "name": "id", - "description": "Find a board by its ID", + "name": "iid", + "description": "IID of the issue. For example, \"1\"", "type": { "kind": "SCALAR", - "name": "ID", + "name": "String", "ofType": null }, "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Board", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "boards", - "description": "Boards of the group", - "args": [ + }, { - "name": "id", - "description": "Find a board by its ID", + "name": "iids", + "description": "List of IIDs of issues. For example, [1, 2]", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "labelName", + "description": "Labels applied to this issue", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "milestoneTitle", + "description": "Milestone applied to this issue", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "assigneeUsername", + "description": "Username of a user assigned to the issue", "type": { "kind": "SCALAR", - "name": "ID", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "assigneeId", + "description": "ID of a user assigned to the issues, \"none\" and \"any\" values supported", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "createdBefore", + "description": "Issues created before this date", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "createdAfter", + "description": "Issues created after this date", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "updatedBefore", + "description": "Issues updated before this date", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "updatedAfter", + "description": "Issues updated after this date", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "closedBefore", + "description": "Issues closed before this date", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "closedAfter", + "description": "Issues closed after this date", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "search", + "description": "Search query for issue title or description", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "types", + "description": "Filter issues by the given issue types", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "IssueType", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "state", + "description": "Current state of this issue", + "type": { + "kind": "ENUM", + "name": "IssuableState", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "sort", + "description": "Sort issues by this criteria", + "type": { + "kind": "ENUM", + "name": "IssueSort", "ofType": null }, + "defaultValue": "created_desc" + }, + { + "name": "iterationId", + "description": "Iterations applied to the issue", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, "defaultValue": null }, + { + "name": "includeSubgroups", + "description": "Include issues belonging to subgroups.", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": "false" + }, { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", @@ -13633,57 +17147,15 @@ ], "type": { "kind": "OBJECT", - "name": "BoardConnection", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": "Description of the namespace", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "descriptionHtml", - "description": "The GitLab Flavored Markdown rendering of `description`", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "emailsDisabled", - "description": "Indicates if a group has email notifications disabled", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "Boolean", + "name": "IssueConnection", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "epic", - "description": "Find a single epic", + "name": "iterations", + "description": "Find iterations", "args": [ { "name": "startDate", @@ -13706,8 +17178,28 @@ "defaultValue": null }, { - "name": "iid", - "description": "IID of the epic, e.g., \"1\"", + "name": "state", + "description": "Filter iterations by state", + "type": { + "kind": "ENUM", + "name": "IterationState", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "title", + "description": "Fuzzy search by title", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": "The ID of the Iteration to look up", "type": { "kind": "SCALAR", "name": "ID", @@ -13716,36 +17208,28 @@ "defaultValue": null }, { - "name": "iids", - "description": "List of IIDs of epics, e.g., [1, 2]", + "name": "iid", + "description": "The internal ID of the Iteration to look up", "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - } + "kind": "SCALAR", + "name": "ID", + "ofType": null }, "defaultValue": null }, { - "name": "state", - "description": "Filter epics by state", + "name": "includeAncestors", + "description": "Whether to include ancestor iterations. Defaults to true", "type": { - "kind": "ENUM", - "name": "EpicState", + "kind": "SCALAR", + "name": "Boolean", "ofType": null }, "defaultValue": null }, { - "name": "search", - "description": "Search query for epic title or description", + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", "type": { "kind": "SCALAR", "name": "String", @@ -13754,46 +17238,118 @@ "defaultValue": null }, { - "name": "sort", - "description": "List epics by sort order", + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", "type": { - "kind": "ENUM", - "name": "EpicSort", + "kind": "SCALAR", + "name": "String", "ofType": null }, "defaultValue": null }, { - "name": "authorUsername", - "description": "Filter epics by author", + "name": "first", + "description": "Returns the first _n_ elements from the list.", "type": { "kind": "SCALAR", - "name": "String", + "name": "Int", "ofType": null }, "defaultValue": null }, { - "name": "labelName", - "description": "Filter epics by labels", + "name": "last", + "description": "Returns the last _n_ elements from the list.", "type": { - "kind": "LIST", + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "IterationConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "label", + "description": "A label available on this group", + "args": [ + { + "name": "title", + "description": "Title of the label", + "type": { + "kind": "NON_NULL", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null } }, "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "Label", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "labels", + "description": "Labels available on this group", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null }, { - "name": "iidStartsWith", - "description": "Filter epics by iid for autocomplete", + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "searchTerm", + "description": "A search term to find labels with", "type": { "kind": "SCALAR", "name": "String", @@ -13803,16 +17359,44 @@ } ], "type": { - "kind": "OBJECT", - "name": "Epic", + "kind": "OBJECT", + "name": "LabelConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "lfsEnabled", + "description": "Indicates if Large File Storage (LFS) is enabled for namespace", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Boolean", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "epics", - "description": "Find epics", + "name": "mentionsDisabled", + "description": "Indicates if a group is disabled from getting mentioned", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "milestones", + "description": "Milestones of the group", "args": [ { "name": "startDate", @@ -13835,18 +17419,8 @@ "defaultValue": null }, { - "name": "iid", - "description": "IID of the epic, e.g., \"1\"", - "type": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "iids", - "description": "List of IIDs of epics, e.g., [1, 2]", + "name": "ids", + "description": "Array of global milestone IDs, e.g., \"gid://gitlab/Milestone/1\"", "type": { "kind": "LIST", "name": null, @@ -13864,68 +17438,20 @@ }, { "name": "state", - "description": "Filter epics by state", - "type": { - "kind": "ENUM", - "name": "EpicState", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "search", - "description": "Search query for epic title or description", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "sort", - "description": "List epics by sort order", + "description": "Filter milestones by state", "type": { "kind": "ENUM", - "name": "EpicSort", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "authorUsername", - "description": "Filter epics by author", - "type": { - "kind": "SCALAR", - "name": "String", + "name": "MilestoneStateEnum", "ofType": null }, "defaultValue": null }, { - "name": "labelName", - "description": "Filter epics by labels", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - }, - "defaultValue": null - }, - { - "name": "iidStartsWith", - "description": "Filter epics by iid for autocomplete", + "name": "includeDescendants", + "description": "Also return milestones in all subgroups and subprojects", "type": { "kind": "SCALAR", - "name": "String", + "name": "Boolean", "ofType": null }, "defaultValue": null @@ -13973,47 +17499,47 @@ ], "type": { "kind": "OBJECT", - "name": "EpicConnection", + "name": "MilestoneConnection", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "epicsEnabled", - "description": "Indicates if Epics are enabled for namespace", + "name": "name", + "description": "Name of the namespace", "args": [ ], "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "fullName", - "description": "Full name of the namespace", + "name": "parent", + "description": "Parent group", "args": [ ], "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "OBJECT", + "name": "Group", + "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "fullPath", - "description": "Full path of the namespace", + "name": "path", + "description": "Path of the namespace", "args": [ ], @@ -14022,7 +17548,7 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "ID", + "name": "String", "ofType": null } }, @@ -14030,110 +17556,46 @@ "deprecationReason": null }, { - "name": "groupTimelogsEnabled", - "description": "Indicates if Group timelogs are enabled for namespace", + "name": "projectCreationLevel", + "description": "The permission level required to create projects in the group", "args": [ ], "type": { "kind": "SCALAR", - "name": "Boolean", + "name": "String", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "id", - "description": "ID of the namespace", - "args": [ - - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "issues", - "description": "Issues of the group", + "name": "projects", + "description": "Projects within this namespace", "args": [ { - "name": "iid", - "description": "IID of the issue. For example, \"1\"", + "name": "includeSubgroups", + "description": "Include also subgroup projects", "type": { "kind": "SCALAR", - "name": "String", + "name": "Boolean", "ofType": null }, - "defaultValue": null - }, - { - "name": "iids", - "description": "List of IIDs of issues. For example, [1, 2]", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - }, - "defaultValue": null + "defaultValue": "false" }, { - "name": "state", - "description": "Current state of this issue", + "name": "hasVulnerabilities", + "description": "Returns only the projects which have vulnerabilities", "type": { - "kind": "ENUM", - "name": "IssuableState", + "kind": "SCALAR", + "name": "Boolean", "ofType": null }, - "defaultValue": null - }, - { - "name": "labelName", - "description": "Labels applied to this issue", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "milestoneTitle", - "description": "Milestones applied to this issue", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null + "defaultValue": "false" }, { - "name": "assigneeUsername", - "description": "Username of a user assigned to the issues", + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", "type": { "kind": "SCALAR", "name": "String", @@ -14142,8 +17604,8 @@ "defaultValue": null }, { - "name": "assigneeId", - "description": "ID of a user assigned to the issues, \"none\" and \"any\" values supported", + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", "type": { "kind": "SCALAR", "name": "String", @@ -14152,28 +17614,143 @@ "defaultValue": null }, { - "name": "createdBefore", - "description": "Issues created before this date", + "name": "first", + "description": "Returns the first _n_ elements from the list.", "type": { "kind": "SCALAR", - "name": "Time", + "name": "Int", "ofType": null }, "defaultValue": null }, { - "name": "createdAfter", - "description": "Issues created after this date", + "name": "last", + "description": "Returns the last _n_ elements from the list.", "type": { "kind": "SCALAR", - "name": "Time", + "name": "Int", "ofType": null }, "defaultValue": null - }, + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "ProjectConnection", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "requestAccessEnabled", + "description": "Indicates if users can request access to namespace", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "requireTwoFactorAuthentication", + "description": "Indicates if all users in this group are required to set up two-factor authentication", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "rootStorageStatistics", + "description": "Aggregated storage statistics of the namespace. Only available for root namespaces", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "RootStorageStatistics", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "shareWithGroupLock", + "description": "Indicates if sharing a project with another group within this group is prevented", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "storageSizeLimit", + "description": "Total storage limit of the root namespace in bytes", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "subgroupCreationLevel", + "description": "The permission level required to create subgroups within the group", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "temporaryStorageIncreaseEndsOn", + "description": "Date until the temporary storage increase is active", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "timelogs", + "description": "Time logged in issues by group members", + "args": [ { - "name": "updatedBefore", - "description": "Issues updated before this date", + "name": "startDate", + "description": "List time logs within a date range where the logged date is equal to or after startDate", "type": { "kind": "SCALAR", "name": "Time", @@ -14182,8 +17759,8 @@ "defaultValue": null }, { - "name": "updatedAfter", - "description": "Issues updated after this date", + "name": "endDate", + "description": "List time logs within a date range where the logged date is equal to or before endDate", "type": { "kind": "SCALAR", "name": "Time", @@ -14192,8 +17769,8 @@ "defaultValue": null }, { - "name": "closedBefore", - "description": "Issues closed before this date", + "name": "startTime", + "description": "List time-logs within a time range where the logged time is equal to or after startTime", "type": { "kind": "SCALAR", "name": "Time", @@ -14202,8 +17779,8 @@ "defaultValue": null }, { - "name": "closedAfter", - "description": "Issues closed after this date", + "name": "endTime", + "description": "List time-logs within a time range where the logged time is equal to or before endTime", "type": { "kind": "SCALAR", "name": "Time", @@ -14211,40 +17788,6 @@ }, "defaultValue": null }, - { - "name": "search", - "description": "Search query for issue title or description", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "sort", - "description": "Sort issues by this criteria", - "type": { - "kind": "ENUM", - "name": "IssueSort", - "ofType": null - }, - "defaultValue": "created_desc" - }, - { - "name": "iterationId", - "description": "Iterations applied to the issue", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - }, - "defaultValue": null - }, { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", @@ -14287,84 +17830,154 @@ } ], "type": { - "kind": "OBJECT", - "name": "IssueConnection", + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "TimelogConnection", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "twoFactorGracePeriod", + "description": "Time before two-factor authentication is enforced", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Int", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "iterations", - "description": "Find iterations", + "name": "userPermissions", + "description": "Permissions for the current user on the resource", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "GroupPermissions", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "visibility", + "description": "Visibility of the namespace", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "vulnerabilities", + "description": "Vulnerabilities reported on the projects in the group and its subgroups", "args": [ { - "name": "startDate", - "description": "List items within a time frame where items.start_date is between startDate and endDate parameters (endDate parameter must be present)", - "type": { - "kind": "SCALAR", - "name": "Time", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "endDate", - "description": "List items within a time frame where items.end_date is between startDate and endDate parameters (startDate parameter must be present)", - "type": { - "kind": "SCALAR", - "name": "Time", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "state", - "description": "Filter iterations by state", + "name": "projectId", + "description": "Filter vulnerabilities by project", "type": { - "kind": "ENUM", - "name": "IterationState", - "ofType": null + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } }, "defaultValue": null }, { - "name": "title", - "description": "Fuzzy search by title", + "name": "reportType", + "description": "Filter vulnerabilities by report type", "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "VulnerabilityReportType", + "ofType": null + } + } }, "defaultValue": null }, { - "name": "id", - "description": "The ID of the Iteration to look up", + "name": "severity", + "description": "Filter vulnerabilities by severity", "type": { - "kind": "SCALAR", - "name": "ID", - "ofType": null + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "VulnerabilitySeverity", + "ofType": null + } + } }, "defaultValue": null }, { - "name": "iid", - "description": "The internal ID of the Iteration to look up", + "name": "state", + "description": "Filter vulnerabilities by state", "type": { - "kind": "SCALAR", - "name": "ID", - "ofType": null + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "VulnerabilityState", + "ofType": null + } + } }, "defaultValue": null }, { - "name": "includeAncestors", - "description": "Whether to include ancestor iterations. Defaults to true", + "name": "scanner", + "description": "Filter vulnerabilities by scanner", "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } }, "defaultValue": null }, @@ -14411,43 +18024,44 @@ ], "type": { "kind": "OBJECT", - "name": "IterationConnection", + "name": "VulnerabilityConnection", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "label", - "description": "A label available on this group", + "name": "vulnerabilitiesCountByDay", + "description": "Number of vulnerabilities per day for the projects in the group and its subgroups", "args": [ { - "name": "title", - "description": "Title of the label", + "name": "startDate", + "description": "First day for which to fetch vulnerability history", "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", - "name": "String", + "name": "ISO8601Date", "ofType": null } }, "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Label", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "labels", - "description": "Labels available on this group", - "args": [ + }, + { + "name": "endDate", + "description": "Last day for which to fetch vulnerability history", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ISO8601Date", + "ofType": null + } + }, + "defaultValue": null + }, { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", @@ -14487,95 +18101,45 @@ "ofType": null }, "defaultValue": null - }, - { - "name": "searchTerm", - "description": "A search term to find labels with", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null } ], "type": { "kind": "OBJECT", - "name": "LabelConnection", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "lfsEnabled", - "description": "Indicates if Large File Storage (LFS) is enabled for namespace", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "mentionsDisabled", - "description": "Indicates if a group is disabled from getting mentioned", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "Boolean", + "name": "VulnerabilitiesCountByDayConnection", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "milestones", - "description": "Find milestones", + "name": "vulnerabilitiesCountByDayAndSeverity", + "description": "Number of vulnerabilities per severity level, per day, for the projects in the group and its subgroups. Deprecated in 13.3: Use `vulnerabilitiesCountByDay`", "args": [ { "name": "startDate", - "description": "List items within a time frame where items.start_date is between startDate and endDate parameters (endDate parameter must be present)", + "description": "First day for which to fetch vulnerability history", "type": { - "kind": "SCALAR", - "name": "Time", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ISO8601Date", + "ofType": null + } }, "defaultValue": null }, { "name": "endDate", - "description": "List items within a time frame where items.end_date is between startDate and endDate parameters (startDate parameter must be present)", - "type": { - "kind": "SCALAR", - "name": "Time", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "state", - "description": "Filter milestones by state", - "type": { - "kind": "ENUM", - "name": "MilestoneStateEnum", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "includeDescendants", - "description": "Return also milestones in all subgroups and subprojects", + "description": "Last day for which to fetch vulnerability history", "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ISO8601Date", + "ofType": null + } }, "defaultValue": null }, @@ -14622,47 +18186,15 @@ ], "type": { "kind": "OBJECT", - "name": "MilestoneConnection", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": "Name of the namespace", - "args": [ - - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "parent", - "description": "Parent group", - "args": [ - - ], - "type": { - "kind": "OBJECT", - "name": "Group", + "name": "VulnerabilitiesCountByDayAndSeverityConnection", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null + "isDeprecated": true, + "deprecationReason": "Use `vulnerabilitiesCountByDay`. Deprecated in 13.3" }, { - "name": "path", - "description": "Path of the namespace", + "name": "vulnerabilityGrades", + "description": "Represents vulnerable project counts for each grade", "args": [ ], @@ -14670,52 +18202,26 @@ "kind": "NON_NULL", "name": null, "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "VulnerableProjectsByGrade", + "ofType": null + } + } } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "projectCreationLevel", - "description": "The permission level required to create projects in the group", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "projects", - "description": "Projects within this namespace", + "name": "vulnerabilityScanners", + "description": "Vulnerability scanners reported on the project vulnerabilties of the group and its subgroups", "args": [ - { - "name": "includeSubgroups", - "description": "Include also subgroup projects", - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": "false" - }, - { - "name": "hasVulnerabilities", - "description": "Returns only the projects which have vulnerabilities", - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": "false" - }, { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", @@ -14756,208 +18262,244 @@ }, "defaultValue": null } + ], + "type": { + "kind": "OBJECT", + "name": "VulnerabilityScannerConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "webUrl", + "description": "Web URL of the group", + "args": [ + ], "type": { "kind": "NON_NULL", "name": null, "ofType": { - "kind": "OBJECT", - "name": "ProjectConnection", + "kind": "SCALAR", + "name": "String", "ofType": null } }, "isDeprecated": false, "deprecationReason": null - }, + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "GroupMember", + "description": "Represents a Group Member", + "fields": [ { - "name": "requestAccessEnabled", - "description": "Indicates if users can request access to namespace", + "name": "accessLevel", + "description": "GitLab::Access level", "args": [ ], "type": { - "kind": "SCALAR", - "name": "Boolean", + "kind": "OBJECT", + "name": "AccessLevel", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "requireTwoFactorAuthentication", - "description": "Indicates if all users in this group are required to set up two-factor authentication", + "name": "createdAt", + "description": "Date and time the membership was created", "args": [ ], "type": { "kind": "SCALAR", - "name": "Boolean", + "name": "Time", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "rootStorageStatistics", - "description": "Aggregated storage statistics of the namespace. Only available for root namespaces", + "name": "createdBy", + "description": "User that authorized membership", "args": [ ], "type": { "kind": "OBJECT", - "name": "RootStorageStatistics", + "name": "User", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "shareWithGroupLock", - "description": "Indicates if sharing a project with another group within this group is prevented", + "name": "expiresAt", + "description": "Date and time the membership expires", "args": [ ], "type": { "kind": "SCALAR", - "name": "Boolean", + "name": "Time", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "storageSizeLimit", - "description": "Total storage limit of the root namespace in bytes", + "name": "group", + "description": "Group that a User is a member of", "args": [ ], "type": { - "kind": "SCALAR", - "name": "Float", + "kind": "OBJECT", + "name": "Group", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "subgroupCreationLevel", - "description": "The permission level required to create subgroups within the group", + "name": "updatedAt", + "description": "Date and time the membership was last updated", "args": [ ], "type": { "kind": "SCALAR", - "name": "String", + "name": "Time", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "temporaryStorageIncreaseEndsOn", - "description": "Date until the temporary storage increase is active", + "name": "userPermissions", + "description": "Permissions for the current user on the resource", "args": [ ], "type": { - "kind": "SCALAR", - "name": "Time", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "GroupPermissions", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + { + "kind": "INTERFACE", + "name": "MemberInterface", + "ofType": null + } + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "GroupMemberConnection", + "description": "The connection type for GroupMember.", + "fields": [ + { + "name": "edges", + "description": "A list of edges.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "GroupMemberEdge", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "timelogs", - "description": "Time logged in issues by group members", + "name": "nodes", + "description": "A list of nodes.", "args": [ - { - "name": "startDate", - "description": "List time logs within a date range where the logged date is equal to or after startDate", - "type": { - "kind": "SCALAR", - "name": "Time", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "endDate", - "description": "List time logs within a date range where the logged date is equal to or before endDate", - "type": { - "kind": "SCALAR", - "name": "Time", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "startTime", - "description": "List time-logs within a time range where the logged time is equal to or after startTime", - "type": { - "kind": "SCALAR", - "name": "Time", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "endTime", - "description": "List time-logs within a time range where the logged time is equal to or before endTime", - "type": { - "kind": "SCALAR", - "name": "Time", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "after", - "description": "Returns the elements in the list that come after the specified cursor.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "before", - "description": "Returns the elements in the list that come before the specified cursor.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "first", - "description": "Returns the first _n_ elements from the list.", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "last", - "description": "Returns the last _n_ elements from the list.", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "GroupMember", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": "Information to aid in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "GroupMemberEdge", + "description": "An edge in a connection.", + "fields": [ + { + "name": "cursor", + "description": "A cursor for use in pagination.", + "args": [ + ], "type": { "kind": "NON_NULL", "name": null, "ofType": { - "kind": "OBJECT", - "name": "TimelogConnection", + "kind": "SCALAR", + "name": "String", "ofType": null } }, @@ -14965,22 +18507,35 @@ "deprecationReason": null }, { - "name": "twoFactorGracePeriod", - "description": "Time before two-factor authentication is enforced", + "name": "node", + "description": "The item at the end of the edge.", "args": [ ], "type": { - "kind": "SCALAR", - "name": "Int", + "kind": "OBJECT", + "name": "GroupMember", "ofType": null }, "isDeprecated": false, "deprecationReason": null - }, + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "GroupPermissions", + "description": null, + "fields": [ { - "name": "userPermissions", - "description": "Permissions for the current user on the resource", + "name": "readGroup", + "description": "Indicates the user can perform `read_group` on this resource", "args": [ ], @@ -14988,122 +18543,80 @@ "kind": "NON_NULL", "name": null, "ofType": { - "kind": "OBJECT", - "name": "GroupPermissions", + "kind": "SCALAR", + "name": "Boolean", "ofType": null } }, "isDeprecated": false, "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "HealthStatus", + "description": "Health status of an issue or epic", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "onTrack", + "description": null, + "isDeprecated": false, + "deprecationReason": null }, { - "name": "visibility", - "description": "Visibility of the namespace", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, + "name": "needsAttention", + "description": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "vulnerabilities", - "description": "Vulnerabilities reported on the projects in the group and its subgroups", + "name": "atRisk", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "ID", + "description": "Represents a unique identifier that is Base64 obfuscated. It is often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `\"VXNlci0xMA==\"`) or integer (such as `4`) input value will be accepted as an ID.", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "ISO8601Date", + "description": "An ISO 8601-encoded date", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "InstanceSecurityDashboard", + "description": null, + "fields": [ + { + "name": "projects", + "description": "Projects selected in Instance Security Dashboard", "args": [ - { - "name": "projectId", - "description": "Filter vulnerabilities by project", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - } - }, - "defaultValue": null - }, - { - "name": "reportType", - "description": "Filter vulnerabilities by report type", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "VulnerabilityReportType", - "ofType": null - } - } - }, - "defaultValue": null - }, - { - "name": "severity", - "description": "Filter vulnerabilities by severity", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "VulnerabilitySeverity", - "ofType": null - } - } - }, - "defaultValue": null - }, - { - "name": "state", - "description": "Filter vulnerabilities by state", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "VulnerabilityState", - "ofType": null - } - } - }, - "defaultValue": null - }, - { - "name": "scanner", - "description": "Filter vulnerabilities by scanner", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - }, - "defaultValue": null - }, { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", @@ -15146,45 +18659,47 @@ } ], "type": { - "kind": "OBJECT", - "name": "VulnerabilityConnection", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "ProjectConnection", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "vulnerabilitiesCountByDayAndSeverity", - "description": "Number of vulnerabilities per severity level, per day, for the projects in the group and its subgroups", + "name": "vulnerabilityGrades", + "description": "Represents vulnerable project counts for each grade", "args": [ - { - "name": "startDate", - "description": "First day for which to fetch vulnerability history", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ISO8601Date", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "endDate", - "description": "Last day for which to fetch vulnerability history", - "type": { + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { "kind": "NON_NULL", "name": null, "ofType": { - "kind": "SCALAR", - "name": "ISO8601Date", + "kind": "OBJECT", + "name": "VulnerableProjectsByGrade", "ofType": null } - }, - "defaultValue": null - }, + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "vulnerabilityScanners", + "description": "Vulnerability scanners reported on the vulnerabilties from projects selected in Instance Security Dashboard", + "args": [ { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", @@ -15228,15 +18743,73 @@ ], "type": { "kind": "OBJECT", - "name": "VulnerabilitiesCountByDayAndSeverityConnection", + "name": "VulnerabilityScannerConnection", "ofType": null }, "isDeprecated": false, "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "Int", + "description": "Represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "IssuableState", + "description": "State of a GitLab issue or merge request", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "opened", + "description": null, + "isDeprecated": false, + "deprecationReason": null }, { - "name": "vulnerabilityScanners", - "description": "Vulnerability scanners reported on the project vulnerabilties of the group and its subgroups", + "name": "closed", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "locked", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "all", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Issue", + "description": null, + "fields": [ + { + "name": "assignees", + "description": "Assignees of the issue", "args": [ { "name": "after", @@ -15281,15 +18854,15 @@ ], "type": { "kind": "OBJECT", - "name": "VulnerabilityScannerConnection", + "name": "UserConnection", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "webUrl", - "description": "Web URL of the group", + "name": "author", + "description": "User that created the issue", "args": [ ], @@ -15297,100 +18870,234 @@ "kind": "NON_NULL", "name": null, "ofType": { - "kind": "SCALAR", - "name": "String", + "kind": "OBJECT", + "name": "User", "ofType": null } }, "isDeprecated": false, "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ + }, + { + "name": "blocked", + "description": "Indicates the issue is blocked", + "args": [ - ], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "GroupMember", - "description": "Represents a Group Member", - "fields": [ + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { - "name": "accessLevel", - "description": "GitLab::Access level", + "name": "closedAt", + "description": "Timestamp of when the issue was closed", "args": [ ], "type": { - "kind": "OBJECT", - "name": "AccessLevel", + "kind": "SCALAR", + "name": "Time", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, + { + "name": "confidential", + "description": "Indicates the issue is confidential", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "createdAt", - "description": "Date and time the membership was created", + "description": "Timestamp of when the issue was created", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "description", + "description": "Description of the issue", "args": [ ], "type": { "kind": "SCALAR", - "name": "Time", + "name": "String", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "createdBy", - "description": "User that authorized membership", + "name": "descriptionHtml", + "description": "The GitLab Flavored Markdown rendering of `description`", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "designCollection", + "description": "Collection of design images associated with this issue", "args": [ ], "type": { "kind": "OBJECT", - "name": "User", + "name": "DesignCollection", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "expiresAt", - "description": "Date and time the membership expires", + "name": "designs", + "description": "The designs associated with this issue. Deprecated in 12.2: Use `designCollection`", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "DesignCollection", + "ofType": null + }, + "isDeprecated": true, + "deprecationReason": "Use `designCollection`. Deprecated in 12.2" + }, + { + "name": "discussionLocked", + "description": "Indicates discussion is locked on the issue", "args": [ ], "type": { - "kind": "SCALAR", - "name": "Time", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "discussions", + "description": "All discussions on this noteable", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "DiscussionConnection", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "group", - "description": "Group that a User is a member of", + "name": "downvotes", + "description": "Number of downvotes the issue has received", "args": [ ], "type": { - "kind": "OBJECT", - "name": "Group", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "updatedAt", - "description": "Date and time the membership was last updated", + "name": "dueDate", + "description": "Due date of the issue", "args": [ ], @@ -15403,79 +19110,36 @@ "deprecationReason": null }, { - "name": "userPermissions", - "description": "Permissions for the current user on the resource", - "args": [ - - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "GroupPermissions", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ - { - "kind": "INTERFACE", - "name": "MemberInterface", - "ofType": null - } - ], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "GroupMemberConnection", - "description": "The connection type for GroupMember.", - "fields": [ - { - "name": "edges", - "description": "A list of edges.", + "name": "epic", + "description": "Epic to which this issue belongs", "args": [ ], "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "GroupMemberEdge", - "ofType": null - } + "kind": "OBJECT", + "name": "Epic", + "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "nodes", - "description": "A list of nodes.", + "name": "healthStatus", + "description": "Current health status. Returns null if `save_issuable_health_status` feature flag is disabled.", "args": [ ], "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "GroupMember", - "ofType": null - } + "kind": "ENUM", + "name": "HealthStatus", + "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "pageInfo", - "description": "Information to aid in pagination.", + "name": "id", + "description": "ID of the issue", "args": [ ], @@ -15483,30 +19147,17 @@ "kind": "NON_NULL", "name": null, "ofType": { - "kind": "OBJECT", - "name": "PageInfo", + "kind": "SCALAR", + "name": "ID", "ofType": null } }, "isDeprecated": false, "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ - - ], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "GroupMemberEdge", - "description": "An edge in a connection.", - "fields": [ + }, { - "name": "cursor", - "description": "A cursor for use in pagination.", + "name": "iid", + "description": "Internal ID of the issue", "args": [ ], @@ -15515,7 +19166,7 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "String", + "name": "ID", "ofType": null } }, @@ -15523,115 +19174,22 @@ "deprecationReason": null }, { - "name": "node", - "description": "The item at the end of the edge.", + "name": "iteration", + "description": "Iteration of the issue", "args": [ ], "type": { "kind": "OBJECT", - "name": "GroupMember", + "name": "Iteration", "ofType": null }, "isDeprecated": false, "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ - - ], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "GroupPermissions", - "description": null, - "fields": [ - { - "name": "readGroup", - "description": "Indicates the user can perform `read_group` on this resource", - "args": [ - - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ - - ], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "HealthStatus", - "description": "Health status of an issue or epic", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "onTrack", - "description": null, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "needsAttention", - "description": null, - "isDeprecated": false, - "deprecationReason": null }, { - "name": "atRisk", - "description": null, - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "ID", - "description": "Represents a unique identifier that is Base64 obfuscated. It is often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `\"VXNlci0xMA==\"`) or integer (such as `4`) input value will be accepted as an ID.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "ISO8601Date", - "description": "An ISO 8601-encoded date", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "InstanceSecurityDashboard", - "description": null, - "fields": [ - { - "name": "projects", - "description": "Projects selected in Instance Security Dashboard", + "name": "labels", + "description": "Labels of the issue", "args": [ { "name": "after", @@ -15675,20 +19233,30 @@ } ], "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "ProjectConnection", - "ofType": null - } + "kind": "OBJECT", + "name": "LabelConnection", + "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "vulnerabilityScanners", - "description": "Vulnerability scanners reported on the vulnerabilties from projects selected in Instance Security Dashboard", + "name": "milestone", + "description": "Milestone of the issue", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "Milestone", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "notes", + "description": "All notes on this noteable", "args": [ { "name": "after", @@ -15732,68 +19300,20 @@ } ], "type": { - "kind": "OBJECT", - "name": "VulnerabilityScannerConnection", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "NoteConnection", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ - - ], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Int", - "description": "Represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "IssuableState", - "description": "State of a GitLab issue or merge request", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "opened", - "description": null, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "closed", - "description": null, - "isDeprecated": false, - "deprecationReason": null }, { - "name": "locked", - "description": null, - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Issue", - "description": null, - "fields": [ - { - "name": "assignees", - "description": "Assignees of the issue", + "name": "participants", + "description": "List of participants in the issue", "args": [ { "name": "after", @@ -15845,8 +19365,99 @@ "deprecationReason": null }, { - "name": "author", - "description": "User that created the issue", + "name": "reference", + "description": "Internal reference of the issue. Returned in shortened format by default", + "args": [ + { + "name": "full", + "description": "Boolean option specifying whether the reference should be returned in full", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": "false" + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "relativePosition", + "description": "Relative position of the issue (used for positioning in epic tree and issue boards)", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "state", + "description": "State of the issue", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "IssueState", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "statusPagePublishedIncident", + "description": "Indicates whether an issue is published to the status page", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "subscribed", + "description": "Indicates the currently logged in user is subscribed to the issue", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "taskCompletionStatus", + "description": "Task completion status of the issue", "args": [ ], @@ -15855,7 +19466,7 @@ "name": null, "ofType": { "kind": "OBJECT", - "name": "User", + "name": "TaskCompletionStatus", "ofType": null } }, @@ -15863,22 +19474,108 @@ "deprecationReason": null }, { - "name": "closedAt", - "description": "Timestamp of when the issue was closed", + "name": "timeEstimate", + "description": "Time estimate of the issue", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "title", + "description": "Title of the issue", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "titleHtml", + "description": "The GitLab Flavored Markdown rendering of `title`", "args": [ ], "type": { "kind": "SCALAR", - "name": "Time", + "name": "String", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "confidential", - "description": "Indicates the issue is confidential", + "name": "totalTimeSpent", + "description": "Total time reported as spent on the issue", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": "Type of the issue", + "args": [ + + ], + "type": { + "kind": "ENUM", + "name": "IssueType", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "updatedAt", + "description": "Timestamp of when the issue was last updated", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "upvotes", + "description": "Number of upvotes the issue has received", "args": [ ], @@ -15887,7 +19584,7 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "Boolean", + "name": "Int", "ofType": null } }, @@ -15895,8 +19592,8 @@ "deprecationReason": null }, { - "name": "createdAt", - "description": "Timestamp of when the issue was created", + "name": "userNotesCount", + "description": "Number of user notes of the issue", "args": [ ], @@ -15905,7 +19602,7 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "Time", + "name": "Int", "ofType": null } }, @@ -15913,64 +19610,93 @@ "deprecationReason": null }, { - "name": "description", - "description": "Description of the issue", + "name": "userPermissions", + "description": "Permissions for the current user on the resource", "args": [ ], "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "IssuePermissions", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "descriptionHtml", - "description": "The GitLab Flavored Markdown rendering of `description`", + "name": "webPath", + "description": "Web path of the issue", "args": [ ], "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "designCollection", - "description": "Collection of design images associated with this issue", + "name": "webUrl", + "description": "Web URL of the issue", "args": [ ], "type": { - "kind": "OBJECT", - "name": "DesignCollection", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "designs", - "description": "The designs associated with this issue. Deprecated in 12.2: Use `designCollection`", + "name": "weight", + "description": "Weight of the issue", "args": [ ], "type": { - "kind": "OBJECT", - "name": "DesignCollection", + "kind": "SCALAR", + "name": "Int", "ofType": null }, - "isDeprecated": true, - "deprecationReason": "Use `designCollection`. Deprecated in 12.2" - }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ { - "name": "discussionLocked", - "description": "Indicates discussion is locked on the issue", + "kind": "INTERFACE", + "name": "Noteable", + "ofType": null + } + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "IssueConnection", + "description": "The connection type for Issue.", + "fields": [ + { + "name": "count", + "description": "Total count of collection", "args": [ ], @@ -15979,7 +19705,7 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "Boolean", + "name": "Int", "ofType": null } }, @@ -15987,56 +19713,17 @@ "deprecationReason": null }, { - "name": "discussions", - "description": "All discussions on this noteable", + "name": "edges", + "description": "A list of edges.", "args": [ - { - "name": "after", - "description": "Returns the elements in the list that come after the specified cursor.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "before", - "description": "Returns the elements in the list that come before the specified cursor.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "first", - "description": "Returns the first _n_ elements from the list.", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "last", - "description": "Returns the last _n_ elements from the list.", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - } + ], "type": { - "kind": "NON_NULL", + "kind": "LIST", "name": null, "ofType": { "kind": "OBJECT", - "name": "DiscussionConnection", + "name": "IssueEdge", "ofType": null } }, @@ -16044,17 +19731,17 @@ "deprecationReason": null }, { - "name": "downvotes", - "description": "Number of downvotes the issue has received", + "name": "nodes", + "description": "A list of nodes.", "args": [ ], "type": { - "kind": "NON_NULL", + "kind": "LIST", "name": null, "ofType": { - "kind": "SCALAR", - "name": "Int", + "kind": "OBJECT", + "name": "Issue", "ofType": null } }, @@ -16062,53 +19749,85 @@ "deprecationReason": null }, { - "name": "dueDate", - "description": "Due date of the issue", + "name": "pageInfo", + "description": "Information to aid in pagination.", "args": [ ], "type": { - "kind": "SCALAR", - "name": "Time", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null - }, + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "IssueEdge", + "description": "An edge in a connection.", + "fields": [ { - "name": "epic", - "description": "Epic to which this issue belongs", + "name": "cursor", + "description": "A cursor for use in pagination.", "args": [ ], "type": { - "kind": "OBJECT", - "name": "Epic", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "healthStatus", - "description": "Current health status. Returns null if `save_issuable_health_status` feature flag is disabled.", + "name": "node", + "description": "The item at the end of the edge.", "args": [ ], "type": { - "kind": "ENUM", - "name": "HealthStatus", + "kind": "OBJECT", + "name": "Issue", "ofType": null }, "isDeprecated": false, "deprecationReason": null - }, - { - "name": "id", - "description": "ID of the issue", - "args": [ + } + ], + "inputFields": null, + "interfaces": [ - ], + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "IssueMoveListInput", + "description": "Autogenerated input type of IssueMoveList", + "fields": null, + "inputFields": [ + { + "name": "projectPath", + "description": "Project the issue to mutate is in", "type": { "kind": "NON_NULL", "name": null, @@ -16118,262 +19837,113 @@ "ofType": null } }, - "isDeprecated": false, - "deprecationReason": null + "defaultValue": null }, { "name": "iid", - "description": "Internal ID of the issue", - "args": [ - - ], + "description": "IID of the issue to mutate", "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", - "name": "ID", + "name": "String", "ofType": null } }, - "isDeprecated": false, - "deprecationReason": null + "defaultValue": null }, { - "name": "iteration", - "description": "Iteration of the issue", - "args": [ - - ], + "name": "boardId", + "description": "Global ID of the board that the issue is in", "type": { - "kind": "OBJECT", - "name": "Iteration", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } }, - "isDeprecated": false, - "deprecationReason": null + "defaultValue": null }, { - "name": "labels", - "description": "Labels of the issue", - "args": [ - { - "name": "after", - "description": "Returns the elements in the list that come after the specified cursor.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "before", - "description": "Returns the elements in the list that come before the specified cursor.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "first", - "description": "Returns the first _n_ elements from the list.", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "last", - "description": "Returns the last _n_ elements from the list.", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - } - ], + "name": "fromListId", + "description": "ID of the board list that the issue will be moved from", "type": { - "kind": "OBJECT", - "name": "LabelConnection", + "kind": "SCALAR", + "name": "ID", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null + "defaultValue": null }, { - "name": "milestone", - "description": "Milestone of the issue", - "args": [ - - ], + "name": "toListId", + "description": "ID of the board list that the issue will be moved to", "type": { - "kind": "OBJECT", - "name": "Milestone", + "kind": "SCALAR", + "name": "ID", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null + "defaultValue": null }, { - "name": "notes", - "description": "All notes on this noteable", - "args": [ - { - "name": "after", - "description": "Returns the elements in the list that come after the specified cursor.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "before", - "description": "Returns the elements in the list that come before the specified cursor.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "first", - "description": "Returns the first _n_ elements from the list.", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "last", - "description": "Returns the last _n_ elements from the list.", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - } - ], + "name": "moveBeforeId", + "description": "ID of issue before which the current issue will be positioned at", "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "NoteConnection", - "ofType": null - } + "kind": "SCALAR", + "name": "ID", + "ofType": null }, - "isDeprecated": false, - "deprecationReason": null + "defaultValue": null }, { - "name": "participants", - "description": "List of participants in the issue", - "args": [ - { - "name": "after", - "description": "Returns the elements in the list that come after the specified cursor.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "before", - "description": "Returns the elements in the list that come before the specified cursor.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "first", - "description": "Returns the first _n_ elements from the list.", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "last", - "description": "Returns the last _n_ elements from the list.", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - } - ], + "name": "moveAfterId", + "description": "ID of issue after which the current issue will be positioned at", "type": { - "kind": "OBJECT", - "name": "UserConnection", + "kind": "SCALAR", + "name": "ID", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null + "defaultValue": null }, { - "name": "reference", - "description": "Internal reference of the issue. Returned in shortened format by default", - "args": [ - { - "name": "full", - "description": "Boolean option specifying whether the reference should be returned in full", - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": "false" - } - ], + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "IssueMoveListPayload", + "description": "Autogenerated return type of IssueMoveList", + "fields": [ { - "name": "relativePosition", - "description": "Relative position of the issue (used for positioning in epic tree and issue boards)", + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", "args": [ ], "type": { "kind": "SCALAR", - "name": "Int", + "name": "String", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "state", - "description": "State of the issue", + "name": "errors", + "description": "Errors encountered during execution of the mutation.", "args": [ ], @@ -16381,17 +19951,52 @@ "kind": "NON_NULL", "name": null, "ofType": { - "kind": "ENUM", - "name": "IssueState", - "ofType": null + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "subscribed", - "description": "Indicates the currently logged in user is subscribed to the issue", + "name": "issue", + "description": "The issue after mutation", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "Issue", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "IssuePermissions", + "description": "Check permissions for the current user on a issue", + "fields": [ + { + "name": "adminIssue", + "description": "Indicates the user can perform `admin_issue` on this resource", "args": [ ], @@ -16408,8 +20013,8 @@ "deprecationReason": null }, { - "name": "taskCompletionStatus", - "description": "Task completion status of the issue", + "name": "createDesign", + "description": "Indicates the user can perform `create_design` on this resource", "args": [ ], @@ -16417,8 +20022,8 @@ "kind": "NON_NULL", "name": null, "ofType": { - "kind": "OBJECT", - "name": "TaskCompletionStatus", + "kind": "SCALAR", + "name": "Boolean", "ofType": null } }, @@ -16426,8 +20031,8 @@ "deprecationReason": null }, { - "name": "timeEstimate", - "description": "Time estimate of the issue", + "name": "createNote", + "description": "Indicates the user can perform `create_note` on this resource", "args": [ ], @@ -16436,7 +20041,7 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "Int", + "name": "Boolean", "ofType": null } }, @@ -16444,8 +20049,8 @@ "deprecationReason": null }, { - "name": "title", - "description": "Title of the issue", + "name": "destroyDesign", + "description": "Indicates the user can perform `destroy_design` on this resource", "args": [ ], @@ -16454,7 +20059,7 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "String", + "name": "Boolean", "ofType": null } }, @@ -16462,22 +20067,8 @@ "deprecationReason": null }, { - "name": "titleHtml", - "description": "The GitLab Flavored Markdown rendering of `title`", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "totalTimeSpent", - "description": "Total time reported as spent on the issue", + "name": "readDesign", + "description": "Indicates the user can perform `read_design` on this resource", "args": [ ], @@ -16486,7 +20077,7 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "Int", + "name": "Boolean", "ofType": null } }, @@ -16494,8 +20085,8 @@ "deprecationReason": null }, { - "name": "updatedAt", - "description": "Timestamp of when the issue was last updated", + "name": "readIssue", + "description": "Indicates the user can perform `read_issue` on this resource", "args": [ ], @@ -16504,7 +20095,7 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "Time", + "name": "Boolean", "ofType": null } }, @@ -16512,8 +20103,8 @@ "deprecationReason": null }, { - "name": "upvotes", - "description": "Number of upvotes the issue has received", + "name": "reopenIssue", + "description": "Indicates the user can perform `reopen_issue` on this resource", "args": [ ], @@ -16522,7 +20113,7 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "Int", + "name": "Boolean", "ofType": null } }, @@ -16530,8 +20121,8 @@ "deprecationReason": null }, { - "name": "userNotesCount", - "description": "Number of user notes of the issue", + "name": "updateIssue", + "description": "Indicates the user can perform `update_issue` on this resource", "args": [ ], @@ -16540,37 +20131,44 @@ "name": null, "ofType": { "kind": "SCALAR", - "name": "Int", + "name": "Boolean", "ofType": null } }, "isDeprecated": false, "deprecationReason": null - }, - { - "name": "userPermissions", - "description": "Permissions for the current user on the resource", - "args": [ + } + ], + "inputFields": null, + "interfaces": [ - ], + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "IssueSetAssigneesInput", + "description": "Autogenerated input type of IssueSetAssignees", + "fields": null, + "inputFields": [ + { + "name": "projectPath", + "description": "The project the issue to mutate is in", "type": { "kind": "NON_NULL", "name": null, "ofType": { - "kind": "OBJECT", - "name": "IssuePermissions", + "kind": "SCALAR", + "name": "ID", "ofType": null } }, - "isDeprecated": false, - "deprecationReason": null + "defaultValue": null }, { - "name": "webPath", - "description": "Web path of the issue", - "args": [ - - ], + "name": "iid", + "description": "The IID of the issue to mutate", "type": { "kind": "NON_NULL", "name": null, @@ -16580,126 +20178,110 @@ "ofType": null } }, - "isDeprecated": false, - "deprecationReason": null + "defaultValue": null }, { - "name": "webUrl", - "description": "Web URL of the issue", - "args": [ - - ], + "name": "assigneeUsernames", + "description": "The usernames to assign to the resource. Replaces existing assignees by default.", "type": { "kind": "NON_NULL", "name": null, "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } } }, - "isDeprecated": false, - "deprecationReason": null + "defaultValue": null }, { - "name": "weight", - "description": "Weight of the issue", - "args": [ - - ], + "name": "operationMode", + "description": "The operation to perform. Defaults to REPLACE.", "type": { - "kind": "SCALAR", - "name": "Int", + "kind": "ENUM", + "name": "MutationOperationMode", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ + "defaultValue": null + }, { - "kind": "INTERFACE", - "name": "Noteable", - "ofType": null + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null } ], + "interfaces": null, "enumValues": null, "possibleTypes": null }, { "kind": "OBJECT", - "name": "IssueConnection", - "description": "The connection type for Issue.", + "name": "IssueSetAssigneesPayload", + "description": "Autogenerated return type of IssueSetAssignees", "fields": [ { - "name": "count", - "description": "Total count of collection", - "args": [ - - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "edges", - "description": "A list of edges.", + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", "args": [ ], "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "IssueEdge", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "nodes", - "description": "A list of nodes.", + "name": "errors", + "description": "Errors encountered during execution of the mutation.", "args": [ ], "type": { - "kind": "LIST", + "kind": "NON_NULL", "name": null, "ofType": { - "kind": "OBJECT", - "name": "Issue", - "ofType": null + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "pageInfo", - "description": "Information to aid in pagination.", + "name": "issue", + "description": "The issue after mutation", "args": [ ], "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "PageInfo", - "ofType": null - } + "kind": "OBJECT", + "name": "Issue", + "ofType": null }, "isDeprecated": false, "deprecationReason": null @@ -16713,16 +20295,28 @@ "possibleTypes": null }, { - "kind": "OBJECT", - "name": "IssueEdge", - "description": "An edge in a connection.", - "fields": [ + "kind": "INPUT_OBJECT", + "name": "IssueSetConfidentialInput", + "description": "Autogenerated input type of IssueSetConfidential", + "fields": null, + "inputFields": [ { - "name": "cursor", - "description": "A cursor for use in pagination.", - "args": [ - - ], + "name": "projectPath", + "description": "The project the issue to mutate is in", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "iid", + "description": "The IID of the issue to mutate", "type": { "kind": "NON_NULL", "name": null, @@ -16732,57 +20326,59 @@ "ofType": null } }, - "isDeprecated": false, - "deprecationReason": null + "defaultValue": null }, { - "name": "node", - "description": "The item at the end of the edge.", - "args": [ - - ], + "name": "confidential", + "description": "Whether or not to set the issue as a confidential.", "type": { - "kind": "OBJECT", - "name": "Issue", + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null + "defaultValue": null } ], - "inputFields": null, - "interfaces": [ - - ], + "interfaces": null, "enumValues": null, "possibleTypes": null }, { "kind": "OBJECT", - "name": "IssuePermissions", - "description": "Check permissions for the current user on a issue", + "name": "IssueSetConfidentialPayload", + "description": "Autogenerated return type of IssueSetConfidential", "fields": [ { - "name": "adminIssue", - "description": "Indicates the user can perform `admin_issue` on this resource", + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", "args": [ ], "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "createDesign", - "description": "Indicates the user can perform `create_design` on this resource", + "name": "errors", + "description": "Errors encountered during execution of the mutation.", "args": [ ], @@ -16790,89 +20386,129 @@ "kind": "NON_NULL", "name": null, "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "createNote", - "description": "Indicates the user can perform `create_note` on this resource", + "name": "issue", + "description": "The issue after mutation", "args": [ ], + "type": { + "kind": "OBJECT", + "name": "Issue", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "IssueSetDueDateInput", + "description": "Autogenerated input type of IssueSetDueDate", + "fields": null, + "inputFields": [ + { + "name": "projectPath", + "description": "The project the issue to mutate is in", "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", - "name": "Boolean", + "name": "ID", "ofType": null } }, - "isDeprecated": false, - "deprecationReason": null + "defaultValue": null }, { - "name": "destroyDesign", - "description": "Indicates the user can perform `destroy_design` on this resource", - "args": [ - - ], + "name": "iid", + "description": "The IID of the issue to mutate", "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", - "name": "Boolean", + "name": "String", "ofType": null } }, - "isDeprecated": false, - "deprecationReason": null + "defaultValue": null }, { - "name": "readDesign", - "description": "Indicates the user can perform `read_design` on this resource", - "args": [ - - ], + "name": "dueDate", + "description": "The desired due date for the issue", "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", - "name": "Boolean", + "name": "Time", "ofType": null } }, - "isDeprecated": false, - "deprecationReason": null + "defaultValue": null }, { - "name": "readIssue", - "description": "Indicates the user can perform `read_issue` on this resource", + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "IssueSetDueDatePayload", + "description": "Autogenerated return type of IssueSetDueDate", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", "args": [ ], "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "reopenIssue", - "description": "Indicates the user can perform `reopen_issue` on this resource", + "name": "errors", + "description": "Errors encountered during execution of the mutation.", "args": [ ], @@ -16880,28 +20516,32 @@ "kind": "NON_NULL", "name": null, "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "updateIssue", - "description": "Indicates the user can perform `update_issue` on this resource", + "name": "issue", + "description": "The issue after mutation", "args": [ ], "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } + "kind": "OBJECT", + "name": "Issue", + "ofType": null }, "isDeprecated": false, "deprecationReason": null @@ -16916,8 +20556,8 @@ }, { "kind": "INPUT_OBJECT", - "name": "IssueSetConfidentialInput", - "description": "Autogenerated input type of IssueSetConfidential", + "name": "IssueSetEpicInput", + "description": "Autogenerated input type of IssueSetEpic", "fields": null, "inputFields": [ { @@ -16936,7 +20576,7 @@ }, { "name": "iid", - "description": "The iid of the issue to mutate", + "description": "The IID of the issue to mutate", "type": { "kind": "NON_NULL", "name": null, @@ -16949,16 +20589,12 @@ "defaultValue": null }, { - "name": "confidential", - "description": "Whether or not to set the issue as a confidential.", + "name": "epicId", + "description": "Global ID of the epic to be assigned to the issue, epic will be removed if absent or set to null", "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } + "kind": "SCALAR", + "name": "ID", + "ofType": null }, "defaultValue": null }, @@ -16979,8 +20615,8 @@ }, { "kind": "OBJECT", - "name": "IssueSetConfidentialPayload", - "description": "Autogenerated return type of IssueSetConfidential", + "name": "IssueSetEpicPayload", + "description": "Autogenerated return type of IssueSetEpic", "fields": [ { "name": "clientMutationId", @@ -17046,8 +20682,8 @@ }, { "kind": "INPUT_OBJECT", - "name": "IssueSetDueDateInput", - "description": "Autogenerated input type of IssueSetDueDate", + "name": "IssueSetIterationInput", + "description": "Autogenerated input type of IssueSetIteration", "fields": null, "inputFields": [ { @@ -17066,7 +20702,7 @@ }, { "name": "iid", - "description": "The iid of the issue to mutate", + "description": "The IID of the issue to mutate", "type": { "kind": "NON_NULL", "name": null, @@ -17079,16 +20715,12 @@ "defaultValue": null }, { - "name": "dueDate", - "description": "The desired due date for the issue", + "name": "iterationId", + "description": "The iteration to assign to the issue.\n", "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Time", - "ofType": null - } + "kind": "SCALAR", + "name": "ID", + "ofType": null }, "defaultValue": null }, @@ -17109,8 +20741,8 @@ }, { "kind": "OBJECT", - "name": "IssueSetDueDatePayload", - "description": "Autogenerated return type of IssueSetDueDate", + "name": "IssueSetIterationPayload", + "description": "Autogenerated return type of IssueSetIteration", "fields": [ { "name": "clientMutationId", @@ -17176,8 +20808,8 @@ }, { "kind": "INPUT_OBJECT", - "name": "IssueSetIterationInput", - "description": "Autogenerated input type of IssueSetIteration", + "name": "IssueSetLockedInput", + "description": "Autogenerated input type of IssueSetLocked", "fields": null, "inputFields": [ { @@ -17196,7 +20828,7 @@ }, { "name": "iid", - "description": "The iid of the issue to mutate", + "description": "The IID of the issue to mutate", "type": { "kind": "NON_NULL", "name": null, @@ -17209,12 +20841,16 @@ "defaultValue": null }, { - "name": "iterationId", - "description": "The iteration to assign to the issue.\n", + "name": "locked", + "description": "Whether or not to lock discussion on the issue", "type": { - "kind": "SCALAR", - "name": "ID", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } }, "defaultValue": null }, @@ -17235,8 +20871,8 @@ }, { "kind": "OBJECT", - "name": "IssueSetIterationPayload", - "description": "Autogenerated return type of IssueSetIteration", + "name": "IssueSetLockedPayload", + "description": "Autogenerated return type of IssueSetLocked", "fields": [ { "name": "clientMutationId", @@ -17302,8 +20938,8 @@ }, { "kind": "INPUT_OBJECT", - "name": "IssueSetLockedInput", - "description": "Autogenerated input type of IssueSetLocked", + "name": "IssueSetSubscriptionInput", + "description": "Autogenerated input type of IssueSetSubscription", "fields": null, "inputFields": [ { @@ -17322,7 +20958,7 @@ }, { "name": "iid", - "description": "The iid of the issue to mutate", + "description": "The IID of the issue to mutate", "type": { "kind": "NON_NULL", "name": null, @@ -17335,8 +20971,8 @@ "defaultValue": null }, { - "name": "locked", - "description": "Whether or not to lock discussion on the issue", + "name": "subscribedState", + "description": "The desired state of the subscription", "type": { "kind": "NON_NULL", "name": null, @@ -17365,8 +21001,8 @@ }, { "kind": "OBJECT", - "name": "IssueSetLockedPayload", - "description": "Autogenerated return type of IssueSetLocked", + "name": "IssueSetSubscriptionPayload", + "description": "Autogenerated return type of IssueSetSubscription", "fields": [ { "name": "clientMutationId", @@ -17452,7 +21088,7 @@ }, { "name": "iid", - "description": "The iid of the issue to mutate", + "description": "The IID of the issue to mutate", "type": { "kind": "NON_NULL", "name": null, @@ -17686,6 +21322,90 @@ "description": null, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "all", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "IssueStatusCountsType", + "description": "Represents total number of issues for the represented statuses.", + "fields": [ + { + "name": "all", + "description": "Number of issues with status ALL for the project", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "closed", + "description": "Number of issues with status CLOSED for the project", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "opened", + "description": "Number of issues with status OPENED for the project", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "IssueType", + "description": "Issue type", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "ISSUE", + "description": "Issue issue type", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "INCIDENT", + "description": "Incident issue type", + "isDeprecated": false, + "deprecationReason": null } ], "possibleTypes": null @@ -17727,6 +21447,20 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "descriptionHtml", + "description": "The GitLab Flavored Markdown rendering of `description`", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "dueDate", "description": "Timestamp of the iteration due date", @@ -17777,6 +21511,34 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "scopedPath", + "description": "Web path of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "scopedUrl", + "description": "Web URL of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "startDate", "description": "Timestamp of the iteration start date", @@ -18001,6 +21763,16 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "SCALAR", + "name": "IterationID", + "description": "Identifier of Iteration", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "ENUM", "name": "IterationState", @@ -19203,6 +22975,16 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "SCALAR", + "name": "LabelID", + "description": "Identifier of Label", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "ENUM", "name": "ListLimitMetric", @@ -19445,6 +23227,59 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "approvedBy", + "description": "Users who approved the merge request", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "UserConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "assignees", "description": "Assignees of the merge request", @@ -19512,6 +23347,20 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "commitCount", + "description": "Number of commits in the merge request", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "createdAt", "description": "Timestamp of when the merge request was created", @@ -20698,6 +24547,24 @@ "name": "MergeRequestConnection", "description": "The connection type for MergeRequest.", "fields": [ + { + "name": "count", + "description": "Total count of collection", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "edges", "description": "A list of edges.", @@ -20832,6 +24699,24 @@ }, "defaultValue": null }, + { + "name": "labels", + "description": "Labels of the merge request", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, { "name": "clientMutationId", "description": "A unique identifier for the client performing the mutation.", @@ -21152,7 +25037,7 @@ }, { "name": "assigneeUsernames", - "description": "The usernames to assign to the merge request. Replaces existing assignees by default.\n", + "description": "The usernames to assign to the resource. Replaces existing assignees by default.", "type": { "kind": "NON_NULL", "name": null, @@ -21174,7 +25059,7 @@ }, { "name": "operationMode", - "description": "The operation to perform. Defaults to REPLACE.\n", + "description": "The operation to perform. Defaults to REPLACE.", "type": { "kind": "ENUM", "name": "MutationOperationMode", @@ -21954,6 +25839,12 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "all", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "merged", "description": null, @@ -22826,6 +26717,16 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "SCALAR", + "name": "MilestoneID", + "description": "Identifier of Milestone", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "ENUM", "name": "MilestoneStateEnum", @@ -23134,6 +27035,33 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "boardListCreate", + "description": null, + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "BoardListCreateInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "BoardListCreatePayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "boardListUpdateLimitMetrics", "description": null, @@ -23188,6 +27116,33 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "configureSast", + "description": null, + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "ConfigureSastInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "ConfigureSastPayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "createAlertIssue", "description": null, @@ -23269,6 +27224,33 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "createClusterAgent", + "description": null, + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CreateClusterAgentInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "CreateClusterAgentPayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "createDiffNote", "description": null, @@ -23458,6 +27440,60 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "dastOnDemandScanCreate", + "description": null, + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "DastOnDemandScanCreateInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "DastOnDemandScanCreatePayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "dastScannerProfileCreate", + "description": null, + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "DastScannerProfileCreateInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "DastScannerProfileCreatePayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "dastSiteProfileCreate", "description": null, @@ -23485,6 +27521,60 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "dastSiteProfileDelete", + "description": null, + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "DastSiteProfileDeleteInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "DastSiteProfileDeletePayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "dastSiteProfileUpdate", + "description": null, + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "DastSiteProfileUpdateInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "DastSiteProfileUpdatePayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "deleteAnnotation", "description": null, @@ -23539,6 +27629,33 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "designManagementMove", + "description": null, + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "DesignManagementMoveInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "DesignManagementMovePayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "designManagementUpload", "description": null, @@ -23755,6 +27872,60 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "issueMoveList", + "description": null, + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "IssueMoveListInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "IssueMoveListPayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "issueSetAssignees", + "description": null, + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "IssueSetAssigneesInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "IssueSetAssigneesPayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "issueSetConfidential", "description": null, @@ -23809,6 +27980,33 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "issueSetEpic", + "description": null, + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "IssueSetEpicInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "IssueSetEpicPayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "issueSetIteration", "description": null, @@ -23863,6 +28061,33 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "issueSetSubscription", + "description": null, + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "IssueSetSubscriptionInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "IssueSetSubscriptionPayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "issueSetWeight", "description": null, @@ -24187,6 +28412,33 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "namespaceIncreaseStorageTemporarily", + "description": null, + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NamespaceIncreaseStorageTemporarilyInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "NamespaceIncreaseStorageTemporarilyPayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "removeAwardEmoji", "description": null, @@ -24430,6 +28682,60 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "updateBoard", + "description": null, + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "UpdateBoardInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "UpdateBoardPayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "updateBoardList", + "description": null, + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "UpdateBoardListInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "UpdateBoardListPayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "updateContainerExpirationPolicy", "description": null, @@ -24770,6 +29076,24 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "isTemporaryStorageIncreaseEnabled", + "description": "Status of the temporary storage increase", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "lfsEnabled", "description": "Indicates if Large File Storage (LFS) is enabled for namespace", @@ -25087,6 +29411,207 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "NamespaceIncreaseStorageTemporarilyInput", + "description": "Autogenerated input type of NamespaceIncreaseStorageTemporarily", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": "The global id of the namespace to mutate", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "NamespaceIncreaseStorageTemporarilyPayload", + "description": "Autogenerated return type of NamespaceIncreaseStorageTemporarily", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "namespace", + "description": "The namespace after mutation", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "Namespace", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "NegatedBoardEpicIssueInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "labelName", + "description": "Filter by label name", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "milestoneTitle", + "description": "Filter by milestone title", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "assigneeUsername", + "description": "Filter by assignee username", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "authorUsername", + "description": "Filter by author username", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "releaseTag", + "description": "Filter by release tag", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "epicId", + "description": "Filter by epic ID", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "myReactionEmoji", + "description": "Filter by reaction emoji", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "weight", + "description": "Filter by weight", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "Note", @@ -26385,6 +30910,20 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "configSource", + "description": "Config source of the pipeline (UNKNOWN_SOURCE, REPOSITORY_SOURCE, AUTO_DEVOPS_SOURCE, WEBIDE_SOURCE, REMOTE_SOURCE, EXTERNAL_PROJECT_SOURCE, BRIDGE_SOURCE, PARAMETER_SOURCE)", + "args": [ + + ], + "type": { + "kind": "ENUM", + "name": "PipelineConfigSourceEnum", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "coverage", "description": "Coverage percentage", @@ -26531,6 +31070,59 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "stages", + "description": "Stages of the pipeline", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "CiStageConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "startedAt", "description": "Timestamp when the pipeline was started", @@ -26581,6 +31173,20 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "user", + "description": "Pipeline user", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "userPermissions", "description": "Permissions for the current user on the resource", @@ -26607,11 +31213,88 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "ENUM", + "name": "PipelineConfigSourceEnum", + "description": null, + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "UNKNOWN_SOURCE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "REPOSITORY_SOURCE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "AUTO_DEVOPS_SOURCE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "WEBIDE_SOURCE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "REMOTE_SOURCE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "EXTERNAL_PROJECT_SOURCE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "BRIDGE_SOURCE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "PARAMETER_SOURCE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, { "kind": "OBJECT", "name": "PipelineConnection", "description": "The connection type for Pipeline.", "fields": [ + { + "name": "count", + "description": "Total count of collection", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "edges", "description": "A list of edges.", @@ -27290,6 +31973,112 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "dastScannerProfiles", + "description": "The DAST scanner profiles associated with the project", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "DastScannerProfileConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "dastSiteProfiles", + "description": "DAST Site Profiles associated with the project", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "DastSiteProfileConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "description", "description": "Short description of the project", @@ -27318,6 +32107,57 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "environment", + "description": "A single environment of the project", + "args": [ + { + "name": "name", + "description": "Name of the environment", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "search", + "description": "Search query for environment name", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "states", + "description": "States of environments that should be included in result", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "Environment", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "environments", "description": "Environments of the project", @@ -27551,16 +32391,6 @@ }, "defaultValue": null }, - { - "name": "state", - "description": "Current state of this issue", - "type": { - "kind": "ENUM", - "name": "IssuableState", - "ofType": null - }, - "defaultValue": null - }, { "name": "labelName", "description": "Labels applied to this issue", @@ -27577,7 +32407,7 @@ }, { "name": "milestoneTitle", - "description": "Milestones applied to this issue", + "description": "Milestone applied to this issue", "type": { "kind": "LIST", "name": null, @@ -27591,7 +32421,7 @@ }, { "name": "assigneeUsername", - "description": "Username of a user assigned to the issues", + "description": "Username of a user assigned to the issue", "type": { "kind": "SCALAR", "name": "String", @@ -27679,6 +32509,34 @@ }, "defaultValue": null }, + { + "name": "types", + "description": "Filter issues by the given issue types", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "IssueType", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "state", + "description": "Current state of this issue", + "type": { + "kind": "ENUM", + "name": "IssuableState", + "ofType": null + }, + "defaultValue": null + }, { "name": "sort", "description": "Sort issues by this criteria", @@ -27713,8 +32571,8 @@ "deprecationReason": null }, { - "name": "issues", - "description": "Issues of the project", + "name": "issueStatusCounts", + "description": "Counts of issues by status for the project", "args": [ { "name": "iid", @@ -27745,15 +32603,182 @@ "defaultValue": null }, { - "name": "state", - "description": "Current state of this issue", + "name": "labelName", + "description": "Labels applied to this issue", "type": { - "kind": "ENUM", - "name": "IssuableState", + "kind": "LIST", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "milestoneTitle", + "description": "Milestone applied to this issue", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "assigneeUsername", + "description": "Username of a user assigned to the issue", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "assigneeId", + "description": "ID of a user assigned to the issues, \"none\" and \"any\" values supported", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "createdBefore", + "description": "Issues created before this date", + "type": { + "kind": "SCALAR", + "name": "Time", "ofType": null }, "defaultValue": null }, + { + "name": "createdAfter", + "description": "Issues created after this date", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "updatedBefore", + "description": "Issues updated before this date", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "updatedAfter", + "description": "Issues updated after this date", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "closedBefore", + "description": "Issues closed before this date", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "closedAfter", + "description": "Issues closed after this date", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "search", + "description": "Search query for issue title or description", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "types", + "description": "Filter issues by the given issue types", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "IssueType", + "ofType": null + } + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "IssueStatusCountsType", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "issues", + "description": "Issues of the project", + "args": [ + { + "name": "iid", + "description": "IID of the issue. For example, \"1\"", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "iids", + "description": "List of IIDs of issues. For example, [1, 2]", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, { "name": "labelName", "description": "Labels applied to this issue", @@ -27770,7 +32795,7 @@ }, { "name": "milestoneTitle", - "description": "Milestones applied to this issue", + "description": "Milestone applied to this issue", "type": { "kind": "LIST", "name": null, @@ -27784,7 +32809,7 @@ }, { "name": "assigneeUsername", - "description": "Username of a user assigned to the issues", + "description": "Username of a user assigned to the issue", "type": { "kind": "SCALAR", "name": "String", @@ -27872,6 +32897,34 @@ }, "defaultValue": null }, + { + "name": "types", + "description": "Filter issues by the given issue types", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "IssueType", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "state", + "description": "Current state of this issue", + "type": { + "kind": "ENUM", + "name": "IssuableState", + "ofType": null + }, + "defaultValue": null + }, { "name": "sort", "description": "Sort issues by this criteria", @@ -27959,6 +33012,129 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "iterations", + "description": "Find iterations", + "args": [ + { + "name": "startDate", + "description": "List items within a time frame where items.start_date is between startDate and endDate parameters (endDate parameter must be present)", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "endDate", + "description": "List items within a time frame where items.end_date is between startDate and endDate parameters (startDate parameter must be present)", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "state", + "description": "Filter iterations by state", + "type": { + "kind": "ENUM", + "name": "IterationState", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "title", + "description": "Fuzzy search by title", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "id", + "description": "The ID of the Iteration to look up", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "iid", + "description": "The internal ID of the Iteration to look up", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "includeAncestors", + "description": "Whether to include ancestor iterations. Defaults to true", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "IterationConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "jiraImportStatus", "description": "Status of Jira import background job of the project", @@ -28271,6 +33447,26 @@ }, "defaultValue": null }, + { + "name": "mergedAfter", + "description": "Merge requests merged after this date", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "mergedBefore", + "description": "Merge requests merged before this date", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", @@ -28348,6 +33544,117 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "milestones", + "description": "Milestones of the project", + "args": [ + { + "name": "startDate", + "description": "List items within a time frame where items.start_date is between startDate and endDate parameters (endDate parameter must be present)", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "endDate", + "description": "List items within a time frame where items.end_date is between startDate and endDate parameters (startDate parameter must be present)", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "ids", + "description": "Array of global milestone IDs, e.g., \"gid://gitlab/Milestone/1\"", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "state", + "description": "Filter milestones by state", + "type": { + "kind": "ENUM", + "name": "MilestoneStateEnum", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "includeAncestors", + "description": "Also return milestones in the project's parent group and its ancestors", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "MilestoneConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "name", "description": "Name of the project (without namespace)", @@ -29080,6 +34387,20 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "securityDashboardPath", + "description": "Path to project's security dashboard", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "securityScanners", "description": "Information about security analyzers used in the project", @@ -31035,6 +36356,55 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "PrometheusAlert", + "description": "The alert condition for Prometheus", + "fields": [ + { + "name": "humanizedText", + "description": "The human-readable text of the alert condition", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "ID of the alert condition", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "Query", @@ -31167,6 +36537,33 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "iteration", + "description": "Find an iteration", + "args": [ + { + "name": "id", + "description": "Find an iteration by its ID", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "IterationID", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "Iteration", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "metadata", "description": "Metadata about GitLab", @@ -31181,6 +36578,33 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "milestone", + "description": "Find a milestone", + "args": [ + { + "name": "id", + "description": "Find a milestone by its ID", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "MilestoneID", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "Milestone", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "namespace", "description": "Find a namespace", @@ -31302,19 +36726,272 @@ ], "type": { "kind": "OBJECT", - "name": "ProjectConnection", + "name": "ProjectConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "snippets", + "description": "Find Snippets visible to the current user", + "args": [ + { + "name": "ids", + "description": "Array of global snippet ids, e.g., \"gid://gitlab/ProjectSnippet/1\"", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "visibility", + "description": "The visibility of the snippet", + "type": { + "kind": "ENUM", + "name": "VisibilityScopesEnum", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "authorId", + "description": "The ID of an author", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "projectId", + "description": "The ID of a project", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "type", + "description": "The type of snippet", + "type": { + "kind": "ENUM", + "name": "TypeEnum", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "explore", + "description": "Explore personal snippets", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "SnippetConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "user", + "description": "Find a user", + "args": [ + { + "name": "id", + "description": "ID of the User", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "username", + "description": "Username of the User", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "users", + "description": "Find users", + "args": [ + { + "name": "ids", + "description": "List of user Global IDs", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "usernames", + "description": "List of usernames", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "sort", + "description": "Sort users by this criteria", + "type": { + "kind": "ENUM", + "name": "Sort", + "ofType": null + }, + "defaultValue": "created_desc" + }, + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "UserConnection", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "snippets", - "description": "Find Snippets visible to the current user", + "name": "vulnerabilities", + "description": "Vulnerabilities reported on projects on the current user's instance security dashboard", "args": [ { - "name": "ids", - "description": "Array of global snippet ids, e.g., \"gid://gitlab/ProjectSnippet/1\"", + "name": "projectId", + "description": "Filter vulnerabilities by project", "type": { "kind": "LIST", "name": null, @@ -31331,144 +37008,44 @@ "defaultValue": null }, { - "name": "visibility", - "description": "The visibility of the snippet", - "type": { - "kind": "ENUM", - "name": "VisibilityScopesEnum", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "authorId", - "description": "The ID of an author", - "type": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "projectId", - "description": "The ID of a project", - "type": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "type", - "description": "The type of snippet", - "type": { - "kind": "ENUM", - "name": "TypeEnum", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "explore", - "description": "Explore personal snippets", - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "after", - "description": "Returns the elements in the list that come after the specified cursor.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "before", - "description": "Returns the elements in the list that come before the specified cursor.", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "first", - "description": "Returns the first _n_ elements from the list.", + "name": "reportType", + "description": "Filter vulnerabilities by report type", "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "VulnerabilityReportType", + "ofType": null + } + } }, "defaultValue": null }, { - "name": "last", - "description": "Returns the last _n_ elements from the list.", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "SnippetConnection", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "user", - "description": "Find a user", - "args": [ - { - "name": "id", - "description": "ID of the User", + "name": "severity", + "description": "Filter vulnerabilities by severity", "type": { - "kind": "SCALAR", - "name": "ID", - "ofType": null + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "VulnerabilitySeverity", + "ofType": null + } + } }, "defaultValue": null }, { - "name": "username", - "description": "Username of the User", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "User", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "users", - "description": "Find users", - "args": [ - { - "name": "ids", - "description": "List of user Global IDs", + "name": "state", + "description": "Filter vulnerabilities by state", "type": { "kind": "LIST", "name": null, @@ -31476,8 +37053,8 @@ "kind": "NON_NULL", "name": null, "ofType": { - "kind": "SCALAR", - "name": "ID", + "kind": "ENUM", + "name": "VulnerabilityState", "ofType": null } } @@ -31485,8 +37062,8 @@ "defaultValue": null }, { - "name": "usernames", - "description": "List of usernames", + "name": "scanner", + "description": "Filter vulnerabilities by scanner", "type": { "kind": "LIST", "name": null, @@ -31502,16 +37079,6 @@ }, "defaultValue": null }, - { - "name": "sort", - "description": "Sort users by this criteria", - "type": { - "kind": "ENUM", - "name": "Sort", - "ofType": null - }, - "defaultValue": "created_desc" - }, { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", @@ -31555,102 +37122,40 @@ ], "type": { "kind": "OBJECT", - "name": "UserConnection", + "name": "VulnerabilityConnection", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, { - "name": "vulnerabilities", - "description": "Vulnerabilities reported on projects on the current user's instance security dashboard", + "name": "vulnerabilitiesCountByDay", + "description": "Number of vulnerabilities per day for the projects on the current user's instance security dashboard", "args": [ { - "name": "projectId", - "description": "Filter vulnerabilities by project", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - } - }, - "defaultValue": null - }, - { - "name": "reportType", - "description": "Filter vulnerabilities by report type", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "VulnerabilityReportType", - "ofType": null - } - } - }, - "defaultValue": null - }, - { - "name": "severity", - "description": "Filter vulnerabilities by severity", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "VulnerabilitySeverity", - "ofType": null - } - } - }, - "defaultValue": null - }, - { - "name": "state", - "description": "Filter vulnerabilities by state", + "name": "startDate", + "description": "First day for which to fetch vulnerability history", "type": { - "kind": "LIST", + "kind": "NON_NULL", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "VulnerabilityState", - "ofType": null - } + "kind": "SCALAR", + "name": "ISO8601Date", + "ofType": null } }, "defaultValue": null }, { - "name": "scanner", - "description": "Filter vulnerabilities by scanner", + "name": "endDate", + "description": "Last day for which to fetch vulnerability history", "type": { - "kind": "LIST", + "kind": "NON_NULL", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "ISO8601Date", + "ofType": null } }, "defaultValue": null @@ -31698,7 +37203,7 @@ ], "type": { "kind": "OBJECT", - "name": "VulnerabilityConnection", + "name": "VulnerabilitiesCountByDayConnection", "ofType": null }, "isDeprecated": false, @@ -31706,7 +37211,7 @@ }, { "name": "vulnerabilitiesCountByDayAndSeverity", - "description": "Number of vulnerabilities per severity level, per day, for the projects on the current user's instance security dashboard", + "description": "Number of vulnerabilities per severity level, per day, for the projects on the current user's instance security dashboard. Deprecated in 13.3: Use `vulnerabilitiesCountByDay`", "args": [ { "name": "startDate", @@ -31782,8 +37287,8 @@ "name": "VulnerabilitiesCountByDayAndSeverityConnection", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null + "isDeprecated": true, + "deprecationReason": "Use `vulnerabilitiesCountByDay`. Deprecated in 13.3" } ], "inputFields": null, @@ -34646,6 +40151,20 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "size", + "description": "Size of the UI component.", + "args": [ + + ], + "type": { + "kind": "ENUM", + "name": "SastUiComponentSize", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "type", "description": "Type of the field value.", @@ -34947,6 +40466,35 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "ENUM", + "name": "SastUiComponentSize", + "description": "Size of UI component in SAST configuration page", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "SMALL", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "MEDIUM", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "LARGE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, { "kind": "OBJECT", "name": "ScannedResource", @@ -35342,6 +40890,12 @@ "description": null, "isDeprecated": false, "deprecationReason": null + }, + { + "name": "COVERAGE_FUZZING", + "description": null, + "isDeprecated": false, + "deprecationReason": null } ], "possibleTypes": null @@ -37243,7 +42797,7 @@ }, { "name": "blob", - "description": "Snippet blob", + "description": "Snippet blob. Deprecated in 13.3: Use `blobs`", "args": [ ], @@ -37256,8 +42810,8 @@ "ofType": null } }, - "isDeprecated": false, - "deprecationReason": null + "isDeprecated": true, + "deprecationReason": "Use `blobs`. Deprecated in 13.3" }, { "name": "blobs", @@ -37840,257 +43394,10 @@ "enumValues": null, "possibleTypes": null }, - { - "kind": "OBJECT", - "name": "SnippetBlobViewer", - "description": "Represents how the blob content should be displayed", - "fields": [ - { - "name": "collapsed", - "description": "Shows whether the blob should be displayed collapsed", - "args": [ - - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "fileType", - "description": "Content file type", - "args": [ - - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "loadAsync", - "description": "Shows whether the blob content is loaded async", - "args": [ - - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "loadingPartialName", - "description": "Loading partial name", - "args": [ - - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "renderError", - "description": "Error rendering the blob content", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "tooLarge", - "description": "Shows whether the blob too large to be displayed", - "args": [ - - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": "Type of blob viewer", - "args": [ - - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "BlobViewersType", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ - - ], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "SnippetConnection", - "description": "The connection type for Snippet.", - "fields": [ - { - "name": "edges", - "description": "A list of edges.", - "args": [ - - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "SnippetEdge", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "nodes", - "description": "A list of nodes.", - "args": [ - - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Snippet", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "pageInfo", - "description": "Information to aid in pagination.", - "args": [ - - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "PageInfo", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ - - ], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "SnippetEdge", - "description": "An edge in a connection.", - "fields": [ - { - "name": "cursor", - "description": "A cursor for use in pagination.", - "args": [ - - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "node", - "description": "The item at the end of the edge.", - "args": [ - - ], - "type": { - "kind": "OBJECT", - "name": "Snippet", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ - - ], - "enumValues": null, - "possibleTypes": null - }, { "kind": "ENUM", - "name": "SnippetFileInputActionEnum", - "description": "Type of a snippet file input action", + "name": "SnippetBlobActionEnum", + "description": "Type of a snippet blob input action", "fields": null, "inputFields": null, "interfaces": null, @@ -38124,7 +43431,7 @@ }, { "kind": "INPUT_OBJECT", - "name": "SnippetFileInputType", + "name": "SnippetBlobActionInputType", "description": "Represents an action to perform over a snippet file", "fields": null, "inputFields": [ @@ -38136,7 +43443,7 @@ "name": null, "ofType": { "kind": "ENUM", - "name": "SnippetFileInputActionEnum", + "name": "SnippetBlobActionEnum", "ofType": null } }, @@ -38181,6 +43488,253 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "SnippetBlobViewer", + "description": "Represents how the blob content should be displayed", + "fields": [ + { + "name": "collapsed", + "description": "Shows whether the blob should be displayed collapsed", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "fileType", + "description": "Content file type", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "loadAsync", + "description": "Shows whether the blob content is loaded async", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "loadingPartialName", + "description": "Loading partial name", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "renderError", + "description": "Error rendering the blob content", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "tooLarge", + "description": "Shows whether the blob too large to be displayed", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": "Type of blob viewer", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "BlobViewersType", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "SnippetConnection", + "description": "The connection type for Snippet.", + "fields": [ + { + "name": "edges", + "description": "A list of edges.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "SnippetEdge", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": "A list of nodes.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Snippet", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": "Information to aid in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "SnippetEdge", + "description": "An edge in a connection.", + "fields": [ + { + "name": "cursor", + "description": "A cursor for use in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": "The item at the end of the edge.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "Snippet", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "SnippetPermissions", @@ -40427,6 +45981,20 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "webPath", + "description": "Web path for the tree entry (directory)", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "webUrl", "description": "Web URL for the tree entry (directory)", @@ -40756,6 +46324,290 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "UpdateBoardInput", + "description": "Autogenerated input type of UpdateBoard", + "fields": null, + "inputFields": [ + { + "name": "id", + "description": "The board global id.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "name", + "description": "Name of the board", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "hideBacklogList", + "description": "Whether or not backlog list is hidden.", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "hideClosedList", + "description": "Whether or not closed list is hidden.", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "assigneeId", + "description": "The id of user to be assigned to the board.", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "milestoneId", + "description": "The id of milestone to be assigned to the board.", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "weight", + "description": "The weight value to be assigned to the board.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "UpdateBoardListInput", + "description": "Autogenerated input type of UpdateBoardList", + "fields": null, + "inputFields": [ + { + "name": "listId", + "description": "Global ID of the list.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "position", + "description": "Position of list within the board", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "collapsed", + "description": "Indicates if list is collapsed for this user", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "UpdateBoardListPayload", + "description": "Autogenerated return type of UpdateBoardList", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "list", + "description": "Mutated list", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "BoardList", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "UpdateBoardPayload", + "description": "Autogenerated return type of UpdateBoard", + "fields": [ + { + "name": "board", + "description": "The board after mutation.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "Board", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", "name": "UpdateContainerExpirationPolicyInput", @@ -41345,7 +47197,7 @@ }, { "name": "iid", - "description": "The iid of the issue to mutate", + "description": "The IID of the issue to mutate", "type": { "kind": "NON_NULL", "name": null, @@ -41397,6 +47249,62 @@ }, "defaultValue": null }, + { + "name": "locked", + "description": "Indicates discussion is locked on the issue", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "addLabelIds", + "description": "The IDs of labels to be added to the issue.", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "removeLabelIds", + "description": "The IDs of labels to be removed from the issue.", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "milestoneId", + "description": "The ID of the milestone to be assigned, milestone will be removed if set to null.", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, { "name": "healthStatus", "description": "The desired health status", @@ -41669,13 +47577,19 @@ "name": "body", "description": "Content of the note", "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "confidential", + "description": "The confidentiality flag of a note. Default is false.", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null }, "defaultValue": null }, @@ -41968,8 +47882,8 @@ "defaultValue": null }, { - "name": "files", - "description": "The snippet files to update", + "name": "blobActions", + "description": "Actions to perform over the snippet repository and blobs", "type": { "kind": "LIST", "name": null, @@ -41978,7 +47892,7 @@ "name": null, "ofType": { "kind": "INPUT_OBJECT", - "name": "SnippetFileInputType", + "name": "SnippetBlobActionInputType", "ofType": null } } @@ -42168,6 +48082,26 @@ }, "defaultValue": null }, + { + "name": "mergedAfter", + "description": "Merge requests merged after this date", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "mergedBefore", + "description": "Merge requests merged before this date", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, { "name": "projectPath", "description": "The full-path of the project the authored merge requests should be in. Incompatible with projectId.", @@ -42323,6 +48257,26 @@ }, "defaultValue": null }, + { + "name": "mergedAfter", + "description": "Merge requests merged after this date", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "mergedBefore", + "description": "Merge requests merged before this date", + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "defaultValue": null + }, { "name": "projectPath", "description": "The full-path of the project the authored merge requests should be in. Incompatible with projectId.", @@ -42406,6 +48360,20 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "email", + "description": "User email", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "groupMemberships", "description": "Group memberships of the user", @@ -42657,6 +48625,20 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "status", + "description": "User status", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "UserStatus", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "todos", "description": "Todos of the user", @@ -42858,6 +48840,24 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "webPath", + "description": "Web path of the user", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "webUrl", "description": "Web URL of the user", @@ -43056,6 +49056,61 @@ ], "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "UserStatus", + "description": null, + "fields": [ + { + "name": "emoji", + "description": "String representation of emoji", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "message", + "description": "User status message", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "messageHtml", + "description": "HTML of the user status message", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, { "kind": "ENUM", "name": "VisibilityLevelsEnum", @@ -43114,6 +49169,163 @@ ], "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "VulnerabilitiesCountByDay", + "description": "Represents the count of vulnerabilities by severity on a particular day", + "fields": [ + { + "name": "critical", + "description": "Total number of vulnerabilities on a particular day with critical severity", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "date", + "description": "Date for the count", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ISO8601Date", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "high", + "description": "Total number of vulnerabilities on a particular day with high severity", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "info", + "description": "Total number of vulnerabilities on a particular day with info severity", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "low", + "description": "Total number of vulnerabilities on a particular day with low severity", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "medium", + "description": "Total number of vulnerabilities on a particular day with medium severity", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "total", + "description": "Total number of vulnerabilities on a particular day", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "unknown", + "description": "Total number of vulnerabilities on a particular day with unknown severity", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "VulnerabilitiesCountByDayAndSeverity", @@ -43281,6 +49493,118 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "VulnerabilitiesCountByDayConnection", + "description": "The connection type for VulnerabilitiesCountByDay.", + "fields": [ + { + "name": "edges", + "description": "A list of edges.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "VulnerabilitiesCountByDayEdge", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": "A list of nodes.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "VulnerabilitiesCountByDay", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": "Information to aid in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "VulnerabilitiesCountByDayEdge", + "description": "An edge in a connection.", + "fields": [ + { + "name": "cursor", + "description": "A cursor for use in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": "The item at the end of the edge.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "VulnerabilitiesCountByDay", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "Vulnerability", @@ -43467,6 +49791,24 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "resolvedOnDefaultBranch", + "description": "Indicates whether the vulnerability is fixed on the default branch or not", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "scanner", "description": "Scanner metadata for the vulnerability.", @@ -43693,6 +50035,47 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "ENUM", + "name": "VulnerabilityGrade", + "description": "The grade of the vulnerable project", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "A", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "B", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "C", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "D", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "F", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, { "kind": "OBJECT", "name": "VulnerabilityIdentifier", @@ -43978,6 +50361,11 @@ "name": "VulnerabilityLocationContainerScanning", "ofType": null }, + { + "kind": "OBJECT", + "name": "VulnerabilityLocationCoverageFuzzing", + "ofType": null + }, { "kind": "OBJECT", "name": "VulnerabilityLocationDast", @@ -44055,6 +50443,89 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "VulnerabilityLocationCoverageFuzzing", + "description": "Represents the location of a vulnerability found by a Coverage Fuzzing scan", + "fields": [ + { + "name": "endLine", + "description": "Number of the last relevant line in the vulnerable file", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "file", + "description": "Path to the vulnerable file", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "startLine", + "description": "Number of the first relevant line in the vulnerable file", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "vulnerableClass", + "description": "Class containing the vulnerability", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "vulnerableMethod", + "description": "Method containing the vulnerability", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "VulnerabilityLocationDast", @@ -44963,6 +51434,112 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "VulnerableProjectsByGrade", + "description": "Represents vulnerability letter grades with associated projects", + "fields": [ + { + "name": "count", + "description": "Number of projects within this grade", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "grade", + "description": "Grade based on the highest severity vulnerability present", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "VulnerabilityGrade", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "projects", + "description": "Projects within this grade", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "ProjectConnection", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "__Directive", diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 6df6632f3bd..8ba1862b009 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -64,6 +64,7 @@ Describes an alert from the project's Alert Management | `createdAt` | Time | Timestamp the alert was created | | `description` | String | Description of the alert | | `details` | JSON | Alert details | +| `detailsUrl` | String! | The URL of the alert detail page | | `endedAt` | Time | Timestamp the alert ended | | `eventCount` | Int | Number of events of this alert | | `hosts` | String! => Array | List of hosts the alert came from | @@ -71,6 +72,8 @@ Describes an alert from the project's Alert Management | `issueIid` | ID | Internal ID of the GitLab issue attached to the alert | | `metricsDashboardUrl` | String | URL for metrics embed for the alert | | `monitoringTool` | String | Monitoring tool the alert came from | +| `prometheusAlert` | PrometheusAlert | The alert condition for Prometheus | +| `runbook` | String | Runbook for the alert as defined in alert details | | `service` | String | Service the alert came from | | `severity` | AlertManagementSeverity | Severity of the alert | | `startedAt` | Time | Timestamp the alert was raised | @@ -178,6 +181,7 @@ Autogenerated return type of AwardEmojiToggle | `path` | String! | Path of the entry | | `sha` | String! | Last commit sha for the entry | | `type` | EntryType! | Type of tree entry | +| `webPath` | String | Web path of the blob | | `webUrl` | String | Web URL of the blob | ## Board @@ -186,9 +190,13 @@ Represents a project or group board | Name | Type | Description | | --- | ---- | ---------- | +| `assignee` | User | The board assignee. | +| `hideBacklogList` | Boolean | Whether or not backlog list is hidden. | +| `hideClosedList` | Boolean | Whether or not closed list is hidden. | | `id` | ID! | ID (global ID) of the board | +| `milestone` | Milestone | The board milestone. | | `name` | String | Name of the board | -| `weight` | Int | Weight of the board | +| `weight` | Int | Weight of the board. | ## BoardList @@ -199,6 +207,7 @@ Represents a list for an issue board | `assignee` | User | Assignee in the list | | `collapsed` | Boolean | Indicates if list is collapsed for this user | | `id` | ID! | ID (global ID) of the list | +| `issuesCount` | Int | Count of issues in the list | | `label` | Label | Label of the list | | `limitMetric` | ListLimitMetric | The current limit metric for the list | | `listType` | String! | Type of the list | @@ -207,6 +216,17 @@ Represents a list for an issue board | `milestone` | Milestone | Milestone of the list | | `position` | Int | Position of list within the board | | `title` | String! | Title of the list | +| `totalWeight` | Int | Total weight of all issues in the list | + +## BoardListCreatePayload + +Autogenerated return type of BoardListCreate + +| Name | Type | Description | +| --- | ---- | ---------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Errors encountered during execution of the mutation. | +| `list` | BoardList | List of the issue board | ## BoardListUpdateLimitMetricsPayload @@ -225,6 +245,35 @@ Autogenerated return type of BoardListUpdateLimitMetrics | `commit` | Commit | Commit for the branch | | `name` | String! | Name of the branch | +## CiGroup + +| Name | Type | Description | +| --- | ---- | ---------- | +| `name` | String | Name of the job group | +| `size` | Int | Size of the group | + +## CiJob + +| Name | Type | Description | +| --- | ---- | ---------- | +| `name` | String | Name of the job | + +## CiStage + +| Name | Type | Description | +| --- | ---- | ---------- | +| `name` | String | Name of the stage | + +## ClusterAgent + +| Name | Type | Description | +| --- | ---- | ---------- | +| `createdAt` | Time | Timestamp the cluster agent was created | +| `id` | ID! | ID of the cluster agent | +| `name` | String | Name of the cluster agent | +| `project` | Project | The project this cluster agent is associated with | +| `updatedAt` | Time | Timestamp the cluster agent was updated | + ## Commit | Name | Type | Description | @@ -234,6 +283,7 @@ Autogenerated return type of BoardListUpdateLimitMetrics | `authorName` | String | Commit authors name | | `authoredDate` | Time | Timestamp of when the commit was authored | | `description` | String | Description of the commit message | +| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` | | `id` | ID! | ID (global ID) of the commit | | `latestPipeline` **{warning-solid}** | Pipeline | **Deprecated:** Use `pipelines`. Deprecated in 12.5 | | `message` | String | Raw commit message | @@ -241,6 +291,7 @@ Autogenerated return type of BoardListUpdateLimitMetrics | `signatureHtml` | String | Rendered HTML of the commit signature | | `title` | String | Title of the commit message | | `titleHtml` | String | The GitLab Flavored Markdown rendering of `title` | +| `webPath` | String! | Web path of the commit | | `webUrl` | String! | Web URL of the commit | ## CommitCreatePayload @@ -261,6 +312,16 @@ Represents a ComplianceFramework associated with a Project | --- | ---- | ---------- | | `name` | ProjectSettingEnum! | Name of the compliance framework | +## ConfigureSastPayload + +Autogenerated return type of ConfigureSast + +| Name | Type | Description | +| --- | ---- | ---------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Errors encountered during execution of the mutation. | +| `result` | JSON | JSON containing the status of MR creation. | + ## ContainerExpirationPolicy A tag expiration policy designed to keep only the images that matter most @@ -309,6 +370,16 @@ Autogenerated return type of CreateBranch | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | +## CreateClusterAgentPayload + +Autogenerated return type of CreateClusterAgent + +| Name | Type | Description | +| --- | ---- | ---------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `clusterAgent` | ClusterAgent | Cluster agent created after mutation | +| `errors` | String! => Array | Errors encountered during execution of the mutation. | + ## CreateDiffNotePayload Autogenerated return type of CreateDiffNote @@ -379,6 +450,50 @@ Autogenerated return type of CreateSnippet | `errors` | String! => Array | Errors encountered during execution of the mutation. | | `snippet` | Snippet | The snippet after mutation | +## DastOnDemandScanCreatePayload + +Autogenerated return type of DastOnDemandScanCreate + +| Name | Type | Description | +| --- | ---- | ---------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Errors encountered during execution of the mutation. | +| `pipelineUrl` | String | URL of the pipeline that was created. | + +## DastScannerProfile + +Represents a DAST scanner profile. + +| Name | Type | Description | +| --- | ---- | ---------- | +| `id` | ID! | ID of the DAST scanner profile | +| `profileName` | String | Name of the DAST scanner profile | +| `spiderTimeout` | Int | The maximum number of seconds allowed for the spider to traverse the site | +| `targetTimeout` | Int | The maximum number of seconds allowed for the site under test to respond to a request | + +## DastScannerProfileCreatePayload + +Autogenerated return type of DastScannerProfileCreate + +| Name | Type | Description | +| --- | ---- | ---------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Errors encountered during execution of the mutation. | +| `id` | ID | ID of the scanner profile. | + +## DastSiteProfile + +Represents a DAST Site Profile. + +| Name | Type | Description | +| --- | ---- | ---------- | +| `editPath` | String | Relative web path to the edit page of a site profile | +| `id` | DastSiteProfileID! | ID of the site profile | +| `profileName` | String | The name of the site profile | +| `targetUrl` | String | The URL of the target to be scanned | +| `userPermissions` | DastSiteProfilePermissions! | Permissions for the current user on the resource | +| `validationStatus` | DastSiteProfileValidationStatusEnum | The current validation status of the site profile | + ## DastSiteProfileCreatePayload Autogenerated return type of DastSiteProfileCreate @@ -387,7 +502,34 @@ Autogenerated return type of DastSiteProfileCreate | --- | ---- | ---------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `id` | ID | ID of the site profile. | +| `id` | DastSiteProfileID | ID of the site profile. | + +## DastSiteProfileDeletePayload + +Autogenerated return type of DastSiteProfileDelete + +| Name | Type | Description | +| --- | ---- | ---------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Errors encountered during execution of the mutation. | + +## DastSiteProfilePermissions + +Check permissions for the current user on site profile + +| Name | Type | Description | +| --- | ---- | ---------- | +| `createOnDemandDastScan` | Boolean! | Indicates the user can perform `create_on_demand_dast_scan` on this resource | + +## DastSiteProfileUpdatePayload + +Autogenerated return type of DastSiteProfileUpdate + +| Name | Type | Description | +| --- | ---- | ---------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Errors encountered during execution of the mutation. | +| `id` | DastSiteProfileID | ID of the site profile. | ## DeleteAnnotationPayload @@ -473,6 +615,16 @@ Autogenerated return type of DesignManagementDelete | `errors` | String! => Array | Errors encountered during execution of the mutation. | | `version` | DesignVersion | The new version in which the designs are deleted | +## DesignManagementMovePayload + +Autogenerated return type of DesignManagementMove + +| Name | Type | Description | +| --- | ---- | ---------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `designCollection` | DesignCollection | The current state of the collection | +| `errors` | String! => Array | Errors encountered during execution of the mutation. | + ## DesignManagementUploadPayload Autogenerated return type of DesignManagementUpload @@ -611,6 +763,7 @@ Describes where code is deployed for a project | Name | Type | Description | | --- | ---- | ---------- | | `id` | ID! | ID of the environment | +| `latestOpenedMostSevereAlert` | AlertManagementAlert | The most severe open alert for the environment. If multiple alerts have equal severity, the most recent is returned. | | `metricsDashboard` | MetricsDashboard | Metrics dashboard schema for the environment | | `name` | String! | Human-readable name of the environment | | `state` | String! | State of the environment, for example: available/stopped | @@ -674,9 +827,9 @@ Counts of descendent epics. | Name | Type | Description | | --- | ---- | ---------- | -| `closedEpics` | Int | Number of closed sub-epics | +| `closedEpics` | Int | Number of closed child epics | | `closedIssues` | Int | Number of closed epic issues | -| `openedEpics` | Int | Number of opened sub-epics | +| `openedEpics` | Int | Number of opened child epics | | `openedIssues` | Int | Number of opened epic issues | ## EpicDescendantWeights @@ -705,6 +858,7 @@ Relationship between an epic and an issue | Name | Type | Description | | --- | ---- | ---------- | | `author` | User! | User that created the issue | +| `blocked` | Boolean! | Indicates the issue is blocked | | `closedAt` | Time | Timestamp of when the issue was closed | | `confidential` | Boolean! | Indicates the issue is confidential | | `createdAt` | Time! | Timestamp of when the issue was created | @@ -726,12 +880,14 @@ Relationship between an epic and an issue | `relationPath` | String | URI path of the epic-issue relation | | `relativePosition` | Int | Relative position of the issue (used for positioning in epic tree and issue boards) | | `state` | IssueState! | State of the issue | +| `statusPagePublishedIncident` | Boolean | Indicates whether an issue is published to the status page | | `subscribed` | Boolean! | Indicates the currently logged in user is subscribed to the issue | | `taskCompletionStatus` | TaskCompletionStatus! | Task completion status of the issue | | `timeEstimate` | Int! | Time estimate of the issue | | `title` | String! | Title of the issue | | `titleHtml` | String | The GitLab Flavored Markdown rendering of `title` | | `totalTimeSpent` | Int! | Total time reported as spent on the issue | +| `type` | IssueType | Type of the issue | | `updatedAt` | Time! | Timestamp of when the issue was last updated | | `upvotes` | Int! | Number of upvotes the issue has received | | `userNotesCount` | Int! | Number of user notes of the issue | @@ -820,6 +976,7 @@ Autogenerated return type of EpicTreeReorder | `fullPath` | ID! | Full path of the namespace | | `groupTimelogsEnabled` | Boolean | Indicates if Group timelogs are enabled for namespace | | `id` | ID! | ID of the namespace | +| `isTemporaryStorageIncreaseEnabled` | Boolean! | Status of the temporary storage increase | | `label` | Label | A label available on this group | | `lfsEnabled` | Boolean | Indicates if Large File Storage (LFS) is enabled for namespace | | `mentionsDisabled` | Boolean | Indicates if a group is disabled from getting mentioned | @@ -837,6 +994,7 @@ Autogenerated return type of EpicTreeReorder | `twoFactorGracePeriod` | Int | Time before two-factor authentication is enforced | | `userPermissions` | GroupPermissions! | Permissions for the current user on the resource | | `visibility` | String | Visibility of the namespace | +| `vulnerabilityGrades` | VulnerableProjectsByGrade! => Array | Represents vulnerable project counts for each grade | | `webUrl` | String! | Web URL of the group | ## GroupMember @@ -859,11 +1017,18 @@ Represents a Group Member | --- | ---- | ---------- | | `readGroup` | Boolean! | Indicates the user can perform `read_group` on this resource | +## InstanceSecurityDashboard + +| Name | Type | Description | +| --- | ---- | ---------- | +| `vulnerabilityGrades` | VulnerableProjectsByGrade! => Array | Represents vulnerable project counts for each grade | + ## Issue | Name | Type | Description | | --- | ---- | ---------- | | `author` | User! | User that created the issue | +| `blocked` | Boolean! | Indicates the issue is blocked | | `closedAt` | Time | Timestamp of when the issue was closed | | `confidential` | Boolean! | Indicates the issue is confidential | | `createdAt` | Time! | Timestamp of when the issue was created | @@ -883,12 +1048,14 @@ Represents a Group Member | `reference` | String! | Internal reference of the issue. Returned in shortened format by default | | `relativePosition` | Int | Relative position of the issue (used for positioning in epic tree and issue boards) | | `state` | IssueState! | State of the issue | +| `statusPagePublishedIncident` | Boolean | Indicates whether an issue is published to the status page | | `subscribed` | Boolean! | Indicates the currently logged in user is subscribed to the issue | | `taskCompletionStatus` | TaskCompletionStatus! | Task completion status of the issue | | `timeEstimate` | Int! | Time estimate of the issue | | `title` | String! | Title of the issue | | `titleHtml` | String | The GitLab Flavored Markdown rendering of `title` | | `totalTimeSpent` | Int! | Total time reported as spent on the issue | +| `type` | IssueType | Type of the issue | | `updatedAt` | Time! | Timestamp of when the issue was last updated | | `upvotes` | Int! | Number of upvotes the issue has received | | `userNotesCount` | Int! | Number of user notes of the issue | @@ -897,6 +1064,16 @@ Represents a Group Member | `webUrl` | String! | Web URL of the issue | | `weight` | Int | Weight of the issue | +## IssueMoveListPayload + +Autogenerated return type of IssueMoveList + +| Name | Type | Description | +| --- | ---- | ---------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Errors encountered during execution of the mutation. | +| `issue` | Issue | The issue after mutation | + ## IssuePermissions Check permissions for the current user on a issue @@ -912,6 +1089,16 @@ Check permissions for the current user on a issue | `reopenIssue` | Boolean! | Indicates the user can perform `reopen_issue` on this resource | | `updateIssue` | Boolean! | Indicates the user can perform `update_issue` on this resource | +## IssueSetAssigneesPayload + +Autogenerated return type of IssueSetAssignees + +| Name | Type | Description | +| --- | ---- | ---------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Errors encountered during execution of the mutation. | +| `issue` | Issue | The issue after mutation | + ## IssueSetConfidentialPayload Autogenerated return type of IssueSetConfidential @@ -932,6 +1119,16 @@ Autogenerated return type of IssueSetDueDate | `errors` | String! => Array | Errors encountered during execution of the mutation. | | `issue` | Issue | The issue after mutation | +## IssueSetEpicPayload + +Autogenerated return type of IssueSetEpic + +| Name | Type | Description | +| --- | ---- | ---------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Errors encountered during execution of the mutation. | +| `issue` | Issue | The issue after mutation | + ## IssueSetIterationPayload Autogenerated return type of IssueSetIteration @@ -952,6 +1149,16 @@ Autogenerated return type of IssueSetLocked | `errors` | String! => Array | Errors encountered during execution of the mutation. | | `issue` | Issue | The issue after mutation | +## IssueSetSubscriptionPayload + +Autogenerated return type of IssueSetSubscription + +| Name | Type | Description | +| --- | ---- | ---------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Errors encountered during execution of the mutation. | +| `issue` | Issue | The issue after mutation | + ## IssueSetWeightPayload Autogenerated return type of IssueSetWeight @@ -962,6 +1169,16 @@ Autogenerated return type of IssueSetWeight | `errors` | String! => Array | Errors encountered during execution of the mutation. | | `issue` | Issue | The issue after mutation | +## IssueStatusCountsType + +Represents total number of issues for the represented statuses. + +| Name | Type | Description | +| --- | ---- | ---------- | +| `all` | Int | Number of issues with status ALL for the project | +| `closed` | Int | Number of issues with status CLOSED for the project | +| `opened` | Int | Number of issues with status OPENED for the project | + ## Iteration Represents an iteration object. @@ -970,9 +1187,12 @@ Represents an iteration object. | --- | ---- | ---------- | | `createdAt` | Time! | Timestamp of iteration creation | | `description` | String | Description of the iteration | +| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` | | `dueDate` | Time | Timestamp of the iteration due date | | `id` | ID! | ID of the iteration | | `iid` | ID! | Internal ID of the iteration | +| `scopedPath` | String | Web path of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts | +| `scopedUrl` | String | Web URL of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts | | `startDate` | Time | Timestamp of the iteration start date | | `state` | IterationState! | State of the iteration | | `title` | String! | Title of the iteration | @@ -1025,7 +1245,6 @@ Autogenerated return type of JiraImportUsers | Name | Type | Description | | --- | ---- | ---------- | | `active` | Boolean | Indicates if the service is active | -| `projects` | JiraProjectConnection | List of all Jira projects fetched through Jira REST API | | `type` | String | Class name of the service | ## JiraUser @@ -1066,6 +1285,7 @@ Autogenerated return type of MarkAsSpamSnippet | --- | ---- | ---------- | | `allowCollaboration` | Boolean | Indicates if members of the target project can push to the fork | | `author` | User | User who created this merge request | +| `commitCount` | Int | Number of commits in the merge request | | `createdAt` | Time! | Timestamp of when the merge request was created | | `defaultMergeCommitMessage` | String | Default merge commit message of the merge request | | `description` | String | Description of the merge request (Markdown rendered as HTML for caching) | @@ -1276,6 +1496,7 @@ Contains statistics about a milestone | `fullName` | String! | Full name of the namespace | | `fullPath` | ID! | Full path of the namespace | | `id` | ID! | ID of the namespace | +| `isTemporaryStorageIncreaseEnabled` | Boolean! | Status of the temporary storage increase | | `lfsEnabled` | Boolean | Indicates if Large File Storage (LFS) is enabled for namespace | | `name` | String! | Name of the namespace | | `path` | String! | Path of the namespace | @@ -1285,6 +1506,16 @@ Contains statistics about a milestone | `temporaryStorageIncreaseEndsOn` | Time | Date until the temporary storage increase is active | | `visibility` | String | Visibility of the namespace | +## NamespaceIncreaseStorageTemporarilyPayload + +Autogenerated return type of NamespaceIncreaseStorageTemporarily + +| Name | Type | Description | +| --- | ---- | ---------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Errors encountered during execution of the mutation. | +| `namespace` | Namespace | The namespace after mutation | + ## Note | Name | Type | Description | @@ -1362,6 +1593,7 @@ Information about pagination in a connection. | --- | ---- | ---------- | | `beforeSha` | String | Base SHA of the source branch | | `committedAt` | Time | Timestamp of the pipeline's commit | +| `configSource` | PipelineConfigSourceEnum | Config source of the pipeline (UNKNOWN_SOURCE, REPOSITORY_SOURCE, AUTO_DEVOPS_SOURCE, WEBIDE_SOURCE, REMOTE_SOURCE, EXTERNAL_PROJECT_SOURCE, BRIDGE_SOURCE, PARAMETER_SOURCE) | | `coverage` | Float | Coverage percentage | | `createdAt` | Time! | Timestamp of the pipeline's creation | | `detailedStatus` | DetailedStatus! | Detailed status of the pipeline | @@ -1374,6 +1606,7 @@ Information about pagination in a connection. | `startedAt` | Time | Timestamp when the pipeline was started | | `status` | PipelineStatusEnum! | Status of the pipeline (CREATED, WAITING_FOR_RESOURCE, PREPARING, PENDING, RUNNING, FAILED, SUCCESS, CANCELED, SKIPPED, MANUAL, SCHEDULED) | | `updatedAt` | Time! | Timestamp of the pipeline's last activity | +| `user` | User | Pipeline user | | `userPermissions` | PipelinePermissions! | Permissions for the current user on the resource | ## PipelinePermissions @@ -1400,6 +1633,7 @@ Information about pagination in a connection. | `createdAt` | Time | Timestamp of the project creation | | `description` | String | Short description of the project | | `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` | +| `environment` | Environment | A single environment of the project | | `forksCount` | Int! | Number of times the project has been forked | | `fullPath` | ID! | Full path of the project | | `grafanaIntegration` | GrafanaIntegration | Grafana integration details for the project | @@ -1408,6 +1642,7 @@ Information about pagination in a connection. | `id` | ID! | ID of the project | | `importStatus` | String | Status of import background job of the project | | `issue` | Issue | A single issue of the project | +| `issueStatusCounts` | IssueStatusCountsType | Counts of issues by status for the project | | `issuesEnabled` | Boolean | Indicates if Issues are enabled for the current user | | `jiraImportStatus` | String | Status of Jira import background job of the project | | `jobsEnabled` | Boolean | Indicates if CI/CD pipeline jobs are enabled for the current user | @@ -1434,6 +1669,7 @@ Information about pagination in a connection. | `requirement` | Requirement | Find a single requirement. Available only when feature flag `requirements_management` is enabled. | | `requirementStatesCount` | RequirementStatesCount | Number of requirements for the project by their state | | `sastCiConfiguration` | SastCiConfiguration | SAST CI configuration for the project | +| `securityDashboardPath` | String | Path to project's security dashboard | | `securityScanners` | SecurityScanners | Information about security analyzers used in the project | | `sentryDetailedError` | SentryDetailedError | Detailed version of a Sentry error on the project | | `sentryErrors` | SentryErrorCollection | Paginated collection of Sentry errors on the project | @@ -1528,6 +1764,15 @@ Represents a Project Member | `storageSize` | Float! | Storage size of the project | | `wikiSize` | Float | Wiki size of the project | +## PrometheusAlert + +The alert condition for Prometheus + +| Name | Type | Description | +| --- | ---- | ---------- | +| `humanizedText` | String! | The human-readable text of the alert condition | +| `id` | ID! | ID of the alert condition | + ## Release Represents a release @@ -1703,6 +1948,7 @@ Represents an entity in SAST CI configuration | `description` | String | Entity description that is displayed on the form. | | `field` | String | CI keyword of entity. | | `label` | String | Label for entity used in the form. | +| `size` | SastUiComponentSize | Size of the UI component. | | `type` | String | Type of the field value. | | `value` | String | Current value of the entity. | @@ -1881,7 +2127,7 @@ Represents a snippet entry | Name | Type | Description | | --- | ---- | ---------- | | `author` | User | The owner of the snippet | -| `blob` | SnippetBlob! | Snippet blob | +| `blob` **{warning-solid}** | SnippetBlob! | **Deprecated:** Use `blobs`. Deprecated in 13.3 | | `blobs` | SnippetBlob! => Array | Snippet blobs | | `createdAt` | Time! | Timestamp this snippet was created | | `description` | String | Description of the snippet | @@ -2072,6 +2318,7 @@ Represents a directory | `path` | String! | Path of the entry | | `sha` | String! | Last commit sha for the entry | | `type` | EntryType! | Type of tree entry | +| `webPath` | String | Web path for the tree entry (directory) | | `webUrl` | String | Web URL for the tree entry (directory) | ## UpdateAlertStatusPayload @@ -2086,6 +2333,26 @@ Autogenerated return type of UpdateAlertStatus | `issue` | Issue | The issue created after mutation | | `todo` | Todo | The todo after mutation | +## UpdateBoardListPayload + +Autogenerated return type of UpdateBoardList + +| Name | Type | Description | +| --- | ---- | ---------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Errors encountered during execution of the mutation. | +| `list` | BoardList | Mutated list | + +## UpdateBoardPayload + +Autogenerated return type of UpdateBoard + +| Name | Type | Description | +| --- | ---- | ---------- | +| `board` | Board | The board after mutation. | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Errors encountered during execution of the mutation. | + ## UpdateContainerExpirationPolicyPayload Autogenerated return type of UpdateContainerExpirationPolicy @@ -2171,11 +2438,14 @@ Autogenerated return type of UpdateSnippet | Name | Type | Description | | --- | ---- | ---------- | | `avatarUrl` | String | URL of the user's avatar | +| `email` | String | User email | | `id` | ID! | ID of the user | | `name` | String! | Human-readable name of the user | | `state` | UserState! | State of the user | +| `status` | UserStatus | User status | | `userPermissions` | UserPermissions! | Permissions for the current user on the resource | | `username` | String! | Username of the user. Unique within this instance of GitLab | +| `webPath` | String! | Web path of the user | | `webUrl` | String! | Web URL of the user | ## UserPermissions @@ -2184,6 +2454,29 @@ Autogenerated return type of UpdateSnippet | --- | ---- | ---------- | | `createSnippet` | Boolean! | Indicates the user can perform `create_snippet` on this resource | +## UserStatus + +| Name | Type | Description | +| --- | ---- | ---------- | +| `emoji` | String | String representation of emoji | +| `message` | String | User status message | +| `messageHtml` | String | HTML of the user status message | + +## VulnerabilitiesCountByDay + +Represents the count of vulnerabilities by severity on a particular day + +| Name | Type | Description | +| --- | ---- | ---------- | +| `critical` | Int! | Total number of vulnerabilities on a particular day with critical severity | +| `date` | ISO8601Date! | Date for the count | +| `high` | Int! | Total number of vulnerabilities on a particular day with high severity | +| `info` | Int! | Total number of vulnerabilities on a particular day with info severity | +| `low` | Int! | Total number of vulnerabilities on a particular day with low severity | +| `medium` | Int! | Total number of vulnerabilities on a particular day with medium severity | +| `total` | Int! | Total number of vulnerabilities on a particular day | +| `unknown` | Int! | Total number of vulnerabilities on a particular day with unknown severity | + ## VulnerabilitiesCountByDayAndSeverity Represents the number of vulnerabilities for a particular severity on a particular day @@ -2207,6 +2500,7 @@ Represents a vulnerability. | `primaryIdentifier` | VulnerabilityIdentifier | Primary identifier of the vulnerability. | | `project` | Project | The project on which the vulnerability was found | | `reportType` | VulnerabilityReportType | Type of the security report that found the vulnerability (SAST, DEPENDENCY_SCANNING, CONTAINER_SCANNING, DAST, SECRET_DETECTION, COVERAGE_FUZZING) | +| `resolvedOnDefaultBranch` | Boolean! | Indicates whether the vulnerability is fixed on the default branch or not | | `scanner` | VulnerabilityScanner | Scanner metadata for the vulnerability. | | `severity` | VulnerabilitySeverity | Severity of the vulnerability (INFO, UNKNOWN, LOW, MEDIUM, HIGH, CRITICAL) | | `state` | VulnerabilityState | State of the vulnerability (DETECTED, DISMISSED, RESOLVED, CONFIRMED) | @@ -2246,6 +2540,18 @@ Represents the location of a vulnerability found by a container security scan | `image` | String | Name of the vulnerable container image | | `operatingSystem` | String | Operating system that runs on the vulnerable container image | +## VulnerabilityLocationCoverageFuzzing + +Represents the location of a vulnerability found by a Coverage Fuzzing scan + +| Name | Type | Description | +| --- | ---- | ---------- | +| `endLine` | String | Number of the last relevant line in the vulnerable file | +| `file` | String | Path to the vulnerable file | +| `startLine` | String | Number of the first relevant line in the vulnerable file | +| `vulnerableClass` | String | Class containing the vulnerability | +| `vulnerableMethod` | String | Method containing the vulnerability | + ## VulnerabilityLocationDast Represents the location of a vulnerability found by a DAST scan @@ -2345,3 +2651,12 @@ Represents a vulnerable package. Used in vulnerability dependency data | Name | Type | Description | | --- | ---- | ---------- | | `name` | String | The name of the vulnerable package | + +## VulnerableProjectsByGrade + +Represents vulnerability letter grades with associated projects + +| Name | Type | Description | +| --- | ---- | ---------- | +| `count` | Int! | Number of projects within this grade | +| `grade` | VulnerabilityGrade! | Grade based on the highest severity vulnerability present | diff --git a/doc/api/graphql/sample_issue_boards.md b/doc/api/graphql/sample_issue_boards.md new file mode 100644 index 00000000000..4ac9317b01a --- /dev/null +++ b/doc/api/graphql/sample_issue_boards.md @@ -0,0 +1,44 @@ +# Identify issue boards with GraphQL + +This page describes how you can use the GraphiQL explorer to identify +existing issue boards in the `gitlab-docs` documentation repository. + +## Set up the GraphiQL explorer + +This procedure presents a substantive example that you can copy and paste into your own +instance of the [GraphiQL explorer](https://gitlab.com/-/graphql-explorer): + +1. Copy the following code excerpt: + + ```graphql + query { + project(fullPath: "gitlab-org/gitlab-docs") { + name + forksCount + statistics { + wikiSize + } + issuesEnabled + boards { + nodes { + id + name + } + } + } + } + ``` + +1. Open the [GraphiQL Explorer](https://gitlab.com/-/graphql-explorer) page. +1. Paste the `query` listed above into the left window of your GraphiQL explorer tool. +1. Click Play to get the result shown here: + +![GraphiQL explorer search for boards](img/sample_issue_boards_v13_2.png) + +If you want to view one of these boards, take one of the numeric identifiers shown in the output. From the screenshot, the first identifier is `105011`. Navigate to the following URL, which includes the identifier: + +```markdown +https://gitlab.com/gitlab-org/gitlab-docs/-/boards/105011 +``` + +For more information on each attribute, see the [GraphQL API Resources](reference/index.md). diff --git a/doc/api/group_activity_analytics.md b/doc/api/group_activity_analytics.md index 302c7703669..90920d1b25c 100644 --- a/doc/api/group_activity_analytics.md +++ b/doc/api/group_activity_analytics.md @@ -1,6 +1,6 @@ # Group Activity Analytics API -> **Note:** This feature was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26460) in GitLab 12.9. +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26460) in GitLab 12.9. ## Get count of recently created issues for group diff --git a/doc/api/group_milestones.md b/doc/api/group_milestones.md index e157655a713..e992637f4f0 100644 --- a/doc/api/group_milestones.md +++ b/doc/api/group_milestones.md @@ -27,13 +27,14 @@ GET /groups/:id/milestones?search=version Parameters: -| Attribute | Type | Required | Description | -| --------- | ------ | -------- | ----------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user | -| `iids[]` | integer array | no | Return only the milestones having the given `iid` | -| `state` | string | no | Return only `active` or `closed` milestones | -| `title` | string | no | Return only the milestones having the given `title` | -| `search` | string | no | Return only milestones with a title or description matching the provided string | +| Attribute | Type | Required | Description | +| --------- | ------ | -------- | ----------- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user | +| `iids[]` | integer array | no | Return only the milestones having the given `iid` (Note: ignored if `include_parent_milestones` is set as `true`) | +| `state` | string | no | Return only `active` or `closed` milestones | +| `title` | string | no | Return only the milestones having the given `title` | +| `search` | string | no | Return only milestones with a title or description matching the provided string | +| `include_parent_milestones` | boolean | optional | Include milestones from parent group and its ancestors. Introduced in [GitLab 13.4](https://gitlab.com/gitlab-org/gitlab/-/issues/196066) | ```shell curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/5/milestones" diff --git a/doc/api/group_wikis.md b/doc/api/group_wikis.md index 62094ffc940..414c795e092 100644 --- a/doc/api/group_wikis.md +++ b/doc/api/group_wikis.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Knowledge +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Wikis API > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212199) in GitLab 13.2. diff --git a/doc/api/groups.md b/doc/api/groups.md index a5a0c210540..07b2738f2d3 100644 --- a/doc/api/groups.md +++ b/doc/api/groups.md @@ -184,7 +184,7 @@ Parameters: | `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user | | `archived` | boolean | no | Limit by archived status | | `visibility` | string | no | Limit by visibility `public`, `internal`, or `private` | -| `order_by` | string | no | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. Default is `created_at` | +| `order_by` | string | no | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, `similarity` (1), or `last_activity_at` fields. Default is `created_at` | | `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` | | `search` | string | no | Return list of authorized projects matching the search criteria | | `simple` | boolean | no | Return only the ID, URL, name, and path of each project | @@ -198,6 +198,13 @@ Parameters: | `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) | | `with_security_reports` | boolean | no | **(ULTIMATE)** Return only projects that have security reports artifacts present in any of their builds. This means "projects with security reports enabled". Default is `false` | +1. Order by similarity: Orders the results by a similarity score calculated from the provided `search` +URL parameter. This is an [alpha](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha) feature [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/221043) in GitLab 13.3. + + The feature is behind a feature flag, you can [enable it](../administration/feature_flags.md#enable-or-disable-the-feature) +with the `similarity_search` flag. When using `order_by=similarity` the `sort` parameter is +ignored. When the `search` parameter is not provided, the API returns the projects ordered by `name`. + Example response: ```json @@ -743,6 +750,7 @@ PUT /groups/:id | `file_template_project_id` | integer | no | **(PREMIUM)** The ID of a project to load custom file templates from. | | `shared_runners_minutes_limit` | integer | no | **(STARTER ONLY)** Pipeline minutes quota for this group (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` | | `extra_shared_runners_minutes_limit` | integer | no | **(STARTER ONLY)** Extra pipeline minutes quota for this group (purchased in addition to the minutes included in the plan). | +| `prevent_forking_outside_group` | boolean | no | **(PREMIUM)** When enabled, users can **not** fork projects from this group to external namespaces NOTE: **Note:** The `projects` and `shared_projects` attributes in the response are deprecated and will be [removed in API v5](https://gitlab.com/gitlab-org/gitlab/-/issues/213797). @@ -839,7 +847,7 @@ Only available to group owners and administrators. This endpoint either: - Removes group, and queues a background job to delete all projects in the group as well. -- Since [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/33257), on [Premium or Silver](https://about.gitlab.com/pricing/) or higher tiers, marks a group for deletion. The deletion will happen 7 days later by default, but this can be changed in the [instance settings](../user/admin_area/settings/visibility_and_access_controls.md#default-deletion-adjourned-period-premium-only). +- Since [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/33257), on [Premium or Silver](https://about.gitlab.com/pricing/) or higher tiers, marks a group for deletion. The deletion will happen 7 days later by default, but this can be changed in the [instance settings](../user/admin_area/settings/visibility_and_access_controls.md#default-deletion-delay-premium-only). ```plaintext DELETE /groups/:id @@ -1156,3 +1164,46 @@ DELETE /groups/:id/share/:group_id | --------- | -------------- | -------- | ----------- | | `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) | | `group_id` | integer | yes | The ID of the group to share with | + +## Push Rules **(STARTER)** + +### Get group push rules + +Get the [push rules](../user/group/index.md#group-push-rules-starter) of a group. + +```plaintext +GET /groups/:id/push_rule +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer/string | yes | The ID of the group or [URL-encoded path of the group](README.md#namespaced-path-encoding) | + +```json +{ + "id": 2, + "created_at": "2020-08-17T19:09:19.580Z", + "commit_message_regex": "[a-zA-Z]", + "commit_message_negative_regex": "[x+]", + "branch_name_regex": "[a-z]", + "deny_delete_tag": true, + "member_check": true, + "prevent_secrets": true, + "author_email_regex": "^[A-Za-z0-9.]+@gitlab.com$", + "file_name_regex": "(exe)$", + "max_file_size": 100 +} +``` + +Users on GitLab [Premium, Silver, or higher](https://about.gitlab.com/pricing/) will also see +the `commit_committer_check` and `reject_unsigned_commits` parameters: + +```json +{ + "id": 2, + "created_at": "2020-08-17T19:09:19.580Z", + "commit_committer_check": true, + "reject_unsigned_commits": false, + ... +} +``` diff --git a/doc/api/instance_level_ci_variables.md b/doc/api/instance_level_ci_variables.md index ceaf7e30c48..d8f306a822c 100644 --- a/doc/api/instance_level_ci_variables.md +++ b/doc/api/instance_level_ci_variables.md @@ -1,3 +1,9 @@ +--- +stage: Verify +group: Continuous Integration +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- + # Instance-level CI/CD variables API > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14108) in GitLab 13.0 @@ -73,7 +79,7 @@ POST /admin/ci/variables | Attribute | Type | required | Description | |-----------------|---------|----------|-----------------------| | `key` | string | yes | The `key` of a variable. Max 255 characters, only `A-Z`, `a-z`, `0-9`, and `_` are allowed. | -| `value` | string | yes | The `value` of a variable. Around 700 characters allowed. | +| `value` | string | yes | The `value` of a variable. 10,000 characters allowed. [Since GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/220028) | | `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file`. | | `protected` | boolean | no | Whether the variable is protected. | | `masked` | boolean | no | Whether the variable is masked. | @@ -103,7 +109,7 @@ PUT /admin/ci/variables/:key | Attribute | Type | required | Description | |-----------------|---------|----------|-------------------------| | `key` | string | yes | The `key` of a variable. | -| `value` | string | yes | The `value` of a variable. | +| `value` | string | yes | The `value` of a variable. [Since GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/220028), around 10,000 characters allowed. Previously 700 characters. | | `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file`. | | `protected` | boolean | no | Whether the variable is protected. | | `masked` | boolean | no | Whether the variable is masked. | diff --git a/doc/api/issues.md b/doc/api/issues.md index 22f5d994f85..478557e1cd1 100644 --- a/doc/api/issues.md +++ b/doc/api/issues.md @@ -72,6 +72,7 @@ GET /issues?confidential=true | `confidential` | boolean | no | Filter confidential or public issues. | | `not` | Hash | no | Return issues that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `my_reaction_emoji` | | `non_archived` | boolean | no | Return issues only from non-archived projects. If `false`, response will return issues from both archived and non-archived projects. Default is `true`. _(Introduced in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/197170))_ | +| `due_date` | string | no | Return issues that have no due date (`0`) or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _(Introduced in [GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/233420))_ | ```shell curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/issues" @@ -134,7 +135,7 @@ Example response: "merge_requests_count": 0, "user_notes_count": 1, "due_date": "2016-07-22", - "web_url": "http://example.com/my-group/my-project/issues/6", + "web_url": "http://gitlab.example.com/my-group/my-project/issues/6", "references": { "short": "#6", "relative": "my-group/my-project#6", @@ -151,10 +152,10 @@ Example response: "confidential": false, "discussion_locked": false, "_links":{ - "self":"http://example.com/api/v4/projects/1/issues/76", - "notes":"`http://example.com/`api/v4/projects/1/issues/76/notes", - "award_emoji":"http://example.com/api/v4/projects/1/issues/76/award_emoji", - "project":"http://example.com/api/v4/projects/1" + "self":"http://gitlab.example.com/api/v4/projects/1/issues/76", + "notes":"http://gitlab.example.com/api/v4/projects/1/issues/76/notes", + "award_emoji":"http://gitlab.example.com/api/v4/projects/1/issues/76/award_emoji", + "project":"http://gitlab.example.com/api/v4/projects/1" }, "task_completion_status":{ "count":0, @@ -178,6 +179,20 @@ the `weight` parameter: ] ``` +Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) will also see +the `health_status` parameter: + +```json +[ + { + "state" : "opened", + "description" : "Ratione dolores corrupti mollitia soluta quia.", + "health_status": "on_track", + ... + } +] +``` + **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API. **Note**: The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists. @@ -231,6 +246,7 @@ GET /groups/:id/issues?confidential=true | `confidential` | boolean | no | Filter confidential or public issues. | | `not` | Hash | no | Return issues that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `my_reaction_emoji`, `search`, `in` | | `non_archived` | boolean | no | Return issues from non archived projects. Default is true. _(Introduced in [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23785))_ | +| `due_date` | string | no | Return issues that have no due date (`0`) or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _(Introduced in [GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/233420))_ | ```shell curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/4/issues" @@ -292,7 +308,7 @@ Example response: "closed_by" : null, "user_notes_count": 1, "due_date": null, - "web_url": "http://example.com/my-group/my-project/issues/1", + "web_url": "http://gitlab.example.com/my-group/my-project/issues/1", "references": { "short": "#1", "relative": "my-project#1", @@ -309,10 +325,10 @@ Example response: "confidential": false, "discussion_locked": false, "_links":{ - "self":"http://example.com/api/v4/projects/4/issues/41", - "notes":"`http://example.com/`api/v4/projects/4/issues/41/notes", - "award_emoji":"http://example.com/api/v4/projects/4/issues/41/award_emoji", - "project":"http://example.com/api/v4/projects/4" + "self":"http://gitlab.example.com/api/v4/projects/4/issues/41", + "notes":"http://gitlab.example.com/api/v4/projects/4/issues/41/notes", + "award_emoji":"http://gitlab.example.com/api/v4/projects/4/issues/41/award_emoji", + "project":"http://gitlab.example.com/api/v4/projects/4" }, "task_completion_status":{ "count":0, @@ -336,6 +352,20 @@ the `weight` parameter: ] ``` +Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) will also see +the `health_status` parameter: + +```json +[ + { + "project_id" : 4, + "description" : "Omnis vero earum sunt corporis dolor et placeat.", + "health_status": "at_risk", + ... + } +] +``` + **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API. **Note**: The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists. @@ -388,6 +418,7 @@ GET /projects/:id/issues?confidential=true | `updated_before` | datetime | no | Return issues updated on or before the given time | | `confidential` | boolean | no | Filter confidential or public issues. | | `not` | Hash | no | Return issues that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `my_reaction_emoji`, `search`, `in` | +| `due_date` | string | no | Return issues that have no due date (`0`) or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _(Introduced in [GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/233420))_ | ```shell curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/4/issues" @@ -456,7 +487,7 @@ Example response: }, "user_notes_count": 1, "due_date": "2016-07-22", - "web_url": "http://example.com/my-group/my-project/issues/1", + "web_url": "http://gitlab.example.com/my-group/my-project/issues/1", "references": { "short": "#1", "relative": "#1", @@ -473,10 +504,10 @@ Example response: "confidential": false, "discussion_locked": false, "_links":{ - "self":"http://example.com/api/v4/projects/4/issues/41", - "notes":"`http://example.com/`api/v4/projects/4/issues/41/notes", - "award_emoji":"http://example.com/api/v4/projects/4/issues/41/award_emoji", - "project":"http://example.com/api/v4/projects/4" + "self":"http://gitlab.example.com/api/v4/projects/4/issues/41", + "notes":"http://gitlab.example.com/api/v4/projects/4/issues/41/notes", + "award_emoji":"http://gitlab.example.com/api/v4/projects/4/issues/41/award_emoji", + "project":"http://gitlab.example.com/api/v4/projects/4" }, "task_completion_status":{ "count":0, @@ -500,6 +531,20 @@ the `weight` parameter: ] ``` +Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) will also see +the `health_status` parameter: + +```json +[ + { + "project_id" : 4, + "description" : "Omnis vero earum sunt corporis dolor et placeat.", + "health_status": "at_risk", + ... + } +] +``` + **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API. **Note**: The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists. @@ -581,7 +626,7 @@ Example response: "subscribed": false, "user_notes_count": 1, "due_date": null, - "web_url": "http://example.com/my-group/my-project/issues/1", + "web_url": "http://gitlab.example.com/my-group/my-project/issues/1", "references": { "short": "#1", "relative": "#1", @@ -596,10 +641,10 @@ Example response: "confidential": false, "discussion_locked": false, "_links": { - "self": "http://example.com/api/v4/projects/1/issues/2", - "notes": "http://example.com/api/v4/projects/1/issues/2/notes", - "award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji", - "project": "http://example.com/api/v4/projects/1" + "self": "http://gitlab.example.com/api/v4/projects/1/issues/2", + "notes": "http://gitlab.example.com/api/v4/projects/1/issues/2/notes", + "award_emoji": "http://gitlab.example.com/api/v4/projects/1/issues/2/award_emoji", + "project": "http://gitlab.example.com/api/v4/projects/1" }, "task_completion_status":{ "count":0, @@ -639,6 +684,20 @@ the `epic` property: } ``` +Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) will also additionally see +the `health_status` property: + +```json +[ + { + "project_id" : 4, + "description" : "Omnis vero earum sunt corporis dolor et placeat.", + "health_status": "on_track", + ... + } +] +``` + **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API. **Note**: The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists. @@ -661,7 +720,7 @@ POST /projects/:id/issues | `title` | string | yes | The title of an issue | | `description` | string | no | The description of an issue. Limited to 1,048,576 characters. | | `confidential` | boolean | no | Set an issue to be confidential. Default is `false`. | -| `assignee_ids` | integer array | no | The ID of a user to assign issue | +| `assignee_ids` | integer array | no | The ID of the user(s) to assign the issue to. | | `milestone_id` | integer | no | The global ID of a milestone to assign issue | | `labels` | string | no | Comma-separated label names for an issue | | `created_at` | string | no | Date time string, ISO 8601 formatted, for example `2016-03-11T03:45:40Z` (requires admin or project/group owner rights) | @@ -710,7 +769,7 @@ Example response: "subscribed" : true, "user_notes_count": 0, "due_date": null, - "web_url": "http://example.com/my-group/my-project/issues/14", + "web_url": "http://gitlab.example.com/my-group/my-project/issues/14", "references": { "short": "#14", "relative": "#14", @@ -725,10 +784,10 @@ Example response: "confidential": false, "discussion_locked": false, "_links": { - "self": "http://example.com/api/v4/projects/1/issues/2", - "notes": "http://example.com/api/v4/projects/1/issues/2/notes", - "award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji", - "project": "http://example.com/api/v4/projects/1" + "self": "http://gitlab.example.com/api/v4/projects/1/issues/2", + "notes": "http://gitlab.example.com/api/v4/projects/1/issues/2/notes", + "award_emoji": "http://gitlab.example.com/api/v4/projects/1/issues/2/award_emoji", + "project": "http://gitlab.example.com/api/v4/projects/1" }, "task_completion_status":{ "count":0, @@ -749,17 +808,28 @@ the `weight` parameter: } ``` +Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) will also see +the `health_status` parameter: + +```json +[ + { + "project_id" : 4, + "description" : "Omnis vero earum sunt corporis dolor et placeat.", + "health_status": "on_track", + ... + } +] +``` + **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API. **Note**: The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists. ## Rate limits -To help avoid abuse, users are limited to: - -| Request Type | Limit | -| ---------------- | --------------------------- | -| Create | 300 issues per minute | +To help avoid abuse, users can be limited to a specific number of `Create` requests per minute. +See [Issues rate limits](../user/admin_area/settings/rate_limit_on_issues_creation.md). ## Edit issue @@ -835,7 +905,7 @@ Example response: "subscribed" : true, "user_notes_count": 0, "due_date": "2016-07-22", - "web_url": "http://example.com/my-group/my-project/issues/15", + "web_url": "http://gitlab.example.com/my-group/my-project/issues/15", "references": { "short": "#15", "relative": "#15", @@ -850,10 +920,10 @@ Example response: "confidential": false, "discussion_locked": false, "_links": { - "self": "http://example.com/api/v4/projects/1/issues/2", - "notes": "http://example.com/api/v4/projects/1/issues/2/notes", - "award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji", - "project": "http://example.com/api/v4/projects/1" + "self": "http://gitlab.example.com/api/v4/projects/1/issues/2", + "notes": "http://gitlab.example.com/api/v4/projects/1/issues/2/notes", + "award_emoji": "http://gitlab.example.com/api/v4/projects/1/issues/2/award_emoji", + "project": "http://gitlab.example.com/api/v4/projects/1" }, "task_completion_status":{ "count":0, @@ -874,6 +944,20 @@ the `weight` parameter: } ``` +Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) will also see +the `health_status` parameter: + +```json +[ + { + "project_id" : 4, + "description" : "Omnis vero earum sunt corporis dolor et placeat.", + "health_status": "on_track", + ... + } +] +``` + NOTE: **Note:** At least one of following parameters is required to be passed for the request to be successful: `:assignee_id`, `:assignee_ids`, `:confidential`, `:created_at`, `:description`, `:discussion_locked`, `:due_date`, `:labels`, `:milestone_id`, `:state_event`, or `:title`. @@ -902,7 +986,7 @@ curl --request DELETE --header "PRIVATE-TOKEN: " "https://git ## Reorder an issue -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211864) as a [community contribution](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35349) in GitLab 13.2. +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211864) in GitLab 13.2. Reorders an issue, you can see the results when sorting issues manually @@ -988,7 +1072,7 @@ Example response: "web_url": "https://gitlab.example.com/solon.cremin" }, "due_date": null, - "web_url": "http://example.com/my-group/my-project/issues/11", + "web_url": "http://gitlab.example.com/my-group/my-project/issues/11", "references": { "short": "#11", "relative": "#11", @@ -1003,10 +1087,10 @@ Example response: "confidential": false, "discussion_locked": false, "_links": { - "self": "http://example.com/api/v4/projects/1/issues/2", - "notes": "http://example.com/api/v4/projects/1/issues/2/notes", - "award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji", - "project": "http://example.com/api/v4/projects/1" + "self": "http://gitlab.example.com/api/v4/projects/1/issues/2", + "notes": "http://gitlab.example.com/api/v4/projects/1/issues/2/notes", + "award_emoji": "http://gitlab.example.com/api/v4/projects/1/issues/2/award_emoji", + "project": "http://gitlab.example.com/api/v4/projects/1" }, "task_completion_status":{ "count":0, @@ -1027,6 +1111,20 @@ the `weight` parameter: } ``` +Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) will also see +the `health_status` parameter: + +```json +[ + { + "project_id" : 4, + "description" : "Omnis vero earum sunt corporis dolor et placeat.", + "health_status": "on_track", + ... + } +] +``` + **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API. **Note**: The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists. @@ -1094,7 +1192,7 @@ Example response: "web_url": "https://gitlab.example.com/solon.cremin" }, "due_date": null, - "web_url": "http://example.com/my-group/my-project/issues/11", + "web_url": "http://gitlab.example.com/my-group/my-project/issues/11", "references": { "short": "#11", "relative": "#11", @@ -1109,10 +1207,10 @@ Example response: "confidential": false, "discussion_locked": false, "_links": { - "self": "http://example.com/api/v4/projects/1/issues/2", - "notes": "http://example.com/api/v4/projects/1/issues/2/notes", - "award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji", - "project": "http://example.com/api/v4/projects/1" + "self": "http://gitlab.example.com/api/v4/projects/1/issues/2", + "notes": "http://gitlab.example.com/api/v4/projects/1/issues/2/notes", + "award_emoji": "http://gitlab.example.com/api/v4/projects/1/issues/2/award_emoji", + "project": "http://gitlab.example.com/api/v4/projects/1" }, "task_completion_status":{ "count":0, @@ -1193,7 +1291,7 @@ Example response: }, "subscribed": false, "due_date": null, - "web_url": "http://example.com/my-group/my-project/issues/12", + "web_url": "http://gitlab.example.com/my-group/my-project/issues/12", "references": { "short": "#12", "relative": "#12", @@ -1300,7 +1398,7 @@ Example response: "downvotes": 0, "merge_requests_count": 0, "due_date": null, - "web_url": "http://example.com/my-group/my-project/issues/10", + "web_url": "http://gitlab.example.com/my-group/my-project/issues/10", "references": { "short": "#10", "relative": "#10", @@ -1732,7 +1830,7 @@ Example response: "username": "user1", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/c922747a93b40d1ea88262bf1aebee62?s=80&d=identicon", - "web_url": "http://localhost/user1" + "web_url": "http://gitlab.example.com/user1" }, { "id": 5, @@ -1740,7 +1838,7 @@ Example response: "username": "user5", "state": "active", "avatar_url": "http://www.gravatar.com/avatar/4aea8cf834ed91844a2da4ff7ae6b491?s=80&d=identicon", - "web_url": "http://localhost/user5" + "web_url": "http://gitlab.example.com/user5" } ] ``` @@ -1775,3 +1873,8 @@ Example response: "akismet_submitted": false } ``` + +## List issue state events + +To track which state was set, who did it, and when it happened, check out +[Resource state events API](./resource_state_events.md#issues). diff --git a/doc/api/job_artifacts.md b/doc/api/job_artifacts.md new file mode 100644 index 00000000000..5df7915ad5c --- /dev/null +++ b/doc/api/job_artifacts.md @@ -0,0 +1,265 @@ +# Job Artifacts API + +## Get job artifacts + +> The use of `CI_JOB_TOKEN` in the artifacts download API was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2346) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.5. + +Get the job's artifacts zipped archive of a project. + +```plaintext +GET /projects/:id/jobs/:job_id/artifacts +``` + +| Attribute | Type | Required | Description | +|-------------|----------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------| +| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `job_id` | integer | yes | ID of a job. | +| `job_token` **(PREMIUM)** | string | no | To be used with [triggers](../ci/triggers/README.md#when-a-pipeline-depends-on-the-artifacts-of-another-pipeline-premium) for multi-project pipelines. It should be invoked only inside `.gitlab-ci.yml`. Its value is always `$CI_JOB_TOKEN`. | + +Example request using the `PRIVATE-TOKEN` header: + +```shell +curl --output artifacts.zip --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/42/artifacts" +``` + +To use this in a [`script` definition](../ci/yaml/README.md#script) inside +`.gitlab-ci.yml` **(PREMIUM)**, you can use either: + +- The `JOB-TOKEN` header with the GitLab-provided `CI_JOB_TOKEN` variable. + For example, the following job will download the artifacts of the job with ID + `42`. Note that the command is wrapped into single quotes since it contains a + colon (`:`): + + ```yaml + artifact_download: + stage: test + script: + - 'curl --location --output artifacts.zip --header "JOB-TOKEN: $CI_JOB_TOKEN" "https://gitlab.example.com/api/v4/projects/1/jobs/42/artifacts"' + ``` + +- Or the `job_token` attribute with the GitLab-provided `CI_JOB_TOKEN` variable. + For example, the following job will download the artifacts of the job with ID `42`: + + ```yaml + artifact_download: + stage: test + script: + - 'curl --location --output artifacts.zip "https://gitlab.example.com/api/v4/projects/1/jobs/42/artifacts?job_token=$CI_JOB_TOKEN"' + ``` + +Possible response status codes: + +| Status | Description | +|-----------|---------------------------------| +| 200 | Serves the artifacts file. | +| 404 | Build not found or no artifacts.| + +## Download the artifacts archive + +> The use of `CI_JOB_TOKEN` in the artifacts download API was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2346) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.5. + +Download the artifacts zipped archive from the latest successful pipeline for +the given reference name and job, provided the job finished successfully. This +is the same as [getting the job's artifacts](#get-job-artifacts), but by +defining the job's name instead of its ID. + +```plaintext +GET /projects/:id/jobs/artifacts/:ref_name/download?job=name +``` + +Parameters + +| Attribute | Type | Required | Description | +|-------------|----------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------| +| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `ref_name` | string | yes | Branch or tag name in repository. HEAD or SHA references are not supported. | +| `job` | string | yes | The name of the job. | +| `job_token` **(PREMIUM)** | string | no | To be used with [triggers](../ci/triggers/README.md#when-a-pipeline-depends-on-the-artifacts-of-another-pipeline-premium) for multi-project pipelines. It should be invoked only inside `.gitlab-ci.yml`. Its value is always `$CI_JOB_TOKEN`. | + +Example request using the `PRIVATE-TOKEN` header: + +```shell +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/download?job=test" +``` + +To use this in a [`script` definition](../ci/yaml/README.md#script) inside +`.gitlab-ci.yml` **(PREMIUM)**, you can use either: + +- The `JOB-TOKEN` header with the GitLab-provided `CI_JOB_TOKEN` variable. + For example, the following job will download the artifacts of the `test` job + of the `master` branch. Note that the command is wrapped into single quotes + since it contains a colon (`:`): + + ```yaml + artifact_download: + stage: test + script: + - 'curl --location --output artifacts.zip --header "JOB-TOKEN: $CI_JOB_TOKEN" "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/jobs/artifacts/master/download?job=test"' + ``` + +- Or the `job_token` attribute with the GitLab-provided `CI_JOB_TOKEN` variable. + For example, the following job will download the artifacts of the `test` job + of the `master` branch: + + ```yaml + artifact_download: + stage: test + script: + - 'curl --location --output artifacts.zip "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/jobs/artifacts/master/download?job=test&job_token=$CI_JOB_TOKEN"' + ``` + +Possible response status codes: + +| Status | Description | +|-----------|---------------------------------| +| 200 | Serves the artifacts file. | +| 404 | Build not found or no artifacts.| + +## Download a single artifact file by job ID + +> Introduced in GitLab 10.0 + +Download a single artifact file from a job with a specified ID from within +the job's artifacts zipped archive. The file is extracted from the archive and +streamed to the client. + +```plaintext +GET /projects/:id/jobs/:job_id/artifacts/*artifact_path +``` + +Parameters + +| Attribute | Type | Required | Description | +|-----------------|----------------|----------|------------------------------------------------------------------------------------------------------------------| +| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `job_id` | integer | yes | The unique job identifier. | +| `artifact_path` | string | yes | Path to a file inside the artifacts archive. | + +Example request: + +```shell +curl --location --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/5/artifacts/some/release/file.pdf" +``` + +Possible response status codes: + +| Status | Description | +|-----------|--------------------------------------| +| 200 | Sends a single artifact file | +| 400 | Invalid path provided | +| 404 | Build not found or no file/artifacts | + +## Download a single artifact file from specific tag or branch + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23538) in GitLab 11.5. + +Download a single artifact file for a specific job of the latest successful +pipeline for the given reference name from within the job's artifacts archive. +The file is extracted from the archive and streamed to the client. + +```plaintext +GET /projects/:id/jobs/artifacts/:ref_name/raw/*artifact_path?job=name +``` + +Parameters: + +| Attribute | Type | Required | Description | +|-----------------|----------------|----------|------------------------------------------------------------------------------------------------------------------| +| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `ref_name` | string | yes | Branch or tag name in repository. HEAD or SHA references are not supported. | +| `artifact_path` | string | yes | Path to a file inside the artifacts archive. | +| `job` | string | yes | The name of the job. | + +Example request: + +```shell +curl --location --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/raw/some/release/file.pdf?job=pdf" +``` + +Possible response status codes: + +| Status | Description | +|-----------|--------------------------------------| +| 200 | Sends a single artifact file | +| 400 | Invalid path provided | +| 404 | Build not found or no file/artifacts | + +## Keep artifacts + +Prevents artifacts from being deleted when expiration is set. + +```plaintext +POST /projects/:id/jobs/:job_id/artifacts/keep +``` + +Parameters + +| Attribute | Type | Required | Description | +|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------| +| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `job_id` | integer | yes | ID of a job. | + +Example request: + +```shell +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/1/artifacts/keep" +``` + +Example response: + +```json +{ + "commit": { + "author_email": "admin@example.com", + "author_name": "Administrator", + "created_at": "2015-12-24T16:51:14.000+01:00", + "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", + "message": "Test the CI integration.", + "short_id": "0ff3ae19", + "title": "Test the CI integration." + }, + "coverage": null, + "allow_failure": false, + "download_url": null, + "id": 42, + "name": "rubocop", + "ref": "master", + "artifacts": [], + "runner": null, + "stage": "test", + "created_at": "2016-01-11T10:13:33.506Z", + "started_at": "2016-01-11T10:13:33.506Z", + "finished_at": "2016-01-11T10:15:10.506Z", + "duration": 97.0, + "status": "failed", + "tag": false, + "web_url": "https://example.com/foo/bar/-/jobs/42", + "user": null +} +``` + +## Delete artifacts + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25522) in GitLab 11.9. + +Delete artifacts of a job. + +```plaintext +DELETE /projects/:id/jobs/:job_id/artifacts +``` + +| Attribute | Type | Required | Description | +|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------| +| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) | +| `job_id` | integer | yes | ID of a job. | + +Example request: + +```shell +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/1/artifacts" +``` + +NOTE: **Note:** +At least Maintainer role is required to delete artifacts. + +If the artifacts were deleted successfully, a response with status `204 No Content` is returned. diff --git a/doc/api/jobs.md b/doc/api/jobs.md index 4dc29fc897d..054260794c7 100644 --- a/doc/api/jobs.md +++ b/doc/api/jobs.md @@ -1,3 +1,9 @@ +--- +stage: Verify +group: Continuous Integration +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- + # Jobs API ## List project jobs @@ -269,6 +275,9 @@ Example of response ] ``` +In GitLab 13.3 and later, this endpoint [returns data for any pipeline](pipelines.md#single-pipeline-requests) +including [child pipelines](../ci/parent_child_pipelines.md). + ## List pipeline bridges Get a list of bridge jobs for a pipeline. @@ -425,198 +434,6 @@ Example of response } ``` -## Get job artifacts - -> **Notes**: -> -> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/2893) in GitLab 8.5. -> - The use of `CI_JOB_TOKEN` in the artifacts download API was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2346) -> in [GitLab Premium](https://about.gitlab.com/pricing/) 9.5. - -Get the job's artifacts zipped archive of a project. - -```plaintext -GET /projects/:id/jobs/:job_id/artifacts -``` - -| Attribute | Type | Required | Description | -|-------------|----------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------| -| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | -| `job_id` | integer | yes | ID of a job. | -| `job_token` **(PREMIUM)** | string | no | To be used with [triggers](../ci/triggers/README.md#when-a-pipeline-depends-on-the-artifacts-of-another-pipeline-premium) for multi-project pipelines. It should be invoked only inside `.gitlab-ci.yml`. Its value is always `$CI_JOB_TOKEN`. | - -Example request using the `PRIVATE-TOKEN` header: - -```shell -curl --output artifacts.zip --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/42/artifacts" -``` - -To use this in a [`script` definition](../ci/yaml/README.md#script) inside -`.gitlab-ci.yml` **(PREMIUM)**, you can use either: - -- The `JOB-TOKEN` header with the GitLab-provided `CI_JOB_TOKEN` variable. - For example, the following job will download the artifacts of the job with ID - `42`. Note that the command is wrapped into single quotes since it contains a - colon (`:`): - - ```yaml - artifact_download: - stage: test - script: - - 'curl --location --output artifacts.zip --header "JOB-TOKEN: $CI_JOB_TOKEN" "https://gitlab.example.com/api/v4/projects/1/jobs/42/artifacts"' - ``` - -- Or the `job_token` attribute with the GitLab-provided `CI_JOB_TOKEN` variable. - For example, the following job will download the artifacts of the job with ID `42`: - - ```yaml - artifact_download: - stage: test - script: - - 'curl --location --output artifacts.zip "https://gitlab.example.com/api/v4/projects/1/jobs/42/artifacts?job_token=$CI_JOB_TOKEN"' - ``` - -Possible response status codes: - -| Status | Description | -|-----------|---------------------------------| -| 200 | Serves the artifacts file. | -| 404 | Build not found or no artifacts.| - -## Download the artifacts archive - -> **Notes**: -> -> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5347) in GitLab 8.10. -> - The use of `CI_JOB_TOKEN` in the artifacts download API was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2346) -> in [GitLab Premium](https://about.gitlab.com/pricing/) 9.5. - -Download the artifacts zipped archive from the latest successful pipeline for -the given reference name and job, provided the job finished successfully. This -is the same as [getting the job's artifacts](#get-job-artifacts), but by -defining the job's name instead of its ID. - -```plaintext -GET /projects/:id/jobs/artifacts/:ref_name/download?job=name -``` - -Parameters - -| Attribute | Type | Required | Description | -|-------------|----------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------| -| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | -| `ref_name` | string | yes | Branch or tag name in repository. HEAD or SHA references are not supported. | -| `job` | string | yes | The name of the job. | -| `job_token` **(PREMIUM)** | string | no | To be used with [triggers](../ci/triggers/README.md#when-a-pipeline-depends-on-the-artifacts-of-another-pipeline-premium) for multi-project pipelines. It should be invoked only inside `.gitlab-ci.yml`. Its value is always `$CI_JOB_TOKEN`. | - -Example request using the `PRIVATE-TOKEN` header: - -```shell -curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/download?job=test" -``` - -To use this in a [`script` definition](../ci/yaml/README.md#script) inside -`.gitlab-ci.yml` **(PREMIUM)**, you can use either: - -- The `JOB-TOKEN` header with the GitLab-provided `CI_JOB_TOKEN` variable. - For example, the following job will download the artifacts of the `test` job - of the `master` branch. Note that the command is wrapped into single quotes - since it contains a colon (`:`): - - ```yaml - artifact_download: - stage: test - script: - - 'curl --location --output artifacts.zip --header "JOB-TOKEN: $CI_JOB_TOKEN" "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/jobs/artifacts/master/download?job=test"' - ``` - -- Or the `job_token` attribute with the GitLab-provided `CI_JOB_TOKEN` variable. - For example, the following job will download the artifacts of the `test` job - of the `master` branch: - - ```yaml - artifact_download: - stage: test - script: - - 'curl --location --output artifacts.zip "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/jobs/artifacts/master/download?job=test&job_token=$CI_JOB_TOKEN"' - ``` - -Possible response status codes: - -| Status | Description | -|-----------|---------------------------------| -| 200 | Serves the artifacts file. | -| 404 | Build not found or no artifacts.| - -## Download a single artifact file by job ID - -> Introduced in GitLab 10.0 - -Download a single artifact file from a job with a specified ID from within -the job's artifacts zipped archive. The file is extracted from the archive and -streamed to the client. - -```plaintext -GET /projects/:id/jobs/:job_id/artifacts/*artifact_path -``` - -Parameters - -| Attribute | Type | Required | Description | -|-----------------|----------------|----------|------------------------------------------------------------------------------------------------------------------| -| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | -| `job_id` | integer | yes | The unique job identifier. | -| `artifact_path` | string | yes | Path to a file inside the artifacts archive. | - -Example request: - -```shell -curl --location --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/5/artifacts/some/release/file.pdf" -``` - -Possible response status codes: - -| Status | Description | -|-----------|--------------------------------------| -| 200 | Sends a single artifact file | -| 400 | Invalid path provided | -| 404 | Build not found or no file/artifacts | - -## Download a single artifact file from specific tag or branch - -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23538) in GitLab 11.5. - -Download a single artifact file for a specific job of the latest successful -pipeline for the given reference name from within the job's artifacts archive. -The file is extracted from the archive and streamed to the client. - -```plaintext -GET /projects/:id/jobs/artifacts/:ref_name/raw/*artifact_path?job=name -``` - -Parameters: - -| Attribute | Type | Required | Description | -|-----------------|----------------|----------|------------------------------------------------------------------------------------------------------------------| -| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | -| `ref_name` | string | yes | Branch or tag name in repository. HEAD or SHA references are not supported. | -| `artifact_path` | string | yes | Path to a file inside the artifacts archive. | -| `job` | string | yes | The name of the job. | - -Example request: - -```shell -curl --location --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/raw/some/release/file.pdf?job=pdf" -``` - -Possible response status codes: - -| Status | Description | -|-----------|--------------------------------------| -| 200 | Sends a single artifact file | -| 400 | Invalid path provided | -| 404 | Build not found or no file/artifacts | - ## Get a log file Get a log (trace) of a specific job of a project: @@ -793,86 +610,6 @@ Example of response } ``` -## Keep artifacts - -Prevents artifacts from being deleted when expiration is set. - -```plaintext -POST /projects/:id/jobs/:job_id/artifacts/keep -``` - -Parameters - -| Attribute | Type | Required | Description | -|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------| -| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | -| `job_id` | integer | yes | ID of a job. | - -Example request: - -```shell -curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/1/artifacts/keep" -``` - -Example response: - -```json -{ - "commit": { - "author_email": "admin@example.com", - "author_name": "Administrator", - "created_at": "2015-12-24T16:51:14.000+01:00", - "id": "0ff3ae198f8601a285adcf5c0fff204ee6fba5fd", - "message": "Test the CI integration.", - "short_id": "0ff3ae19", - "title": "Test the CI integration." - }, - "coverage": null, - "allow_failure": false, - "download_url": null, - "id": 42, - "name": "rubocop", - "ref": "master", - "artifacts": [], - "runner": null, - "stage": "test", - "created_at": "2016-01-11T10:13:33.506Z", - "started_at": "2016-01-11T10:13:33.506Z", - "finished_at": "2016-01-11T10:15:10.506Z", - "duration": 97.0, - "status": "failed", - "tag": false, - "web_url": "https://example.com/foo/bar/-/jobs/42", - "user": null -} -``` - -## Delete artifacts - -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25522) in GitLab 11.9. - -Delete artifacts of a job. - -```plaintext -DELETE /projects/:id/jobs/:job_id/artifacts -``` - -| Attribute | Type | Required | Description | -|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------| -| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) | -| `job_id` | integer | yes | ID of a job. | - -Example request: - -```shell -curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/jobs/1/artifacts" -``` - -NOTE: **Note:** -At least Maintainer role is required to delete artifacts. - -If the artifacts were deleted successfully, a response with status `204 No Content` is returned. - ## Play a job Triggers a manual action to start a job. diff --git a/doc/api/keys.md b/doc/api/keys.md index 6294ac300ce..b9e45c23e77 100644 --- a/doc/api/keys.md +++ b/doc/api/keys.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Keys API ## Get SSH key with user by ID of an SSH key diff --git a/doc/api/lint.md b/doc/api/lint.md index b5889884e48..f4d8a0bc011 100644 --- a/doc/api/lint.md +++ b/doc/api/lint.md @@ -1,3 +1,9 @@ +--- +stage: Verify +group: Continuous Integration +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- + # Validate the `.gitlab-ci.yml` (API) > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5953) in GitLab 8.12. diff --git a/doc/api/markdown.md b/doc/api/markdown.md index 32810ee349e..4e5c8515126 100644 --- a/doc/api/markdown.md +++ b/doc/api/markdown.md @@ -1,7 +1,8 @@ --- -stage: Plan -group: Project Management -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api --- # Markdown API diff --git a/doc/api/members.md b/doc/api/members.md index 8cd7bafdd77..90c36a0b822 100644 --- a/doc/api/members.md +++ b/doc/api/members.md @@ -16,6 +16,12 @@ Due to [an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/219299), projects in personal namespaces will not show owner (`50`) permission for owner. +## Limitations + +The `group_saml_identity` attribute is only visible to a group owner for [SSO enabled groups](../user/group/saml_sso/index.md). + +The `email` attribute is only visible to a group owner who manages the user through [Group Managed Accounts](../user/group/saml_sso/group_managed_accounts.md). + ## List all members of a group or project Gets a list of group or project members viewable by the authenticated user. @@ -172,6 +178,7 @@ Example response: "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "access_level": 30, + "email": "john@example.com", "expires_at": null, "group_saml_identity": null } @@ -209,6 +216,7 @@ Example response: "avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon", "web_url": "http://192.168.1.8:3000/root", "access_level": 30, + "email": "john@example.com", "expires_at": null, "group_saml_identity": null } @@ -247,6 +255,7 @@ Example response: "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-10-22T14:13:35Z", "access_level": 30, + "email": "john@example.com", "group_saml_identity": null } ``` @@ -284,6 +293,7 @@ Example response: "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-10-22T14:13:35Z", "access_level": 40, + "email": "john@example.com", "group_saml_identity": null } ``` @@ -320,6 +330,7 @@ Example response: "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-10-22T14:13:35Z", "access_level": 40, + "email": "john@example.com", "override": true } ``` @@ -356,6 +367,7 @@ Example response: "web_url": "http://192.168.1.8:3000/root", "expires_at": "2012-10-22T14:13:35Z", "access_level": 40, + "email": "john@example.com", "override": false } ``` diff --git a/doc/api/merge_request_approvals.md b/doc/api/merge_request_approvals.md index 746a79e1b8e..643d03b6fb8 100644 --- a/doc/api/merge_request_approvals.md +++ b/doc/api/merge_request_approvals.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Merge request approvals API **(STARTER)** Configuration for approvals on all Merge Requests (MR) in the project. Must be authenticated for all endpoints. @@ -392,9 +399,11 @@ DELETE /projects/:id/approval_rules/:approval_rule_id ### Change allowed approvers ->**Note:** This API endpoint has been deprecated. Please use Approval Rule API instead. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/183) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6. +NOTE: **Note:** +This API endpoint has been deprecated. Please use Approval Rule API instead. + If you are allowed to, you can change approvers and approver groups using the following endpoint: @@ -541,9 +550,11 @@ POST /projects/:id/merge_requests/:merge_request_iid/approvals ### Change allowed approvers for Merge Request ->**Note:** This API endpoint has been deprecated. Please use Approval Rule API instead. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/183) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6. +NOTE: **Note:** +This API endpoint has been deprecated. Please use Approval Rule API instead. + If you are allowed to, you can change approvers and approver groups using the following endpoint: diff --git a/doc/api/merge_request_context_commits.md b/doc/api/merge_request_context_commits.md index e9ba31401ef..9b4697390d1 100644 --- a/doc/api/merge_request_context_commits.md +++ b/doc/api/merge_request_context_commits.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Merge request context commits API ## List MR context commits diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index 959cf87ba62..4798145e837 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Merge requests API Every API call to merge requests must be authenticated. @@ -2449,3 +2456,8 @@ Example response: ## Approvals **(STARTER)** For approvals, please see [Merge Request Approvals](merge_request_approvals.md) + +## List merge request state events + +To track which state was set, who did it, and when it happened, check out +[Resource state events API](./resource_state_events.md#merge-requests). diff --git a/doc/api/milestones.md b/doc/api/milestones.md index b5702c7d6e0..7b4d1cc331d 100644 --- a/doc/api/milestones.md +++ b/doc/api/milestones.md @@ -25,13 +25,14 @@ GET /projects/:id/milestones?search=version Parameters: -| Attribute | Type | Required | Description | -| --------- | ------ | -------- | ----------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | -| `iids[]` | integer array | optional | Return only the milestones having the given `iid` | -| `state` | string | optional | Return only `active` or `closed` milestones | -| `title` | string | optional | Return only the milestones having the given `title` | -| `search` | string | optional | Return only milestones with a title or description matching the provided string | +| Attribute | Type | Required | Description | +| ---------------------------- | ------ | -------- | ----------- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | +| `iids[]` | integer array | optional | Return only the milestones having the given `iid` (Note: ignored if `include_parent_milestones` is set as `true`) | +| `state` | string | optional | Return only `active` or `closed` milestones | +| `title` | string | optional | Return only the milestones having the given `title` | +| `search` | string | optional | Return only milestones with a title or description matching the provided string | +| `include_parent_milestones` | boolean | optional | Include group milestones from parent group and its ancestors. Introduced in [GitLab 13.4](https://gitlab.com/gitlab-org/gitlab/-/issues/196066) | ```shell curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/milestones" diff --git a/doc/api/namespaces.md b/doc/api/namespaces.md index e38e725fb97..ba59d467bc8 100644 --- a/doc/api/namespaces.md +++ b/doc/api/namespaces.md @@ -31,7 +31,14 @@ Example response: "name": "user1", "path": "user1", "kind": "user", - "full_path": "user1" + "full_path": "user1", + "parent_id": null, + "avatar_url": "https://secure.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "web_url": "https://gitlab.example.com/user1", + "billable_members_count": 1, + "plan": "default", + "trial_ends_on": null, + "trial": false }, { "id": 2, @@ -40,7 +47,13 @@ Example response: "kind": "group", "full_path": "group1", "parent_id": null, - "members_count_with_descendants": 2 + "avatar_url": null, + "web_url": "https://gitlab.example.com/groups/group1", + "members_count_with_descendants": 2, + "billable_members_count": 2, + "plan": "default", + "trial_ends_on": null, + "trial": false }, { "id": 3, @@ -49,7 +62,13 @@ Example response: "kind": "group", "full_path": "foo/bar", "parent_id": 9, - "members_count_with_descendants": 5 + "avatar_url": null, + "web_url": "https://gitlab.example.com/groups/foo/bar", + "members_count_with_descendants": 5, + "billable_members_count": 5, + "plan": "default", + "trial_ends_on": null, + "trial": false } ] ``` @@ -100,7 +119,13 @@ Example response: "kind": "group", "full_path": "twitter", "parent_id": null, - "members_count_with_descendants": 2 + "avatar_url": null, + "web_url": "https://gitlab.example.com/groups/twitter", + "members_count_with_descendants": 2, + "billable_members_count": 2, + "plan": "default", + "trial_ends_on": null, + "trial": false } ] ``` @@ -133,7 +158,13 @@ Example response: "kind": "group", "full_path": "group1", "parent_id": null, - "members_count_with_descendants": 2 + "avatar_url": null, + "web_url": "https://gitlab.example.com/groups/group1", + "members_count_with_descendants": 2, + "billable_members_count": 2, + "plan": "default", + "trial_ends_on": null, + "trial": false } ``` @@ -153,6 +184,12 @@ Example response: "kind": "group", "full_path": "group1", "parent_id": null, - "members_count_with_descendants": 2 + "avatar_url": null, + "web_url": "https://gitlab.example.com/groups/group1", + "members_count_with_descendants": 2, + "billable_members_count": 2, + "plan": "default", + "trial_ends_on": null, + "trial": false } ``` diff --git a/doc/api/notes.md b/doc/api/notes.md index 9a75b950f28..3a68454507a 100644 --- a/doc/api/notes.md +++ b/doc/api/notes.md @@ -7,7 +7,19 @@ Notes are comments on: - Merge requests - Epics **(ULTIMATE)** -This includes system notes, which are notes about changes to the object (for example, when a milestone changes, there will be a corresponding system note). Label notes are not part of this API, but recorded as separate events in [resource label events](resource_label_events.md). +This includes system notes, which are notes about changes to the object (for example, when an +assignee changes, there will be a corresponding system note). + +## Resource events + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/38096) in GitLab 13.3 for state, milestone, and weight events. + +Some system notes are not part of this API, but are recorded as separate events: + +- [Resource label events](resource_label_events.md) +- [Resource state events](resource_state_events.md) +- [Resource milestone events](resource_milestone_events.md) +- [Resource weight events](resource_weight_events.md) **(STARTER)** ## Notes pagination @@ -133,10 +145,11 @@ PUT /projects/:id/issues/:issue_iid/notes/:note_id Parameters: -- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) -- `issue_iid` (required) - The IID of an issue -- `note_id` (required) - The ID of a note -- `body` (required) - The content of a note. Limited to 1,000,000 characters. +- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). +- `issue_iid` (required) - The IID of an issue. +- `note_id` (required) - The ID of a note. +- `body` (optional) - The content of a note. Limited to 1,000,000 characters. +- `confidential` (optional) - The confidential flag of a note. ```shell curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/issues/11/notes?body=note" diff --git a/doc/api/notification_settings.md b/doc/api/notification_settings.md index ffdf6d34832..8442e371a56 100644 --- a/doc/api/notification_settings.md +++ b/doc/api/notification_settings.md @@ -32,6 +32,7 @@ If the `custom` level is used, specific email events can be controlled. Availabl - `failed_pipeline` - `fixed_pipeline` - `success_pipeline` +- `moved_project` - `new_epic` **(ULTIMATE)** ## Global notification settings @@ -86,7 +87,8 @@ curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab | `failed_pipeline` | boolean | no | Enable/disable this notification | | `fixed_pipeline` | boolean | no | Enable/disable this notification | | `success_pipeline` | boolean | no | Enable/disable this notification | -| `new_epic` | boolean | no | Enable/disable this notification ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6626) in 11.3) **(ULTIMATE)** | +| `moved_project` | boolean | no | Enable/disable this notification ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30371) in GitLab 13.3) | +| `new_epic` | boolean | no | Enable/disable this notification ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5863) in GitLab 11.3) **(ULTIMATE)** | Example response: @@ -156,7 +158,8 @@ curl --request PUT --header "PRIVATE-TOKEN: " "https://gitlab | `failed_pipeline` | boolean | no | Enable/disable this notification | | `fixed_pipeline` | boolean | no | Enable/disable this notification | | `success_pipeline` | boolean | no | Enable/disable this notification | -| `new_epic` | boolean | no | Enable/disable this notification ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6626) in 11.3) **(ULTIMATE)** | +| `moved_project` | boolean | no | Enable/disable this notification ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30371) in GitLab 13.3) | +| `new_epic` | boolean | no | Enable/disable this notification ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5863) in GitLab 11.3) **(ULTIMATE)** | Example responses: @@ -187,8 +190,8 @@ Example responses: } ``` -Users on GitLab [Ultimate or Gold](https://about.gitlab.com/pricing/) will also see -the `new_epic` parameter: +Users on GitLab [Ultimate or Gold](https://about.gitlab.com/pricing/) also see the `new_epic` +parameter: ```json { diff --git a/doc/api/packages.md b/doc/api/packages.md index 19828208a26..cf65b518844 100644 --- a/doc/api/packages.md +++ b/doc/api/packages.md @@ -4,7 +4,7 @@ group: Package info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers --- -# Packages API **(PREMIUM)** +# Packages API This is the API docs of [GitLab Packages](../administration/packages/index.md). diff --git a/doc/api/personal_access_tokens.md b/doc/api/personal_access_tokens.md new file mode 100644 index 00000000000..517e26f3d85 --- /dev/null +++ b/doc/api/personal_access_tokens.md @@ -0,0 +1,88 @@ +# Personal access tokens API **(ULTIMATE)** + +You can read more about [personal access tokens](../user/profile/personal_access_tokens.md#personal-access-tokens). + +## List personal access tokens + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227264) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.3. + +Get a list of personal access tokens. + +```plaintext +GET /personal_access_tokens +``` + +| Attribute | Type | required | Description | +|-----------|---------|----------|---------------------| +| `user_id` | integer/string | no | The ID of the user to filter by | + +NOTE: **Note:** +Administrators can use the `user_id` parameter to filter by a user. Non-administrators cannot filter by any user except themselves. Attempting to do so will result in a `401 Unauthorized` response. + +```shell +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/personal_access_tokens" +``` + +```json +[ + { + "id": 4, + "name": "Test Token", + "revoked": false, + "created_at": "2020-07-23T14:31:47.729Z", + "scopes": [ + "api" + ], + "active": true, + "user_id": 24, + "expires_at": null + } +] +``` + +```shell +curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/personal_access_tokens?user_id=3" +``` + +```json +[ + { + "id": 4, + "name": "Test Token", + "revoked": false, + "created_at": "2020-07-23T14:31:47.729Z", + "scopes": [ + "api" + ], + "active": true, + "user_id": 3, + "expires_at": null + } +] +``` + +## Revoke a personal access token + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216004) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.3. + +Revoke a personal access token. + +```plaintext +DELETE /personal_access_tokens/:id +``` + +| Attribute | Type | required | Description | +|-----------|---------|----------|---------------------| +| `id` | integer/string | yes | ID of personal access token | + +NOTE: **Note:** +Non-administrators can revoke their own tokens. Administrators can revoke tokens of any user. + +```shell +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/personal_access_tokens/" +``` + +### Responses + +- `204: No Content` if successfully revoked. +- `400 Bad Request` if not revoked successfully. diff --git a/doc/api/pipeline_schedules.md b/doc/api/pipeline_schedules.md index dc16157ef4b..1faa6ef56db 100644 --- a/doc/api/pipeline_schedules.md +++ b/doc/api/pipeline_schedules.md @@ -1,3 +1,9 @@ +--- +stage: Verify +group: Continuous Integration +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- + # Pipeline schedules API You can read more about [pipeline schedules](../ci/pipelines/schedules.md). diff --git a/doc/api/pipeline_triggers.md b/doc/api/pipeline_triggers.md index 1a63a04be71..c46992de51b 100644 --- a/doc/api/pipeline_triggers.md +++ b/doc/api/pipeline_triggers.md @@ -1,3 +1,9 @@ +--- +stage: Verify +group: Continuous Integration +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- + # Pipeline triggers API You can read more about [triggering pipelines through the API](../ci/triggers/README.md). diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md index 563829b8192..dc81ef0e25e 100644 --- a/doc/api/pipelines.md +++ b/doc/api/pipelines.md @@ -1,5 +1,19 @@ +--- +stage: Verify +group: Continuous Integration +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- + # Pipelines API +## Single Pipeline Requests + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36494) in GitLab 13.3. + +Endpoints that request information about a single pipeline return data for any pipeline. +Before 13.3, requests for [child pipelines](../ci/parent_child_pipelines.md) returned +a 404 error. + ## Pipelines pagination By default, `GET` requests return 20 results at a time because the API results @@ -19,7 +33,7 @@ GET /projects/:id/pipelines |-----------|---------|----------|---------------------| | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | | `scope` | string | no | The scope of pipelines, one of: `running`, `pending`, `finished`, `branches`, `tags` | -| `status` | string | no | The status of pipelines, one of: `running`, `pending`, `success`, `failed`, `canceled`, `skipped`, `created`, `manual` | +| `status` | string | no | The status of pipelines, one of: `created`, `waiting_for_resource`, `preparing`, `pending`, `running`, `success`, `failed`, `canceled`, `skipped`, `manual`, `scheduled` | | `ref` | string | no | The ref of pipelines | | `sha` | string | no | The SHA of pipelines | | `yaml_errors`| boolean | no | Returns pipelines with invalid configurations | @@ -205,7 +219,7 @@ POST /projects/:id/pipeline |-------------|---------|----------|---------------------| | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | | `ref` | string | yes | Reference to commit | -| `variables` | array | no | An array containing the variables available in the pipeline, matching the structure `[{ 'key' => 'UPLOAD_TO_S3', 'variable_type' => 'file', 'value' => 'true' }]` | +| `variables` | array | no | An array containing the variables available in the pipeline, matching the structure `[{ 'key': 'UPLOAD_TO_S3', 'variable_type': 'file', 'value': 'true' }]` | ```shell curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/pipeline?ref=master" diff --git a/doc/api/project_aliases.md b/doc/api/project_aliases.md index d80decfe53c..cfd225639f9 100644 --- a/doc/api/project_aliases.md +++ b/doc/api/project_aliases.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Project Aliases API **(PREMIUM ONLY)** > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3264) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.1. diff --git a/doc/api/project_badges.md b/doc/api/project_badges.md index 86b1ba6ce19..936bd40d1ee 100644 --- a/doc/api/project_badges.md +++ b/doc/api/project_badges.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Project badges API > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17082) in GitLab 10.6. diff --git a/doc/api/project_import_export.md b/doc/api/project_import_export.md index 74902a22594..5565eaa97f7 100644 --- a/doc/api/project_import_export.md +++ b/doc/api/project_import_export.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Project import/export API > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41899) in GitLab 10.6. diff --git a/doc/api/project_level_variables.md b/doc/api/project_level_variables.md index 407e506e082..4760816f5d0 100644 --- a/doc/api/project_level_variables.md +++ b/doc/api/project_level_variables.md @@ -1,3 +1,10 @@ +--- +stage: Verify +group: Continuous Integration +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +type: reference, api +--- + # Project-level Variables API ## List project variables @@ -148,8 +155,10 @@ curl --request DELETE --header "PRIVATE-TOKEN: " "https://git > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34490) in GitLab 13.2. > - It's deployed behind a feature flag, disabled by default. -> - It's disabled on GitLab.com. -> - To use it in GitLab self-managed instances, ask a GitLab administrator to enable it. +> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39209) on GitLab 13.3. +> - It's enabled on GitLab.com. +> - It's recommended for production use. +> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable). This parameter is used for filtering by attributes, such as `environment_scope`. @@ -161,17 +170,18 @@ curl --request DELETE --header "PRIVATE-TOKEN: " "https://git ### Enable or disable +It is deployed behind a feature flag that is **enabled by default**. [GitLab administrators with access to the GitLab Rails console](../administration/feature_flags.md) -can enable it for your instance. +can opt to disable it for your instance. -To enable it: +To disable it: ```ruby -Feature.enable(:ci_variables_api_filter_environment_scope) +Feature.disable(:ci_variables_api_filter_environment_scope) ``` -To disable it: +To enable it: ```ruby -Feature.disable(:ci_variables_api_filter_environment_scope) +Feature.enable(:ci_variables_api_filter_environment_scope) ``` diff --git a/doc/api/project_snippets.md b/doc/api/project_snippets.md index fd8cbd6e256..eccc8b4212d 100644 --- a/doc/api/project_snippets.md +++ b/doc/api/project_snippets.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Editor +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Project snippets ## Snippet visibility level diff --git a/doc/api/project_statistics.md b/doc/api/project_statistics.md index d96d3de6a73..344aeaa588f 100644 --- a/doc/api/project_statistics.md +++ b/doc/api/project_statistics.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Project statistics API Every API call to [project](../user/project/index.md) statistics must be authenticated. diff --git a/doc/api/project_templates.md b/doc/api/project_templates.md index e9658423b63..e08ff56925e 100644 --- a/doc/api/project_templates.md +++ b/doc/api/project_templates.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Project templates API This API is a project-specific version of these endpoints: @@ -6,15 +13,14 @@ This API is a project-specific version of these endpoints: - [Gitignore templates](templates/gitignores.md) - [GitLab CI/CD Configuration templates](templates/gitlab_ci_ymls.md) - [Open source license templates](templates/licenses.md) +- [Issue and merge request templates](../user/project/description_templates.md) + ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37890) in GitLab 13.3) It deprecates these endpoints, which will be removed for API version 5. In addition to templates common to the entire instance, project-specific templates are also available from this API endpoint. -Support will be added for [Issue and Merge Request templates](../user/project/description_templates.md) -in a future release. - Support for [Group-level file templates](../user/group/index.md#group-file-templates-premium) **(PREMIUM)** was [added](https://gitlab.com/gitlab-org/gitlab/-/issues/5987) in GitLab 11.5 @@ -28,7 +34,7 @@ GET /projects/:id/templates/:type | Attribute | Type | Required | Description | | ---------- | ------ | -------- | ----------- | | `id` | integer / string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) | -| `type` | string | yes| The type `(dockerfiles|gitignores|gitlab_ci_ymls|licenses)` of the template | +| `type` | string | yes| The type `(dockerfiles|gitignores|gitlab_ci_ymls|licenses|issues|merge_requests)` of the template | Example response (licenses): @@ -94,7 +100,7 @@ GET /projects/:id/templates/:type/:key | Attribute | Type | Required | Description | | ---------- | ------ | -------- | ----------- | | `id` | integer / string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) | -| `type` | string | yes| The type `(dockerfiles|gitignores|gitlab_ci_ymls|licenses)` of the template | +| `type` | string | yes| The type `(dockerfiles|gitignores|gitlab_ci_ymls|licenses|issues|merge_requests)` of the template | | `key` | string | yes | The key of the template, as obtained from the collection endpoint | | `project` | string | no | The project name to use when expanding placeholders in the template. Only affects licenses | | `fullname` | string | no | The full name of the copyright holder to use when expanding placeholders in the template. Only affects licenses | diff --git a/doc/api/project_vulnerabilities.md b/doc/api/project_vulnerabilities.md index c4f1adccd3c..8ab02ed9ea6 100644 --- a/doc/api/project_vulnerabilities.md +++ b/doc/api/project_vulnerabilities.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Project Vulnerabilities API **(ULTIMATE)** > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10242) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.6. diff --git a/doc/api/projects.md b/doc/api/projects.md index 6257f37f0e6..ee9779b54e0 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -1085,7 +1085,7 @@ POST /projects | `template_project_id` | integer | no | **(PREMIUM)** When used with `use_custom_template`, project ID of a custom project template. This is preferable to using `template_name` since `template_name` may be ambiguous. | | `use_custom_template` | boolean | no | **(PREMIUM)** Use either custom [instance](../user/admin_area/custom_project_templates.md) or [group](../user/group/custom_project_templates.md) (with `group_with_project_templates_id`) project template | | `group_with_project_templates_id` | integer | no | **(PREMIUM)** For group-level custom templates, specifies ID of group from which all the custom project templates are sourced. Leave empty for instance-level templates. Requires `use_custom_template` to be true | -| `packages_enabled` | boolean | no | **(PREMIUM ONLY)** Enable or disable packages repository feature | +| `packages_enabled` | boolean | no | Enable or disable packages repository feature | NOTE: **Note:** If your HTTP repository is not publicly accessible, @@ -1156,7 +1156,7 @@ POST /projects/user/:user_id | `template_name` | string | no | When used without `use_custom_template`, name of a [built-in project template](../gitlab-basics/create-project.md#built-in-templates). When used with `use_custom_template`, name of a custom project template | | `use_custom_template` | boolean | no | **(PREMIUM)** Use either custom [instance](../user/admin_area/custom_project_templates.md) or [group](../user/group/custom_project_templates.md) (with `group_with_project_templates_id`) project template | | `group_with_project_templates_id` | integer | no | **(PREMIUM)** For group-level custom templates, specifies ID of group from which all the custom project templates are sourced. Leave empty for instance-level templates. Requires `use_custom_template` to be true | -| `packages_enabled` | boolean | no | **(PREMIUM ONLY)** Enable or disable packages repository feature | +| `packages_enabled` | boolean | no | Enable or disable packages repository feature | NOTE: **Note:** If your HTTP repository is not publicly accessible, @@ -1227,8 +1227,8 @@ PUT /projects/:id | `mirror_trigger_builds` | boolean | no | **(STARTER)** Pull mirroring triggers builds | | `only_mirror_protected_branches` | boolean | no | **(STARTER)** Only mirror protected branches | | `mirror_overwrites_diverged_branches` | boolean | no | **(STARTER)** Pull mirror overwrites diverged branches | -| `packages_enabled` | boolean | no | **(PREMIUM ONLY)** Enable or disable packages repository feature | -| `service_desk_enabled` | boolean | no | Enable or disable service desk feature | +| `packages_enabled` | boolean | no | Enable or disable packages repository feature | +| `service_desk_enabled` | boolean | no | Enable or disable Service Desk feature | NOTE: **Note:** If your HTTP repository is not publicly accessible, @@ -1258,7 +1258,7 @@ POST /projects/:id/fork ## List Forks of a project ->**Note:** This feature was introduced in GitLab 10.1 +> Introduced in GitLab 10.1. List the projects accessible to the calling user that have an established, forked relationship with the specified project @@ -1832,16 +1832,16 @@ Example response: } ``` -## Remove project +## Delete project This endpoint: -- Removes a project including all associated resources (issues, merge requests etc). +- Deletes a project including all associated resources (issues, merge requests etc). - From [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) on [Premium or Silver](https://about.gitlab.com/pricing/) or higher tiers, group admins can [configure](../user/group/index.md#enabling-delayed-project-removal-premium) projects within a group to be deleted after a delayed period. When enabled, actual deletion happens after the number of days -specified in the [default deletion period](../user/admin_area/settings/visibility_and_access_controls.md#default-deletion-adjourned-period-premium-only). +specified in the [default deletion delay](../user/admin_area/settings/visibility_and_access_controls.md#default-deletion-delay-premium-only). CAUTION: **Warning:** The default behavior of [Delayed Project deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) in GitLab 12.6 @@ -1985,6 +1985,7 @@ GET /projects/:id/hooks/:hook_id "job_events": true, "pipeline_events": true, "wiki_page_events": true, + "deployment_events": true, "enable_ssl_verification": true, "created_at": "2012-10-12T17:04:47Z" } @@ -2013,6 +2014,7 @@ POST /projects/:id/hooks | `job_events` | boolean | no | Trigger hook on job events | | `pipeline_events` | boolean | no | Trigger hook on pipeline events | | `wiki_page_events` | boolean | no | Trigger hook on wiki events | +| `deployment_events` | boolean | no | Trigger hook on deployment events | | `enable_ssl_verification` | boolean | no | Do SSL verification when triggering the hook | | `token` | string | no | Secret token to validate received payloads; this will not be returned in the response | @@ -2040,6 +2042,7 @@ PUT /projects/:id/hooks/:hook_id | `job_events` | boolean | no | Trigger hook on job events | | `pipeline_events` | boolean | no | Trigger hook on pipeline events | | `wiki_events` | boolean | no | Trigger hook on wiki events | +| `deployment_events` | boolean | no | Trigger hook on deployment events | | `enable_ssl_verification` | boolean | no | Do SSL verification when triggering the hook | | `token` | string | no | Secret token to validate received payloads; this will not be returned in the response | @@ -2121,7 +2124,7 @@ POST /projects/:id/housekeeping ### Get project push rules -Get the push rules of a project. +Get the [push rules](../push_rules/push_rules.md#enabling-push-rules) of a project. ```plaintext GET /projects/:id/push_rule diff --git a/doc/api/protected_branches.md b/doc/api/protected_branches.md index 4206fe6a565..1f4f1eb933a 100644 --- a/doc/api/protected_branches.md +++ b/doc/api/protected_branches.md @@ -1,6 +1,13 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Protected branches API ->**Note:** This feature was introduced in GitLab 9.5 +> Introduced in GitLab 9.5. **Valid access levels** diff --git a/doc/api/protected_tags.md b/doc/api/protected_tags.md index 01de19f54ea..9f9c1ad8b5d 100644 --- a/doc/api/protected_tags.md +++ b/doc/api/protected_tags.md @@ -1,6 +1,13 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Protected tags API ->**Note:** This feature was introduced in GitLab 11.3 +> Introduced in GitLab 11.3. **Valid access levels** diff --git a/doc/api/releases/index.md b/doc/api/releases/index.md index 2c933061c37..357f7e7a125 100644 --- a/doc/api/releases/index.md +++ b/doc/api/releases/index.md @@ -360,7 +360,7 @@ POST /projects/:id/releases | `name` | string | no | The release name. | | `tag_name` | string | yes | The tag where the release will be created from. | | `description` | string | no | The description of the release. You can use [Markdown](../../user/markdown.md). | -| `ref` | string | yes, if `tag_name` doesn't exist | If `tag_name` doesn't exist, the release will be created from `ref`. It can be a commit SHA, another tag name, or a branch name. | +| `ref` | string | yes, if `tag_name` doesn't exist | If a tag specified in `tag_name` doesn't exist, the release will be created from `ref` and tagged with `tag_name`. It can be a commit SHA, another tag name, or a branch name. | | `milestones` | array of string | no | The title of each milestone the release is associated with. | | `assets:links` | array of hash | no | An array of assets links. | | `assets:links:name`| string | required by: `assets:links` | The name of the link. | diff --git a/doc/api/remote_mirrors.md b/doc/api/remote_mirrors.md index 6495f6d8383..a8355fb9009 100644 --- a/doc/api/remote_mirrors.md +++ b/doc/api/remote_mirrors.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Project remote mirrors API [Push mirrors](../user/project/repository/repository_mirroring.md#pushing-to-a-remote-repository-core) diff --git a/doc/api/repositories.md b/doc/api/repositories.md index 7e601ec96ec..305216f853a 100644 --- a/doc/api/repositories.md +++ b/doc/api/repositories.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Repositories API ## List repository tree @@ -192,6 +199,9 @@ authentication if the repository is publicly accessible. GET /projects/:id/repository/contributors ``` +CAUTION: **Deprecation:** +The `additions` and `deletions` attributes are deprecated [as of GitLab 13.4](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39653) because they [always return `0`](https://gitlab.com/gitlab-org/gitlab/-/issues/233119). + Parameters: - `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user @@ -205,14 +215,14 @@ Response: "name": "Example User", "email": "example@example.com", "commits": 117, - "additions": 2097, - "deletions": 517 + "additions": 0, + "deletions": 0 }, { "name": "Sample User", "email": "sample@example.com", "commits": 33, - "additions": 338, - "deletions": 244 + "additions": 0, + "deletions": 0 }] ``` diff --git a/doc/api/repository_files.md b/doc/api/repository_files.md index 9d934a0f855..cc1f0aa970c 100644 --- a/doc/api/repository_files.md +++ b/doc/api/repository_files.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Repository files API **CRUD for repository files** diff --git a/doc/api/repository_submodules.md b/doc/api/repository_submodules.md index 40708f5bcb0..9a5dcacbc2f 100644 --- a/doc/api/repository_submodules.md +++ b/doc/api/repository_submodules.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Repository submodules API > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41213) in GitLab 11.5 diff --git a/doc/api/resource_milestone_events.md b/doc/api/resource_milestone_events.md index 8a81615857c..146f67527b7 100644 --- a/doc/api/resource_milestone_events.md +++ b/doc/api/resource_milestone_events.md @@ -6,6 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Resource milestone events API +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31720) in GitLab 13.1. + Resource milestone events keep track of what happens to GitLab [issues](../user/project/issues/) and [merge requests](../user/project/merge_requests/). diff --git a/doc/api/resource_state_events.md b/doc/api/resource_state_events.md index 6b257f10c6e..f93e0408300 100644 --- a/doc/api/resource_state_events.md +++ b/doc/api/resource_state_events.md @@ -6,6 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Resource state events API +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35210/) in GitLab 13.2. + Resource state events keep track of what happens to GitLab [issues](../user/project/issues/) and [merge requests](../user/project/merge_requests/). diff --git a/doc/api/resource_weight_events.md b/doc/api/resource_weight_events.md index 700ef288440..028878874d2 100644 --- a/doc/api/resource_weight_events.md +++ b/doc/api/resource_weight_events.md @@ -6,6 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Resource weight events API +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32542) in GitLab 13.2. + Resource weight events keep track of what happens to GitLab [issues](../user/project/issues/). Use them to track which weight was set, who did it, and when it happened. diff --git a/doc/api/scim.md b/doc/api/scim.md index 7c8da37a949..0a5703ad8db 100644 --- a/doc/api/scim.md +++ b/doc/api/scim.md @@ -35,7 +35,7 @@ Pagination follows the [SCIM spec](https://tools.ietf.org/html/rfc7644#section-3 Example request: ```shell -curl 'https://example.gitlab.com/api/scim/v2/groups/test_group/Users?filter=id%20eq%20"0b1d561c-21ff-4092-beab-8154b17f82f2"' --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +curl 'https://gitlab.example.com/api/scim/v2/groups/test_group/Users?filter=id%20eq%20"0b1d561c-21ff-4092-beab-8154b17f82f2"' --header "Authorization: Bearer " --header "Content-Type: application/scim+json" ``` Example response: @@ -86,7 +86,7 @@ Parameters: Example request: ```shell -curl "https://example.gitlab.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +curl "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" --header "Authorization: Bearer " --header "Content-Type: application/scim+json" ``` Example response: @@ -130,7 +130,7 @@ Parameters: Example request: ```shell -curl --verbose --request POST "https://example.gitlab.com/api/scim/v2/groups/test_group/Users" --data '{"externalId":"test_uid","active":null,"userName":"username","emails":[{"primary":true,"type":"work","value":"name@example.com"}],"name":{"formatted":"Test User","familyName":"User","givenName":"Test"},"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"meta":{"resourceType":"User"}}' --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +curl --verbose --request POST "https://gitlab.example.com/api/scim/v2/groups/test_group/Users" --data '{"externalId":"test_uid","active":null,"userName":"username","emails":[{"primary":true,"type":"work","value":"name@example.com"}],"name":{"formatted":"Test User","familyName":"User","givenName":"Test"},"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"meta":{"resourceType":"User"}}' --header "Authorization: Bearer " --header "Content-Type: application/scim+json" ``` Example response: @@ -184,7 +184,7 @@ Parameters: Example request: ```shell -curl --verbose --request PATCH "https://example.gitlab.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" --data '{ "Operations": [{"op":"Add","path":"name.formatted","value":"New Name"}] }' --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +curl --verbose --request PATCH "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" --data '{ "Operations": [{"op":"Add","path":"name.formatted","value":"New Name"}] }' --header "Authorization: Bearer " --header "Content-Type: application/scim+json" ``` Returns an empty response with a `204` status code if successful. @@ -207,7 +207,7 @@ Parameters: Example request: ```shell -curl --verbose --request DELETE "https://example.gitlab.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +curl --verbose --request DELETE "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" --header "Authorization: Bearer " --header "Content-Type: application/scim+json" ``` Returns an empty response with a `204` status code if successful. diff --git a/doc/api/search.md b/doc/api/search.md index 9c4eef7dfe8..4c87a826ca8 100644 --- a/doc/api/search.md +++ b/doc/api/search.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Search API > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41763) in GitLab 10.5. @@ -279,7 +286,8 @@ Example response: ] ``` -**Note:** `filename` is deprecated in favor of `path`. Both return the full path of the file inside the repository, but in the future `filename` will be only the file name and not the full path. For details, see [issue 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521). +NOTE: **Note:** +`filename` is deprecated in favor of `path`. Both return the full path of the file inside the repository, but in the future `filename` will be only the file name and not the full path. For details, see [issue 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521). ### Scope: commits **(STARTER)** @@ -350,7 +358,8 @@ Example response: ] ``` -**Note:** `filename` is deprecated in favor of `path`. Both return the full path of the file inside the repository, but in the future `filename` will be only the file name and not the full path. For details, see [issue 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521). +NOTE: **Note:** +`filename` is deprecated in favor of `path`. Both return the full path of the file inside the repository, but in the future `filename` will be only the file name and not the full path. For details, see [issue 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521). ### Scope: users @@ -620,7 +629,8 @@ Example response: ] ``` -**Note:** `filename` is deprecated in favor of `path`. Both return the full path of the file inside the repository, but in the future `filename` will be only the file name and not the full path. For details, see [issue 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521). +NOTE **Note:** +`filename` is deprecated in favor of `path`. Both return the full path of the file inside the repository, but in the future `filename` will be only the file name and not the full path. For details, see [issue 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521). ### Scope: commits **(STARTER)** @@ -691,7 +701,8 @@ Example response: ] ``` -**Note:** `filename` is deprecated in favor of `path`. Both return the full path of the file inside the repository, but in the future `filename` will be only the file name and not the full path. For details, see [issue 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521). +NOTE **Note:** +`filename` is deprecated in favor of `path`. Both return the full path of the file inside the repository, but in the future `filename` will be only the file name and not the full path. For details, see [issue 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521). ### Scope: users @@ -976,7 +987,8 @@ Example response: ] ``` -**Note:** `filename` is deprecated in favor of `path`. Both return the full path of the file inside the repository, but in the future `filename` will be only the file name and not the full path. For details, see [issue 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521). +NOTE: **Note:** +`filename` is deprecated in favor of `path`. Both return the full path of the file inside the repository, but in the future `filename` will be only the file name and not the full path. For details, see [issue 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521). ### Scope: commits @@ -1049,7 +1061,8 @@ Example response: ] ``` -**Note:** `filename` is deprecated in favor of `path`. Both return the full path of the file inside the repository, but in the future `filename` will be only the file name and not the full path. For details, see [issue 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521). +NOTE: **Note:** +`filename` is deprecated in favor of `path`. Both return the full path of the file inside the repository, but in the future `filename` will be only the file name and not the full path. For details, see [issue 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521). ### Scope: users diff --git a/doc/api/services.md b/doc/api/services.md index 4052fd22641..25ad025027a 100644 --- a/doc/api/services.md +++ b/doc/api/services.md @@ -1,6 +1,7 @@ # Services API ->**Note:** This API requires an access token with Maintainer or Owner permissions +NOTE: **Note:** +This API requires an access token with Maintainer or Owner permissions ## List all active services @@ -229,8 +230,8 @@ Parameters: | Parameter | Type | Required | Description | | --------- | ---- | -------- | ----------- | | `token` | string | true | Buildkite project GitLab token | -| `project_url` | string | true | `https://buildkite.com/example/project` | -| `enable_ssl_verification` | boolean | false | Enable SSL verification | +| `project_url` | string | true | Pipeline URL. For example, `https://buildkite.com/example/pipeline` | +| `enable_ssl_verification` | boolean | false | DEPRECATED: This parameter has no effect since SSL verification will always be enabled | | `push_events` | boolean | false | Enable notifications for push events | ### Delete Buildkite service @@ -636,9 +637,9 @@ GET /projects/:id/services/github ## Hangouts Chat -Google GSuite team collaboration tool. +> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20290) in GitLab 11.2. ->**Note:** This service was [introduced in v11.2](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20290) +Google GSuite team collaboration tool. ### Create/Edit Hangouts Chat service @@ -648,7 +649,8 @@ Set Hangouts Chat service for a project. PUT /projects/:id/services/hangouts-chat ``` ->**Note:** Specific event parameters (for example, `push_events` flag) were [introduced in v10.4](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11435) +NOTE: **Note:** +Specific event parameters (for example, `push_events` flag) were [introduced in v10.4](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11435) Parameters: @@ -1151,7 +1153,8 @@ Set Slack service for a project. PUT /projects/:id/services/slack ``` ->**Note:** Specific event parameters (for example, `push_events` flag and `push_channel`) were [introduced in v10.4](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11435) +NOTE: **Note:** +Specific event parameters (for example, `push_events` flag and `push_channel`) were [introduced in v10.4](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11435) Parameters: @@ -1260,7 +1263,8 @@ Set Mattermost service for a project. PUT /projects/:id/services/mattermost ``` ->**Note:** Specific event parameters (for example, `push_events` flag and `push_channel`) were [introduced in v10.4](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11435) +NOTE: **Note:** +Specific event parameters (for example, `push_events` flag and `push_channel`) were [introduced in v10.4](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11435) Parameters: diff --git a/doc/api/settings.md b/doc/api/settings.md index d87a3c72a7e..64c529b0222 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -71,8 +71,10 @@ Example response: "asset_proxy_url": "https://assets.example.com", "asset_proxy_whitelist": ["example.com", "*.example.com", "your-instance.com"], "npm_package_requests_forwarding": true, + "snippet_size_limit": 52428800, "issues_create_limit": 300, - "raw_blob_request_limit": 300 + "raw_blob_request_limit": 300, + "wiki_page_max_content_bytes": 52428800 } ``` @@ -161,8 +163,10 @@ Example response: "allow_local_requests_from_web_hooks_and_services": true, "allow_local_requests_from_system_hooks": false, "npm_package_requests_forwarding": true, + "snippet_size_limit": 52428800, "issues_create_limit": 300, - "raw_blob_request_limit": 300 + "raw_blob_request_limit": 300, + "wiki_page_max_content_bytes": 52428800 } ``` @@ -214,27 +218,29 @@ are listed in the descriptions of the relevant settings. | `default_ci_config_path` | string | no | Default CI configuration path for new projects (`.gitlab-ci.yml` if not set). | | `default_group_visibility` | string | no | What visibility level new groups receive. Can take `private`, `internal` and `public` as a parameter. Default is `private`. | | `default_project_creation` | integer | no | Default project creation protection. Can take: `0` _(No one)_, `1` _(Maintainers)_ or `2` _(Developers + Maintainers)_| -| `default_projects_limit` | integer | no | Project limit per user. Default is `100000`. | | `default_project_visibility` | string | no | What visibility level new projects receive. Can take `private`, `internal` and `public` as a parameter. Default is `private`. | +| `default_projects_limit` | integer | no | Project limit per user. Default is `100000`. | | `default_snippet_visibility` | string | no | What visibility level new snippets receive. Can take `private`, `internal` and `public` as a parameter. Default is `private`. | +| `deletion_adjourned_period` | integer | no | **(PREMIUM ONLY)** The number of days to wait before deleting a project or group that is marked for deletion. Value must be between 0 and 90. | `diff_max_patch_bytes` | integer | no | Maximum diff patch size (Bytes). | | `disabled_oauth_sign_in_sources` | array of strings | no | Disabled OAuth sign-in sources. | | `dns_rebinding_protection_enabled` | boolean | no | Enforce DNS rebinding attack protection. | -| `domain_blacklist` | array of strings | no | Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: `domain.com`, `*.domain.com`. | | `domain_blacklist_enabled` | boolean | no | (**If enabled, requires:** `domain_blacklist`) Allows blocking sign-ups from emails from specific domains. | +| `domain_blacklist` | array of strings | no | Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: `domain.com`, `*.domain.com`. | | `domain_whitelist` | array of strings | no | Force people to use only corporate emails for sign-up. Default is `null`, meaning there is no restriction. | | `dsa_key_restriction` | integer | no | The minimum allowed bit length of an uploaded DSA key. Default is `0` (no restriction). `-1` disables DSA keys. | | `ecdsa_key_restriction` | integer | no | The minimum allowed curve size (in bits) of an uploaded ECDSA key. Default is `0` (no restriction). `-1` disables ECDSA keys. | | `ed25519_key_restriction` | integer | no | The minimum allowed curve size (in bits) of an uploaded ED25519 key. Default is `0` (no restriction). `-1` disables ED25519 keys. | -| `eks_integration_enabled` | boolean | no | Enable integration with Amazon EKS | -| `eks_account_id` | string | no | Amazon account ID | | `eks_access_key_id` | string | no | AWS IAM access key ID | +| `eks_account_id` | string | no | Amazon account ID | +| `eks_integration_enabled` | boolean | no | Enable integration with Amazon EKS | | `eks_secret_access_key` | string | no | AWS IAM secret access key | | `elasticsearch_aws_access_key` | string | no | **(PREMIUM)** AWS IAM access key | -| `elasticsearch_aws` | boolean | no | **(PREMIUM)** Enable the use of AWS hosted Elasticsearch | | `elasticsearch_aws_region` | string | no | **(PREMIUM)** The AWS region the Elasticsearch domain is configured | | `elasticsearch_aws_secret_access_key` | string | no | **(PREMIUM)** AWS IAM secret access key | +| `elasticsearch_aws` | boolean | no | **(PREMIUM)** Enable the use of AWS hosted Elasticsearch | | `elasticsearch_indexed_field_length_limit` | integer | no | **(PREMIUM)** Maximum size of text fields that will be indexed by Elasticsearch. 0 value means no limit. This does not apply to repository and wiki indexing. | +| `elasticsearch_indexed_file_size_limit_kb` | integer | no | **(PREMIUM)** Maximum size of repository and wiki files that will be indexed by Elasticsearch. | | `elasticsearch_indexing` | boolean | no | **(PREMIUM)** Enable Elasticsearch indexing | | `elasticsearch_limit_indexing` | boolean | no | **(PREMIUM)** Limit Elasticsearch to index certain namespaces and projects | | `elasticsearch_max_bulk_concurrency` | integer | no | **(PREMIUM)** Maximum concurrency of Elasticsearch bulk requests per indexing operation. This only applies to repository indexing operations. | @@ -246,6 +252,7 @@ are listed in the descriptions of the relevant settings. | `email_additional_text` | string | no | **(PREMIUM)** Additional text added to the bottom of every email for legal/auditing/compliance reasons | | `email_author_in_body` | boolean | no | Some email servers do not support overriding the email sender name. Enable this option to include the name of the author of the issue, merge request or comment in the email body instead. | | `enabled_git_access_protocol` | string | no | Enabled protocols for Git access. Allowed values are: `ssh`, `http`, and `nil` to allow both protocols. | +| `enforce_namespace_storage_limit` | boolean | no | Enabling this permits enforcement of namespace storage limits. | | `enforce_terms` | boolean | no | (**If enabled, requires:** `terms`) Enforce application ToS to all users. | | `external_auth_client_cert` | string | no | (**If enabled, requires:** `external_auth_client_key`) The certificate to use to authenticate with the external authorization service | | `external_auth_client_key_pass` | string | no | Passphrase to use for the private key when authenticating with the external service this is encrypted when stored | @@ -279,7 +286,10 @@ are listed in the descriptions of the relevant settings. | `html_emails_enabled` | boolean | no | Enable HTML emails. | | `import_sources` | array of strings | no | Sources to allow project import from, possible values: `github`, `bitbucket`, `bitbucket_server`, `gitlab`, `google_code`, `fogbugz`, `git`, `gitlab_project`, `gitea`, `manifest`, and `phabricator`. | | `instance_statistics_visibility_private` | boolean | no | When set to `true` Instance statistics will only be available to admins. | +| `issues_create_limit` | integer | no | Max number of issue creation requests per minute per user. Disabled by default.| | `local_markdown_version` | integer | no | Increase this value when any cached Markdown should be invalidated. | +| `maintenance_mode_message` | string | no | **(PREMIUM)** Message displayed when instance is in maintenance mode | +| `maintenance_mode` | boolean | no | **(PREMIUM)** When instance is in maintenance mode, non-admin users can sign in with read-only access and make read-only API requests | | `max_artifacts_size` | integer | no | Maximum artifacts size in MB | | `max_attachment_size` | integer | no | Limit attachment size in MB | | `max_import_size` | integer | no | Maximum import size in MB. 0 for unlimited. Default = 50 | @@ -291,8 +301,6 @@ are listed in the descriptions of the relevant settings. | `mirror_max_capacity` | integer | no | **(PREMIUM)** Maximum number of mirrors that can be synchronizing at the same time. | | `mirror_max_delay` | integer | no | **(PREMIUM)** Maximum time (in minutes) between updates that a mirror can have when scheduled to synchronize. | | `npm_package_requests_forwarding` | boolean | no | **(PREMIUM)** Use npmjs.org as a default remote repository when the package is not found in the GitLab NPM Registry | -| `maintenance_mode` | boolean | no | **(PREMIUM)** When instance is in maintenance mode, non-admin users can sign in with read-only access and make read-only API requests | -| `maintenance_mode_message` | string | no | **(PREMIUM)** Message displayed when instance is in maintenance mode | | `outbound_local_requests_whitelist` | array of strings | no | Define a list of trusted domains or ip addresses to which local requests are allowed when local requests for hooks and services are disabled. | `pages_domain_verification_enabled` | boolean | no | Require users to prove ownership of custom domains. Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled. | | `password_authentication_enabled_for_git` | boolean | no | Enable authentication for Git over HTTP(S) via a GitLab account password. Default is `true`. | @@ -303,21 +311,21 @@ are listed in the descriptions of the relevant settings. | `plantuml_enabled` | boolean | no | (**If enabled, requires:** `plantuml_url`) Enable PlantUML integration. Default is `false`. | | `plantuml_url` | string | required by: `plantuml_enabled` | The PlantUML instance URL for integration. | | `polling_interval_multiplier` | decimal | no | Interval multiplier used by endpoints that perform polling. Set to `0` to disable polling. | -| `deletion_adjourned_period` | integer | no | **(PREMIUM ONLY)** The number of days to wait before removing a project or group that is marked for deletion. Value must be between 0 and 90. | `project_export_enabled` | boolean | no | Enable project export. | | `prometheus_metrics_enabled` | boolean | no | Enable Prometheus metrics. | | `protected_ci_variables` | boolean | no | Environment variables are protected by default. | | `pseudonymizer_enabled` | boolean | no | **(PREMIUM)** When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory. -| `push_event_hooks_limit` | integer | no | Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value. | | `push_event_activities_limit` | integer | no | Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push events will be created. [Bulk push events will be created](../user/admin_area/settings/push_event_activities_limit.md) if it surpasses that value. | +| `push_event_hooks_limit` | integer | no | Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value. | +| `raw_blob_request_limit` | integer | no | Max number of requests per minute for each raw path. Default: 300. To disable throttling set to 0.| | `recaptcha_enabled` | boolean | no | (**If enabled, requires:** `recaptcha_private_key` and `recaptcha_site_key`) Enable reCAPTCHA. | | `recaptcha_private_key` | string | required by: `recaptcha_enabled` | Private key for reCAPTCHA. | | `recaptcha_site_key` | string | required by: `recaptcha_enabled` | Site key for reCAPTCHA. | | `receive_max_input_size` | integer | no | Maximum push size (MB). | | `repository_checks_enabled` | boolean | no | GitLab will periodically run `git fsck` in all project and wiki repositories to look for silent disk corruption issues. | | `repository_size_limit` | integer | no | **(PREMIUM)** Size limit per repository (MB) | -| `repository_storages` | array of strings | no | (GitLab 13.0 and earlier) List of names of enabled storage paths, taken from `gitlab.yml`. New projects are created in one of these stores, chosen at random. | | `repository_storages_weighted` | hash of strings to integers | no | (GitLab 13.1 and later) Hash of names of taken from `gitlab.yml` to weights. New projects are created in one of these stores, chosen by a weighted random selection. | +| `repository_storages` | array of strings | no | (GitLab 13.0 and earlier) List of names of enabled storage paths, taken from `gitlab.yml`. New projects are created in one of these stores, chosen at random. | | `require_two_factor_authentication` | boolean | no | (**If enabled, requires:** `two_factor_grace_period`) Require all users to set up Two-factor authentication. | | `restricted_visibility_levels` | array of strings | no | Selected levels cannot be used by non-admin users for groups, projects or snippets. Can take `private`, `internal` and `public` as a parameter. Default is `null` which means there is no restriction. | | `rsa_key_restriction` | integer | no | The minimum allowed bit length of an uploaded RSA key. Default is `0` (no restriction). `-1` disables RSA keys. | @@ -326,21 +334,22 @@ are listed in the descriptions of the relevant settings. | `shared_runners_enabled` | boolean | no | (**If enabled, requires:** `shared_runners_text` and `shared_runners_minutes`) Enable shared runners for new projects. | | `shared_runners_minutes` | integer | required by: `shared_runners_enabled` | **(PREMIUM)** Set the maximum number of pipeline minutes that a group can use on shared Runners per month. | | `shared_runners_text` | string | required by: `shared_runners_enabled` | Shared runners text. | -| `signin_enabled` | string | no | (Deprecated: Use `password_authentication_enabled_for_web` instead) Flag indicating if password authentication is enabled for the web interface. | | `sign_in_text` | string | no | Text on the login page. | +| `signin_enabled` | string | no | (Deprecated: Use `password_authentication_enabled_for_web` instead) Flag indicating if password authentication is enabled for the web interface. | | `signup_enabled` | boolean | no | Enable registration. Default is `true`. | | `slack_app_enabled` | boolean | no | **(PREMIUM)** (**If enabled, requires:** `slack_app_id`, `slack_app_secret` and `slack_app_secret`) Enable Slack app. | | `slack_app_id` | string | required by: `slack_app_enabled` | **(PREMIUM)** The app ID of the Slack-app. | | `slack_app_secret` | string | required by: `slack_app_enabled` | **(PREMIUM)** The app secret of the Slack-app. | | `slack_app_verification_token` | string | required by: `slack_app_enabled` | **(PREMIUM)** The verification token of the Slack-app. | +| `snippet_size_limit` | integer | no | Max snippet content size in **bytes**. Default: 52428800 Bytes (50MB).| +| `snowplow_app_id` | string | no | The Snowplow site name / application ID. (for example, `gitlab`) | | `snowplow_collector_hostname` | string | required by: `snowplow_enabled` | The Snowplow collector hostname. (for example, `snowplow.trx.gitlab.net`) | | `snowplow_cookie_domain` | string | no | The Snowplow cookie domain. (for example, `.gitlab.com`) | | `snowplow_enabled` | boolean | no | Enable snowplow tracking. | -| `snowplow_app_id` | string | no | The Snowplow site name / application ID. (for example, `gitlab`) | | `snowplow_iglu_registry_url` | string | no | The Snowplow base Iglu Schema Registry URL to use for custom context and self describing events'| | `sourcegraph_enabled` | boolean | no | Enables Sourcegraph integration. Default is `false`. **If enabled, requires** `sourcegraph_url`. | -| `sourcegraph_url` | string | required by: `sourcegraph_enabled` | The Sourcegraph instance URL for integration. | | `sourcegraph_public_only` | boolean | no | Blocks Sourcegraph from being loaded on private and internal projects. Default is `true`. | +| `sourcegraph_url` | string | required by: `sourcegraph_enabled` | The Sourcegraph instance URL for integration. | | `spam_check_endpoint_enabled` | boolean | no | Enables Spam Check via external API endpoint. Default is `false`. | | `spam_check_endpoint_url` | string | no | URL of the external Spam Check service endpoint. | | `terminal_max_session_time` | integer | no | Maximum time for web terminal websocket connection (in seconds). Set to `0` for unlimited time. | @@ -366,6 +375,4 @@ are listed in the descriptions of the relevant settings. | `user_show_add_ssh_key_message` | boolean | no | When set to `false` disable the "You won't be able to pull or push project code via SSH" warning shown to users with no uploaded SSH key. | | `version_check_enabled` | boolean | no | Let GitLab inform you when an update is available. | | `web_ide_clientside_preview_enabled` | boolean | no | Live Preview (allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview). | -| `snippet_size_limit` | integer | no | Max snippet content size in **bytes**. Default: 52428800 Bytes (50MB).| -| `issues_create_limit` | integer | no | Max number of issue creation requests per minute per user. Default: 300. To disable throttling set to 0.| -| `raw_blob_request_limit` | integer | no | Max number of requests per minute for each raw path. Default: 300. To disable throttling set to 0.| +| `wiki_page_max_content_bytes` | integer | no | Maximum wiki page content size in **bytes**. Default: 52428800 Bytes (50 MB). The minimum value is 1024 bytes. | diff --git a/doc/api/sidekiq_metrics.md b/doc/api/sidekiq_metrics.md index 8523ac88e00..95acc992789 100644 --- a/doc/api/sidekiq_metrics.md +++ b/doc/api/sidekiq_metrics.md @@ -1,6 +1,6 @@ # Sidekiq Metrics API ->**Note:** This endpoint is only available on GitLab 8.9 and above. +> Introduced in GitLab 8.9. This API endpoint allows you to retrieve some information about the current state of Sidekiq, its jobs, queues, and processes. diff --git a/doc/api/snippets.md b/doc/api/snippets.md index db94716c2d4..0cdc07b1f46 100644 --- a/doc/api/snippets.md +++ b/doc/api/snippets.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Editor +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Snippets API > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/6373) in GitLab 8.15. diff --git a/doc/api/suggestions.md b/doc/api/suggestions.md index e3bbcaa51c3..10528fe33b9 100644 --- a/doc/api/suggestions.md +++ b/doc/api/suggestions.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Suggest Changes API Every API call to suggestions must be authenticated. diff --git a/doc/api/tags.md b/doc/api/tags.md index 569271d6206..cf6cfd25dbb 100644 --- a/doc/api/tags.md +++ b/doc/api/tags.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Source Code +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Tags API ## List project repository tags diff --git a/doc/api/templates/dockerfiles.md b/doc/api/templates/dockerfiles.md index a2c21ada05b..2fa3d7b7fa1 100644 --- a/doc/api/templates/dockerfiles.md +++ b/doc/api/templates/dockerfiles.md @@ -92,6 +92,10 @@ Example response: "key": "Ruby-alpine", "name": "Ruby-alpine" }, + { + "key": "Rust", + "name": "Rust" + }, { "key": "Swift", "name": "Swift" diff --git a/doc/api/templates/gitignores.md b/doc/api/templates/gitignores.md index 6e2e3e2d07f..3acd666ad66 100644 --- a/doc/api/templates/gitignores.md +++ b/doc/api/templates/gitignores.md @@ -2,7 +2,7 @@ type: reference --- -# `.gitignore` API +# .gitignore API In GitLab, there is an API endpoint available for `.gitignore`. For more information on `gitignore`, see the diff --git a/doc/api/templates/gitlab_ci_ymls.md b/doc/api/templates/gitlab_ci_ymls.md index 816061c6235..dfe22fc453e 100644 --- a/doc/api/templates/gitlab_ci_ymls.md +++ b/doc/api/templates/gitlab_ci_ymls.md @@ -1,4 +1,7 @@ --- +stage: Verify +group: Continuous Integration +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers type: reference --- @@ -8,9 +11,9 @@ In GitLab, there is an API endpoint available to work with GitLab CI/CD YMLs. Fo information on CI/CD pipeline configuration in GitLab, see the [configuration reference documentation](../../ci/yaml/README.md). -## List GitLab CI YML templates +## List GitLab CI YAML templates -Get all GitLab CI/CD YML templates. +Get all GitLab CI/CD YAML templates. ```plaintext GET /templates/gitlab_ci_ymls @@ -19,7 +22,7 @@ GET /templates/gitlab_ci_ymls Example request: ```shell -curl https://gitlab.example.com/api/v4/templates/gitlab_ci_ymls +curl "https://gitlab.example.com/api/v4/templates/gitlab_ci_ymls" ``` Example response: @@ -109,9 +112,9 @@ Example response: ] ``` -## Single GitLab CI YML template +## Single GitLab CI YAML template -Get a single GitLab CI/CD YML template. +Get a single GitLab CI/CD YAML template. ```plaintext GET /templates/gitlab_ci_ymls/:key @@ -119,12 +122,12 @@ GET /templates/gitlab_ci_ymls/:key | Attribute | Type | Required | Description | | ---------- | ------ | -------- | ------------------------------------- | -| `key` | string | yes | The key of the GitLab CI/CD YML template | +| `key` | string | yes | The key of the GitLab CI/CD YAML template | Example request: ```shell -curl https://gitlab.example.com/api/v4/templates/gitlab_ci_ymls/Ruby +curl "https://gitlab.example.com/api/v4/templates/gitlab_ci_ymls/Ruby" ``` Example response: diff --git a/doc/api/templates/licenses.md b/doc/api/templates/licenses.md index f66fb70e108..4eb3c0f6111 100644 --- a/doc/api/templates/licenses.md +++ b/doc/api/templates/licenses.md @@ -120,7 +120,7 @@ GET /templates/licenses/:key | `project` | string | no | The copyrighted project name | | `fullname` | string | no | The full-name of the copyright holder | ->**Note:** +NOTE: **Note:** If you omit the `fullname` parameter but authenticate your request, the name of the authenticated user will be used to replace the copyright holder placeholder. diff --git a/doc/api/users.md b/doc/api/users.md index 505468945cb..76075e8b7be 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -314,7 +314,8 @@ Example Responses: "current_sign_in_ip": "196.165.1.102", "last_sign_in_ip": "172.127.2.22", "plan": "gold", - "trial": true + "trial": true, + "sign_in_count": 1337 } ``` @@ -1053,6 +1054,10 @@ curl --request DELETE --header "PRIVATE-TOKEN: " "https://git Get a list of currently authenticated user's emails. +NOTE: **Note:** +Due to [a bug](https://gitlab.com/gitlab-org/gitlab/-/issues/25077) this endpoint currently +does not return the primary email address. + ```plaintext GET /user/emails ``` @@ -1078,6 +1083,10 @@ Parameters: Get a list of a specified user's emails. Available only for admin +NOTE: **Note:** +Due to [a bug](https://gitlab.com/gitlab-org/gitlab/-/issues/25077) this endpoint currently +does not return the primary email address. + ```plaintext GET /users/:id/emails ``` @@ -1284,6 +1293,7 @@ Example response: [ { "active" : true, + "user_id" : 2, "scopes" : [ "api" ], @@ -1296,6 +1306,7 @@ Example response: }, { "active" : false, + "user_id" : 2, "scopes" : [ "read_user" ], @@ -1335,6 +1346,7 @@ Example response: ```json { "active" : true, + "user_id" : 2, "scopes" : [ "api" ], @@ -1378,6 +1390,7 @@ Example response: { "id" : 2, "revoked" : false, + "user_id" : 2, "scopes" : [ "api" ], diff --git a/doc/api/version.md b/doc/api/version.md index 661fdfb4b03..3c6feaae071 100644 --- a/doc/api/version.md +++ b/doc/api/version.md @@ -1,6 +1,6 @@ # Version API ->**Note:** This feature was introduced in GitLab 8.13 +> Introduced in GitLab 8.13. Retrieve version information for this GitLab instance. Responds `200 OK` for authenticated users. diff --git a/doc/api/visual_review_discussions.md b/doc/api/visual_review_discussions.md index bcbfdbdc6d0..c9863784038 100644 --- a/doc/api/visual_review_discussions.md +++ b/doc/api/visual_review_discussions.md @@ -1,3 +1,10 @@ +--- +stage: Verify +group: Testing +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +type: reference, api +--- + # Visual Review discussions API **(STARTER)** > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18710) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.5. diff --git a/doc/api/vulnerabilities.md b/doc/api/vulnerabilities.md index 70f29d961e3..a0d871af127 100644 --- a/doc/api/vulnerabilities.md +++ b/doc/api/vulnerabilities.md @@ -6,7 +6,7 @@ NOTE: **Note:** The former Vulnerabilities API was renamed to Vulnerability Findings API and its documentation was moved to [a different location](vulnerability_findings.md). This document now describes the new Vulnerabilities API that provides access to -[Standalone Vulnerabilities](https://gitlab.com/groups/gitlab-org/-/epics/634). +[Vulnerabilities](https://gitlab.com/groups/gitlab-org/-/epics/634). CAUTION: **Caution:** This API is in an alpha stage and considered unstable. diff --git a/doc/api/vulnerability_findings.md b/doc/api/vulnerability_findings.md index e21d903e474..96171f0229d 100644 --- a/doc/api/vulnerability_findings.md +++ b/doc/api/vulnerability_findings.md @@ -4,7 +4,7 @@ NOTE: **Note:** This API resource is renamed from Vulnerabilities to Vulnerability Findings because the Vulnerabilities are reserved -for serving the upcoming [Standalone Vulnerability objects](https://gitlab.com/gitlab-org/gitlab/-/issues/13561). +for serving [Vulnerability objects](https://gitlab.com/gitlab-org/gitlab/-/issues/13561). To fix any broken integrations with the former Vulnerabilities API, change the `vulnerabilities` URL part to be `vulnerability_findings`. diff --git a/doc/api/wikis.md b/doc/api/wikis.md index f7595e7efe6..7d16a5a38ee 100644 --- a/doc/api/wikis.md +++ b/doc/api/wikis.md @@ -1,3 +1,10 @@ +--- +stage: Create +group: Knowledge +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers" +type: reference, api +--- + # Wikis API > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13372) in GitLab 10.0. diff --git a/doc/articles/index.md b/doc/articles/index.md index 7fc4c18f771..4b965b0256f 100644 --- a/doc/articles/index.md +++ b/doc/articles/index.md @@ -1,18 +1,5 @@ --- -comments: false +redirect_to: '../topics/index.md' --- -# Technical articles list (deprecated) - -Technical articles are -topic-related documentation, written with a user-friendly approach and language, aiming -to provide the community with guidance on specific processes to achieve certain objectives. - -The list of technical articles was [deprecated](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41138) in favor of having them linked from their topic-related documentation: - -- [Git](../topics/git/index.md) -- [GitLab administrator](../administration/index.md) -- [GitLab CI/CD](../ci/README.md) -- [GitLab Pages](../user/project/pages/index.md) -- [GitLab user](../user/index.md) -- [Install GitLab](../install/README.md) +This document was moved to [another location](../topics/index.md) diff --git a/doc/ci/README.md b/doc/ci/README.md index 43e66adbd35..6f15fa52550 100644 --- a/doc/ci/README.md +++ b/doc/ci/README.md @@ -63,7 +63,7 @@ the following documents: If you're migrating from another CI/CD tool, check out our handy references: - [Migrating from CircleCI](migration/circleci.md) -- [Migrating from Jenkins](jenkins/index.md) +- [Migrating from Jenkins](migration/jenkins.md) You can also get started by using one of the [`.gitlab-ci.yml` templates](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/lib/gitlab/ci/templates) diff --git a/doc/ci/ci_cd_for_external_repos/github_integration.md b/doc/ci/ci_cd_for_external_repos/github_integration.md index 5365ef49944..dc1135742ea 100644 --- a/doc/ci/ci_cd_for_external_repos/github_integration.md +++ b/doc/ci/ci_cd_for_external_repos/github_integration.md @@ -23,7 +23,7 @@ cannot be used to authenticate with GitHub as an external CI/CD repository. NOTE: **Note:** Personal access tokens can only be used to connect GitHub.com -repositories to GitLab, and the GitHub user must have the [owner role](https://help.github.com/en/github/getting-started-with-github/access-permissions-on-github). +repositories to GitLab, and the GitHub user must have the [owner role](https://docs.github.com/en/github/getting-started-with-github/access-permissions-on-github). To perform a one-off authorization with GitHub to grant GitLab access your repositories: diff --git a/doc/ci/cloud_deployment/index.md b/doc/ci/cloud_deployment/index.md index 29ce8bdf625..355bc7813d9 100644 --- a/doc/ci/cloud_deployment/index.md +++ b/doc/ci/cloud_deployment/index.md @@ -81,11 +81,12 @@ path to point to your ECR image. ### Deploy your application to the AWS Elastic Container Service (ECS) -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207962) in GitLab 12.9. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207962) in GitLab 12.9. +> - The `Deploy-ECS.gitlab-ci.yml` template was [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/220821) to `AWS/Deploy-ECS.gitlab-ci.yml` in GitLab 13.2. GitLab provides a series of [CI templates that you can include in your project](../yaml/README.md#include). To automate deployments of your application to your [Amazon Elastic Container Service](https://aws.amazon.com/ecs/) (AWS ECS) -cluster, you can `include` the `Deploy-ECS.gitlab-ci.yml` template in your `.gitlab-ci.yml` file. +cluster, you can `include` the `AWS/Deploy-ECS.gitlab-ci.yml` template in your `.gitlab-ci.yml` file. GitLab also provides [Docker images](https://gitlab.com/gitlab-org/cloud-deploy/-/tree/master/aws) that can be used in your `gitlab-ci.yml` file to simplify working with AWS: @@ -96,11 +97,25 @@ Before getting started with this process, you need a cluster on AWS ECS, as well components, like an ECS service, ECS task definition, a database on AWS RDS, etc. [Read more about AWS ECS](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html). -After you're all set up on AWS ECS, follow these steps: +The ECS task definition can be: + +- An existing task definition in AWS ECS +- A JSON file containing a task definition. Create the JSON file by using the template provided in + the [AWS documentation](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/create-task-definition.html#task-definition-template). + Copy the task definition into a new file in your project, for example `/ci/aws/task-definition.json`. + [Available](https://gitlab.com/gitlab-org/gitlab/-/issues/222618) in GitLab 13.3 and later. + +After you have these prerequisites ready, follow these steps: 1. Make sure your AWS credentials are set up as environment variables for your project. You can follow [the steps above](#run-aws-commands-from-gitlab-cicd) to complete this setup. -1. Add these variables to your project's `.gitlab-ci.yml` file: +1. Add these variables to your project's `.gitlab-ci.yml` file, or in the project's + [CI/CD settings](../variables/README.md#create-a-custom-variable-in-the-ui): + + - `CI_AWS_ECS_CLUSTER`: The name of the AWS ECS cluster that you're targeting for your deployments. + - `CI_AWS_ECS_SERVICE`: The name of the targeted service tied to your AWS ECS cluster. + - `CI_AWS_ECS_TASK_DEFINITION`: The name of an existing task definition in ECS tied + to the service mentioned above. ```yaml variables: @@ -109,19 +124,37 @@ After you're all set up on AWS ECS, follow these steps: CI_AWS_ECS_TASK_DEFINITION: my-task-definition ``` - Three variables are defined in this snippet: - - - `CI_AWS_ECS_CLUSTER`: The name of your AWS ECS cluster that you're - targeting for your deployments. - - `CI_AWS_ECS_SERVICE`: The name of the targeted service tied to - your AWS ECS cluster. - - `CI_AWS_ECS_TASK_DEFINITION`: The name of the task definition tied - to the service mentioned above. - You can find these names after selecting the targeted cluster on your [AWS ECS dashboard](https://console.aws.amazon.com/ecs/home): ![AWS ECS dashboard](../img/ecs_dashboard_v12_9.png) + Alternatively, if you want to use a task definition defined in a JSON file, use + `CI_AWS_ECS_TASK_DEFINITION_FILE` instead: + + ```yaml + variables: + CI_AWS_ECS_CLUSTER: my-cluster + CI_AWS_ECS_SERVICE: my-service + CI_AWS_ECS_TASK_DEFINITION_FILE: ci/aws/my_task_definition.json + ``` + + You can create your `CI_AWS_ECS_TASK_DEFINITION_FILE` variable as a + [file-typed environment variable](../variables/README.md#custom-environment-variables-of-type-file) instead of a + regular environment variable. If you choose to do so, set the variable value to be the full contents of + the JSON task definition. You can then remove the JSON file from your project. + + In both cases, make sure that the value for the `containerDefinitions[].name` attribute is + the same as the `Container name` defined in your targeted ECS service. + + CAUTION: **Warning:** + `CI_AWS_ECS_TASK_DEFINITION_FILE` takes precedence over `CI_AWS_ECS_TASK_DEFINITION` if both these environment + variables are defined within your project. + + NOTE: **Note:** + If the name of the task definition you wrote in your JSON file is the same name + as an existing task definition on AWS, then a new revision is created for it. + Otherwise, a brand new task definition is created, starting at revision 1. + 1. Include this template in `.gitlab-ci.yml`: ```yaml @@ -129,12 +162,15 @@ After you're all set up on AWS ECS, follow these steps: - template: AWS/Deploy-ECS.gitlab-ci.yml ``` - The `Deploy-ECS` template ships with GitLab and is available [on + The `AWS/Deploy-ECS` template ships with GitLab and is available [on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml). 1. Commit and push your updated `.gitlab-ci.yml` to your project's repository, and you're done! Your application Docker image will be rebuilt and pushed to the GitLab registry. + If your image is located in a private registry, make sure your task definition is + [configured with a `repositoryCredentials` attribute](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/private-auth.html). + Then the targeted task definition will be updated with the location of the new Docker image, and a new revision will be created in ECS as result. @@ -143,17 +179,17 @@ After you're all set up on AWS ECS, follow these steps: application. CAUTION: **Warning:** -The [`Deploy-ECS.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml) +The [`AWS/Deploy-ECS.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml) template includes both the [`Jobs/Build.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml) and [`Jobs/Deploy/ECS.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml) "sub-templates". Do not include these "sub-templates" on their own, and only include the main -`Deploy-ECS.gitlab-ci.yml` template. The "sub-templates" are designed to only be +`AWS/Deploy-ECS.gitlab-ci.yml` template. The "sub-templates" are designed to only be used along with the main template. They may move or change unexpectedly causing your pipeline to fail if you didn't include the main template. Also, the job names within these templates may change. Do not override these jobs names in your own pipeline, as the override will stop working when the name changes. -Alternatively, if you don't wish to use the `Deploy-ECS.gitlab-ci.yml` template +Alternatively, if you don't wish to use the `AWS/Deploy-ECS.gitlab-ci.yml` template to deploy to AWS ECS, you can always use our `aws-base` Docker image to run your own [AWS CLI commands for ECS](https://docs.aws.amazon.com/cli/latest/reference/ecs/index.html#cli-aws-ecs). diff --git a/doc/ci/directed_acyclic_graph/index.md b/doc/ci/directed_acyclic_graph/index.md index b7dd74a0230..8fc58df51fe 100644 --- a/doc/ci/directed_acyclic_graph/index.md +++ b/doc/ci/directed_acyclic_graph/index.md @@ -84,6 +84,7 @@ are certain use cases that you may need to work around. For more information: > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/215517) in GitLab 13.1 as a [Beta feature](https://about.gitlab.com/handbook/product/#beta). > - It was deployed behind a feature flag, disabled by default. > - It became [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36802) in 13.2. +> - It became a [standard feature](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38517) in 13.3. > - It's enabled on GitLab.com. > - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-dag-visualization-core-only). @@ -97,9 +98,7 @@ Clicking a node will highlight all the job paths it depends on. ### Enable or disable DAG Visualization **(CORE ONLY)** -DAG Visualization is under development, but is being made available as a beta feature so users can check its limitations and uses. - -It is deployed behind a feature flag that is **enabled by default**. +DAG Visualization is deployed behind a feature flag that is **enabled by default**. [GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md) can opt to disable it for your instance: diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md index 4bed6d9e323..88d6dc3aae4 100644 --- a/doc/ci/docker/using_docker_build.md +++ b/doc/ci/docker/using_docker_build.md @@ -32,7 +32,7 @@ during jobs. ## Runner Configuration There are three methods to enable the use of `docker build` and `docker run` -during jobs; each with their own tradeoffs. +during jobs, each with their own tradeoffs. An alternative to using `docker build` is to [use kaniko](using_kaniko.md). This avoids having to execute Runner in privileged mode. @@ -61,8 +61,8 @@ GitLab Runner then executes job scripts as the `gitlab-runner` user. 1. Install Docker Engine on server. - For more information how to install Docker Engine on different systems - checkout the [Supported installations](https://docs.docker.com/engine/installation/). + For more information how to install Docker Engine on different systems, + check out the [Supported installations](https://docs.docker.com/engine/installation/). 1. Add `gitlab-runner` user to `docker` group: @@ -118,13 +118,13 @@ not without its own challenges: - When using Docker-in-Docker, each job is in a clean environment without the past history. Concurrent jobs work fine because every build gets its own - instance of Docker engine so they won't conflict with each other. But this + instance of Docker engine so they don't conflict with each other. But this also means that jobs can be slower because there's no caching of layers. - By default, Docker 17.09 and higher uses `--storage-driver overlay2` which is the recommended storage driver. See [Using the overlayfs driver](#use-the-overlayfs-driver) for details. - Since the `docker:19.03.12-dind` container and the Runner container don't share their - root filesystem, the job's working directory can be used as a mount point for + root file system, the job's working directory can be used as a mount point for child containers. For example, if you have files you want to share with a child container, you may create a subdirectory under `/builds/$CI_PROJECT_PATH` and use it as your mount point (for a more thorough explanation, check [issue @@ -143,8 +143,8 @@ An example project using this approach can be found here: . + certificates inside of that directory. For more information on how + Docker with TLS works, check . - The above command will create a `config.toml` entry similar to this: + The above command creates a `config.toml` entry similar to this: ```toml [[runners]] @@ -215,7 +215,7 @@ support this. image: docker:19.03.12 variables: - # When using dind service, we need to instruct docker, to talk with + # When using dind service, we need to instruct docker to talk with # the daemon started inside of the service. The daemon is available # with a network connection instead of the default # /var/run/docker.sock socket. Docker 19.03 does this automatically @@ -337,13 +337,13 @@ In order to do that, follow the steps: --docker-volumes /var/run/docker.sock:/var/run/docker.sock ``` - The above command will register a new Runner to use the special + The above command registers a new Runner to use the special `docker:19.03.12` image which is provided by Docker. **Notice that it's using the Docker daemon of the Runner itself, and any containers spawned by Docker - commands will be siblings of the Runner rather than children of the Runner.** + commands are siblings of the Runner rather than children of the Runner.** This may have complications and limitations that are unsuitable for your workflow. - The above command will create a `config.toml` entry similar to this: + The above command creates a `config.toml` entry similar to this: ```toml [[runners]] @@ -387,7 +387,7 @@ aware of the following implications: containers. - Concurrent jobs may not work; if your tests create containers with specific names, they may conflict with each other. -- Sharing files and directories from the source repo into containers may not +- Sharing files and directories from the source repository into containers may not work as expected since volume mounting is done in the context of the host machine, not the build container. For example: @@ -397,7 +397,7 @@ aware of the following implications: ## Making Docker-in-Docker builds faster with Docker layer caching -When using Docker-in-Docker, Docker will download all layers of your image every +When using Docker-in-Docker, Docker downloads all layers of your image every time you create a build. Recent versions of Docker (Docker 1.13 and above) can use a pre-existing image as a cache during the `docker build` step, considerably speeding up the build process. @@ -504,7 +504,7 @@ environment variable in the environment = ["DOCKER_DRIVER=overlay2"] ``` -If you're running multiple Runners you will have to modify all configuration files. +If you're running multiple Runners, you have to modify all configuration files. NOTE: **Note:** Read more about the [Runner configuration](https://docs.gitlab.com/runner/configuration/) @@ -523,7 +523,7 @@ This is a common error when you are using [Docker in Docker](#use-docker-in-docker-workflow-with-docker-executor) v19.03 or higher. -This occurs because Docker starts on TLS automatically, so you need to do some set up. +This occurs because Docker starts on TLS automatically, so you need to do some setup. If: - This is the first time setting it up, carefully read diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md index 735cf35584f..db39532bbf2 100644 --- a/doc/ci/docker/using_docker_images.md +++ b/doc/ci/docker/using_docker_images.md @@ -16,12 +16,12 @@ instance. [Docker Hub](https://hub.docker.com/) has a rich database of pre-built used to test and build your applications. When used with GitLab CI/CD, Docker runs each job in a separate and isolated -container using the predefined image that is set up in +container using the predefined image that's set up in [`.gitlab-ci.yml`](../yaml/README.md). This makes it easier to have a simple and reproducible build environment that can also run on your workstation. The added benefit is that you can test all -the commands that we will explore later from your shell, rather than having to +the commands that we explore later from your shell, rather than having to test them on a dedicated CI server. ## Register Docker Runner @@ -54,16 +54,16 @@ sudo gitlab-runner register \ --docker-image ruby:2.6 ``` -The registered runner will use the `ruby:2.6` Docker image and will run two -services, `postgres:latest` and `mysql:latest`, both of which will be +The registered runner uses the `ruby:2.6` Docker image and runs two +services, `postgres:latest` and `mysql:latest`, both of which are accessible during the build process. ## What is an image The `image` keyword is the name of the Docker image the Docker executor -will run to perform the CI tasks. +runs to perform the CI tasks. -By default, the executor will only pull images from [Docker Hub](https://hub.docker.com/), +By default, the executor only pulls images from [Docker Hub](https://hub.docker.com/), however this can be configured in the `gitlab-runner/config.toml` by setting the [Docker pull policy](https://docs.gitlab.com/runner/executors/docker.html#how-pull-policies-work) to allow using local images. @@ -72,16 +72,16 @@ the [Docker Fundamentals](https://docs.docker.com/engine/understanding-docker/) ## What is a service -The `services` keyword defines just another Docker image that is run during +The `services` keyword defines just another Docker image that's run during your job and is linked to the Docker image that the `image` keyword defines. This allows you to access the service image during build time. The service image can run any application, but the most common use case is to -run a database container, e.g., `mysql`. It's easier and faster to use an +run a database container, for example, `mysql`. It's easier and faster to use an existing image and run it as an additional container than install `mysql` every time the project is built. -You are not limited to have only database services. You can add as many +You're not limited to have only database services. You can add as many services you need to `.gitlab-ci.yml` or manually modify `config.toml`. Any image found at [Docker Hub](https://hub.docker.com/) or your private Container Registry can be used as a service. @@ -97,10 +97,10 @@ You can see some widely used services examples in the relevant documentation of To better understand how the container linking works, read [Linking containers together](https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/). -To summarize, if you add `mysql` as service to your application, the image will -then be used to create a container that is linked to the job container. +To summarize, if you add `mysql` as service to your application, the image is +then used to create a container that's linked to the job container. -The service container for MySQL will be accessible under the hostname `mysql`. +The service container for MySQL is accessible under the hostname `mysql`. So, in order to access your database service you have to connect to the host named `mysql` instead of a socket or `localhost`. Read more in [accessing the services](#accessing-the-services). @@ -109,7 +109,7 @@ services](#accessing-the-services). Services are designed to provide additional functionality which is **network accessible**. It may be a database like MySQL, or Redis, and even `docker:stable-dind` which -allows you to use Docker in Docker. It can be practically anything that is +allows you to use Docker in Docker. It can be practically anything that's required for the CI/CD job to proceed and is accessed by network. To make sure this works, the Runner: @@ -121,8 +121,8 @@ When the second stage of the check fails, either because there is no opened port service, or the service was not started properly before the timeout and the port is not responding, it prints the warning: `*** WARNING: Service XYZ probably didn't start properly`. -In most cases it will affect the job, but there may be situations when the job -will still succeed even if that warning was printed. For example: +In most cases it affects the job, but there may be situations when the job +still succeeds even if that warning was printed. For example: - The service was started a little after the warning was raised, and the job is not using the linked service from the beginning. In that case, when the @@ -130,8 +130,8 @@ will still succeed even if that warning was printed. For example: connections. - The service container is not providing any networking service, but it's doing something with the job's directory (all services have the job directory mounted - as a volume under `/builds`). In that case, the service will do its job, and - since the job is not trying to connect to it, it won't fail. + as a volume under `/builds`). In that case, the service does its job, and + since the job is not trying to connect to it, it does not fail. ### What services are not for @@ -139,12 +139,12 @@ As it was mentioned before, this feature is designed to provide **network access services. A database is the simplest example of such a service. NOTE: **Note:** -The services feature is not designed to, and will not add any software from the +The services feature is not designed to, and does not add any software from the defined `services` image(s) to the job's container. For example, if you have the following `services` defined in your job, the `php`, -`node` or `go` commands will **not** be available for your script, and thus -the job will fail: +`node` or `go` commands are **not** available for your script, and thus +the job fails: ```yaml job: @@ -163,7 +163,7 @@ If you need to have `php`, `node` and `go` available for your script, you should either: - Choose an existing Docker image that contains all required tools. -- Create your own Docker image, which will have all the required tools included +- Create your own Docker image, with all the required tools included and use that in your job. ### Accessing the services @@ -180,7 +180,7 @@ services: ``` If you don't [specify a service alias](#available-settings-for-services), -when the job is run, `tutum/wordpress` will be started and you will have +when the job is run, `tutum/wordpress` is started and you have access to it from your build container under two hostnames to choose from: - `tutum-wordpress` @@ -204,7 +204,7 @@ To override the default behavior, you can ## Define `image` and `services` from `.gitlab-ci.yml` -You can simply define an image that will be used for all jobs and a list of +You can simply define an image that's used for all jobs and a list of services that you want to use during build time: ```yaml @@ -228,7 +228,7 @@ The image name must be in one of the following formats: - `image: :` - `image: @` -It is also possible to define different images and services per job: +It's also possible to define different images and services per job: ```yaml default: @@ -280,7 +280,7 @@ to fine tune your Docker `images` and `services` directly in the `.gitlab-ci.yml For more information, see [custom environment variables](../variables/README.md#gitlab-ciyml-defined-variables) ```yaml -# The following variables will automatically be passed down to the Postgres container +# The following variables are automatically passed down to the Postgres container # as well as the Ruby container and available within each. variables: HTTPS_PROXY: "https://10.1.1.1:8090" @@ -353,7 +353,7 @@ For example, the following two definitions are equal: | Setting | Required | GitLab version | Description | |------------|----------|----------------| ----------- | | `name` | yes, when used with any other option | 9.4 |Full name of the image that should be used. It should contain the Registry part if needed. | -| `entrypoint` | no | 9.4 |Command or script that should be executed as the container's entrypoint. It will be translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) directive, where each shell token is a separate string in the array. | +| `entrypoint` | no | 9.4 |Command or script that should be executed as the container's entrypoint. It's translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) directive, where each shell token is a separate string in the array. | ### Available settings for `services` @@ -362,8 +362,8 @@ For example, the following two definitions are equal: | Setting | Required | GitLab version | Description | |------------|----------|----------------| ----------- | | `name` | yes, when used with any other option | 9.4 | Full name of the image that should be used. It should contain the Registry part if needed. | -| `entrypoint` | no | 9.4 |Command or script that should be executed as the container's entrypoint. It will be translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) directive, where each shell token is a separate string in the array. | -| `command` | no | 9.4 |Command or script that should be used as the container's command. It will be translated to arguments passed to Docker after the image's name. The syntax is similar to [`Dockerfile`'s `CMD`](https://docs.docker.com/engine/reference/builder/#cmd) directive, where each shell token is a separate string in the array. | +| `entrypoint` | no | 9.4 |Command or script that should be executed as the container's entrypoint. It's translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) directive, where each shell token is a separate string in the array. | +| `command` | no | 9.4 |Command or script that should be used as the container's command. It's translated to arguments passed to Docker after the image's name. The syntax is similar to [`Dockerfile`'s `CMD`](https://docs.docker.com/engine/reference/builder/#cmd) directive, where each shell token is a separate string in the array. | | `alias` | no | 9.4 |Additional alias that can be used to access the service from the job's container. Read [Accessing the services](#accessing-the-services) for more information. | NOTE: **Note:** @@ -398,8 +398,8 @@ services: alias: mysql-2 ``` -The Runner will still start two containers using the `mysql:latest` image, -however now each of them will also be accessible with the alias configured +The Runner still starts two containers using the `mysql:latest` image, +however now each of them are also accessible with the alias configured in `.gitlab-ci.yml` file. ### Setting a command for the service @@ -408,7 +408,7 @@ in `.gitlab-ci.yml` file. Let's assume you have a `super/sql:latest` image with some SQL database inside it and you would like to use it as a service for your job. Let's also -assume that this image doesn't start the database process while starting +assume that this image does not start the database process while starting the container and the user needs to manually use `/usr/bin/super-sql run` as a command to start the database. @@ -462,8 +462,8 @@ CI jobs: output. To override the entrypoint of a Docker image, the recommended solution is to -define an empty `entrypoint` in `.gitlab-ci.yml`, so the Runner doesn't start -a useless shell layer. However, that will not work for all Docker versions, and +define an empty `entrypoint` in `.gitlab-ci.yml`, so the Runner does not start +a useless shell layer. However, that does not work for all Docker versions, and you should check which one your Runner is using. Specifically: - If Docker 17.06 or later is used, the `entrypoint` can be set to an empty value. @@ -476,8 +476,8 @@ Let's assume you have a `super/sql:experimental` image with some SQL database inside it and you would like to use it as a base image for your job because you want to execute some tests with this database binary. Let's also assume that this image is configured with `/usr/bin/super-sql run` as an entrypoint. That -means that when starting the container without additional options, it will run -the database's process, while Runner expects that the image will have no +means that when starting the container without additional options, it runs +the database's process, while Runner expects that the image has no entrypoint or that the entrypoint is prepared to start a shell command. With the extended Docker configuration options, instead of creating your @@ -511,7 +511,7 @@ Look for the `[runners.docker]` section: services = ["mysql:latest", "postgres:latest"] ``` -The image and services defined this way will be added to all job run by +The image and services defined this way are added to all job run by that runner. ## Define an image from a private Container Registry @@ -530,12 +530,12 @@ To define which should be used, the GitLab Runner process reads the configuratio - `DOCKER_AUTH_CONFIG` variable provided as environment variable in `config.toml` of the Runner. - `config.json` file placed in `$HOME/.docker` directory of the user running GitLab Runner process. If the `--user` flag is provided to run the GitLab Runner child processes as unprivileged user, - the home directory of the main GitLab Runner process user will be used. + the home directory of the main GitLab Runner process user is used. NOTE: **Note:** GitLab Runner reads this configuration **only** from `config.toml` and ignores it if it's provided as an environment variable. This is because GitLab Runner uses **only** -`config.toml` configuration and doesn't interpolate **ANY** environment variables at +`config.toml` configuration and does not interpolate **ANY** environment variables at runtime. ### Requirements and limitations @@ -593,9 +593,9 @@ There are two ways to determine the value of `DOCKER_AUTH_CONFIG`: ``` - **Second way -** In some setups, it's possible that Docker client - will use the available system key store to store the result of `docker + uses the available system key store to store the result of `docker login`. In that case, it's impossible to read `~/.docker/config.json`, - so you will need to prepare the required base64-encoded version of + so you need to prepare the required base64-encoded version of `${username}:${password}` and create the Docker configuration JSON manually. Open a terminal and execute the following command: @@ -644,7 +644,7 @@ follow these steps: image: registry.example.com:5000/namespace/image:tag ``` - In the example above, GitLab Runner will look at `registry.example.com:5000` for the + In the example above, GitLab Runner looks at `registry.example.com:5000` for the image `namespace/image:tag`. You can add configuration for as many registries as you want, adding more @@ -655,19 +655,19 @@ The full `hostname:port` combination is required everywhere for the Runner to match the `DOCKER_AUTH_CONFIG`. For example, if `registry.example.com:5000/namespace/image:tag` is specified in `.gitlab-ci.yml`, then the `DOCKER_AUTH_CONFIG` must also specify `registry.example.com:5000`. -Specifying only `registry.example.com` will not work. +Specifying only `registry.example.com` does not work. ### Configuring a Runner -If you have many pipelines that access the same registry, it'll -probably be better to setup registry access at the runner level. This +If you have many pipelines that access the same registry, it is +probably better to set up registry access at the runner level. This allows pipeline authors to have access to a private registry just by running a job on the appropriate runner. It also makes registry changes and credential rotations much simpler. Of course this means that any job on that runner can access the registry with the same privilege, even across projects. If you need to -control access to the registry, you'll need to be sure to control +control access to the registry, you need to be sure to control access to the runner. To add `DOCKER_AUTH_CONFIG` to a Runner: @@ -713,14 +713,14 @@ To configure credentials store, follow these steps: } ``` - - Or, if you are running self-managed Runners, add the above JSON to - `${GITLAB_RUNNER_HOME}/.docker/config.json`. GitLab Runner will read this configuration file - and will use the needed helper for this specific repository. + - Or, if you're running self-managed Runners, add the above JSON to + `${GITLAB_RUNNER_HOME}/.docker/config.json`. GitLab Runner reads this configuration file + and uses the needed helper for this specific repository. NOTE: **Note:** `credsStore` is used to access ALL the registries. -If you will want to use both images from private registry and public images from DockerHub, -pulling from DockerHub will fail, because Docker daemon will try to use the same credentials for **ALL** the registries. +If you want to use both images from private registry and public images from DockerHub, +pulling from DockerHub would fail, because Docker daemon tries to use the same credentials for **ALL** the registries. ### Using Credential Helpers @@ -762,9 +762,9 @@ To configure access for `aws_account_id.dkr.ecr.region.amazonaws.com`, follow th This configures Docker to use the credential helper for all Amazon ECR registries. - - Or, if you are running self-managed Runners, + - Or, if you're running self-managed Runners, add the above JSON to `${GITLAB_RUNNER_HOME}/.docker/config.json`. - GitLab Runner will read this configuration file and will use the needed helper for this + GitLab Runner reads this configuration file and uses the needed helper for this specific repository. 1. You can now use any private image from `aws_account_id.dkr.ecr.region.amazonaws.com` defined in @@ -774,7 +774,7 @@ To configure access for `aws_account_id.dkr.ecr.region.amazonaws.com`, follow th image: aws_account_id.dkr.ecr.region.amazonaws.com/private/image:latest ``` - In the example above, GitLab Runner will look at `aws_account_id.dkr.ecr.region.amazonaws.com` for the + In the example above, GitLab Runner looks at `aws_account_id.dkr.ecr.region.amazonaws.com` for the image `private/image:latest`. You can add configuration for as many registries as you want, adding more @@ -792,7 +792,7 @@ For all possible configuration variables check the documentation of each image provided in their corresponding Docker hub page. NOTE: **Note:** -All variables will be passed to all services containers. It's not +All variables are passed to all services containers. It's not designed to distinguish which variable should go where. ### PostgreSQL service example @@ -838,7 +838,7 @@ EOF ``` Here we use as an example the GitLab Runner repository which contains a -Makefile, so running `make` will execute the commands defined in the Makefile. +Makefile, so running `make` executes the commands defined in the Makefile. Your mileage may vary, so instead of `make` you could run the command which is specific to your project. @@ -849,9 +849,9 @@ docker run -d --name service-mysql mysql:latest docker run -d --name service-postgres postgres:latest ``` -This will create two service containers, named `service-mysql` and +This creates two service containers, named `service-mysql` and `service-postgres` which use the latest MySQL and PostgreSQL images -respectively. They will both run in the background (`-d`). +respectively. They both run in the background (`-d`). Finally, create a build container by executing the `build_script` file we created earlier: @@ -860,7 +860,7 @@ created earlier: docker run --name build -i --link=service-mysql:mysql --link=service-postgres:postgres ruby:2.6 /bin/bash < build_script ``` -The above command will create a container named `build` that is spawned from +The above command creates a container named `build` that's spawned from the `ruby:2.6` image and has two services linked to it. The `build_script` is piped using STDIN to the bash interpreter which in turn executes the `build_script` in the `build` container. @@ -872,6 +872,6 @@ with: docker rm -f -v build service-mysql service-postgres ``` -This will forcefully (`-f`) remove the `build` container, the two service +This forcefully (`-f`) removes the `build` container, the two service containers as well as all volumes (`-v`) that were created with the container creation. diff --git a/doc/ci/docker/using_kaniko.md b/doc/ci/docker/using_kaniko.md index 1580080ac6e..41c8f04f66e 100644 --- a/doc/ci/docker/using_kaniko.md +++ b/doc/ci/docker/using_kaniko.md @@ -63,6 +63,7 @@ build: name: gcr.io/kaniko-project/executor:debug entrypoint: [""] script: + - mkdir -p /kaniko/.docker - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG only: diff --git a/doc/ci/environments/deployment_safety.md b/doc/ci/environments/deployment_safety.md index a4ff164a5ba..a0b7adb5279 100644 --- a/doc/ci/environments/deployment_safety.md +++ b/doc/ci/environments/deployment_safety.md @@ -1,3 +1,9 @@ +--- +stage: Release +group: Release Management +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- + # Deployment safety Deployment jobs can be more sensitive than other jobs in a pipeline, diff --git a/doc/ci/examples/authenticating-with-hashicorp-vault/img/vault-read-secrets-production.png b/doc/ci/examples/authenticating-with-hashicorp-vault/img/vault-read-secrets-production.png index 65c8546deb2..16c15071dd7 100644 Binary files a/doc/ci/examples/authenticating-with-hashicorp-vault/img/vault-read-secrets-production.png and b/doc/ci/examples/authenticating-with-hashicorp-vault/img/vault-read-secrets-production.png differ diff --git a/doc/ci/examples/authenticating-with-hashicorp-vault/img/vault-read-secrets-staging.png b/doc/ci/examples/authenticating-with-hashicorp-vault/img/vault-read-secrets-staging.png index 2399d8f8879..7a92a3c2d50 100644 Binary files a/doc/ci/examples/authenticating-with-hashicorp-vault/img/vault-read-secrets-staging.png and b/doc/ci/examples/authenticating-with-hashicorp-vault/img/vault-read-secrets-staging.png differ diff --git a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md index ee0938b4d4c..c27566d38cf 100644 --- a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md +++ b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md @@ -150,7 +150,7 @@ Now, let's clone our repository on the server just to make sure the `deployer` u git clone git@gitlab.example.com:/laravel-sample.git ``` ->**Note:** +NOTE: **Note:** Answer **yes** if asked `Are you sure you want to continue connecting (yes/no)?`. It adds GitLab.com to the known hosts. @@ -174,7 +174,7 @@ server { } ``` ->**Note:** +NOTE: **Note:** You may replace the app's name in `/var/www/app/current/public` with the folder name of your application. ## Setting up Envoy @@ -398,7 +398,7 @@ But let's take a step forward to do it automatically with [Continuous Delivery]( We need to check every commit with a set of automated tests to become aware of issues at the earliest, and then, we can deploy to the target environment if we are happy with the result of the tests. [GitLab CI/CD](../../README.md) allows us to use [Docker](https://www.docker.com) engine to handle the process of testing and deploying our app. -In the case you're not familiar with Docker, refer to [How to Automate Docker Deployments](http://paislee.io/how-to-automate-docker-deployments/). +In case you're not familiar with Docker, refer to [Set up automated builds](https://docs.docker.com/get-started/). To be able to build, test, and deploy our app with GitLab CI/CD, we need to prepare our work environment. To do that, we'll use a Docker image which has the minimum requirements that a Laravel app needs to run. @@ -464,14 +464,14 @@ docker build -t registry.gitlab.com//laravel-sample . docker push registry.gitlab.com//laravel-sample ``` ->**Note:** +NOTE: **Note:** To run the above commands, we first need to have [Docker](https://docs.docker.com/engine/installation/) installed on our machine. Congratulations! You just pushed the first Docker image to the GitLab Registry, and if you refresh the page you should be able to see it: ![container registry page with image](img/container_registry_page_with_image.jpg) ->**Note:** +NOTE: **Note:** You can also [use GitLab CI/CD](https://about.gitlab.com/blog/2016/05/23/gitlab-container-registry/#use-with-gitlab-ci) to build and push your Docker images, rather than doing that on your machine. We'll use this image further down in the `.gitlab-ci.yml` configuration file to handle the process of testing and deploying our app. @@ -551,7 +551,7 @@ services: ... ``` ->**Note:** +NOTE: **Note:** If you wish to test your app with different PHP versions and [database management systems](../../services/README.md), you can define different `image` and `services` keywords for each test job. #### Variables diff --git a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md index c901f6c9c66..f2620461c09 100644 --- a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md +++ b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md @@ -123,7 +123,7 @@ Generated hello_gitlab_ci app The database for HelloGitlabCi.Repo has been created ``` -> **Note:** +NOTE: **Note:** Phoenix assumes that our PostgreSQL database will have a `postgres` user account with the correct permissions and a password of `postgres`. If it's not your case, check [Ecto's instructions](https://hexdocs.pm/ecto/Ecto.html#module-repositories). @@ -211,7 +211,8 @@ when running our Phoenix in our `localhost`. Without `.gitkeep`, Git will not upload this empty directory and we'll got an error when running our test on GitLab. - > **Note:** If we add a folder via the GitLab UI, GitLab itself will add the `.gitkeep` to that new dir. + NOTE: **Note:** + If we add a folder via the GitLab UI, GitLab itself will add the `.gitkeep` to that new dir. Now, let's run a local test and see if everything we did didn't break anything. diff --git a/doc/ci/img/ci_lint.png b/doc/ci/img/ci_lint.png new file mode 100644 index 00000000000..e62de011293 Binary files /dev/null and b/doc/ci/img/ci_lint.png differ diff --git a/doc/ci/img/ci_lint_dry_run.png b/doc/ci/img/ci_lint_dry_run.png new file mode 100644 index 00000000000..4092b66d534 Binary files /dev/null and b/doc/ci/img/ci_lint_dry_run.png differ diff --git a/doc/ci/img/metrics_reports_advanced_v13_0.png b/doc/ci/img/metrics_reports_advanced_v13_0.png index c092c6a84e4..e96fdcf620a 100644 Binary files a/doc/ci/img/metrics_reports_advanced_v13_0.png and b/doc/ci/img/metrics_reports_advanced_v13_0.png differ diff --git a/doc/ci/introduction/index.md b/doc/ci/introduction/index.md index db18624d4e9..c97f4e51d30 100644 --- a/doc/ci/introduction/index.md +++ b/doc/ci/introduction/index.md @@ -230,7 +230,7 @@ syntax and with its attributes. This document [introduces the concepts of GitLab CI/CD in the scope of GitLab Pages](../../user/project/pages/getting_started/pages_from_scratch.md), for deploying static websites. Although it's meant for users who want to write their own Pages script from scratch, it also serves as an introduction to the setup process for GitLab CI/CD. -It covers the very first general steps of writing a CI/CD configuration +It covers the first general steps of writing a CI/CD configuration file, so we recommend you read through it to understand GitLab's CI/CD logic, and learn how to write your own script (or tweak an existing one) for any application. diff --git a/doc/ci/jenkins/index.md b/doc/ci/jenkins/index.md index 1d029dcdd14..34600dd6540 100644 --- a/doc/ci/jenkins/index.md +++ b/doc/ci/jenkins/index.md @@ -1,359 +1,5 @@ --- -stage: Verify -group: Continuous Integration -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers -comments: false -type: index, howto +redirect_to: '../migration/jenkins.md' --- -# Migrating from Jenkins - -A lot of GitLab users have successfully migrated to GitLab CI/CD from Jenkins. To make this -easier if you're just getting started, we've collected several resources here that you might find useful -before diving in. Think of this page as a "GitLab CI/CD for Jenkins Users" guide. - -The following list of recommended steps was created after observing organizations -that were able to quickly complete this migration: - -1. Start by reading the GitLab CI/CD [Quick Start Guide](../quick_start/README.md) and [important product differences](#important-product-differences). -1. Learn the importance of [managing the organizational transition](#managing-the-organizational-transition). -1. [Add Runners](../runners/README.md) to your GitLab instance. -1. Educate and enable your developers to independently perform the following steps in their projects: - 1. Review the [Quick Start Guide](../quick_start/README.md) and [Pipeline Configuration Reference](../yaml/README.md). - 1. Use the [Jenkins Wrapper](#jenkinsfile-wrapper) to temporarily maintain fragile Jenkins jobs. - 1. Migrate the build and CI jobs and configure them to show results directly in your merge requests. They can use [Auto DevOps](../../topics/autodevops/index.md) as a starting point, and [customize](../../topics/autodevops/customize.md) or [decompose](../../topics/autodevops/customize.md#using-components-of-auto-devops) the configuration as needed. - 1. Add [Review Apps](../review_apps/index.md). - 1. Migrate the deployment jobs using [cloud deployment templates](../cloud_deployment/index.md), adding [environments](../environments/index.md), and [deploy boards](../..//user/project/deploy_boards.md). - 1. Work to unwrap any jobs still running with the use of the Jenkins wrapper. -1. Take stock of any common CI/CD job definitions then create and share [templates](#templates) for them. - -For an example of how to convert a Jenkins pipeline into a GitLab CI/CD pipeline, -or how to use Auto DevOps to test your code automatically, watch the -[Migrating from Jenkins to GitLab](https://www.youtube.com/watch?v=RlEVGOpYF5Y) video. - -Otherwise, read on for important information that will help you get the ball rolling. Welcome -to GitLab! - -If you have questions that are not answered here, the [GitLab community forum](https://forum.gitlab.com/) -can be a great resource. - -## Managing the organizational transition - -An important part of transitioning from Jenkins to GitLab is the cultural and organizational -changes that comes with the move, and successfully managing them. There are a few -things we have found that helps this: - -- Setting and communicating a clear vision of what your migration goals are helps - your users understand why the effort is worth it. The value will be clear when - the work is done, but people need to be aware while it's in progress too. -- Sponsorship and alignment from the relevant leadership team helps with the point above. -- Spending time educating your users on what's different, sharing this document with them, - and so on will help ensure you are successful. -- Finding ways to sequence or delay parts of the migration can help a lot, but you - don't want to leave things in a non-migrated (or partially-migrated) state for too - long. To gain all the benefits of GitLab, moving your existing Jenkins setup over - as-is, including any current problems, will not be enough. You need to take advantage - of the improvements that GitLab offers, and this requires (eventually) updating - your implementation as part of the transition. - -## JenkinsFile Wrapper - -We are building a [JenkinsFile Wrapper](https://gitlab.com/gitlab-org/jfr-container-builder/) which will allow -you to run a complete Jenkins instance inside of a GitLab job, including plugins. This can help ease the process -of transition, by letting you delay the migration of less urgent pipelines for a period of time. - -If you are interested in helping GitLab test the wrapper, join our [public testing issue](https://gitlab.com/gitlab-org/gitlab/-/issues/215675) for instructions and to provide your feedback. - -## Important product differences - -There are some high level differences between the products worth mentioning: - -- With GitLab you don't need a root `pipeline` keyword to wrap everything. -- The way pipelines are triggered and [trigger other pipelines](../yaml/README.md#trigger) - is different than Jenkins. GitLab pipelines can be triggered: - - - on push - - on [schedule](../pipelines/schedules.md) - - from the [GitLab UI](../pipelines/index.md#run-a-pipeline-manually) - - by [API call](../triggers/README.md) - - by [webhook](../triggers/README.md#triggering-a-pipeline-from-a-webhook) - - by [ChatOps](../chatops/README.md) - -- You can control which jobs run in which cases, depending on how they are triggered, - with the [`rules` syntax](../yaml/README.md#rules). -- GitLab [pipeline scheduling concepts](../pipelines/schedules.md) are also different than with Jenkins. -- You can reuse pipeline configurations using the [`include` keyword](../yaml/README.md#include) - and [templates](#templates). Your templates can be kept in a central repository (with different - permissions), and then any project can use them. This central project could also - contain scripts or other reusable code. -- You can also use the [`extends` keyword](../yaml/README.md#extends) to reuse configuration - within a single pipeline configuration. -- All jobs within a single stage always run in parallel, and all stages run in sequence. We are planning - to allow certain jobs to break this sequencing as needed with our [directed acyclic graph](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47063) - feature. -- The [`parallel`](../yaml/README.md#parallel) keyword can automatically parallelize tasks, - like tests that support parallelization. -- Normally all jobs within a single stage run in parallel, and all stages run in sequence. - There are different [pipeline architectures](../pipelines/pipeline_architectures.md) - that allow you to change this behavior. -- The new [`rules` syntax](../yaml/README.md#rules) is the recommended method of - controlling when different jobs run. It is more powerful than the `only/except` syntax. -- One important difference is that jobs run independently of each other and have a - fresh environment in each job. Passing artifacts between jobs is controlled using the - [`artifacts`](../yaml/README.md#artifacts) and [`dependencies`](../yaml/README.md#dependencies) - keywords. When finished, the planned [Workspaces](https://gitlab.com/gitlab-org/gitlab/-/issues/29265) - feature will allow you to more easily persist a common workspace between serial jobs. -- The `.gitlab-ci.yml` file is checked in to the root of your repository, much like a Jenkinsfile, but - is in the YAML format (see [complete reference](../yaml/README.md)) instead of a Groovy DSL. It's most - analogous to the declarative Jenkinsfile format. -- Manual approvals or gates can be set up as [`when:manual` jobs](../yaml/README.md#whenmanual). These can - also leverage [`protected environments`](../yaml/README.md#protecting-manual-jobs-premium) - to control who is able to approve them. -- GitLab comes with a [container registry](../../user/packages/container_registry/index.md), and we recommend using - container images to set up your build environment. For example, set up one pipeline that builds your build environment - itself and publish that to the container registry. Then, have your pipelines use this instead of each building their - own environment, which will be slower and may be less consistent. We have extensive docs on [how to use the Container Registry](../../user/packages/container_registry/index.md). -- A central utilities repository can be a great place to put assorted scheduled jobs - or other manual jobs that function like utilities. Jenkins installations tend to - have a few of these. - -## Agents vs. Runners - -Both Jenkins agents and GitLab Runners are the hosts that run jobs. To convert the -Jenkins agent, simply uninstall it and then [install and register the runner](../runners/README.md). -Runners do not require much overhead, so you can size them similarly to the Jenkins -agents you were using. - -There are some important differences in the way Runners work in comparison to agents: - -- Runners can be set up as [shared across an instance, be added at the group level, or set up at the project level](../runners/README.md#types-of-runners). - They will self-select jobs from the scopes you've defined automatically. -- You can also [use tags](../runners/README.md#use-tags-to-limit-the-number-of-jobs-using-the-runner) for finer control, and - associate runners with specific jobs. For example, you can use a tag for jobs that - require dedicated, more powerful, or specific hardware. -- GitLab has [autoscaling for Runners](https://docs.gitlab.com/runner/configuration/autoscale.html) - which will let you configure them to be provisioned as needed, and scaled down when not. - This is similar to ephemeral agents in Jenkins. - -If you are using `gitlab.com`, you can take advantage of our [shared Runner fleet](../../user/gitlab_com/index.md#shared-runners) -to run jobs without provisioning your own Runners. We are investigating making them -[available for self-managed instances](https://gitlab.com/groups/gitlab-org/-/epics/835) -as well. - -## Groovy vs. YAML - -Jenkins Pipelines are based on [Groovy](https://groovy-lang.org/), so the pipeline specification is written as code. -GitLab works a bit differently, we use the more highly structured [YAML](https://yaml.org/) format, which -places scripting elements inside of `script:` blocks separate from the pipeline specification itself. - -This is a strength of GitLab, in that it helps keep the learning curve much simpler to get up and running -and avoids some of the problem of unconstrained complexity which can make your Jenkinsfile hard to understand -and manage. - -That said, we do of course still value DRY (don't repeat yourself) principles and want to ensure that -behaviors of your jobs can be codified once and applied as needed. You can use the `extends:` syntax to -[reuse configuration in your jobs](../yaml/README.md#extends), and `include:` can -be used to [reuse pipeline configurations](../yaml/README.md#include) in pipelines -in different projects: - -```yaml -.in-docker: - tags: - - docker - image: alpine - -rspec: - extends: - - .in-docker - script: - - rake rspec -``` - -## Artifact publishing - -Artifacts may work a bit differently than you've used them with Jenkins. In GitLab, any job can define -a set of artifacts to be saved by using the `artifacts:` keyword. This can be configured to point to a file -or set of files that can then be persisted from job to job. Read more on our detailed -[artifacts documentation](../pipelines/job_artifacts.md): - -```yaml -pdf: - script: xelatex mycv.tex - artifacts: - paths: - - ./mycv.pdf - - ./output/ - expire_in: 1 week -``` - -Additionally, we have package management features like a built-in container, NPM, and Maven registry that you -can leverage. You can see the complete list of packaging features (which includes links to documentation) -in the [Packaging section of our documentation](../../README.md#package). - -## Integrated features - -Where you may have used plugins to get things like code quality, unit tests, security scanning, and so on working in Jenkins, -GitLab takes advantage of our connected ecosystem to automatically pull these kinds of results into -your Merge Requests, pipeline details pages, and other locations. You may find that you actually don't -need to configure anything to have these appear. - -If they aren't working as expected, or if you'd like to see what's available, our [CI feature index](../README.md#feature-set) has the full list -of bundled features and links to the documentation for each. - -### Templates - -For advanced CI/CD teams, project templates can enable the reuse of pipeline configurations, -as well as encourage inner sourcing. - -In self-managed GitLab instances, you can build an [Instance Template Repository](../../user/admin_area/settings/instance_template_repository.md). -Development teams across the whole organization can select templates from a dropdown menu. -A group administrator is able to set a group to use as the source for the -[custom project templates](../../user/admin_area/custom_project_templates.md), which can -be used by all projects in the group. An instance administrator can set a group as -the source for [instance project templates](../../user/group/custom_project_templates.md), -which can be used by projects in that instance. - -## Converting a declarative Jenkinsfile - -A declarative Jenkinsfile contains "Sections" and "Directives" which are used to control the behavior of your -pipelines. There are equivalents for all of these in GitLab, which we've documented below. - -This section is based on the [Jenkinsfile syntax documentation](https://www.jenkins.io/doc/book/pipeline/syntax/) -and is meant to be a mapping of concepts there to concepts in GitLab. - -### Sections - -#### `agent` - -The agent section is used to define how a pipeline will be executed. For GitLab, we use the [GitLab Runner](../runners/README.md) -to provide this capability. You can configure your own runners in Kubernetes or on any host, or take advantage -of our shared runner fleet (note that the shared runner fleet is only available for GitLab.com users.) The link above will bring you to the documentation which will describe how to get -up and running quickly. We also support using [tags](../runners/README.md#use-tags-to-limit-the-number-of-jobs-using-the-runner) to direct different jobs -to different Runners (execution agents). - -The `agent` section also allows you to define which Docker images should be used for execution, for which we use -the [`image`](../yaml/README.md#image) keyword. The `image` can be set on a single job or at the top level, in which -case it will apply to all jobs in the pipeline: - -```yaml -my_job: - image: alpine - ... -``` - -#### `post` - -The `post` section defines the actions that should be performed at the end of the pipeline. GitLab also supports -this through the use of stages. You can define your stages as follows, and any jobs assigned to the `before_pipeline` -or `after_pipeline` stages will run as expected. You can call these stages anything you like: - -```yaml -stages: - - before_pipeline - - build - - test - - deploy - - after_pipeline -``` - -Setting a step to be performed before and after any job can be done via the -[`before_script` and `after_script` keywords](../yaml/README.md#before_script-and-after_script): - -```yaml -default: - before_script: - - echo "I run before any jobs starts in the entire pipeline, and can be responsible for setting up the environment." -``` - -#### `stages` - -GitLab CI/CD also lets you define stages, but is a little bit more free-form to configure. The GitLab [`stages` keyword](../yaml/README.md#stages) -is a top level setting that enumerates the list of stages, but you are not required to nest individual jobs underneath -the `stages` section. Any job defined in the `.gitlab-ci.yml` can be made a part of any stage through use of the -[`stage:` keyword](../yaml/README.md#stage). - -Note that, unless otherwise specified, every pipeline is instantiated with a `build`, `test`, and `deploy` stage -which are run in that order. Jobs that have no `stage` defined are placed by default in the `test` stage. -Of course, each job that refers to a stage must refer to a stage that exists in the pipeline configuration. - -```yaml -stages: - - build - - test - - deploy - -my_job: - stage: build - ... -``` - -#### `steps` - -The `steps` section is equivalent to the [`script` section](../yaml/README.md#script) of an individual job. This is -a simple YAML array with each line representing an individual command to be run: - -```yaml -my_job: - script: - - echo "hello! the current time is:" - - time - ... -``` - -### Directives - -#### `environment` - -In GitLab, we use the [`variables` keyword](../yaml/README.md#variables) to define different variables at runtime. -These can also be set up through the GitLab UI, under CI/CD settings. See also our [general documentation on variables](../variables/README.md), -including the section on [protected variables](../variables/README.md#protect-a-custom-variable) which can be used -to limit access to certain variables to certain environments or runners: - -```yaml -variables: - POSTGRES_USER: user - POSTGRES_PASSWORD: testing_password -``` - -#### `options` - -Here, options for different things exist associated with the object in question itself. For example, options related -to jobs are defined in relation to the job itself. If you're looking for a certain option, you should be able to find -where it's located by searching our [complete configuration reference](../yaml/README.md) page. - -#### `parameters` - -GitLab does not require you to define which variables you want to be available when starting a manual job. A user -can provide any variables they like. - -#### `triggers` / `cron` - -Because GitLab is integrated tightly with Git, SCM polling options for triggers are not needed. We support an easy to use -[syntax for scheduling pipelines](../pipelines/schedules.md). - -#### `tools` - -GitLab does not support a separate `tools` directive. Our best-practice recommendation is to use pre-built -container images, which can be cached, and can be built to already contain the tools you need for your pipelines. Pipelines can -be set up to automatically build these images as needed and deploy them to the [container registry](../../user/packages/container_registry/index.md). - -If you're not using container images with Docker/Kubernetes, for example on Mac or FreeBSD, then the `shell` executor does require you to -set up your environment either in advance or as part of the jobs. You could create a `before_script` -action that handles this for you. - -#### `input` - -Similar to the `parameters` keyword, this is not needed because a manual job can always be provided runtime -variable entry. - -#### `when` - -GitLab does support a [`when` keyword](../yaml/README.md#when) which is used to indicate when a job should be -run in case of (or despite) failure, but most of the logic for controlling pipelines can be found in -our very powerful [`only/except` rules system](../yaml/README.md#onlyexcept-basic) -(see also our [advanced syntax](../yaml/README.md#onlyexcept-basic)): - -```yaml -my_job: - only: [branches] -``` +This document was moved to [another location](../migration/jenkins.md). diff --git a/doc/ci/junit_test_reports.md b/doc/ci/junit_test_reports.md index aedda3c8341..8bc55a6e4f3 100644 --- a/doc/ci/junit_test_reports.md +++ b/doc/ci/junit_test_reports.md @@ -66,10 +66,6 @@ execution time and the error output. ## How to set it up -NOTE: **Note:** -For a list of supported languages on JUnit tests, check the -[Wikipedia article](https://en.wikipedia.org/wiki/JUnit#Ports). - To enable the JUnit reports in merge requests, you need to add [`artifacts:reports:junit`](pipelines/job_artifacts.md#artifactsreportsjunit) in `.gitlab-ci.yml`, and specify the path(s) of the generated test reports. @@ -80,9 +76,11 @@ collects the JUnit test report from each job. After each job is executed, the XML reports are stored in GitLab as artifacts and their results are shown in the merge request widget. +To make the JUnit output files browsable, include them with the +[`artifacts:paths`](yaml/README.md#artifactspaths) keyword as well, as shown in the [Ruby example](#ruby-example). + NOTE: **Note:** -If you also want the ability to browse JUnit output files, include the -[`artifacts:paths`](yaml/README.md#artifactspaths) keyword. An example of this is shown in the Ruby example below. +You cannot have multiple tests with the same name and class in your JUnit report. ### Ruby example @@ -140,6 +138,9 @@ java: junit: build/test-results/test/**/TEST-*.xml ``` +NOTE: **Note:** +Support for `**` was added in [GitLab Runner 13.0](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2620). + #### Maven For parsing [Surefire](https://maven.apache.org/surefire/maven-surefire-plugin/) @@ -236,9 +237,8 @@ Test: ## Viewing JUnit test reports on GitLab -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24792) in GitLab 12.5. -> - It's deployed behind a feature flag, disabled by default. -> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enabling-the-junit-test-reports-feature-core-only). **(CORE ONLY)** +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24792) in GitLab 12.5 behind a feature flag (`junit_pipeline_view`), disabled by default. +> - The feature flag was removed and the feature was [made generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/216478) in GitLab 13.3. If JUnit XML files are generated and uploaded as part of a pipeline, these reports can be viewed inside the pipelines details page. The **Tests** tab on this page will @@ -247,27 +247,10 @@ display a list of test suites and cases reported from the XML file. ![Test Reports Widget](img/pipelines_junit_test_report_ui_v12_5.png) You can view all the known test suites and click on each of these to see further -details, including the cases that makeup the suite. Cases are ordered by status, -with failed showing at the top, skipped next and successful cases last. +details, including the cases that make up the suite. You can also retrieve the reports via the [GitLab API](../api/pipelines.md#get-a-pipelines-test-report). -### Enabling the JUnit test reports feature **(CORE ONLY)** - -This feature comes with the `:junit_pipeline_view` feature flag disabled by default. This -feature is disabled due to some performance issues with very large data sets. -When [the performance is improved](https://gitlab.com/groups/gitlab-org/-/epics/2854), the feature will be enabled by default. - -To enable this feature, ask a GitLab administrator with [Rails console access](../administration/feature_flags.md#how-to-enable-and-disable-features-behind-flags) to run the -following command: - -```ruby -Feature.enable(:junit_pipeline_view) - -# Enable the feature for a specific project, GitLab 13.0 and above only. -Feature.enable(:junit_pipeline_view, Project.find()) -``` - ## Viewing JUnit screenshots on GitLab > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202114) in GitLab 13.0. diff --git a/doc/ci/large_repositories/index.md b/doc/ci/large_repositories/index.md index b4652050654..00e912d47dc 100644 --- a/doc/ci/large_repositories/index.md +++ b/doc/ci/large_repositories/index.md @@ -124,6 +124,10 @@ are dependent on Git version. [`GIT_FETCH_EXTRA_FLAGS`](../yaml/README.md#git-fetch-extra-flags) allows you to modify `git fetch` behavior by passing extra flags. +For example, if your project contains a large number of tags that your CI jobs don't rely on, +you could add [`--no-tags`](https://git-scm.com/docs/git-fetch#Documentation/git-fetch.txt---no-tags) +to the extra flags to make your fetches faster and more compact. + See the [`GIT_FETCH_EXTRA_FLAGS` documentation](../yaml/README.md#git-fetch-extra-flags) for more information. @@ -253,3 +257,11 @@ concurrent = 4 This makes the cloning configuration to be part of given Runner and does not require us to update each `.gitlab-ci.yml`. + +## Pre-clone step + +For very active repositories with a large number of references and files, you can also +optimize your CI jobs by seeding repository data with GitLab Runner's [`pre_clone_script`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section). + +See [our development documentation](../../development/pipelines.md#pre-clone-step) for +an overview of how we implemented this approach on GitLab.com for the main GitLab repository. diff --git a/doc/ci/lint.md b/doc/ci/lint.md new file mode 100644 index 00000000000..716a4218d97 --- /dev/null +++ b/doc/ci/lint.md @@ -0,0 +1,41 @@ +# CI Lint + +If you want to test the validity of your GitLab CI/CD configuration before committing +the changes, you can use the CI Lint tool. This tool checks for syntax and logical +errors by default, and can simulate pipeline creation to try to find more complicated +issues as well. + +To access the CI Lint tool, navigate to **CI/CD > Pipelines** or **CI/CD > Jobs** +in your project and click **CI lint**. + +## Validate basic logic and syntax + +By default, the CI lint checks the syntax of your CI YAML configuration and also runs +some basic logical validations. + +To use the CI lint, paste a complete CI configuration (`.gitlab-ci.yml` for example) +into the text box and click **Validate**: + +![CI Lint](img/ci_lint.png) + +## Pipeline simulation + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229794) in GitLab 13.3. + +Not all pipeline configuration issues can be found by the [basic CI lint validation](#validate-basic-logic-and-syntax). +You can simulate the creation of a pipeline for deeper validation that can discover +more complicated issues. + +To validate the configuration by running a pipeline simulation: + +1. Paste the GitLab CI configuration to verify into the text box. +1. Click the **Simulate pipeline creation for the default branch** checkbox. +1. Click **Validate**. + +![Dry run](img/ci_lint_dry_run.png) + +### Pipeline simulation limitations + +Simulations run as `git push` events against the default branch. You must have +[permissions](../user/permissions.md#project-members-permissions) to create pipelines +on this branch to validate with a simulation. diff --git a/doc/ci/merge_request_pipelines/index.md b/doc/ci/merge_request_pipelines/index.md index 2a6008e6307..73b971c2d41 100644 --- a/doc/ci/merge_request_pipelines/index.md +++ b/doc/ci/merge_request_pipelines/index.md @@ -166,31 +166,33 @@ Read the [documentation on Pipelines for Merged Results](pipelines_for_merged_re Read the [documentation on Merge Trains](pipelines_for_merged_results/merge_trains/index.md). -## Important notes about merge requests from forked projects +## Run pipelines in the parent project for merge requests from a forked project **(STARTER)** -Note that the current behavior is subject to change. In the usual contribution -flow, external contributors follow the following steps: +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217451) in GitLab 13.3. -1. Fork a parent project. -1. Create a merge request from the forked project that targets the `master` branch - in the parent project. -1. A pipeline runs on the merge request. -1. A maintainer from the parent project checks the pipeline result, and merge - into a target branch if the latest pipeline has passed. +By default, external contributors working from forks can't create pipelines in the +parent project. When a pipeline for merge requests is triggered by a merge request +coming from a fork: -Currently, those pipelines are created in a **forked** project, not in the -parent project. This means you cannot completely trust the pipeline result, -because, technically, external contributors can disguise their pipeline results -by tweaking their GitLab Runner in the forked project. +- It's created and runs in the fork (source) project, not the parent (target) project. +- It uses the fork project's CI/CD configuration and resources. -There are multiple reasons why GitLab doesn't allow those pipelines to be -created in the parent project, but one of the biggest reasons is security concern. -External users could steal secret variables from the parent project by modifying -`.gitlab-ci.yml`, which could be some sort of credentials. This should not happen. +Sometimes parent project members want the pipeline to run in the parent +project. This could be to ensure that the post-merge pipeline passes in the parent project. +For example, a fork project could try to use a corrupted Runner that doesn't execute +test scripts properly, but reports a passed pipeline. Reviewers in the parent project +could mistakenly trust the merge request because it passed a faked pipeline. -We're discussing a secure solution of running pipelines for merge requests -that are submitted from forked projects, -see [the issue about the permission extension](https://gitlab.com/gitlab-org/gitlab/-/issues/11934). +Parent project members with at least [Developer permissions](../../user/permissions.md) +can create pipelines in the parent project for merge requests +from a forked project. In the merge request, go to the **Pipelines** and click +**Run Pipeline** button. + +CAUTION: **Caution:** +Fork merge requests could contain malicious code that tries to steal secrets in the +parent project when the pipeline runs, even before merge. Reviewers must carefully +check the changes in the merge request before triggering the pipeline. GitLab shows +a warning that must be accepted before the pipeline can be triggered. ## Additional predefined variables @@ -206,19 +208,19 @@ The variable names begin with the `CI_MERGE_REQUEST_` prefix. ### Two pipelines created when pushing to a merge request If you are experiencing duplicated pipelines when using `rules`, take a look at -the [important differences between `rules` and `only`/`except`](../yaml/README.md#differences-between-rules-and-onlyexcept), +the [important differences between `rules` and `only`/`except`](../yaml/README.md#prevent-duplicate-pipelines), which will help you get your starting configuration correct. If you are seeing two pipelines when using `only/except`, please see the caveats related to using `only/except` above (or, consider moving to `rules`). +It is not possible to run a job for branch pipelines first, then only for merge request +pipelines after the merge request is created (skipping the duplicate branch pipeline). See +the [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/201845) for more details. + ### Two pipelines created when pushing an invalid CI configuration file Pushing to a branch with an invalid CI configuration file can trigger the creation of two types of failed pipelines. One pipeline is a failed merge request pipeline, and the other is a failed branch pipeline, but both are caused by the same invalid configuration. - -In rare cases, duplicate pipelines are created. - -See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/201845) for details. diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md index 84fbefb080f..685c93b3be4 100644 --- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md +++ b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md @@ -45,8 +45,6 @@ To enable pipelines for merge results: - You must have maintainer [permissions](../../../user/permissions.md). - You must be using [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner) 11.9 or later. -- You must not be forking or using cross-repo workflows. To follow progress, - see [#11934](https://gitlab.com/gitlab-org/gitlab/-/issues/11934). - You must not be using [fast forward merges](../../../user/project/merge_requests/fast_forward_merge.md) yet. To follow progress, see [#58226](https://gitlab.com/gitlab-org/gitlab/-/issues/26996). diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md index e12c9d109cc..d91d88c8e12 100644 --- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md +++ b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md @@ -11,6 +11,8 @@ last_update: 2019-07-03 > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9186) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.0. > - [Squash and merge](../../../../user/project/merge_requests/squash_and_merge.md) support [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13001) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.6. +For more information about why you might want to use Merge Trains, read [How merge trains keep your master green](https://about.gitlab.com/blog/2020/01/30/all-aboard-merge-trains/). + When [pipelines for merged results](../index.md#pipelines-for-merged-results-premium) are enabled, the pipeline jobs run as if the changes from your source branch have already been merged into the target branch. diff --git a/doc/ci/migration/circleci.md b/doc/ci/migration/circleci.md index 625b15ca4fb..78705815c24 100644 --- a/doc/ci/migration/circleci.md +++ b/doc/ci/migration/circleci.md @@ -1,4 +1,7 @@ --- +stage: Verify +group: Continuous Integration +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers comments: false type: index, howto --- diff --git a/doc/ci/migration/jenkins.md b/doc/ci/migration/jenkins.md new file mode 100644 index 00000000000..1d029dcdd14 --- /dev/null +++ b/doc/ci/migration/jenkins.md @@ -0,0 +1,359 @@ +--- +stage: Verify +group: Continuous Integration +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +comments: false +type: index, howto +--- + +# Migrating from Jenkins + +A lot of GitLab users have successfully migrated to GitLab CI/CD from Jenkins. To make this +easier if you're just getting started, we've collected several resources here that you might find useful +before diving in. Think of this page as a "GitLab CI/CD for Jenkins Users" guide. + +The following list of recommended steps was created after observing organizations +that were able to quickly complete this migration: + +1. Start by reading the GitLab CI/CD [Quick Start Guide](../quick_start/README.md) and [important product differences](#important-product-differences). +1. Learn the importance of [managing the organizational transition](#managing-the-organizational-transition). +1. [Add Runners](../runners/README.md) to your GitLab instance. +1. Educate and enable your developers to independently perform the following steps in their projects: + 1. Review the [Quick Start Guide](../quick_start/README.md) and [Pipeline Configuration Reference](../yaml/README.md). + 1. Use the [Jenkins Wrapper](#jenkinsfile-wrapper) to temporarily maintain fragile Jenkins jobs. + 1. Migrate the build and CI jobs and configure them to show results directly in your merge requests. They can use [Auto DevOps](../../topics/autodevops/index.md) as a starting point, and [customize](../../topics/autodevops/customize.md) or [decompose](../../topics/autodevops/customize.md#using-components-of-auto-devops) the configuration as needed. + 1. Add [Review Apps](../review_apps/index.md). + 1. Migrate the deployment jobs using [cloud deployment templates](../cloud_deployment/index.md), adding [environments](../environments/index.md), and [deploy boards](../..//user/project/deploy_boards.md). + 1. Work to unwrap any jobs still running with the use of the Jenkins wrapper. +1. Take stock of any common CI/CD job definitions then create and share [templates](#templates) for them. + +For an example of how to convert a Jenkins pipeline into a GitLab CI/CD pipeline, +or how to use Auto DevOps to test your code automatically, watch the +[Migrating from Jenkins to GitLab](https://www.youtube.com/watch?v=RlEVGOpYF5Y) video. + +Otherwise, read on for important information that will help you get the ball rolling. Welcome +to GitLab! + +If you have questions that are not answered here, the [GitLab community forum](https://forum.gitlab.com/) +can be a great resource. + +## Managing the organizational transition + +An important part of transitioning from Jenkins to GitLab is the cultural and organizational +changes that comes with the move, and successfully managing them. There are a few +things we have found that helps this: + +- Setting and communicating a clear vision of what your migration goals are helps + your users understand why the effort is worth it. The value will be clear when + the work is done, but people need to be aware while it's in progress too. +- Sponsorship and alignment from the relevant leadership team helps with the point above. +- Spending time educating your users on what's different, sharing this document with them, + and so on will help ensure you are successful. +- Finding ways to sequence or delay parts of the migration can help a lot, but you + don't want to leave things in a non-migrated (or partially-migrated) state for too + long. To gain all the benefits of GitLab, moving your existing Jenkins setup over + as-is, including any current problems, will not be enough. You need to take advantage + of the improvements that GitLab offers, and this requires (eventually) updating + your implementation as part of the transition. + +## JenkinsFile Wrapper + +We are building a [JenkinsFile Wrapper](https://gitlab.com/gitlab-org/jfr-container-builder/) which will allow +you to run a complete Jenkins instance inside of a GitLab job, including plugins. This can help ease the process +of transition, by letting you delay the migration of less urgent pipelines for a period of time. + +If you are interested in helping GitLab test the wrapper, join our [public testing issue](https://gitlab.com/gitlab-org/gitlab/-/issues/215675) for instructions and to provide your feedback. + +## Important product differences + +There are some high level differences between the products worth mentioning: + +- With GitLab you don't need a root `pipeline` keyword to wrap everything. +- The way pipelines are triggered and [trigger other pipelines](../yaml/README.md#trigger) + is different than Jenkins. GitLab pipelines can be triggered: + + - on push + - on [schedule](../pipelines/schedules.md) + - from the [GitLab UI](../pipelines/index.md#run-a-pipeline-manually) + - by [API call](../triggers/README.md) + - by [webhook](../triggers/README.md#triggering-a-pipeline-from-a-webhook) + - by [ChatOps](../chatops/README.md) + +- You can control which jobs run in which cases, depending on how they are triggered, + with the [`rules` syntax](../yaml/README.md#rules). +- GitLab [pipeline scheduling concepts](../pipelines/schedules.md) are also different than with Jenkins. +- You can reuse pipeline configurations using the [`include` keyword](../yaml/README.md#include) + and [templates](#templates). Your templates can be kept in a central repository (with different + permissions), and then any project can use them. This central project could also + contain scripts or other reusable code. +- You can also use the [`extends` keyword](../yaml/README.md#extends) to reuse configuration + within a single pipeline configuration. +- All jobs within a single stage always run in parallel, and all stages run in sequence. We are planning + to allow certain jobs to break this sequencing as needed with our [directed acyclic graph](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47063) + feature. +- The [`parallel`](../yaml/README.md#parallel) keyword can automatically parallelize tasks, + like tests that support parallelization. +- Normally all jobs within a single stage run in parallel, and all stages run in sequence. + There are different [pipeline architectures](../pipelines/pipeline_architectures.md) + that allow you to change this behavior. +- The new [`rules` syntax](../yaml/README.md#rules) is the recommended method of + controlling when different jobs run. It is more powerful than the `only/except` syntax. +- One important difference is that jobs run independently of each other and have a + fresh environment in each job. Passing artifacts between jobs is controlled using the + [`artifacts`](../yaml/README.md#artifacts) and [`dependencies`](../yaml/README.md#dependencies) + keywords. When finished, the planned [Workspaces](https://gitlab.com/gitlab-org/gitlab/-/issues/29265) + feature will allow you to more easily persist a common workspace between serial jobs. +- The `.gitlab-ci.yml` file is checked in to the root of your repository, much like a Jenkinsfile, but + is in the YAML format (see [complete reference](../yaml/README.md)) instead of a Groovy DSL. It's most + analogous to the declarative Jenkinsfile format. +- Manual approvals or gates can be set up as [`when:manual` jobs](../yaml/README.md#whenmanual). These can + also leverage [`protected environments`](../yaml/README.md#protecting-manual-jobs-premium) + to control who is able to approve them. +- GitLab comes with a [container registry](../../user/packages/container_registry/index.md), and we recommend using + container images to set up your build environment. For example, set up one pipeline that builds your build environment + itself and publish that to the container registry. Then, have your pipelines use this instead of each building their + own environment, which will be slower and may be less consistent. We have extensive docs on [how to use the Container Registry](../../user/packages/container_registry/index.md). +- A central utilities repository can be a great place to put assorted scheduled jobs + or other manual jobs that function like utilities. Jenkins installations tend to + have a few of these. + +## Agents vs. Runners + +Both Jenkins agents and GitLab Runners are the hosts that run jobs. To convert the +Jenkins agent, simply uninstall it and then [install and register the runner](../runners/README.md). +Runners do not require much overhead, so you can size them similarly to the Jenkins +agents you were using. + +There are some important differences in the way Runners work in comparison to agents: + +- Runners can be set up as [shared across an instance, be added at the group level, or set up at the project level](../runners/README.md#types-of-runners). + They will self-select jobs from the scopes you've defined automatically. +- You can also [use tags](../runners/README.md#use-tags-to-limit-the-number-of-jobs-using-the-runner) for finer control, and + associate runners with specific jobs. For example, you can use a tag for jobs that + require dedicated, more powerful, or specific hardware. +- GitLab has [autoscaling for Runners](https://docs.gitlab.com/runner/configuration/autoscale.html) + which will let you configure them to be provisioned as needed, and scaled down when not. + This is similar to ephemeral agents in Jenkins. + +If you are using `gitlab.com`, you can take advantage of our [shared Runner fleet](../../user/gitlab_com/index.md#shared-runners) +to run jobs without provisioning your own Runners. We are investigating making them +[available for self-managed instances](https://gitlab.com/groups/gitlab-org/-/epics/835) +as well. + +## Groovy vs. YAML + +Jenkins Pipelines are based on [Groovy](https://groovy-lang.org/), so the pipeline specification is written as code. +GitLab works a bit differently, we use the more highly structured [YAML](https://yaml.org/) format, which +places scripting elements inside of `script:` blocks separate from the pipeline specification itself. + +This is a strength of GitLab, in that it helps keep the learning curve much simpler to get up and running +and avoids some of the problem of unconstrained complexity which can make your Jenkinsfile hard to understand +and manage. + +That said, we do of course still value DRY (don't repeat yourself) principles and want to ensure that +behaviors of your jobs can be codified once and applied as needed. You can use the `extends:` syntax to +[reuse configuration in your jobs](../yaml/README.md#extends), and `include:` can +be used to [reuse pipeline configurations](../yaml/README.md#include) in pipelines +in different projects: + +```yaml +.in-docker: + tags: + - docker + image: alpine + +rspec: + extends: + - .in-docker + script: + - rake rspec +``` + +## Artifact publishing + +Artifacts may work a bit differently than you've used them with Jenkins. In GitLab, any job can define +a set of artifacts to be saved by using the `artifacts:` keyword. This can be configured to point to a file +or set of files that can then be persisted from job to job. Read more on our detailed +[artifacts documentation](../pipelines/job_artifacts.md): + +```yaml +pdf: + script: xelatex mycv.tex + artifacts: + paths: + - ./mycv.pdf + - ./output/ + expire_in: 1 week +``` + +Additionally, we have package management features like a built-in container, NPM, and Maven registry that you +can leverage. You can see the complete list of packaging features (which includes links to documentation) +in the [Packaging section of our documentation](../../README.md#package). + +## Integrated features + +Where you may have used plugins to get things like code quality, unit tests, security scanning, and so on working in Jenkins, +GitLab takes advantage of our connected ecosystem to automatically pull these kinds of results into +your Merge Requests, pipeline details pages, and other locations. You may find that you actually don't +need to configure anything to have these appear. + +If they aren't working as expected, or if you'd like to see what's available, our [CI feature index](../README.md#feature-set) has the full list +of bundled features and links to the documentation for each. + +### Templates + +For advanced CI/CD teams, project templates can enable the reuse of pipeline configurations, +as well as encourage inner sourcing. + +In self-managed GitLab instances, you can build an [Instance Template Repository](../../user/admin_area/settings/instance_template_repository.md). +Development teams across the whole organization can select templates from a dropdown menu. +A group administrator is able to set a group to use as the source for the +[custom project templates](../../user/admin_area/custom_project_templates.md), which can +be used by all projects in the group. An instance administrator can set a group as +the source for [instance project templates](../../user/group/custom_project_templates.md), +which can be used by projects in that instance. + +## Converting a declarative Jenkinsfile + +A declarative Jenkinsfile contains "Sections" and "Directives" which are used to control the behavior of your +pipelines. There are equivalents for all of these in GitLab, which we've documented below. + +This section is based on the [Jenkinsfile syntax documentation](https://www.jenkins.io/doc/book/pipeline/syntax/) +and is meant to be a mapping of concepts there to concepts in GitLab. + +### Sections + +#### `agent` + +The agent section is used to define how a pipeline will be executed. For GitLab, we use the [GitLab Runner](../runners/README.md) +to provide this capability. You can configure your own runners in Kubernetes or on any host, or take advantage +of our shared runner fleet (note that the shared runner fleet is only available for GitLab.com users.) The link above will bring you to the documentation which will describe how to get +up and running quickly. We also support using [tags](../runners/README.md#use-tags-to-limit-the-number-of-jobs-using-the-runner) to direct different jobs +to different Runners (execution agents). + +The `agent` section also allows you to define which Docker images should be used for execution, for which we use +the [`image`](../yaml/README.md#image) keyword. The `image` can be set on a single job or at the top level, in which +case it will apply to all jobs in the pipeline: + +```yaml +my_job: + image: alpine + ... +``` + +#### `post` + +The `post` section defines the actions that should be performed at the end of the pipeline. GitLab also supports +this through the use of stages. You can define your stages as follows, and any jobs assigned to the `before_pipeline` +or `after_pipeline` stages will run as expected. You can call these stages anything you like: + +```yaml +stages: + - before_pipeline + - build + - test + - deploy + - after_pipeline +``` + +Setting a step to be performed before and after any job can be done via the +[`before_script` and `after_script` keywords](../yaml/README.md#before_script-and-after_script): + +```yaml +default: + before_script: + - echo "I run before any jobs starts in the entire pipeline, and can be responsible for setting up the environment." +``` + +#### `stages` + +GitLab CI/CD also lets you define stages, but is a little bit more free-form to configure. The GitLab [`stages` keyword](../yaml/README.md#stages) +is a top level setting that enumerates the list of stages, but you are not required to nest individual jobs underneath +the `stages` section. Any job defined in the `.gitlab-ci.yml` can be made a part of any stage through use of the +[`stage:` keyword](../yaml/README.md#stage). + +Note that, unless otherwise specified, every pipeline is instantiated with a `build`, `test`, and `deploy` stage +which are run in that order. Jobs that have no `stage` defined are placed by default in the `test` stage. +Of course, each job that refers to a stage must refer to a stage that exists in the pipeline configuration. + +```yaml +stages: + - build + - test + - deploy + +my_job: + stage: build + ... +``` + +#### `steps` + +The `steps` section is equivalent to the [`script` section](../yaml/README.md#script) of an individual job. This is +a simple YAML array with each line representing an individual command to be run: + +```yaml +my_job: + script: + - echo "hello! the current time is:" + - time + ... +``` + +### Directives + +#### `environment` + +In GitLab, we use the [`variables` keyword](../yaml/README.md#variables) to define different variables at runtime. +These can also be set up through the GitLab UI, under CI/CD settings. See also our [general documentation on variables](../variables/README.md), +including the section on [protected variables](../variables/README.md#protect-a-custom-variable) which can be used +to limit access to certain variables to certain environments or runners: + +```yaml +variables: + POSTGRES_USER: user + POSTGRES_PASSWORD: testing_password +``` + +#### `options` + +Here, options for different things exist associated with the object in question itself. For example, options related +to jobs are defined in relation to the job itself. If you're looking for a certain option, you should be able to find +where it's located by searching our [complete configuration reference](../yaml/README.md) page. + +#### `parameters` + +GitLab does not require you to define which variables you want to be available when starting a manual job. A user +can provide any variables they like. + +#### `triggers` / `cron` + +Because GitLab is integrated tightly with Git, SCM polling options for triggers are not needed. We support an easy to use +[syntax for scheduling pipelines](../pipelines/schedules.md). + +#### `tools` + +GitLab does not support a separate `tools` directive. Our best-practice recommendation is to use pre-built +container images, which can be cached, and can be built to already contain the tools you need for your pipelines. Pipelines can +be set up to automatically build these images as needed and deploy them to the [container registry](../../user/packages/container_registry/index.md). + +If you're not using container images with Docker/Kubernetes, for example on Mac or FreeBSD, then the `shell` executor does require you to +set up your environment either in advance or as part of the jobs. You could create a `before_script` +action that handles this for you. + +#### `input` + +Similar to the `parameters` keyword, this is not needed because a manual job can always be provided runtime +variable entry. + +#### `when` + +GitLab does support a [`when` keyword](../yaml/README.md#when) which is used to indicate when a job should be +run in case of (or despite) failure, but most of the logic for controlling pipelines can be found in +our very powerful [`only/except` rules system](../yaml/README.md#onlyexcept-basic) +(see also our [advanced syntax](../yaml/README.md#onlyexcept-basic)): + +```yaml +my_job: + only: [branches] +``` diff --git a/doc/ci/multi_project_pipelines.md b/doc/ci/multi_project_pipelines.md index 40d495a69f1..3df2db8539e 100644 --- a/doc/ci/multi_project_pipelines.md +++ b/doc/ci/multi_project_pipelines.md @@ -62,6 +62,14 @@ together, allowing you to visualize their relationships on pipeline graphs. These relationships are displayed in the pipeline graph by showing inbound and outbound connections for upstream and downstream pipeline dependencies. +When using: + +- Variables or [`rules`](yaml/README.md#rulesif) to control job behavior, the value of + the [`$CI_PIPELINE_SOURCE` predefined variable](variables/predefined_variables.md) is + `pipeline` for multi-project pipeline triggered through the API with `CI_JOB_TOKEN`. +- [`only/except`](yaml/README.md#onlyexcept-basic) to control job behavior, use the + `pipelines` keyword. + ## Creating multi-project pipelines from `.gitlab-ci.yml` > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8997) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.8. @@ -100,6 +108,15 @@ downstream project (`my/deployment` in this case). If a downstream project can not be found, or a user does not have access rights to create pipeline there, the `staging` job is going to be marked as _failed_. +When using: + +- Variables or [`rules`](yaml/README.md#rulesif) to control job behavior, the value of + the [`$CI_PIPELINE_SOURCE` predefined variable](variables/predefined_variables.md) is + `pipeline` for multi-project pipelines triggered with a bridge job (using the + [`trigger:`](yaml/README.md#trigger) keyword). +- [`only/except`](yaml/README.md#onlyexcept-basic) to control job behavior, use the + `pipelines` keyword. + CAUTION: **Caution:** In the example, `staging` will be marked as succeeded as soon as a downstream pipeline gets created. If you want to display the downstream pipeline's status instead, see @@ -138,6 +155,12 @@ Use: GitLab will use a commit that is currently on the HEAD of the branch when creating a downstream pipeline. +NOTE: **Note:** +Pipelines triggered on a protected branch in a downstream project use the [permissions](../user/permissions.md) +of the user that ran the trigger job in the upstream project. If the user does not +have permission to run CI/CD pipelines against the protected branch, the pipeline fails. See +[pipeline security for protected branches](pipelines/index.md#pipeline-security-on-protected-branches). + ### Passing variables to a downstream pipeline Sometimes you might want to pass variables to a downstream pipeline. @@ -254,5 +277,5 @@ tag in a different project: Any pipelines that complete successfully for new tags in the subscribed project will now trigger a pipeline on the current project's default branch. The maximum -number of upstream pipeline subscriptions is 2, for both the upstream and -downstream projects. +number of upstream pipeline subscriptions is 2 by default, for both the upstream and +downstream projects. This [application limit](../administration/instance_limits.md#number-of-cicd-subscriptions-to-a-project) can be changed on self-managed instances by a GitLab administrator. diff --git a/doc/ci/parent_child_pipelines.md b/doc/ci/parent_child_pipelines.md index c936bd8f5fe..1cfa698bfa5 100644 --- a/doc/ci/parent_child_pipelines.md +++ b/doc/ci/parent_child_pipelines.md @@ -43,8 +43,8 @@ Child pipelines work well with other GitLab CI/CD features: - Since the parent pipeline in `.gitlab-ci.yml` and the child pipeline run as normal pipelines, they can have their own behaviors and sequencing in relation to triggers. -All of this will work with the [`include:`](yaml/README.md#include) feature so you can compose -the child pipeline configuration. +See the [`trigger:`](yaml/README.md#trigger) keyword documentation for full details on how to +include the child pipeline configuration. For an overview, see [Parent-Child Pipelines feature demo](https://youtu.be/n8KpBSqZNbk). @@ -145,6 +145,8 @@ build a matrix of targets and architectures. For an overview, see [Create child pipelines using dynamically generated configurations](https://youtu.be/nMdfus2JWHM). +We also have an [example project using Dynamic Child Pipelines with Jsonnet](https://gitlab.com/gitlab-org/project-templates/jsonnet) which shows how to use a data templating language to generate your `.gitlab-ci.yml` at runtime. You could use a similar process for other templating languages like [Dhall](https://dhall-lang.org/) or [`ytt`](https://get-ytt.io/). + In GitLab 12.9, the child pipeline could fail to be created in certain cases, causing the parent pipeline to fail. This is [resolved in GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/issues/209070). diff --git a/doc/ci/pipelines/index.md b/doc/ci/pipelines/index.md index 18b3fe10bec..8419b474d54 100644 --- a/doc/ci/pipelines/index.md +++ b/doc/ci/pipelines/index.md @@ -87,13 +87,13 @@ to its **Pipelines** tab. ![Pipelines index page](img/pipelines_index_v13_0.png) -Clicking a pipeline will bring you to the **Pipeline Details** page and show +Click a pipeline to open the **Pipeline Details** page and show the jobs that were run for that pipeline. From here you can cancel a running pipeline, retry jobs on a failed pipeline, or [delete a pipeline](#delete-a-pipeline). [Starting in GitLab 12.3](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/50499), a link to the latest pipeline for the last commit of a given branch is available at `/project/pipelines/[branch]/latest`. -Also, `/project/pipelines/latest` will redirect you to the latest pipeline for the last commit +Also, `/project/pipelines/latest` redirects you to the latest pipeline for the last commit on the project's default branch. [Starting in GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/215367), @@ -120,14 +120,14 @@ To execute a pipeline manually: 1. Enter any [environment variables](../variables/README.md) required for the pipeline run. 1. Click the **Create pipeline** button. -The pipeline will execute the jobs as configured. +The pipeline now executes the jobs as configured. ### Run a pipeline by using a URL query string > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24146) in GitLab 12.5. You can use a query string to pre-populate the **Run Pipeline** page. For example, the query string -`.../pipelines/new?ref=my_branch&var[foo]=bar&file_var[file_foo]=file_bar` will pre-populate the +`.../pipelines/new?ref=my_branch&var[foo]=bar&file_var[file_foo]=file_bar` pre-populates the **Run Pipeline** page with: - **Run for** field: `my_branch`. @@ -174,7 +174,7 @@ stage has a job with a manual action. > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27188) in GitLab 11.11. Multiple manual actions in a single stage can be started at the same time using the "Play all manual" button. -Once the user clicks this button, each individual manual action will be triggered and refreshed +Once you click this button, each individual manual action is triggered and refreshed to an updated status. This functionality is only available: @@ -193,7 +193,7 @@ page, then using the **Delete** button. ![Pipeline Delete Button](img/pipeline-delete.png) CAUTION: **Warning:** -Deleting a pipeline will expire all pipeline caches, and delete all related objects, +Deleting a pipeline expires all pipeline caches, and deletes all related objects, such as builds, logs, artifacts, and triggers. **This action cannot be undone.** ### Pipeline quotas @@ -252,6 +252,7 @@ on that specific branch: - Run manual pipelines (using the [Web UI](#run-a-pipeline-manually) or [pipelines API](#pipelines-api)). - Run scheduled pipelines. - Run pipelines using triggers. +- Run on-demand DAST scan. - Trigger manual actions on existing pipelines. - Retry or cancel existing jobs (using the Web UI or pipelines API). @@ -263,13 +264,13 @@ sensitive information like deployment credentials and tokens. branches, preventing untrusted code from executing on the protected runner and preserving deployment keys and other credentials from being unintentionally accessed. In order to ensure that jobs intended to be executed on protected -runners will not use regular runners, they must be tagged accordingly. +runners do not use regular runners, they must be tagged accordingly. ## View jobs in a pipeline When you access a pipeline, you can see the related jobs for that pipeline. -Clicking an individual job will show you its job log, and allow you to: +Clicking an individual job shows you its job log, and allows you to: - Cancel the job. - Retry the job. @@ -325,10 +326,10 @@ If you have many similar jobs, your [pipeline graph](#visualize-pipelines) becom to read. You can automatically group similar jobs together. If the job names are formatted in a certain way, -they will be collapsed into a single group in regular pipeline graphs (not the mini graphs). +they are collapsed into a single group in regular pipeline graphs (not the mini graphs). -You'll know when a pipeline has grouped jobs if you don't see the retry or -cancel button inside them. Hovering over them will show the number of grouped +You can recognize when a pipeline has grouped jobs if you don't see the retry or +cancel button inside them. Hovering over them shows the number of grouped jobs. Click to expand them. ![Grouped pipelines](img/pipelines_grouped.png) @@ -342,7 +343,7 @@ separate each job name with a number and one of the following: You can use these symbols interchangeably. -For example, these three jobs will be in a group named `build ruby`: +In the example below, these three jobs are in a group named `build ruby`: ```yaml build ruby 1/3: @@ -365,7 +366,7 @@ In the pipeline, the result is a group named `build ruby` with three jobs: ![Job group](img/job_group_v12_10.png) -The jobs will be ordered by comparing the numbers from left to right. You +The jobs are be ordered by comparing the numbers from left to right. You usually want the first number to be the index and the second number to be the total. [This regular expression](https://gitlab.com/gitlab-org/gitlab/blob/2f3dc314f42dbd79813e6251792853bc231e69dd/app/models/commit_status.rb#L99) @@ -383,7 +384,7 @@ the pipeline view, *not* the play (**{play}**) button. This is useful when you want to alter the execution of a job that uses [custom environment variables](../variables/README.md#custom-environment-variables). -Adding a variable name (key) and value here will override the value defined in +Add a variable name (key) and value here to override the value defined in [the UI or `.gitlab-ci.yml`](../variables/README.md#custom-environment-variables), for a single run of the manual job. @@ -410,7 +411,7 @@ For example, if you start rolling out new code and: > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14664) in GitLab 12.0. -Job logs are divided into sections that can be collapsed or expanded. Each section will display +Job logs are divided into sections that can be collapsed or expanded. Each section displays the duration. In the following example: @@ -422,8 +423,11 @@ In the following example: #### Custom collapsible sections -You can create collapsible sections in job logs by manually outputting special codes -that GitLab will use to determine what sections to collapse: +> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14664) in GitLab 12.0. + +You can create [collapsible sections in job logs](../pipelines/index.md#expand-and-collapse-job-log-sections) +by manually outputting special codes +that GitLab uses to determine what sections to collapse: - Section start marker: `section_start:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K` + `TEXT_OF_SECTION_HEADER` - Section end marker: `section_end:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K` diff --git a/doc/ci/pipelines/job_artifacts.md b/doc/ci/pipelines/job_artifacts.md index c4457d17dc2..be6886fe6b2 100644 --- a/doc/ci/pipelines/job_artifacts.md +++ b/doc/ci/pipelines/job_artifacts.md @@ -11,13 +11,13 @@ type: reference, howto > - Introduced in GitLab 8.2 and GitLab Runner 0.7.0. > - Starting with GitLab 8.4 and GitLab Runner 1.0, the artifacts archive format changed to `ZIP`, and it's now possible to browse its contents, with the added ability of downloading the files separately. > - In GitLab 8.17, builds were renamed to jobs. -> - The artifacts browser will be available only for new artifacts that are sent to GitLab using GitLab Runner version 1.0 and up. It won't be possible to browse old artifacts already uploaded to GitLab. +> - The artifacts browser is available only for new artifacts that are sent to GitLab using GitLab Runner version 1.0 and up. You cannot browse old artifacts already uploaded to GitLab. Job artifacts are a list of files and directories created by a job once it finishes. This feature is [enabled by default](../../administration/job_artifacts.md) in all GitLab installations. -Job artifacts created by GitLab Runner are uploaded to GitLab and are downloadable as a single archive using the GitLab UI or the [GitLab API](../../api/jobs.md#get-job-artifacts). +Job artifacts created by GitLab Runner are uploaded to GitLab and are downloadable as a single archive using the GitLab UI or the [GitLab API](../../api/job_artifacts.md#get-job-artifacts). For an overview, watch the video [GitLab CI Pipeline, Artifacts, and Environments](https://www.youtube.com/watch?v=PCKDICEe10s). @@ -42,9 +42,9 @@ the latex source file `mycv.tex`. We then define the `artifacts` paths which in turn are defined with the `paths` keyword. All paths to files and directories are relative to the repository that was cloned during the build. -The artifacts will be uploaded when the job succeeds by default, but can be set to upload -when the job fails, or always, if the [`artifacts:when`](../yaml/README.md#artifactswhen) -parameter is used. These uploaded artifacts will be kept in GitLab for 1 week as defined +By default, the artifacts upload when the job succeeds. You can also set artifacts to upload +when the job fails, or always, by using [`artifacts:when`](../yaml/README.md#artifactswhen) +parameter. GitLab keeps these uploaded artifacts for 1 week, as defined by the `expire_in` definition. You can keep the artifacts from expiring via the [web interface](#browsing-artifacts). If the expiry time is not defined, it defaults to the [instance wide setting](../../user/admin_area/settings/continuous_integration.md#default-artifacts-expiration-core-only). @@ -94,13 +94,12 @@ rspec: junit: rspec.xml ``` -The collected JUnit reports will be uploaded to GitLab as an artifact and will -be automatically shown in merge requests. +The collected JUnit reports upload to GitLab as an artifact and display in merge requests. NOTE: **Note:** -In case the JUnit tool you use exports to multiple XML files, you can specify -multiple test report paths within a single job and they will be automatically -concatenated into a single file. Use a filename pattern (`junit: rspec-*.xml`), +If the JUnit tool you use exports to multiple XML files, specify +multiple test report paths within a single job to +concatenate them into a single file. Use a filename pattern (`junit: rspec-*.xml`), an array of filenames (`junit: [rspec-1.xml, rspec-2.xml, rspec-3.xml]`), or a combination thereof (`junit: [rspec.xml, test-results/TEST-*.xml]`). @@ -130,8 +129,8 @@ There are a couple of exceptions to the [original dotenv rules](https://github.c > - Requires [GitLab Runner](https://docs.gitlab.com/runner/) 11.5 and above. The `cobertura` report collects [Cobertura coverage XML files](../../user/project/merge_requests/test_coverage_visualization.md). -The collected Cobertura coverage reports will be uploaded to GitLab as an artifact -and will be automatically shown in merge requests. +The collected Cobertura coverage reports upload to GitLab as an artifact +and display in merge requests. Cobertura was originally developed for Java, but there are many third party ports for other languages like JavaScript, Python, Ruby, and so on. @@ -142,7 +141,7 @@ third party ports for other languages like JavaScript, Python, Ruby, and so on. > - Requires [GitLab Runner](https://docs.gitlab.com/runner/) 11.5 and above. The `terraform` report obtains a Terraform `tfplan.json` file. [JQ processing required to remove credentials](../../user/infrastructure/index.md#output-terraform-plan-information-into-a-merge-request). The collected Terraform -plan report will be uploaded to GitLab as an artifact and will be automatically shown +plan report uploads to GitLab as an artifact and displays in merge requests. For more information, see [Output `terraform plan` information into a merge request](../../user/infrastructure/index.md#output-terraform-plan-information-into-a-merge-request). @@ -155,8 +154,7 @@ in merge requests. For more information, see The `codequality` report collects [CodeQuality issues](../../user/project/merge_requests/code_quality.md) as artifacts. -The collected Code Quality report will be uploaded to GitLab as an artifact and will -be summarized in merge requests. +The collected Code Quality report uploads to GitLab as an artifact and is summarized in merge requests. #### `artifacts:reports:sast` **(ULTIMATE)** @@ -166,8 +164,8 @@ be summarized in merge requests. The `sast` report collects [SAST vulnerabilities](../../user/application_security/sast/index.md) as artifacts. -The collected SAST report will be uploaded to GitLab as an artifact and will be summarized -in the merge requests and pipeline view. It's also used to provide data for security +The collected SAST report uploads to GitLab as an artifact and is summarized +in merge requests and the pipeline view. It's also used to provide data for security dashboards. #### `artifacts:reports:secret_detection` **(ULTIMATE)** @@ -190,8 +188,7 @@ dashboards. The `dependency_scanning` report collects [Dependency Scanning vulnerabilities](../../user/application_security/dependency_scanning/index.md) as artifacts. -The collected Dependency Scanning report will be uploaded to GitLab as an artifact and will -be summarized in the merge requests and pipeline view. It's also used to provide data for security +The collected Dependency Scanning report uploads to GitLab as an artifact and is summarized in merge requests and the pipeline view. It's also used to provide data for security dashboards. #### `artifacts:reports:container_scanning` **(ULTIMATE)** @@ -202,8 +199,8 @@ dashboards. The `container_scanning` report collects [Container Scanning vulnerabilities](../../user/application_security/container_scanning/index.md) as artifacts. -The collected Container Scanning report will be uploaded to GitLab as an artifact and will -be summarized in the merge requests and pipeline view. It's also used to provide data for security +The collected Container Scanning report uploads to GitLab as an artifact and +is summarized in merge requests and the pipeline view. It's also used to provide data for security dashboards. #### `artifacts:reports:dast` **(ULTIMATE)** @@ -214,8 +211,7 @@ dashboards. The `dast` report collects [DAST vulnerabilities](../../user/application_security/dast/index.md) as artifacts. -The collected DAST report will be uploaded to GitLab as an artifact and will -be summarized in the merge requests and pipeline view. It's also used to provide data for security +The collected DAST report uploads to GitLab as an artifact and is summarized in merge requests and the pipeline view. It's also used to provide data for security dashboards. #### `artifacts:reports:license_management` **(ULTIMATE)** @@ -231,8 +227,7 @@ introduced in GitLab 12.8. The `license_management` report collects [Licenses](../../user/compliance/license_compliance/index.md) as artifacts. -The collected License Compliance report will be uploaded to GitLab as an artifact and will -be summarized in the merge requests and pipeline view. It's also used to provide data for security +The collected License Compliance report uploads to GitLab as an artifact and is summarized in merge requests and the pipeline view. It's also used to provide data for security dashboards. #### `artifacts:reports:license_scanning` **(ULTIMATE)** @@ -243,8 +238,7 @@ dashboards. The `license_scanning` report collects [Licenses](../../user/compliance/license_compliance/index.md) as artifacts. -The License Compliance report will be uploaded to GitLab as an artifact and will -be automatically shown in merge requests, pipeline view and provide data for security +The License Compliance report uploads to GitLab as an artifact and displays automatically in merge requests and the pipeline view, and provide data for security dashboards. #### `artifacts:reports:performance` **(PREMIUM)** @@ -255,8 +249,7 @@ dashboards. The `performance` report collects [Browser Performance Testing metrics](../../user/project/merge_requests/browser_performance_testing.md) as artifacts. -The collected Browser Performance report will be uploaded to GitLab as an artifact and will -be automatically shown in merge requests. +The collected Browser Performance report uploads to GitLab as an artifact and displays in merge requests. #### `artifacts:reports:load_performance` **(PREMIUM)** @@ -276,8 +269,7 @@ shown in merge requests automatically. The `metrics` report collects [Metrics](../metrics_reports.md) as artifacts. -The collected Metrics report will be uploaded to GitLab as an artifact and will -be automatically shown in merge requests. +The collected Metrics report uploads to GitLab as an artifact and displays in merge requests. #### `artifacts:reports:requirements` **(ULTIMATE)** @@ -286,15 +278,15 @@ be automatically shown in merge requests. The `requirements` report collects `requirements.json` files as artifacts. -The collected Requirements report will be uploaded to GitLab as an artifact and -existing [requirements](../../user/project/requirements/index.md) will be +The collected Requirements report uploads to GitLab as an artifact and +existing [requirements](../../user/project/requirements/index.md) are marked as Satisfied. ## Browsing artifacts > - From GitLab 9.2, PDFs, images, videos, and other formats can be previewed directly in the job artifacts browser without the need to download them. > - Introduced in [GitLab 10.1](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14399), HTML files in a public project can be previewed directly in a new tab without the need to download them when [GitLab Pages](../../administration/pages/index.md) is enabled. The same applies for textual formats (currently supported extensions: `.txt`, `.json`, and `.log`). -> - Introduced in [GitLab 12.4](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16675), artifacts in private projects can be previewed when [GitLab Pages access control](../../administration/pages/index.md#access-control) is enabled. +> - Introduced in [GitLab 12.4](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16675), artifacts in internal and private projects can be previewed when [GitLab Pages access control](../../administration/pages/index.md#access-control) is enabled. After a job finishes, if you visit the job's specific page, there are three buttons. You can download the artifacts archive or browse its contents, whereas @@ -311,6 +303,8 @@ Below you can see what browsing looks like. In this case we have browsed inside the archive and at this point there is one directory, a couple files, and one HTML file that you can view directly online when [GitLab Pages](../../administration/pages/index.md) is enabled (opens in a new tab). +Select artifacts in internal and private projects can only be previewed when +[GitLab Pages access control](../../administration/pages/index.md#access-control) is enabled. ![Job artifacts browser](img/job_artifacts_browser.png) @@ -346,10 +340,8 @@ so you can use it for scripting purposes. NOTE: **Note:** The latest artifacts are created by jobs in the **most recent** successful pipeline -for the specific ref. If you run two types of pipelines for the same ref, the latest -artifact will be determined by timing. For example, if a branch pipeline created -by merging a merge request runs at the same time as a scheduled pipeline, the -latest artifact will be from the pipeline that completed most recently. +for the specific ref. If you run two types of pipelines for the same ref, timing determines the latest +artifact. For example, if a merge request creates a branch pipeline at the same time as a scheduled pipeline, the pipeline that completed most recently creates the latest artifact. Artifacts for other pipelines can be accessed with direct access to them. @@ -423,7 +415,7 @@ information in the UI. DANGER: **Danger:** This is a destructive action that leads to data loss. Use with caution. -You can erase a single job via the UI, which will also remove the job's +You can erase a single job via the UI, which also removes the job's artifacts and trace, if you are: - The owner of the job. @@ -437,7 +429,7 @@ To erase a job: ## Retrieve artifacts of private projects when using GitLab CI -In order to retrieve a job artifact of a different project, you might need to use a private token in order to [authenticate and download](../../api/jobs.md#get-job-artifacts) the artifacts. +In order to retrieve a job artifact of a different project, you might need to use a private token in order to [authenticate and download](../../api/job_artifacts.md#get-job-artifacts) the artifacts. - + In GitLab CI/CD, Runners run the code defined in [`.gitlab-ci.yml`](../yaml/README.md). A GitLab Runner is a lightweight, highly-scalable agent that picks up a CI job through @@ -118,7 +118,7 @@ You can also enable shared Runners for individual projects. To enable shared Runners: -1. Go to the project's **{settings}** **Settings > CI/CD** and expand the **Runners** section. +1. Go to the project's **Settings > CI/CD** and expand the **Runners** section. 1. Click **Allow shared Runners**. #### Disable shared Runners @@ -128,12 +128,12 @@ You must have Owner permissions for the project. To disable shared Runners for a project: -1. Go to the project's **{settings}** **Settings > CI/CD** and expand the **Runners** section. +1. Go to the project's **Settings > CI/CD** and expand the **Runners** section. 1. In the **Shared Runners** area, click **Disable shared Runners**. +From this page, you can edit, pause, and remove Runners from the group, its subgroups, and projects. #### Pause or remove a group Runner @@ -191,11 +191,11 @@ You can pause or remove a group Runner for your self-managed GitLab instance or You must have [Owner permissions](../../user/permissions.md#group-members-permissions) for the group. 1. Go to the group you want to remove or pause the Runner for. -1. Go to **{settings}** **Settings > CI/CD** and expand the **Runners** section. +1. Go to **Settings > CI/CD** and expand the **Runners** section. 1. Click **Pause** or **Remove Runner**. - - - + - If you pause a group Runner that is used by multiple projects, the Runner pauses for all projects. + - From the group view, you cannot remove a Runner that is assigned to more than one project. + You must remove it from each project first. 1. On the confirmation dialog, click **OK**. ### Specific Runners @@ -223,7 +223,7 @@ You must have [Owner permissions](../../user/permissions.md#project-members-perm To create a specific Runner: 1. [Install Runner](https://docs.gitlab.com/runner/install/). -1. Go to the project's **{settings}** **Settings > CI/CD** and expand the **Runners** section. +1. Go to the project's **Settings > CI/CD** and expand the **Runners** section. 1. Note the URL and token. 1. [Register the Runner](https://docs.gitlab.com/runner/register/). @@ -237,7 +237,7 @@ enable a specific Runner to apply to additional projects. To enable or disable a specific Runner for a project: -1. Go to the project's **{settings}** **Settings > CI/CD** and expand the **Runners** section. +1. Go to the project's **Settings > CI/CD** and expand the **Runners** section. 1. Click **Enable for this project** or **Disable for this project**. #### Prevent a specific Runner from being enabled for other projects @@ -248,7 +248,7 @@ but can also be changed later. To lock or unlock a Runner: -1. Go to the project's **{settings}** **Settings > CI/CD** and expand the **Runners** section. +1. Go to the project's **Settings > CI/CD** and expand the **Runners** section. 1. Find the Runner you want to lock or unlock. Make sure it's enabled. 1. Click the pencil button. 1. Check the **Lock to current projects** option. @@ -266,7 +266,7 @@ if smaller than the [project defined timeout](../pipelines/settings.md#timeout), This feature can be used to prevent your shared Runner from being overwhelmed by a project that has jobs with a long timeout (for example, one week). -When not configured, Runners will not override the project timeout. +When not configured, Runners do not override the project timeout. How this feature works: @@ -317,7 +317,7 @@ and ignores other jobs. To protect or unprotect a Runner: -1. Go to the project's **{settings}** **Settings > CI/CD** and expand the **Runners** section. +1. Go to the project's **Settings > CI/CD** and expand the **Runners** section. 1. Find the Runner you want to protect or unprotect. Make sure it's enabled. 1. Click the pencil button. 1. Check the **Protected** option. @@ -329,8 +329,7 @@ To protect or unprotect a Runner: Whenever a project is forked, it copies the settings of the jobs that relate to it. This means that if you have shared Runners set up for a project and -someone forks that project, the shared Runners will also serve jobs of this -project. +someone forks that project, the shared Runners serve jobs of this project. ### Attack vectors in Runners @@ -346,14 +345,14 @@ may then be used to obtain the values of secret variables or to clone project co To reset the token: -1. Go to the project's **{settings}** **Settings > CI/CD**. +1. Go to the project's **Settings > CI/CD**. 1. Expand the **General pipelines settings** section. 1. Find the **Runner token** form field and click the **Reveal value** button. 1. Delete the value and save the form. 1. After the page is refreshed, expand the **Runners settings** section and check the registration token - it should be changed. -From now on the old token is no longer valid and will not register +From now on the old token is no longer valid and does not register any new Runners to the project. If you are using any tools to provision and register new Runners, the tokens used in those tools should be updated to reflect the value of the new token. @@ -376,7 +375,7 @@ different places. To view the IP address of a shared Runner you must have admin access to the GitLab instance. To determine this: -1. Visit **{admin}** **Admin Area > Overview > Runners**. +1. Visit **Admin Area > Overview > Runners**. 1. Look for the Runner in the table and you should see a column for **IP Address**. ![shared Runner IP address](img/shared_runner_ip_address.png) @@ -386,7 +385,7 @@ the GitLab instance. To determine this: To can find the IP address of a Runner for a specific project, you must have Owner [permissions](../../user/permissions.md#project-members-permissions) for the project. -1. Go to the project's **{settings}** **Settings > CI/CD** and expand the **Runners** section. +1. Go to the project's **Settings > CI/CD** and expand the **Runners** section. 1. On the details page you should see a row for **IP Address**. ![specific Runner IP address](img/specific_runner_ip_address.png) @@ -409,7 +408,7 @@ To change this, you must have Owner [permissions](../../user/permissions.md#proj To make a Runner pick untagged jobs: -1. Go to the project's **{settings}** **Settings > CI/CD** and expand the **Runners** section. +1. Go to the project's **Settings > CI/CD** and expand the **Runners** section. 1. Find the Runner you want to pick untagged jobs and make sure it's enabled. 1. Click the pencil button. 1. Check the **Run untagged jobs** option. diff --git a/doc/ci/services/redis.md b/doc/ci/services/redis.md index 193f78f240b..77668d9104b 100644 --- a/doc/ci/services/redis.md +++ b/doc/ci/services/redis.md @@ -34,7 +34,7 @@ And that's it. Redis will now be available to be used within your testing framework. You can also use any other Docker image available on [Docker Hub](https://hub.docker.com/_/redis). -For example, to use Redis 2.8 the service becomes `redis:2.8`. +For example, to use Redis 6.0 the service becomes `redis:6.0`. ## Use Redis with the Shell executor diff --git a/doc/ci/ssh_keys/README.md b/doc/ci/ssh_keys/README.md index 4ad4758b281..b1847ffbc60 100644 --- a/doc/ci/ssh_keys/README.md +++ b/doc/ci/ssh_keys/README.md @@ -66,7 +66,7 @@ to access it. This is where an SSH key pair comes in handy. ## Install ssh-agent if not already installed, it is required by Docker. ## (change apt-get to yum if you use an RPM-based image) ## - - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )' + - 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )' ## ## Run ssh-agent (inside the build environment) diff --git a/doc/ci/triggers/README.md b/doc/ci/triggers/README.md index 47f11a6228c..2b006b8779b 100644 --- a/doc/ci/triggers/README.md +++ b/doc/ci/triggers/README.md @@ -7,12 +7,6 @@ type: tutorial # Triggering pipelines through the API -> **Notes**: -> -> - [Introduced](https://about.gitlab.com/releases/2015/08/22/gitlab-7-14-released/) in GitLab 7.14. -> - GitLab 8.12 has a completely redesigned job permissions system. Read all -> about the [new model and its implications](../../user/project/new_ci_build_permissions_model.md#pipeline-triggers). - Triggers can be used to force a pipeline rerun of a specific `ref` (branch or tag) with an API call. @@ -97,7 +91,7 @@ This allows you to use that for multi-project pipelines and download artifacts from any project to which you have access as this follows the same principles with the [permission model](../../user/permissions.md#job-permissions). -Read more about the [jobs API](../../api/jobs.md#download-the-artifacts-archive). +Read more about the [jobs API](../../api/job_artifacts.md#download-the-artifacts-archive). ## Adding a new trigger @@ -120,11 +114,6 @@ The action is irreversible. ## Triggering a pipeline -> **Notes**: -> -> - Valid refs are only the branches and tags. If you pass a commit SHA as a ref, -> it will not trigger a job. - To trigger a job you need to send a `POST` request to GitLab's API endpoint: ```plaintext @@ -132,8 +121,8 @@ POST /projects/:id/trigger/pipeline ``` The required parameters are the [trigger's `token`](#authentication-tokens) -and the Git `ref` on which the trigger will be performed. Valid refs are the -branch and the tag. The `:id` of a project can be found by +and the Git `ref` on which the trigger will be performed. Valid refs are +branches or tags. The `:id` of a project can be found by [querying the API](../../api/projects.md) or by visiting the **CI/CD** settings page which provides self-explanatory examples. @@ -142,16 +131,12 @@ UI under the **Jobs** page and the jobs are marked as triggered 'by API'. ![Marked rebuilds as on jobs page](img/builds_page.png) ---- - You can see which trigger caused the rebuild by visiting the single job page. A part of the trigger's token is exposed in the UI as you can see from the image below. ![Marked rebuilds as triggered on a single job page](img/trigger_single_build.png) ---- - By using cURL you can trigger a pipeline rerun with minimal effort, for example: ```shell @@ -191,14 +176,6 @@ This means that whenever a new tag is pushed on project A, the job will run and ## Triggering a pipeline from a webhook -> **Notes**: -> -> - Introduced in GitLab 8.14. -> - `ref` should be passed as part of the URL in order to take precedence over -> `ref` from the webhook body that designates the branch ref that fired the -> trigger in the source repository. -> - `ref` should be URL-encoded if it contains slashes. - To trigger a job from a webhook of another project you need to add the following webhook URL for Push and Tag events (change the project ID, ref and token): @@ -206,6 +183,10 @@ webhook URL for Push and Tag events (change the project ID, ref and token): https://gitlab.example.com/api/v4/projects/9/ref/master/trigger/pipeline?token=TOKEN ``` +`ref` should be passed as part of the URL in order to take precedence over +`ref` from the webhook body that designates the branch ref that fired the +trigger in the source repository. `ref` should be URL-encoded if it contains slashes. + ## Making use of trigger variables You can pass any number of arbitrary variables in the trigger API call and they @@ -271,7 +252,7 @@ of all types of variables. ## Using cron to trigger nightly pipelines ->**Note:** +NOTE: **Note:** The following behavior can also be achieved through GitLab's UI with [pipeline schedules](../pipelines/schedules.md). diff --git a/doc/ci/troubleshooting.md b/doc/ci/troubleshooting.md index a019f8232a9..96d94a6c165 100644 --- a/doc/ci/troubleshooting.md +++ b/doc/ci/troubleshooting.md @@ -7,6 +7,24 @@ type: reference # Troubleshooting CI/CD +## Pipeline warnings + +Pipeline configuration warnings are shown when you: + +- [View pipeline details](pipelines/index.md#view-pipelines). +- [Validate configuration with the CI Lint tool](yaml/README.md#validate-the-gitlab-ciyml). +- [Manually run a pipeline](pipelines/index.md#run-a-pipeline-manually). + +### "Job may allow multiple pipelines to run for a single action" + +When you use [`rules`](yaml/README.md#rules) with a `when:` clause without +an `if:` clause, multiple pipelines may run. Usually +this occurs when you push a commit to a branch that has an open merge request associated with it. + +To [prevent duplicate pipelines](yaml/README.md#prevent-duplicate-pipelines), use +[`workflow: rules`](yaml/README.md#workflowrules) or rewrite your rules +to control which pipelines can run. + ## Merge request pipeline widget The merge request pipeline widget shows information about the pipeline status in a Merge Request. It's displayed above the [merge request ability to merge widget](#merge-request-ability-to-merge-widget). @@ -15,16 +33,15 @@ There are several messages that can be displayed depending on the status of the ### "Checking pipeline status" -This message is shown when the merge request has no pipeline associated with the latest commit yet and [Pipelines must succeed](../user/project/merge_requests/merge_when_pipeline_succeeds.md#only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds) is turned on. This might be because: +This message is shown when the merge request has no pipeline associated with the latest commit yet. This might be because: - GitLab hasn't finished creating the pipeline yet. - You are using an external CI service and GitLab hasn't heard back from the service yet. - You are not using CI/CD pipelines in your project. +- The latest pipeline was deleted (this is a [known issue](https://gitlab.com/gitlab-org/gitlab/-/issues/214323)). After the pipeline is created, the message will update with the pipeline status. -Note: Currently if you delete the latest pipeline of a Merge Request, this message will be shown instead of a meaningful error message. This is a known issue and should be resolved soon. - ## Merge request ability to merge widget The merge request status widget shows the **Merge** button and whether or not a merge request is ready to merge. If the merge request can't be merged, the reason for this is displayed. diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md index 4f9a1d8dd27..61bc466692e 100644 --- a/doc/ci/variables/README.md +++ b/doc/ci/variables/README.md @@ -74,8 +74,8 @@ pages: - echo $CI_PAGES_DOMAIN ``` -For GitLab.com users, the output will be `gitlab.io`. For your -private instance, the output will be whatever your sysadmin has +For GitLab.com users, the output is `gitlab.io`. For your +private instance, the output is whatever your sysadmin has defined. ## Custom environment variables @@ -120,8 +120,8 @@ From within the UI, you can add or update custom environment variables: - **Value**: No limitations. - **Type**: `File` or `Variable`. - **Environment scope**: `All`, or specific environments. - - **Protect variable** (Optional): If selected, the variable will only be available in pipelines that run on protected branches or tags. - - **Mask variable** (Optional): If selected, the variable's **Value** will be masked in job logs. The variable fails to save if the value does not meet the [masking requirements](#masked-variable-requirements). + - **Protect variable** (Optional): If selected, the variable is only available in pipelines that run on protected branches or tags. + - **Mask variable** (Optional): If selected, the variable's **Value** is masked in job logs. The variable fails to save if the value does not meet the [masking requirements](#masked-variable-requirements). After a variable is created, you can update any of the details by clicking the **{pencil}** **Edit** button. @@ -137,7 +137,7 @@ test_variable: - cat $GREETING # the temp file itself contains the variable value ``` -The output will be: +The output is: ![Output custom variable](img/custom_variables_output.png) @@ -187,7 +187,7 @@ kubectl config set-cluster e2e --server="$KUBE_URL" --certificate-authority="$KU > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/13784) in GitLab 11.10 -Variables can be masked so that the value of the variable will be hidden in job logs. +Variables can be masked so that the value of the variable is hidden in job logs. To mask a variable: @@ -308,7 +308,7 @@ job_name: You can also list all environment variables with the `export` command in Bash or `dir env:` command in PowerShell. -Be aware that this will also expose the values of all the variables +Be aware that this also exposes the values of all the variables you set, in the job log: ```yaml @@ -376,8 +376,8 @@ These variables are saved in the repository, and they are meant to store non-sensitive project configuration, like `RAILS_ENV` or `DATABASE_URL`. -For example, if you set the variable below globally (not inside a job), it will -be used in all executed commands and scripts: +For example, if you set the variable below globally (not inside a job), it is +used in all executed commands and scripts: ```yaml variables: @@ -419,9 +419,9 @@ Group-level variables can be added by: 1. Navigating to your group's **Settings > CI/CD** page. 1. Inputting variable types, keys, and values in the **Variables** section. - Any variables of [subgroups](../../user/group/subgroups/index.md) will be inherited recursively. + Any variables of [subgroups](../../user/group/subgroups/index.md) are inherited recursively. -Once you set them, they will be available for all subsequent pipelines. Any group-level user defined variables can be viewed in projects by: +Once you set them, they are available for all subsequent pipelines. Any group-level user defined variables can be viewed in projects by: 1. Navigating to the project's **Settings > CI/CD** page. 1. Expanding the **Variables** section. @@ -444,11 +444,11 @@ To add an instance-level variable: 1. Navigate to your admin area's **Settings > CI/CD** and expand the **Variables** section. 1. Click the **Add variable** button, and fill in the details: - - **Key**: Must be one line, using only letters, numbers, or `_` (underscore), with no spaces. - - **Value**: 700 characters allowed. - - **Type**: `File` or `Variable`. - - **Protect variable** (Optional): If selected, the variable will only be available in pipelines that run on protected branches or tags. - - **Mask variable** (Optional): If selected, the variable's **Value** will not be shown in job logs. The variable will not be saved if the value does not meet the [masking requirements](#masked-variable-requirements). + - **Key**: Must be one line, using only letters, numbers, or `_` (underscore), with no spaces. + - **Value**: [Since GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/220028), 10,000 characters allowed. This is also bounded by the limits of the selected Runner operating system. In GitLab 13.0 to 13.2, 700 characters allowed. + - **Type**: `File` or `Variable`. + - **Protect variable** (Optional): If selected, the variable is only available in pipelines that run on protected branches or tags. + - **Mask variable** (Optional): If selected, the variable's **Value** is not shown in job logs. The variable is not saved if the value does not meet the [masking requirements](#masked-variable-requirements). After a variable is created, you can update any of the details by clicking the **{pencil}** **Edit** button. @@ -540,14 +540,14 @@ For example, if you define: - `API_TOKEN=secure` as a project variable. - `API_TOKEN=yaml` in your `.gitlab-ci.yml`. -`API_TOKEN` will take the value `secure` as the project +`API_TOKEN` takes the value `secure` as the project variables take precedence over those defined in `.gitlab-ci.yml`. ## Unsupported variables Variable names are limited by the underlying shell used to execute scripts (see [available shells](https://docs.gitlab.com/runner/shells/index.html). Each shell has its own unique set of reserved variable names. -You will also want to keep in mind the [scope of environment variables](where_variables_can_be_used.md) to ensure a variable is defined in the scope +You also want to keep in mind the [scope of environment variables](where_variables_can_be_used.md) to ensure a variable is defined in the scope in which you wish to use it. ## Where variables can be used @@ -585,8 +585,8 @@ pass CI variables to the running application by prefixing the key of the variable with `K8S_SECRET_`. These [prefixed -variables](../../topics/autodevops/customize.md#application-secret-variables) will -then be available as environment variables on the running application +variables](../../topics/autodevops/customize.md#application-secret-variables) are +then available as environment variables on the running application container. CAUTION: **Caution:** @@ -649,94 +649,132 @@ This follows the usual rules for [`only` / `except` policies](../yaml/README.md# ### Syntax of environment variable expressions -Below you can find supported syntax reference: +Below you can find supported syntax reference. + +#### Equality matching using a string + +Examples: + +- `$VARIABLE == "some value"` +- `$VARIABLE != "some value"` (introduced in GitLab 11.11) + +You can use equality operator `==` or `!=` to compare a variable content to a +string. We support both, double quotes and single quotes to define a string +value, so both `$VARIABLE == "some value"` and `$VARIABLE == 'some value'` +are supported. `"some value" == $VARIABLE` is correct too. + +#### Checking for an undefined value + +Examples: + +- `$VARIABLE == null` +- `$VARIABLE != null` (introduced in GitLab 11.11) + +It sometimes happens that you want to check whether a variable is defined +or not. To do that, you can compare a variable to `null` keyword, like +`$VARIABLE == null`. This expression evaluates to true if +variable is not defined when `==` is used, or to false if `!=` is used. + +#### Checking for an empty variable -1. Equality matching using a string +Examples: - Examples: +- `$VARIABLE == ""` +- `$VARIABLE != ""` (introduced in GitLab 11.11) - - `$VARIABLE == "some value"` - - `$VARIABLE != "some value"` (introduced in GitLab 11.11) +If you want to check whether a variable is defined, but is empty, you can +simply compare it against an empty string, like `$VAR == ''` or non-empty +string `$VARIABLE != ""`. - You can use equality operator `==` or `!=` to compare a variable content to a - string. We support both, double quotes and single quotes to define a string - value, so both `$VARIABLE == "some value"` and `$VARIABLE == 'some value'` - are supported. `"some value" == $VARIABLE` is correct too. +#### Comparing two variables -1. Checking for an undefined value +Examples: - Examples: +- `$VARIABLE_1 == $VARIABLE_2` +- `$VARIABLE_1 != $VARIABLE_2` (introduced in GitLab 11.11) - - `$VARIABLE == null` - - `$VARIABLE != null` (introduced in GitLab 11.11) +It is possible to compare two variables. This compares values +of these variables. - It sometimes happens that you want to check whether a variable is defined - or not. To do that, you can compare a variable to `null` keyword, like - `$VARIABLE == null`. This expression evaluates to true if - variable is not defined when `==` is used, or to false if `!=` is used. +#### Variable presence check -1. Checking for an empty variable +Example: `$STAGING` - Examples: +If you only want to create a job when there is some variable present, +which means that it is defined and non-empty, you can simply use +variable name as an expression, like `$STAGING`. If `$STAGING` variable +is defined, and is non empty, expression evaluates to `true`. +`$STAGING` value needs to be a string, with length higher than zero. +Variable that contains only whitespace characters is not an empty variable. - - `$VARIABLE == ""` - - `$VARIABLE != ""` (introduced in GitLab 11.11) +#### Regex pattern matching - If you want to check whether a variable is defined, but is empty, you can - simply compare it against an empty string, like `$VAR == ''` or non-empty - string `$VARIABLE != ""`. +> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/43601) in GitLab 11.0 -1. Comparing two variables +Examples: - Examples: +- `=~`: True if pattern is matched. Ex: `$VARIABLE =~ /^content.*/` +- `!~`: True if pattern is not matched. Ex: `$VARIABLE_1 !~ /^content.*/` ([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/61900) in GitLab 11.11) - - `$VARIABLE_1 == $VARIABLE_2` - - `$VARIABLE_1 != $VARIABLE_2` (introduced in GitLab 11.11) +Variable pattern matching with regular expressions uses the +[RE2 regular expression syntax](https://github.com/google/re2/wiki/Syntax). +Expressions evaluate as `true` if: - It is possible to compare two variables. This is going to compare values - of these variables. +- Matches are found when using `=~`. +- Matches are *not* found when using `!~`. -1. Variable presence check +Pattern matching is case-sensitive by default. Use `i` flag modifier, like +`/pattern/i` to make a pattern case-insensitive. - Example: `$STAGING` +#### Conjunction / Disjunction - If you only want to create a job when there is some variable present, - which means that it is defined and non-empty, you can simply use - variable name as an expression, like `$STAGING`. If `$STAGING` variable - is defined, and is non empty, expression will evaluate to truth. - `$STAGING` value needs to be a string, with length higher than zero. - Variable that contains only whitespace characters is not an empty variable. +> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/62867) in GitLab 12.0 -1. Pattern matching (introduced in GitLab 11.0) +Examples: - Examples: +- `$VARIABLE1 =~ /^content.*/ && $VARIABLE2 == "something"` +- `$VARIABLE1 =~ /^content.*/ && $VARIABLE2 =~ /thing$/ && $VARIABLE3` +- `$VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/ && $VARIABLE3` - - `=~`: True if pattern is matched. Ex: `$VARIABLE =~ /^content.*/` - - `!~`: True if pattern is not matched. Ex: `$VARIABLE_1 !~ /^content.*/` ([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/61900) in GitLab 11.11) +It is possible to join multiple conditions using `&&` or `||`. Any of the otherwise +supported syntax may be used in a conjunctive or disjunctive statement. +Precedence of operators follows the +[Ruby 2.5 standard](https://ruby-doc.org/core-2.5.0/doc/syntax/precedence_rdoc.html), +so `&&` is evaluated before `||`. - Variable pattern matching with regular expressions uses the - [RE2 regular expression syntax](https://github.com/google/re2/wiki/Syntax). - Expressions evaluate as `true` if: +#### Parentheses - - Matches are found when using `=~`. - - Matches are *not* found when using `!~`. +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230938) in GitLab 13.3 - Pattern matching is case-sensitive by default. Use `i` flag modifier, like - `/pattern/i` to make a pattern case-insensitive. +It is possible to use parentheses to group conditions. Parentheses have the highest +precedence of all operators. Expressions enclosed in parentheses are evaluated first, +and the result is used for the rest of the expression. -1. Conjunction / Disjunction ([introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27925) in GitLab 12.0) +Many nested parentheses can be used to create complex conditions, and the inner-most +expressions in parentheses are evaluated first. For an expression to be valid an equal +number of `(` and `)` need to be used. - Examples: +Examples: - - `$VARIABLE1 =~ /^content.*/ && $VARIABLE2 == "something"` - - `$VARIABLE1 =~ /^content.*/ && $VARIABLE2 =~ /thing$/ && $VARIABLE3` - - `$VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/ && $VARIABLE3` +- `($VARIABLE1 =~ /^content.*/ || $VARIABLE2) && ($VARIABLE3 =~ /thing$/ || $VARIABLE4)` +- `($VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/) && $VARIABLE3` +- `$CI_COMMIT_BRANCH == "my-branch" || (($VARIABLE1 == "thing" || $VARIABLE2 == "thing") && $VARIABLE3)` - It is possible to join multiple conditions using `&&` or `||`. Any of the otherwise - supported syntax may be used in a conjunctive or disjunctive statement. - Precedence of operators follows the - [Ruby 2.5 standard](https://ruby-doc.org/core-2.5.0/doc/syntax/precedence_rdoc.html), - so `&&` is evaluated before `||`. +The feature is currently deployed behind a feature flag that is **enabled by default**. +[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md) +can opt to disable it for your instance. + +To enable it: + +```ruby +Feature.enable(:ci_if_parenthesis_enabled) +``` + +To disable it: + +```ruby +Feature.disable(:ci_if_parenthesis_enabled) +``` ### Storing regular expressions in variables diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md index 98a2e7ae22f..c79ea4b0d05 100644 --- a/doc/ci/variables/predefined_variables.md +++ b/doc/ci/variables/predefined_variables.md @@ -16,9 +16,8 @@ version of Runner required. NOTE: **Note:** Starting with GitLab 9.0, we have deprecated some variables. Read the -[9.0 Renaming](deprecated_variables.md#gitlab-90-renamed-variables) section to find out their replacements. **You are -strongly advised to use the new variables as we will remove the old ones in -future GitLab releases.** +[9.0 Renaming](deprecated_variables.md#gitlab-90-renamed-variables) section to find out their replacements. +**To avoid problems with deprecated and removed variables in future releases, you are strongly advised to use the new variables.** You can add a command to your `.gitlab-ci.yml` file to [output the values of all variables available for a job](README.md#list-all-environment-variables). @@ -49,6 +48,7 @@ Kubernetes-specific environment variables are detailed in the | `CI_CONFIG_PATH` | 9.4 | 0.5 | The path to CI configuration file. Defaults to `.gitlab-ci.yml` | | `CI_DEBUG_TRACE` | all | 1.7 | Whether [debug logging (tracing)](README.md#debug-logging) is enabled | | `CI_DEFAULT_BRANCH` | 12.4 | all | The name of the default branch for the project. | +| `CI_DEPLOY_FREEZE` | 13.2 | all | Included with the value `true` if the pipeline runs during a [deploy freeze window](../../user/project/releases/index.md#prevent-unintentional-releases-by-setting-a-deploy-freeze). | | `CI_DEPLOY_PASSWORD` | 10.8 | all | Authentication password of the [GitLab Deploy Token](../../user/project/deploy_tokens/index.md#gitlab-deploy-token), only present if the Project has one related. | | `CI_DEPLOY_USER` | 10.8 | all | Authentication username of the [GitLab Deploy Token](../../user/project/deploy_tokens/index.md#gitlab-deploy-token), only present if the Project has one related. | | `CI_DISPOSABLE_ENVIRONMENT` | all | 10.1 | Marks that the job is executed in a disposable environment (something that is created only for this job and disposed of/destroyed after the execution - all executors except `shell` and `ssh`). If the environment is disposable, it is set to true, otherwise it is not defined at all. | @@ -56,6 +56,8 @@ Kubernetes-specific environment variables are detailed in the | `CI_ENVIRONMENT_SLUG` | 8.15 | all | A simplified version of the environment name, suitable for inclusion in DNS, URLs, Kubernetes labels, etc. Only present if [`environment:name`](../yaml/README.md#environmentname) is set. | | `CI_ENVIRONMENT_URL` | 9.3 | all | The URL of the environment for this job. Only present if [`environment:url`](../yaml/README.md#environmenturl) is set. | | `CI_EXTERNAL_PULL_REQUEST_IID` | 12.3 | all | Pull Request ID from GitHub if the [pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. | +| `CI_EXTERNAL_PULL_REQUEST_SOURCE_REPOSITORY` | 13.3 | all | The source repository name of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. | +| `CI_EXTERNAL_PULL_REQUEST_TARGET_REPOSITORY` | 13.3 | all | The target repository name of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. | | `CI_EXTERNAL_PULL_REQUEST_SOURCE_BRANCH_NAME` | 12.3 | all | The source branch name of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. | | `CI_EXTERNAL_PULL_REQUEST_SOURCE_BRANCH_SHA` | 12.3 | all | The HEAD SHA of the source branch of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. | | `CI_EXTERNAL_PULL_REQUEST_TARGET_BRANCH_NAME` | 12.3 | all | The target branch name of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. | @@ -71,8 +73,8 @@ Kubernetes-specific environment variables are detailed in the | `CI_JOB_URL` | 11.1 | 0.5 | Job details URL | | `CI_KUBERNETES_ACTIVE` | 13.0 | all | Included with the value `true` only if the pipeline has a Kubernetes cluster available for deployments. Not included if no cluster is available. Can be used as an alternative to [`only:kubernetes`/`except:kubernetes`](../yaml/README.md#onlykubernetesexceptkubernetes) with [`rules:if`](../yaml/README.md#rulesif) | | `CI_MERGE_REQUEST_ASSIGNEES` | 11.9 | all | Comma-separated list of username(s) of assignee(s) for the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | -| `CI_MERGE_REQUEST_ID` | 11.6 | all | The project-level ID of the merge request. Only available if [the pipelines are for merge requests](../merge_request_pipelines/index.md) and the merge request is created. | -| `CI_MERGE_REQUEST_IID` | 11.6 | all | The instance-level IID of the merge request. Only available If [the pipelines are for merge requests](../merge_request_pipelines/index.md) and the merge request is created. | +| `CI_MERGE_REQUEST_ID` | 11.6 | all | The instance-level ID of the merge request. Only available if [the pipelines are for merge requests](../merge_request_pipelines/index.md) and the merge request is created. | +| `CI_MERGE_REQUEST_IID` | 11.6 | all | The project-level IID (internal ID) of the merge request. Only available If [the pipelines are for merge requests](../merge_request_pipelines/index.md) and the merge request is created. | | `CI_MERGE_REQUEST_LABELS` | 11.9 | all | Comma-separated label names of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | | `CI_MERGE_REQUEST_MILESTONE` | 11.9 | all | The milestone title of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | | `CI_MERGE_REQUEST_PROJECT_ID` | 11.6 | all | The ID of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | @@ -92,9 +94,9 @@ Kubernetes-specific environment variables are detailed in the | `CI_NODE_TOTAL` | 11.5 | all | Total number of instances of this job running in parallel. If the job is not parallelized, this variable is set to `1`. | | `CI_PAGES_DOMAIN` | 11.8 | all | The configured domain that hosts GitLab Pages. | | `CI_PAGES_URL` | 11.8 | all | URL to GitLab Pages-built pages. Always belongs to a subdomain of `CI_PAGES_DOMAIN`. | -| `CI_PIPELINE_ID` | 8.10 | all | The unique ID of the current pipeline that GitLab CI/CD uses internally | -| `CI_PIPELINE_IID` | 11.0 | all | The unique ID of the current pipeline scoped to project | -| `CI_PIPELINE_SOURCE` | 10.0 | all | Indicates how the pipeline was triggered. Possible options are: `push`, `web`, `schedule`, `api`, `external`, `chat`, `webide`, `merge_request_event`, `external_pull_request_event`, `parent_pipeline`, [`trigger`, or `pipeline`](../triggers/README.md#authentication-tokens) (renamed to `cross_project_pipeline` since 13.0). For pipelines created before GitLab 9.5, this will show as `unknown`. | +| `CI_PIPELINE_ID` | 8.10 | all | The instance-level ID of the current pipeline. | +| `CI_PIPELINE_IID` | 11.0 | all | The project-level IID (internal ID) of the current pipeline. | +| `CI_PIPELINE_SOURCE` | 10.0 | all | Indicates how the pipeline was triggered. Possible options are: `push`, `web`, `schedule`, `api`, `external`, `chat`, `webide`, `merge_request_event`, `external_pull_request_event`, `parent_pipeline`, [`trigger`, or `pipeline`](../triggers/README.md#authentication-tokens) (renamed to `cross_project_pipeline` since 13.0). For pipelines created before GitLab 9.5, this is displayed as `unknown`. | | `CI_PIPELINE_TRIGGERED` | all | all | The flag to indicate that job was [triggered](../triggers/README.md) | | `CI_PIPELINE_URL` | 11.1 | 0.5 | Pipeline details URL | | `CI_PROJECT_DIR` | all | all | The full path where the repository is cloned and where the job is run. If the GitLab Runner `builds_dir` parameter is set, this variable is set relative to the value of `builds_dir`. For more information, see [Advanced configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section) for GitLab Runner. | @@ -108,7 +110,7 @@ Kubernetes-specific environment variables are detailed in the | `CI_PROJECT_TITLE` | 12.4 | all | The human-readable project name as displayed in the GitLab web interface. | | `CI_PROJECT_URL` | 8.10 | 0.5 | The HTTP(S) address to access project | | `CI_PROJECT_VISIBILITY` | 10.3 | all | The project visibility (internal, private, public) | -| `CI_REGISTRY` | 8.10 | 0.5 | If the Container Registry is enabled it returns the address of GitLab's Container Registry. This variable will include a `:port` value if one has been specified in the registry configuration. | +| `CI_REGISTRY` | 8.10 | 0.5 | If the Container Registry is enabled it returns the address of GitLab's Container Registry. This variable includes a `:port` value if one has been specified in the registry configuration. | | `CI_REGISTRY_IMAGE` | 8.10 | 0.5 | If the Container Registry is enabled for the project it returns the address of the registry tied to the specific project | | `CI_REGISTRY_PASSWORD` | 9.0 | all | The password to use to push containers to the GitLab Container Registry, for the current project. | | `CI_REGISTRY_USER` | 9.0 | all | The username to use to push containers to the GitLab Container Registry, for the current project. | diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index e1d1d27efed..694754a33d1 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -34,8 +34,8 @@ We have complete examples of configuring pipelines: > from 30 days to under 8 hours with GitLab. NOTE: **Note:** -If you have a [mirrored repository where GitLab pulls from](../../user/project/repository/repository_mirroring.md#pulling-from-a-remote-repository-starter), -you may need to enable pipeline triggering in your project's +If you have a [mirrored repository that GitLab pulls from](../../user/project/repository/repository_mirroring.md#pulling-from-a-remote-repository-starter), +you may need to enable pipeline triggering. Go to your project's **Settings > Repository > Pull from a remote repository > Trigger pipelines for mirror updates**. ## Introduction @@ -63,8 +63,8 @@ jobs, where each of the jobs executes a different command. Of course a command can execute code directly (`./configure;make;make install`) or run a script (`test.sh`) in the repository. -Jobs are picked up by [Runners](../runners/README.md) and executed within the -environment of the Runner. What is important, is that each job is run +Jobs are picked up by [runners](../runners/README.md) and executed within the +environment of the runner. What is important is that each job is run independently from each other. ### Validate the `.gitlab-ci.yml` @@ -103,37 +103,34 @@ The following table lists available parameters for jobs: | Keyword | Description | |:---------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [`script`](#script) | Shell script which is executed by Runner. | -| [`image`](#image) | Use Docker images. Also available: `image:name` and `image:entrypoint`. | -| [`services`](#services) | Use Docker services images. Also available: `services:name`, `services:alias`, `services:entrypoint`, and `services:command`. | -| [`before_script`](#before_script-and-after_script) | Override a set of commands that are executed before job. | +| [`script`](#script) | Shell script that is executed by a runner. | | [`after_script`](#before_script-and-after_script) | Override a set of commands that are executed after job. | -| [`stage`](#stage) | Defines a job stage (default: `test`). | -| [`only`](#onlyexcept-basic) | Limit when jobs are created. Also available: [`only:refs`, `only:kubernetes`, `only:variables`, and `only:changes`](#onlyexcept-advanced). | -| [`except`](#onlyexcept-basic) | Limit when jobs are not created. Also available: [`except:refs`, `except:kubernetes`, `except:variables`, and `except:changes`](#onlyexcept-advanced). | -| [`rules`](#rules) | List of conditions to evaluate and determine selected attributes of a job, and whether or not it's created. May not be used alongside `only`/`except`. | -| [`tags`](#tags) | List of tags which are used to select Runner. | -| [`allow_failure`](#allow_failure) | Allow job to fail. Failed job does not contribute to commit status. | -| [`when`](#when) | When to run job. Also available: `when:manual` and `when:delayed`. | -| [`environment`](#environment) | Name of an environment to which the job deploys. Also available: `environment:name`, `environment:url`, `environment:on_stop`, `environment:auto_stop_in` and `environment:action`. | +| [`allow_failure`](#allow_failure) | Allow job to fail. Failed job does not contribute to commit status. | +| [`artifacts`](#artifacts) | List of files and directories to attach to a job on success. Also available: `artifacts:paths`, `artifacts:exclude`, `artifacts:expose_as`, `artifacts:name`, `artifacts:untracked`, `artifacts:when`, `artifacts:expire_in`, `artifacts:reports`. | +| [`before_script`](#before_script-and-after_script) | Override a set of commands that are executed before job. | | [`cache`](#cache) | List of files that should be cached between subsequent runs. Also available: `cache:paths`, `cache:key`, `cache:untracked`, and `cache:policy`. | -| [`artifacts`](#artifacts) | List of files and directories to attach to a job on success. Also available: `artifacts:paths`, `artifacts:exclude`, `artifacts:expose_as`, `artifacts:name`, `artifacts:untracked`, `artifacts:when`, `artifacts:expire_in`, `artifacts:reports`, `artifacts:reports:codequality`, `artifacts:reports:junit`, `artifacts:reports:cobertura`, and `artifacts:reports:terraform`.

In GitLab [Enterprise Edition](https://about.gitlab.com/pricing/), these are available: `artifacts:reports:sast`, `artifacts:reports:dependency_scanning`, `artifacts:reports:container_scanning`, `artifacts:reports:dast`, `artifacts:reports:license_scanning`, `artifacts:reports:license_management` (removed in GitLab 13.0), `artifacts:reports:performance`, `artifacts:reports:load_performance`, and `artifacts:reports:metrics`. | -| [`dependencies`](#dependencies) | Restrict which artifacts are passed to a specific job by providing a list of jobs to fetch artifacts from. | | [`coverage`](#coverage) | Code coverage settings for a given job. | +| [`dependencies`](#dependencies) | Restrict which artifacts are passed to a specific job by providing a list of jobs to fetch artifacts from. | +| [`environment`](#environment) | Name of an environment to which the job deploys. Also available: `environment:name`, `environment:url`, `environment:on_stop`, `environment:auto_stop_in` and `environment:action`. | +| [`except`](#onlyexcept-basic) | Limit when jobs are not created. Also available: [`except:refs`, `except:kubernetes`, `except:variables`, and `except:changes`](#onlyexcept-advanced). | +| [`extends`](#extends) | Configuration entries that this job inherits from. | +| [`image`](#image) | Use Docker images. Also available: `image:name` and `image:entrypoint`. | +| [`include`](#include) | Allows this job to include external YAML files. Also available: `include:local`, `include:file`, `include:template`, and `include:remote`. | +| [`interruptible`](#interruptible) | Defines if a job can be canceled when made redundant by a newer run. | +| [`only`](#onlyexcept-basic) | Limit when jobs are created. Also available: [`only:refs`, `only:kubernetes`, `only:variables`, and `only:changes`](#onlyexcept-advanced). | +| [`pages`](#pages) | Upload the result of a job to use with GitLab Pages. | +| [`parallel`](#parallel) | How many instances of a job should be run in parallel. | +| [`release`](#release) | Instructs the runner to generate a [Release](../../user/project/releases/index.md) object. | +| [`resource_group`](#resource_group) | Limit job concurrency. | | [`retry`](#retry) | When and how many times a job can be auto-retried in case of a failure. | +| [`rules`](#rules) | List of conditions to evaluate and determine selected attributes of a job, and whether or not it's created. May not be used alongside `only`/`except`. | +| [`services`](#services) | Use Docker services images. Also available: `services:name`, `services:alias`, `services:entrypoint`, and `services:command`. | +| [`stage`](#stage) | Defines a job stage (default: `test`). | +| [`tags`](#tags) | List of tags that are used to select a runner. | | [`timeout`](#timeout) | Define a custom job-level timeout that takes precedence over the project-wide setting. | -| [`parallel`](#parallel) | How many instances of a job should be run in parallel. | | [`trigger`](#trigger) | Defines a downstream pipeline trigger. | -| [`include`](#include) | Allows this job to include external YAML files. Also available: `include:local`, `include:file`, `include:template`, and `include:remote`. | -| [`extends`](#extends) | Configuration entries that this job is going to inherit from. | -| [`pages`](#pages) | Upload the result of a job to use with GitLab Pages. | | [`variables`](#variables) | Define job variables on a job level. | -| [`interruptible`](#interruptible) | Defines if a job can be canceled when made redundant by a newer run. | -| [`resource_group`](#resource_group) | Limit job concurrency. | -| [`release`](#release) | Instructs the Runner to generate a [Release](../../user/project/releases/index.md) object. | - -NOTE: **Note:** -Parameters `types` and `type` are [deprecated](#deprecated-parameters). +| [`when`](#when) | When to run job. Also available: `when:manual` and `when:delayed`. | ## Global parameters @@ -293,31 +290,66 @@ There are also two edge cases worth mentioning: > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29654) in GitLab 12.5 -The top-level `workflow:` key applies to the entirety of a pipeline, and will -determine whether or not a pipeline is created. It currently accepts a single +The top-level `workflow:` key applies to the entirety of a pipeline, and +determines whether or not a pipeline is created. It accepts a single `rules:` key that operates similarly to [`rules:` defined within jobs](#rules), enabling dynamic configuration of the pipeline. If you are new to GitLab CI/CD and `workflow: rules`, you may find the [`workflow:rules` templates](#workflowrules-templates) useful. -To define your own `workflow: rules`, the configuration options currently available are: +To define your own `workflow: rules`, the available configuration options are: - [`if`](#rulesif): Define a rule. - [`when`](#when): May be set to `always` or `never` only. If not provided, the default value is `always`​. -The list of `if` rules is evaluated until a single one is matched. If none -match, the last `when` will be used: +If a pipeline attempts to run but matches no rule, it's dropped and doesn't run. + +Use the example rules below exactly as written to allow pipelines that match the rule +to run. Add `when: never` to prevent pipelines that match the rule from running. See +the [common `if` clauses for `rules`](#common-if-clauses-for-rules) for more examples. + +| Example rules | Details | +|------------------------------------------------------|-----------------------------------------------------------| +| `if: '$CI_PIPELINE_SOURCE == "merge_request_event"'` | Control when merge request pipelines run. | +| `if: '$CI_PIPELINE_SOURCE == "push"'` | Control when both branch pipelines and tag pipelines run. | +| `if: $CI_COMMIT_TAG` | Control when tag pipelines run. | +| `if: $CI_COMMIT_BRANCH` | Control when branch pipelines run. | + +For example, in the following configuration, pipelines run for all `push` events (changes to +branches and new tags). Only push events with `-wip` in the commit message are excluded. Scheduled +pipelines and merge request pipelines don't run, as there's no rule allowing them. ```yaml workflow: rules: - if: $CI_COMMIT_REF_NAME =~ /-wip$/ when: never - - if: $CI_COMMIT_TAG + - if: '$CI_PIPELINE_SOURCE == "push"' +``` + +This example has strict rules, and no other pipelines can run. + +Alternatively, you can have loose rules by using only `when: never` rules, followed +by a final `when: always` rule. This allows all types of pipelines, except for any +that match the `when: never` rules: + +```yaml +workflow: + rules: + - if: '$CI_PIPELINE_SOURCE == "schedule"' + when: never + - if: '$CI_PIPELINE_SOURCE == "push"' when: never - when: always ``` +This example never allows pipelines for schedules or `push` (branches and tags) pipelines, +but does allow pipelines in **all** other cases, *including* merge request pipelines. + +As with `rules` defined in jobs, be careful not to use a configuration that allows +merge request pipelines and branch pipelines to run at the same time, or you could +have [duplicate pipelines](#prevent-duplicate-pipelines). + #### `workflow:rules` templates > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217732) in GitLab 13.0. @@ -367,7 +399,7 @@ It's also possible to have template files stored in a central repository and pro configuration files. This helps avoid duplicated configuration, for example, global default variables for all projects. `include` requires the external YAML file to have the extensions `.yml` or `.yaml`, -otherwise the external file won't be included. +otherwise the external file is not included. `include` supports the following inclusion methods: @@ -376,14 +408,14 @@ otherwise the external file won't be included. | [`local`](#includelocal) | Include a file from the local project repository. | | [`file`](#includefile) | Include a file from a different project repository. | | [`remote`](#includeremote) | Include a file from a remote URL. Must be publicly accessible. | -| [`template`](#includetemplate) | Include templates which are provided by GitLab. | +| [`template`](#includetemplate) | Include templates that are provided by GitLab. | The `include` methods do not support [variable expansion](../variables/where_variables_can_be_used.md#variables-usage). NOTE: **Note:** `.gitlab-ci.yml` configuration included by all methods is evaluated at pipeline creation. The configuration is a snapshot in time and persisted in the database. Any changes to -referenced `.gitlab-ci.yml` configuration won't be reflected in GitLab until the next pipeline is created. +referenced `.gitlab-ci.yml` configuration is not reflected in GitLab until the next pipeline is created. The files defined by `include` are: @@ -393,7 +425,7 @@ The files defined by `include` are: TIP: **Tip:** Use merging to customize and override included CI/CD configurations with local -definitions. Local definitions in `.gitlab-ci.yml` will override included definitions. +definitions. Local definitions in `.gitlab-ci.yml` override included definitions. NOTE: **Note:** Using [YAML anchors](#anchors) across different YAML files sourced by `include` is not @@ -405,11 +437,11 @@ of using YAML anchors, you can use the [`extends` keyword](#extends). `include:local` includes a file from the same repository as `.gitlab-ci.yml`. It's referenced using full paths relative to the root directory (`/`). -You can only use files that are currently tracked by Git on the same branch +You can only use files that are tracked by Git on the same branch your configuration file is on. In other words, when using a `include:local`, make sure that both `.gitlab-ci.yml` and the local file are on the same branch. -All [nested includes](#nested-includes) will be executed in the scope of the same project, +All [nested includes](#nested-includes) are executed in the scope of the same project, so it's possible to use local, project, remote, or template includes. NOTE: **Note:** @@ -423,7 +455,7 @@ include: ``` TIP: **Tip:** -Local includes can be used as a replacement for symbolic links which are not followed. +Local includes can be used as a replacement for symbolic links that are not followed. This can be defined as a short local include: @@ -462,7 +494,7 @@ include: file: '/templates/.gitlab-ci-template.yml' ``` -All [nested includes](#nested-includes) will be executed in the scope of the target project, +All [nested includes](#nested-includes) are executed in the scope of the target project, so it's possible to use local (relative to target project), project, remote or template includes. @@ -478,7 +510,7 @@ include: - remote: 'https://gitlab.com/awesome-project/raw/master/.gitlab-ci-template.yml' ``` -All [nested includes](#nested-includes) will be executed without context as public user, so only another remote +All [nested includes](#nested-includes) are executed without context as public user, so only another remote or public project, or template, is allowed. #### `include:template` @@ -504,7 +536,7 @@ include: - template: Auto-DevOps.gitlab-ci.yml ``` -All [nested includes](#nested-includes) will be executed only with the permission of the user, +All [nested includes](#nested-includes) are executed only with the permission of the user, so it's possible to use project, remote or template includes. #### Nested includes @@ -584,7 +616,7 @@ For more information, see [Available settings for `services`](../docker/using_do ### `script` `script` is the only required keyword that a job needs. It's a shell script -which is executed by the Runner. For example: +that is executed by the runner. For example: ```yaml job: @@ -603,14 +635,14 @@ job: ``` NOTE: **Note:** -Sometimes, `script` commands will need to be wrapped in single or double quotes. -For example, commands that contain a colon (`:`) need to be wrapped in quotes so +Sometimes, `script` commands must be wrapped in single or double quotes. +For example, commands that contain a colon (`:`) must be wrapped in quotes so that the YAML parser knows to interpret the whole thing as a string rather than a "key: value" pair. Be careful when using special characters: `:`, `{`, `}`, `[`, `]`, `,`, `&`, `*`, `#`, `?`, `|`, `-`, `<`, `>`, `=`, `!`, `%`, `@`, `` ` ``. -If any of the script commands return an exit code different from zero, the job -will fail and further commands won't be executed. This behavior can be avoided by +If any of the script commands return an exit code other than zero, the job +fails and further commands are not executed. You can avoid this behavior by storing the exit code in a variable: ```yaml @@ -631,7 +663,7 @@ This must be an array. Scripts specified in `before_script` are concatenated with any scripts specified in the main [`script`](#script), and executed together in a single shell. -`after_script` is used to define the command that will be run after each +`after_script` is used to define the command that runs after each job, including failed ones. This must be an array. Scripts specified in `after_script` are executed in a new shell, separate from any @@ -640,12 +672,12 @@ Scripts specified in `after_script` are executed in a new shell, separate from a - Have a current working directory set back to the default. - Have no access to changes done by scripts defined in `before_script` or `script`, including: - Command aliases and variables exported in `script` scripts. - - Changes outside of the working tree (depending on the Runner executor), like + - Changes outside of the working tree (depending on the runner executor), like software installed by a `before_script` or `script` script. - Have a separate timeout, which is hard coded to 5 minutes. See [related issue](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2716) for details. - Don't affect the job's exit code. If the `script` section succeeds and the - `after_script` times out or fails, the job will exit with code `0` (`Job Succeeded`). + `after_script` times out or fails, the job exits with code `0` (`Job Succeeded`). It's possible to overwrite a globally defined `before_script` or `after_script` if you set it per-job: @@ -704,14 +736,14 @@ job: - Write-Host "This text is not colored" ``` -#### Multiline commands +#### Multi-line commands You can split long commands into multi-line commands to improve readability -using [`|` (literal) and `>` (folded) YAML multiline block scalar indicators](https://yaml-multiline.info/). +using [`|` (literal) and `>` (folded) YAML multi-line block scalar indicators](https://yaml-multiline.info/). CAUTION: **Warning:** If multiple commands are combined into one command string, only the last command's -failure or success will be reported, +failure or success is reported, [incorrectly ignoring failures from earlier commands due to a bug](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25394). If the success of the job depends on the success or failure of these commands, you can run the commands as separate `script:` items, or add `exit 1` commands @@ -774,7 +806,7 @@ First command line is split over two lines. Second command line. ``` -When the `>` or `|` block scalar indicators are omitted, GitLab will form the command +When you omit the `>` or `|` block scalar indicators, GitLab forms the command by concatenating non-empty lines, so make sure the lines can run when concatenated. Shell [here documents](https://en.wikipedia.org/wiki/Here_document) work with the @@ -799,9 +831,13 @@ $ tr a-z A-Z << END_TEXT # collapsed multi-line command FOUR FIVE SIX ``` +#### Custom collapsible sections + +See [custom collapsible sections](../pipelines/index.md#custom-collapsible-sections). + ### `stage` -`stage` is defined per-job and relies on [`stages`](#stages) which is defined +`stage` is defined per-job and relies on [`stages`](#stages), which is defined globally. It allows to group jobs into different stages, and jobs of the same `stage` are executed in parallel (subject to [certain conditions](#using-your-own-runners)). For example: @@ -836,16 +872,16 @@ job 5: script: make something useful at the end of pipeline ``` -#### Using your own Runners +#### Using your own runners -When using your own Runners, GitLab Runner runs only one job at a time by default (see the -`concurrent` flag in [Runner global settings](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section) -for more information). +When you use your own runners, GitLab Runner runs only one job at a time by default. See the +`concurrent` flag in [runner global settings](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section) +for more information. -Jobs will run on your own Runners in parallel only if: +Jobs run on your own runners in parallel only if: -- Run on different Runners. -- The Runner's `concurrent` setting has been changed. +- Run on different runners. +- The runner's `concurrent` setting has been changed. #### `.pre` and `.post` @@ -890,14 +926,14 @@ For example, the following are equivalent configuration: ``` NOTE: **Note:** -A pipeline won't be created if it only contains jobs in `.pre` or `.post` stages. +A pipeline is not created if all jobs are in `.pre` or `.post` stages. ### `extends` > Introduced in GitLab 11.3. -`extends` defines entry names that a job that uses `extends` is going to -inherit from. +`extends` defines entry names that a job that uses `extends` +inherits from. It's an alternative to using [YAML anchors](#anchors) and is a little more flexible and readable: @@ -919,12 +955,12 @@ rspec: ``` In the example above, the `rspec` job inherits from the `.tests` template job. -GitLab will perform a reverse deep merge based on the keys. GitLab will: +GitLab performs a reverse deep merge based on the keys. GitLab: -- Merge the `rspec` contents into `.tests` recursively. -- Not merge the values of the keys. +- Merges the `rspec` contents into `.tests` recursively. +- Doesn't merge the values of the keys. -This results in the following `rspec` job: +The result is this `rspec` job: ```yaml rspec: @@ -945,8 +981,8 @@ If you do want to include the `rake test`, see [`before_script` and `after_scrip `.tests` in this example is a [hidden job](#hide-jobs), but it's possible to inherit from regular jobs as well. -`extends` supports multi-level inheritance, however it's not recommended to -use more than three levels. The maximum nesting level that is supported is 10. +`extends` supports multi-level inheritance. You should avoid using more than 3 levels, +but you can use as many as ten. The following example has two levels of inheritance: ```yaml @@ -980,7 +1016,7 @@ In GitLab 12.0 and later, it's also possible to use multiple parents for `extends` is able to merge hashes but not arrays. The algorithm used for merge is "closest scope wins", so -keys from the last member will always override anything defined on other +keys from the last member always override anything defined on other levels. For example: ```yaml @@ -1062,7 +1098,7 @@ useTemplate: extends: .template ``` -This will run a job called `useTemplate` that runs `echo Hello!` as defined in +This example runs a job called `useTemplate` that runs `echo Hello!` as defined in the `.template` job, and uses the `alpine` Docker image as defined in the local job. ### `rules` @@ -1077,8 +1113,8 @@ If included, the job also has [certain attributes](#rules-attributes) added to it. CAUTION: **Caution:** -`rules` can't be used in combination with [`only/except`](#onlyexcept-basic) because it is a replacement for -that functionality. If you attempt to do this, the linter returns a +`rules` replaces [`only/except`](#onlyexcept-basic) and can't be used in conjunction with it. +If you attempt to use both keywords in the same job, the linter returns a `key may not be used with rules` error. #### Rules attributes @@ -1182,19 +1218,22 @@ job: - In **all other cases**, the job is added to the pipeline, with `when: on_success`. CAUTION: **Caution:** -If you use `when: on_success`, `always`, or `delayed` as the final rule, two +If you use a `when:` clause as the final rule (not including `when: never`), two simultaneous pipelines may start. Both push pipelines and merge request pipelines can be triggered by the same event (a push to the source branch for an open merge request). -See the [important differences between `rules` and `only`/`except`](#differences-between-rules-and-onlyexcept) +See how to [prevent duplicate pipelines](#prevent-duplicate-pipelines) for more details. -#### Differences between `rules` and `only`/`except` +#### Prevent duplicate pipelines -Jobs defined with `only/except` do not trigger merge request pipelines by default. -You must explicitly add `only: merge_requests`. +Jobs defined with `rules` can trigger multiple pipelines with the same action. You +don't have to explicitly configure rules for each type of pipeline to trigger them +accidentally. Rules that are too loose (allowing too many types of pipelines) could +cause a second pipeline to run unexpectedly. -Jobs defined with `rules` can trigger all types of pipelines. -You do not have to explicitly configure each type. +Some configurations that have the potential to cause duplicate pipelines cause a +[pipeline warning](../troubleshooting.md#pipeline-warnings) to be displayed. +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/219431) in GitLab 13.3. For example: @@ -1210,19 +1249,79 @@ job: This job does not run when `$CUSTOM_VARIABLE` is false, but it *does* run in **all** other pipelines, including **both** push (branch) and merge request pipelines. With this configuration, every push to an open merge request's source branch -causes duplicated pipelines. Explicitly allowing both push and merge request pipelines -in the same job could have the same effect. +causes duplicated pipelines. + +There are multiple ways to avoid this: + +- Use [`workflow: rules`](#workflowrules) to specify which types of pipelines + can run. To eliminate duplicate pipelines, allow only merge request pipelines + or push (branch) pipelines. + +- Rewrite the rules to run the job only in very specific cases, + and avoid using a final `when:` rule: -We recommend using [`workflow: rules`](#workflowrules) to limit which types of pipelines -are permitted. Allowing only merge request pipelines, or only branch pipelines, -eliminates duplicated pipelines. Alternatively, you can rewrite the rules to be -stricter, or avoid using a final `when` (`always`, `on_success` or `delayed`). + ```yaml + job: + script: "echo This does NOT create double pipelines!" + rules: + - if: '$CUSTOM_VARIABLE == "true" && $CI_PIPELINE_SOURCE == "merge_request_event"' + ``` -Also, we don't recommend mixing `only/except` jobs with `rules` jobs in the same pipeline. -It may not cause YAML errors, but debugging the exact execution behavior can be complex -due to the different default behaviors of `only/except` and `rules`. +You can prevent duplicate pipelines by changing the job rules to avoid either push (branch) +pipelines or merge request pipelines. However, if you use a `- when: always` rule without +`workflow: rules`, GitLab still displays a [pipeline warning](../troubleshooting.md#pipeline-warnings). -##### `rules:if` +For example, the following does not trigger double pipelines, but is not recommended +without `workflow: rules`: + +```yaml +job: + script: "echo This does NOT create double pipelines!" + rules: + - if: '$CI_PIPELINE_SOURCE == "push"' + when: never + - when: always +``` + +Do not include both push and merge request pipelines in the same job: + +```yaml +job: + script: "echo This creates double pipelines!" + rules: + - if: '$CI_PIPELINE_SOURCE == "push"' + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' +``` + +Also, do not mix `only/except` jobs with `rules` jobs in the same pipeline. +It may not cause YAML errors, but the different default behaviors of `only/except` +and `rules` can cause issues that are difficult to troubleshoot: + +```yaml +job-with-no-rules: + script: "echo This job runs in branch pipelines." + +job-with-rules: + script: "echo This job runs in merge request pipelines." + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' +``` + +For every change pushed to the branch, duplicate pipelines run. One +branch pipeline runs a single job (`job-with-no-rules`), and one merge request pipeline +runs the other job (`job-with-rules`). Jobs with no rules default +to [`except: merge_requests`](#onlyexcept-basic), so `job-with-no-rules` +runs in all cases except merge requests. + +It is not possible to define rules based on whether or not a branch has an open +merge request associated with it. You can't configure a job to be included in: + +- Only branch pipelines when the branch doesn't have a merge request associated with it. +- Only merge request pipelines when the branch has a merge request associated with it. + +See the [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/201845) for more details. + +#### `rules:if` `rules:if` clauses determine whether or not jobs are added to a pipeline by evaluating a simple `if` statement. If the `if` statement is true, the job is either included @@ -1233,7 +1332,8 @@ or excluded from a pipeline. In plain English, `if` rules can be interpreted as `rules:if` differs slightly from `only:variables` by accepting only a single expression string per rule, rather than an array of them. Any set of expressions to be -evaluated can be conjoined into a single expression by using `&&` or `||`, and use +evaluated can be [conjoined into a single expression](../variables/README.md#conjunction--disjunction) +by using `&&` or `||`, and use the [variable matching syntax](../variables/README.md#syntax-of-environment-variable-expressions). `if:` clauses are evaluated based on the values of [predefined environment variables](../variables/predefined_variables.md) @@ -1264,23 +1364,25 @@ Some details regarding the logic that determines the `when` for the job: - You can define `when` once per rule, or once at the job-level, which applies to all rules. You can't mix `when` at the job-level with `when` in rules. +##### Common `if` clauses for `rules` + For behavior similar to the [`only`/`except` keywords](#onlyexcept-basic), you can -check the value of the `$CI_PIPELINE_SOURCE` variable. - -| Value | Description | -|-------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `push` | For pipelines triggered by a `git push` event, including for branches and tags. | -| `web` | For pipelines created by using **Run pipeline** button in the GitLab UI, from the project's **CI/CD > Pipelines** section. | -| `trigger` | For pipelines created by using a trigger token. | -| `schedule` | For [scheduled pipelines](../pipelines/schedules.md). | -| `api` | For pipelines triggered by the [pipelines API](../../api/pipelines.md#create-a-new-pipeline). | -| `external` | When using CI services other than GitLab. | -| `pipelines` | For multi-project pipelines created by [using the API with `CI_JOB_TOKEN`](../triggers/README.md#when-used-with-multi-project-pipelines). | -| `chat` | For pipelines created by using a [GitLab ChatOps](../chatops/README.md) command. | -| `webide` | For pipelines created by using the [WebIDE](../../user/project/web_ide/index.md). | +check the value of the `$CI_PIPELINE_SOURCE` variable: + +| Value | Description | +|-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `api` | For pipelines triggered by the [pipelines API](../../api/pipelines.md#create-a-new-pipeline). | +| `chat` | For pipelines created by using a [GitLab ChatOps](../chatops/README.md) command. | +| `external` | When using CI services other than GitLab. | +| `external_pull_request_event` | When an external pull request on GitHub is created or updated. See [Pipelines for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). | | `merge_request_event` | For pipelines created when a merge request is created or updated. Required to enable [merge request pipelines](../merge_request_pipelines/index.md), [merged results pipelines](../merge_request_pipelines/pipelines_for_merged_results/index.md), and [merge trains](../merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md). | -| `external_pull_request_event` | When an external pull request on GitHub is created or updated. See [Pipelines for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). | -| `parent_pipeline` | For pipelines triggered by a [parent/child pipeline](../parent_child_pipelines.md) with `rules`, use this in the child pipeline configuration so that it can be triggered by the parent pipeline. | +| `parent_pipeline` | For pipelines triggered by a [parent/child pipeline](../parent_child_pipelines.md) with `rules`, use this in the child pipeline configuration so that it can be triggered by the parent pipeline. | +| `pipeline` | For [multi-project pipelines](../multi_project_pipelines.md) created by [using the API with `CI_JOB_TOKEN`](../multi_project_pipelines.md#triggering-multi-project-pipelines-through-api), or the [`trigger`](#trigger) keyword. | +| `push` | For pipelines triggered by a `git push` event, including for branches and tags. | +| `schedule` | For [scheduled pipelines](../pipelines/schedules.md). | +| `trigger` | For pipelines created by using a [trigger token](../triggers/README.md#trigger-token). | +| `web` | For pipelines created by using **Run pipeline** button in the GitLab UI, from the project's **CI/CD > Pipelines** section. | +| `webide` | For pipelines created by using the [WebIDE](../../user/project/web_ide/index.md). | For example: @@ -1325,14 +1427,14 @@ Other commonly used variables for `if` clauses: - `if: '$CUSTOM_VARIABLE == "value1"'`: If the custom variable `CUSTOM_VARIABLE` is exactly `value1`. -##### `rules:changes` +#### `rules:changes` To determine if jobs should be added to a pipeline, `rules: changes` clauses check the files changed by Git push events. `rules: changes` works exactly the same way as [`only: changes` and `except: changes`](#onlychangesexceptchanges), accepting an array of paths. Similarly, it always returns true if there is no -Git push event. It should only be used for branch pipelines or merge request pipelines. +Git push event, for example, when a new tag is created. It should only be used for branch pipelines or merge request pipelines. For example: @@ -1357,11 +1459,14 @@ In this example: to continue running even if the job is not triggered (`allow_failure: true`). - If `Dockerfile` has not changed, do not add job to any pipeline (same as `when: never`). -##### `rules:exists` +To implement a rule similar to [`except: changes`](#onlychangesexceptchanges), +use `when: never`. + +#### `rules:exists` > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24021) in GitLab 12.4. -`exists` accepts an array of paths and will match if any of these paths exist +`exists` accepts an array of paths and matches if any of these paths exist as files in the repository. For example: @@ -1389,9 +1494,9 @@ job: NOTE: **Note:** For performance reasons, using `exists` with patterns is limited to 10000 -checks. After the 10000th check, rules with patterned globs will always match. +checks. After the 10000th check, rules with patterned globs always match. -##### `rules:allow_failure` +#### `rules:allow_failure` > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30235) in GitLab 12.8. @@ -1412,18 +1517,18 @@ job: allow_failure: true ``` -In this example, if the first rule matches, then the job will have `when: manual` and `allow_failure: true`. +In this example, if the first rule matches, then the job has `when: manual` and `allow_failure: true`. #### Complex rule clauses -To conjoin `if`, `changes`, and `exists` clauses with an AND, use them in the +To conjoin `if`, `changes`, and `exists` clauses with an `AND`, use them in the same rule. In the following example: -- We run the job manually if `Dockerfile` or any file in `docker/scripts/` - has changed AND `$VAR == "string value"`. -- Otherwise, the job won't be included in the pipeline. +- If the dockerfile or any file in `/docker/scripts` has changed, and var=blah, + then the job runs manually +- Otherwise, the job isn't included in the pipeline. ```yaml docker build: @@ -1453,9 +1558,9 @@ the most out of your pipelines. `only` and `except` are two parameters that set a job policy to limit when jobs are created: -1. `only` defines the names of branches and tags for which the job will run. -1. `except` defines the names of branches and tags for which the job will - **not** run. +1. `only` defines the names of branches and tags the job runs for. +1. `except` defines the names of branches and tags the job does + **not** run for. There are a few rules that apply to the usage of job policy: @@ -1467,20 +1572,20 @@ There are a few rules that apply to the usage of job policy: In addition, `only` and `except` allow the use of special keywords: -| **Value** | **Description** | -|--------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `branches` | When the Git reference for a pipeline is a branch. | -| `tags` | When the Git reference for a pipeline is a tag. | -| `api` | For pipelines triggered by the [pipelines API](../../api/pipelines.md#create-a-new-pipeline). | -| `external` | When using CI services other than GitLab. | -| `pipelines` | For multi-project pipelines created by using the API with `CI_JOB_TOKEN`. | -| `pushes` | For pipelines triggered by a `git push` event, including for branches and tags. | -| `schedules` | For [scheduled pipelines](../pipelines/schedules.md). | -| `triggers` | For pipelines created by using a trigger token. | -| `web` | For pipelines created by using **Run pipeline** button in the GitLab UI, from the project's **CI/CD > Pipelines** section. | -| `merge_requests` | For pipelines created when a merge request is created or updated. Enables [merge request pipelines](../merge_request_pipelines/index.md), [merged results pipelines](../merge_request_pipelines/pipelines_for_merged_results/index.md), and [merge trains](../merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md). | -| `external_pull_requests` | When an external pull request on GitHub is created or updated (See [Pipelines for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests)). | -| `chat` | For pipelines created by using a [GitLab ChatOps](../chatops/README.md) command. | +| **Value** | **Description** | +|--------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `api` | For pipelines triggered by the [pipelines API](../../api/pipelines.md#create-a-new-pipeline). | +| `branches` | When the Git reference for a pipeline is a branch. | +| `chat` | For pipelines created by using a [GitLab ChatOps](../chatops/README.md) command. | +| `external` | When using CI services other than GitLab. | +| `external_pull_requests` | When an external pull request on GitHub is created or updated (See [Pipelines for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests)). | +| `merge_requests` | For pipelines created when a merge request is created or updated. Enables [merge request pipelines](../merge_request_pipelines/index.md), [merged results pipelines](../merge_request_pipelines/pipelines_for_merged_results/index.md), and [merge trains](../merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md). | +| `pipelines` | For [multi-project pipelines](../multi_project_pipelines.md) created by [using the API with `CI_JOB_TOKEN`](../multi_project_pipelines.md#triggering-multi-project-pipelines-through-api), or the [`trigger`](#trigger) keyword. | +| `pushes` | For pipelines triggered by a `git push` event, including for branches and tags. | +| `schedules` | For [scheduled pipelines](../pipelines/schedules.md). | +| `tags` | When the Git reference for a pipeline is a tag. | +| `triggers` | For pipelines created by using a [trigger token](../triggers/README.md#trigger-token). | +| `web` | For pipelines created by using **Run pipeline** button in the GitLab UI, from the project's **CI/CD > Pipelines** section. | In the example below, `job` will run only for refs that start with `issue-`, whereas all branches will be skipped: @@ -1863,8 +1968,8 @@ properly corrected any failures from previous pipelines. Without [pipelines for merge requests](../merge_request_pipelines/index.md), pipelines run on branches or tags that don't have an explicit association with a merge request. -In this case, a previous SHA is used to calculate the diff, which equivalent to `git diff HEAD~`. -This could result in some unexpected behavior, including: +In this case, a previous SHA is used to calculate the diff, which is equivalent to `git diff HEAD~`. +This can result in some unexpected behavior, including: - When pushing a new branch or a new tag to GitLab, the policy always evaluates to true. - When pushing a new commit, the changed files are calculated using the previous commit @@ -1943,9 +2048,7 @@ This example creates four paths of execution: - The maximum number of jobs that a single job can need in the `needs:` array is limited: - For GitLab.com, the limit is ten. For more information, see our [infrastructure issue](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/7541). - - For self-managed instances, the limit is: - - 10, if the `ci_dag_limit_needs` feature flag is enabled (default). - - 50, if the `ci_dag_limit_needs` feature flag is disabled. + - For self-managed instances, the limit is: 50. This limit [can be changed](#changing-the-needs-job-limit-core-only). - If `needs:` refers to a job that is marked as `parallel:`. the current job will depend on all parallel jobs created. - `needs:` is similar to `dependencies:` in that it needs to use jobs from prior stages, @@ -1954,23 +2057,20 @@ This example creates four paths of execution: - Related to the above, stages must be explicitly defined for all jobs that have the keyword `needs:` or are referred to by one. -##### Changing the `needs:` job limit +##### Changing the `needs:` job limit **(CORE ONLY)** -The maximum number of jobs that can be defined within `needs:` defaults to 10, but -can be changed to 50 via a feature flag. To change the limit to 50, -[start a Rails console session](../../administration/troubleshooting/debug.md#starting-a-rails-console-session) -and run: +The maximum number of jobs that can be defined within `needs:` defaults to 50. -```ruby -Feature::disable(:ci_dag_limit_needs) -``` - -To set it back to 10, run the opposite command: +A GitLab administrator with [access to the GitLab Rails console](../../administration/feature_flags.md) +can choose a custom limit. For example, to set the limit to 100: ```ruby -Feature::enable(:ci_dag_limit_needs) +Plan.default.actual_limits.update!(ci_needs_size_limit: 100) ``` +NOTE: **Note:** +To disable the ability to use DAG, set the limit to `0`. + #### Artifact downloads with `needs` > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14311) in GitLab v12.6. @@ -2023,7 +2123,7 @@ rspec: `needs` can be used to download artifacts from up to five jobs in pipelines on [other refs in the same project](#artifact-downloads-between-pipelines-in-the-same-project), -or pipelines in different projects: +or pipelines in different projects, groups and namespaces: ```yaml build_job: @@ -2031,14 +2131,18 @@ build_job: script: - ls -lhR needs: - - project: group/project-name + - project: namespace/group/project-name job: build-1 ref: master artifacts: true ``` `build_job` will download the artifacts from the latest successful `build-1` job -on the `master` branch in the `group/project-name` project. +on the `master` branch in the `group/project-name` project. If the project is in the +same group or namespace, you can omit them from the `project:` key. For example, +`project: group/project-name` or `project: project-name`. + +The user running the pipeline must have at least `reporter` access to the group or project, or the group/project must have public visibility. ##### Artifact downloads between pipelines in the same project @@ -2059,18 +2163,38 @@ build_job: artifacts: true ``` +Environment variables support for `project:`, `job:`, and `ref` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202093) +in GitLab 13.3. This is under development, but it is ready for production use. It is deployed +behind the `ci_expand_names_for_cross_pipeline_artifacts` feature flag, which is **disabled by default**. +[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md) +can enable it for your instance. + +For example: + +```yaml +build_job: + stage: build + script: + - ls -lhR + needs: + - project: $CI_PROJECT_PATH + job: $DEPENDENCY_JOB_NAME + ref: $CI_COMMIT_BRANCH + artifacts: true +``` + NOTE: **Note:** Downloading artifacts from jobs that are run in [`parallel:`](#parallel) is not supported. ### `tags` -`tags` is used to select specific Runners from the list of all Runners that are +`tags` is used to select specific runners from the list of all runners that are allowed to run this project. -During the registration of a Runner, you can specify the Runner's tags, for +During the registration of a runner, you can specify the runner's tags, for example `ruby`, `postgres`, `development`. -`tags` allow you to run jobs with Runners that have the specified tags +`tags` allow you to run jobs with runners that have the specified tags assigned to them: ```yaml @@ -2080,11 +2204,11 @@ job: - postgres ``` -The specification above, will make sure that `job` is built by a Runner that +The specification above, will make sure that `job` is built by a runner that has both `ruby` AND `postgres` tags defined. Tags are also a great way to run different jobs on different platforms, for -example, given an OS X Runner with tag `osx` and Windows Runner with tag +example, given an OS X runner with tag `osx` and Windows runner with tag `windows`, the following jobs run on respective platforms: ```yaml @@ -2160,6 +2284,9 @@ failure. [manual actions](#whenmanual) below. 1. `delayed` - execute job after a certain period (added in GitLab 11.14). Read about [delayed actions](#whendelayed) below. +1. `never`: + - With [`rules`](#rules), don't execute job. + - With [`workflow:rules`](#workflowrules), don't run pipeline. For example: @@ -2323,8 +2450,8 @@ timed rollout 10%: You can stop the active timer of a delayed job by clicking the **{time-out}** (**Unschedule**) button. This job will never be executed in the future unless you execute the job manually. -You can start a delayed job immediately by clicking the **Play** button. -GitLab Runner will pick your job soon and start the job. +To start a delayed job immediately, click the **Play** button. +Soon GitLab Runner picks up and starts the job. ### `environment` @@ -2394,11 +2521,10 @@ deploy to production: > including predefined, secure variables and `.gitlab-ci.yml` [`variables`](#variables). > You however can't use variables defined under `script`. -This is an optional value that when set, it exposes buttons in various places -in GitLab which when clicked take you to the defined URL. +This optional value exposes buttons that take you to the defined URL -In the example below, if the job finishes successfully, it will create buttons -in the merge requests and in the environments/deployments pages which will point +In this example, if the job finishes successfully, it creates buttons +in the merge requests and in the environments/deployments pages that point to `https://prod.example.com`. ```yaml @@ -2427,8 +2553,13 @@ Read the `environment:action` section for an example. > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/22191) in GitLab 8.13. -The `action` keyword is to be used in conjunction with `on_stop` and is defined -in the job that is called to close the environment. +The `action` keyword can be used to specify jobs that prepare, start, or stop environments. + +| **Value** | **Description** | +|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------| +| start | Default value. Indicates that job starts the environment. Deployment will be created after job starts. | +| prepare | Indicates that job is only preparing the environment. Does not affect deployments. [Read more about environments](../environments/index.md#prepare-an-environment) | +| stop | Indicates that job stops deployment. See the example below. | Take for instance: @@ -2556,13 +2687,13 @@ deploy as review app: The `deploy as review app` job will be marked as deployment to dynamically create the `review/$CI_COMMIT_REF_NAME` environment, where `$CI_COMMIT_REF_NAME` -is an [environment variable](../variables/README.md) set by the Runner. The +is an [environment variable](../variables/README.md) set by the runner. The `$CI_ENVIRONMENT_SLUG` variable is based on the environment name, but suitable for inclusion in URLs. In this case, if the `deploy as review app` job was run in a branch named `pow`, this environment would be accessible with an URL like `https://review-pow.example.com/`. -This of course implies that the underlying server which hosts the application +This implies that the underlying server that hosts the application is properly configured. The common use case is to create dynamic environments for branches and use them @@ -2581,7 +2712,7 @@ TIP: **Learn more:** Read how caching works and find out some good practices in the [caching dependencies documentation](../caching/index.md). -`cache` is used to specify a list of files and directories which should be +`cache` is used to specify a list of files and directories that should be cached between jobs. You can only use paths that are within the local working copy. @@ -2590,7 +2721,7 @@ globally and all jobs will use that definition. #### `cache:paths` -Use the `paths` directive to choose which files or directories will be cached. Paths +Use the `paths` directive to choose which files or directories to cache. Paths are relative to the project directory (`$CI_PROJECT_DIR`) and can't directly link outside it. Wildcards can be used that follow the [glob](https://en.wikipedia.org/wiki/Glob_(programming)) patterns and: @@ -2645,8 +2776,8 @@ or any other way that fits your workflow. This way, you can fine tune caching, allowing you to cache data between different jobs or even different branches. The `cache:key` variable can use any of the -[predefined variables](../variables/README.md), and the default key, if not -set, is just literal `default` which means everything is shared between +[predefined variables](../variables/README.md). The default key, if not +set, is just literal `default`, which means everything is shared between pipelines and jobs by default, starting from GitLab 9.0. NOTE: **Note:** @@ -2818,7 +2949,7 @@ skip the download step. > - Not all executors are [supported](https://docs.gitlab.com/runner/executors/#compatibility-chart). > - Job artifacts are only collected for successful jobs by default. -`artifacts` is used to specify a list of files and directories which should be +`artifacts` is used to specify a list of files and directories that are attached to the job when it [succeeds, fails, or always](#artifactswhen). The artifacts will be sent to GitLab after the job finishes and will @@ -2961,11 +3092,11 @@ Note the following: > Introduced in GitLab 8.6 and GitLab Runner v1.1.0. -The `name` directive allows you to define the name of the created artifacts -archive. That way, you can have a unique name for every archive which could be -useful when you'd like to download the archive from GitLab. The `artifacts:name` +Use the `name` directive to define the name of the created artifacts +archive. You can specify a unique name for every archive, which can be +useful when you want to download the archive from GitLab. The `artifacts:name` variable can make use of any of the [predefined variables](../variables/README.md). -The default name is `artifacts`, which becomes `artifacts.zip` when downloaded. +The default name is `artifacts`, which becomes `artifacts.zip` when you download it. NOTE: **Note:** If your branch-name contains forward slashes @@ -3102,8 +3233,11 @@ stored on GitLab. If the expiry time is not defined, it defaults to the [instance wide setting](../../user/admin_area/settings/continuous_integration.md#default-artifacts-expiration-core-only) (30 days by default). -You can use the **Keep** button on the job page to override expiration and -keep artifacts forever. +To override the expiration date and protect artifacts from being automatically deleted: + +- Use the **Keep** button on the job page. +- Set the value of `expire_in` to `never`. [Available](https://gitlab.com/gitlab-org/gitlab/-/issues/22761) + in GitLab 13.3 and later. After their expiry, artifacts are deleted hourly by default (via a cron job), and are not accessible anymore. @@ -3118,6 +3252,7 @@ provided. Examples of valid values: - `6 mos 1 day` - `47 yrs 6 mos and 4d` - `3 weeks and 2 days` +- `never` To expire artifacts 1 week after being uploaded: @@ -3143,20 +3278,20 @@ These are the available report types: | Parameter | Description | |--------------------------------------------------------------------------------------------------------------------------------------|-------------| -| [`artifacts:reports:junit`](../pipelines/job_artifacts.md#artifactsreportsjunit) | The `junit` report collects JUnit XML files. | -| [`artifacts:reports:dotenv`](../pipelines/job_artifacts.md#artifactsreportsdotenv) | The `dotenv` report collects a set of environment variables. | | [`artifacts:reports:cobertura`](../pipelines/job_artifacts.md#artifactsreportscobertura) | The `cobertura` report collects Cobertura coverage XML files. | -| [`artifacts:reports:terraform`](../pipelines/job_artifacts.md#artifactsreportsterraform) | The `terraform` report collects Terraform `tfplan.json` files. | | [`artifacts:reports:codequality`](../pipelines/job_artifacts.md#artifactsreportscodequality) | The `codequality` report collects CodeQuality issues. | -| [`artifacts:reports:sast`](../pipelines/job_artifacts.md#artifactsreportssast-ultimate) **(ULTIMATE)** | The `sast` report collects Static Application Security Testing vulnerabilities. | -| [`artifacts:reports:dependency_scanning`](../pipelines/job_artifacts.md#artifactsreportsdependency_scanning-ultimate) **(ULTIMATE)** | The `dependency_scanning` report collects Dependency Scanning vulnerabilities. | | [`artifacts:reports:container_scanning`](../pipelines/job_artifacts.md#artifactsreportscontainer_scanning-ultimate) **(ULTIMATE)** | The `container_scanning` report collects Container Scanning vulnerabilities. | | [`artifacts:reports:dast`](../pipelines/job_artifacts.md#artifactsreportsdast-ultimate) **(ULTIMATE)** | The `dast` report collects Dynamic Application Security Testing vulnerabilities. | +| [`artifacts:reports:dependency_scanning`](../pipelines/job_artifacts.md#artifactsreportsdependency_scanning-ultimate) **(ULTIMATE)** | The `dependency_scanning` report collects Dependency Scanning vulnerabilities. | +| [`artifacts:reports:dotenv`](../pipelines/job_artifacts.md#artifactsreportsdotenv) | The `dotenv` report collects a set of environment variables. | +| [`artifacts:reports:junit`](../pipelines/job_artifacts.md#artifactsreportsjunit) | The `junit` report collects JUnit XML files. | | [`artifacts:reports:license_management`](../pipelines/job_artifacts.md#artifactsreportslicense_management-ultimate) **(ULTIMATE)** | The `license_management` report collects Licenses (*removed from GitLab 13.0*). | | [`artifacts:reports:license_scanning`](../pipelines/job_artifacts.md#artifactsreportslicense_scanning-ultimate) **(ULTIMATE)** | The `license_scanning` report collects Licenses. | -| [`artifacts:reports:performance`](../pipelines/job_artifacts.md#artifactsreportsperformance-premium) **(PREMIUM)** | The `performance` report collects Browser Performance metrics. | | [`artifacts:reports:load_performance`](../pipelines/job_artifacts.md#artifactsreportsload_performance-premium) **(PREMIUM)** | The `load_performance` report collects load performance metrics. | | [`artifacts:reports:metrics`](../pipelines/job_artifacts.md#artifactsreportsmetrics-premium) **(PREMIUM)** | The `metrics` report collects Metrics. | +| [`artifacts:reports:performance`](../pipelines/job_artifacts.md#artifactsreportsperformance-premium) **(PREMIUM)** | The `performance` report collects Browser Performance metrics. | +| [`artifacts:reports:sast`](../pipelines/job_artifacts.md#artifactsreportssast-ultimate) **(ULTIMATE)** | The `sast` report collects Static Application Security Testing vulnerabilities. | +| [`artifacts:reports:terraform`](../pipelines/job_artifacts.md#artifactsreportsterraform) | The `terraform` report collects Terraform `tfplan.json` files. | #### `dependencies` @@ -3167,7 +3302,7 @@ are passed, but you can use the `dependencies` parameter to define a limited list of jobs (or no jobs) to fetch artifacts from. To use this feature, define `dependencies` in context of the job and pass -a list of all previous jobs from which the artifacts should be downloaded. +a list of all previous jobs the artifacts should be downloaded from. You can only define jobs from stages that are executed before the current one. An error will be shown if you define jobs from the current stage or next ones. Defining an empty array will skip downloading any artifacts for that job. @@ -3251,7 +3386,7 @@ job1: ### `retry` > - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/3442) in GitLab 9.5. -> - [Behavior expanded](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3515) in GitLab 11.5 to control on which failures to retry. +> - [Behavior expanded](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3515) in GitLab 11.5 to control which failures to retry on. `retry` allows you to configure how many times a job is going to be retried in case of a failure. @@ -3272,7 +3407,7 @@ test: ``` By default, a job will be retried on all failure cases. To have a better control -on which failures to retry, `retry` can be a hash with the following keys: +over which failures to retry, `retry` can be a hash with the following keys: - `max`: The maximum number of retries. - `when`: The failure cases to retry. @@ -3347,7 +3482,7 @@ test: The job-level timeout can exceed the [project-level timeout](../pipelines/settings.md#timeout) but can't -exceed the Runner-specific timeout. +exceed the runner-specific timeout. ### `parallel` @@ -3398,6 +3533,48 @@ Please be aware that semaphore_test_boosters reports usages statistics to the au You can then navigate to the **Jobs** tab of a new pipeline build and see your RSpec job split into three separate jobs. +#### Parallel `matrix` jobs + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15356) in GitLab 13.3. + +`matrix:` allows you to configure different variables for jobs that are running in parallel. +There can be from 2 to 50 jobs. + +Every job gets the same `CI_NODE_TOTAL` [environment variable](../variables/README.md#predefined-environment-variables) value, and a unique `CI_NODE_INDEX` value. + +```yaml +deploystacks: + stage: deploy + script: + - bin/deploy + parallel: + matrix: + - PROVIDER: aws + STACK: + - monitoring + - app1 + - app2 + - PROVIDER: ovh + STACK: [monitoring, backup, app] + - PROVIDER: [gcp, vultr] + STACK: [data, processing] +``` + +This generates 10 parallel `deploystacks` jobs, each with different values for `PROVIDER` and `STACK`: + +```plaintext +deploystacks 1/10 with PROVIDER=aws and STACK=monitoring +deploystacks 2/10 with PROVIDER=aws and STACK=app1 +deploystacks 3/10 with PROVIDER=aws and STACK=app2 +deploystacks 4/10 with PROVIDER=ovh and STACK=monitoring +deploystacks 5/10 with PROVIDER=ovh and STACK=backup +deploystacks 6/10 with PROVIDER=ovh and STACK=app +deploystacks 7/10 with PROVIDER=gcp and STACK=data +deploystacks 8/10 with PROVIDER=gcp and STACK=processing +deploystacks 9/10 with PROVIDER=vultr and STACK=data +deploystacks 10/10 with PROVIDER=vultr and STACK=processing +``` + ### `trigger` > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8997) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.8. @@ -3606,16 +3783,16 @@ Once an uninterruptible job is running, the pipeline will never be canceled, reg > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15536) in GitLab 12.7. -Sometimes running multiples jobs or pipelines at the same time in an environment +Sometimes running multiple jobs or pipelines at the same time in an environment can lead to errors during the deployment. To avoid these errors, the `resource_group` attribute can be used to ensure that -the Runner won't run certain jobs simultaneously. +the runner doesn't run certain jobs simultaneously. When the `resource_group` key is defined for a job in `.gitlab-ci.yml`, job executions are mutually exclusive across different pipelines for the same project. If multiple jobs belonging to the same resource group are enqueued simultaneously, -only one of the jobs will be picked by the Runner, and the other jobs will wait until the +only one of the jobs is picked by the runner, and the other jobs wait until the `resource_group` is free. Here is a simple example: @@ -3645,8 +3822,7 @@ For more information, see [Deployments Safety](../environments/deployment_safety > [Introduced](https://gitlab.com/gitlab-org/gitlab/merge_requests/19298) in GitLab 13.2. -`release` indicates that the job creates a [Release](../../user/project/releases/index.md), -and optionally includes URLs for Release assets. +`release` indicates that the job creates a [Release](../../user/project/releases/index.md). These methods are supported: @@ -3779,25 +3955,46 @@ tags. These options cannot be used together, so choose one: # or can use a variable. ``` -- To create a release automatically when changes are pushed to the default branch, +- To create a release automatically when commits are pushed or merged to the default branch, using a new Git tag that is defined with variables: +NOTE: **Note:** +Environment variables set in `before_script` or `script` are not available for expanding +in the same job. Read more about +[potentially making variables available for expanding](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6400). + ```yaml + prepare_job: + stage: prepare # This stage must run before the release stage + rules: + - if: $CI_COMMIT_TAG + when: never # Do not run this job when a tag is created manually + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch + script: + - echo "EXTRA_DESCRIPTION=some message" >> variables.env # Generate the EXTRA_DESCRIPTION and TAG environment variables + - echo "TAG=v$(cat VERSION)" >> variables.env # and append to the variables.env file + artifacts: + reports: + dotenv: variables.env # Use artifacts:reports:dotenv to expose the variables to other jobs + release_job: stage: release image: registry.gitlab.com/gitlab-org/release-cli:latest + needs: + - job: prepare_job + artifacts: true rules: - if: $CI_COMMIT_TAG when: never # Do not run this job when a tag is created manually - - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when the default branch changes + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch script: - - echo 'running release_job' + - echo 'running release_job for $TAG' release: - name: 'Release $CI_COMMIT_SHA' - description: 'Created using the release-cli $EXTRA_DESCRIPTION' # $EXTRA_DESCRIPTION and the tag_name - tag_name: 'v${MAJOR}.${MINOR}.${REVISION}' # variables must be defined elsewhere - ref: '$CI_COMMIT_SHA' # in the pipeline. - milestones: + name: 'Release $TAG' + description: 'Created using the release-cli $EXTRA_DESCRIPTION' # $EXTRA_DESCRIPTION and the $TAG + tag_name: '$TAG' # variables must be defined elsewhere + ref: '$CI_COMMIT_SHA' # in the pipeline. For example, in the + milestones: # prepare_job - 'm1' - 'm2' - 'm3' @@ -3871,13 +4068,13 @@ These variables can be later used in all executed commands and scripts. The YAML-defined variables are also set to all created service containers, thus allowing to fine tune them. -Except for the user defined variables, there are also the ones [set up by the -Runner itself](../variables/README.md#predefined-environment-variables). -One example would be `CI_COMMIT_REF_NAME` which has the value of -the branch or tag name for which project is built. Apart from the variables -you can set in `.gitlab-ci.yml`, there are also the so called -[Variables](../variables/README.md#gitlab-cicd-environment-variables) -which can be set in GitLab's UI. +Except for the user-defined variables, there are also variables [set up by the +runner itself](../variables/README.md#predefined-environment-variables). +One example would be `CI_COMMIT_REF_NAME`, which has the value of +the branch or tag name the project is built for. Apart from the variables +you can set in `.gitlab-ci.yml`, there are also environment +[variables](../variables/README.md#gitlab-cicd-environment-variables), +which can be set in the GitLab UI. [YAML anchors for variables](#yaml-anchors-for-variables) are available. @@ -3978,7 +4175,7 @@ The `GIT_CHECKOUT` variable can be used when the `GIT_STRATEGY` is set to either specified, it defaults to true. You can set them globally or per-job in the [`variables`](#variables) section. -If set to `false`, the Runner will: +If set to `false`, the runner will: - when doing `fetch` - update the repository and leave working copy on the current revision, @@ -3986,7 +4183,7 @@ If set to `false`, the Runner will: default branch. Having this setting set to `true` will mean that for both `clone` and `fetch` -strategies the Runner will checkout the working copy to a revision related +strategies the runner will checkout the working copy to a revision related to the CI pipeline: ```yaml @@ -4060,7 +4257,7 @@ The configurtion above will result in `git fetch` being called this way: git fetch origin $REFSPECS --depth 50 --prune ``` -Where `$REFSPECS` is a value provided to the Runner internally by GitLab. +Where `$REFSPECS` is a value provided to the runner internally by GitLab. ### Job stages attempts @@ -4069,12 +4266,12 @@ Where `$REFSPECS` is a value provided to the Runner internally by GitLab. You can set the number for attempts the running job will try to execute each of the following stages: -| Variable | Description | -|-----------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| **GET_SOURCES_ATTEMPTS** | Number of attempts to fetch sources running a job | -| **ARTIFACT_DOWNLOAD_ATTEMPTS** | Number of attempts to download artifacts running a job | -| **RESTORE_CACHE_ATTEMPTS** | Number of attempts to restore the cache running a job | +| Variable | Description | +|-----------------------------------|--------------------------------------------------------| +| **ARTIFACT_DOWNLOAD_ATTEMPTS** | Number of attempts to download artifacts running a job | | **EXECUTOR_JOB_SECTION_ATTEMPTS** | [Since GitLab 12.10](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4450), the number of attempts to run a section in a job after a [`No Such Container`](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4450) error ([Docker executor](https://docs.gitlab.com/runner/executors/docker.html) only). | +| **GET_SOURCES_ATTEMPTS** | Number of attempts to fetch sources running a job | +| **RESTORE_CACHE_ATTEMPTS** | Number of attempts to restore the cache running a job | The default is one single attempt. @@ -4094,8 +4291,8 @@ You can set them globally or per-job in the [`variables`](#variables) section. NOTE: **Note:** As of GitLab 12.0, newly created projects will automatically have a [default `git depth` value of `50`](../pipelines/settings.md#git-shallow-clone). -You can specify the depth of fetching and cloning using `GIT_DEPTH`. This allows -shallow cloning of the repository which can significantly speed up cloning for +You can specify the depth of fetching and cloning using `GIT_DEPTH`. This does a +shallow clone of the repository and can significantly speed up cloning for repositories with a large number of commits or old, large binaries. The value is passed to `git fetch` and `git clone`. @@ -4103,7 +4300,7 @@ NOTE: **Note:** If you use a depth of 1 and have a queue of jobs or retry jobs, jobs may fail. -Since Git fetching and cloning is based on a ref, such as a branch name, Runners +Since Git fetching and cloning is based on a ref, such as a branch name, runners can't clone a specific commit SHA. If there are multiple jobs in the queue, or you're retrying an old job, the commit to be tested needs to be within the Git history that is cloned. Setting too small a value for `GIT_DEPTH` can make @@ -4124,18 +4321,18 @@ You can set it globally or per-job in the [`variables`](#variables) section. ### Custom build directories -> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2211) in GitLab Runner 11.10 +> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2211) in GitLab Runner 11.10. NOTE: **Note:** -This can only be used when `custom_build_dir` is enabled in the [Runner's +This can only be used when `custom_build_dir` is enabled in the [runner's configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnerscustom_build_dir-section). This is the default configuration for `docker` and `kubernetes` executor. By default, GitLab Runner clones the repository in a unique subpath of the `$CI_BUILDS_DIR` directory. However, your project might require the code in a specific directory (Go projects, for example). In that case, you can specify -the `GIT_CLONE_PATH` variable to tell the Runner in which directory to clone the -repository: +the `GIT_CLONE_PATH` variable to tell the runner the directory to clone the +repository in: ```yaml variables: @@ -4156,9 +4353,9 @@ An executor using a concurrency greater than `1` might lead to failures because multiple jobs might be working on the same directory if the `builds_dir` is shared between jobs. GitLab Runner does not try to prevent this situation. It's up to the administrator -and developers to comply with the requirements of Runner configuration. +and developers to comply with the requirements of runner configuration. -To avoid this scenario, you can use a unique path within `$CI_BUILDS_DIR`, because Runner +To avoid this scenario, you can use a unique path within `$CI_BUILDS_DIR`, because runner exposes two additional variables that provide a unique `ID` of concurrency: - `$CI_CONCURRENT_ID`: Unique ID for all jobs running within the given executor. @@ -4209,7 +4406,7 @@ because `$CI_BUILDS_DIR` is not expanded. ## Special YAML features It's possible to use special YAML features like anchors (`&`), aliases (`*`) -and map merging (`<<`), which will allow you to greatly reduce the complexity +and map merging (`<<`), which allows you to greatly reduce the complexity of `.gitlab-ci.yml`. Read more about the various [YAML features](https://learnxinyminutes.com/docs/yaml/). diff --git a/doc/development/README.md b/doc/development/README.md index ab86c252948..74068db726c 100644 --- a/doc/development/README.md +++ b/doc/development/README.md @@ -5,6 +5,17 @@ description: 'Learn how to contribute to GitLab.' # Contributor and Development Docs +Learn the processes and technical information needed for contributing to GitLab. + +This content is intended for members of the GitLab Team as well as community contributors. +Content specific to the GitLab Team should instead be included in the [Handbook](https://about.gitlab.com/handbook/). + +For information on using GitLab to work on your own software projects, see the [GitLab user documentation](../user/index.md). + +For information on working with GitLab's API, see the [API documentation](../api/README.md). + +For information on how to install, configure, update, and upgrade your own GitLab instance, see the [administration documentation](../administration/index.md). + ## Get started - Set up GitLab's development environment with [GitLab Development Kit (GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/README.md) @@ -45,6 +56,7 @@ Complementary reads: - [Danger bot](dangerbot.md) - [Generate a changelog entry with `bin/changelog`](changelog.md) - [Requesting access to Chatops on GitLab.com](chatops_on_gitlabcom.md#requesting-access) (for GitLab team members) +- [Patch release process for developers](https://gitlab.com/gitlab-org/release/docs/blob/master/general/patch/process.md#process-for-developers) ## UX and Frontend guides @@ -134,6 +146,10 @@ See [database guidelines](database/index.md). - [Refactoring guidelines](refactoring_guide/index.md) +## Deprecation guides + +- [Deprecation guidelines](deprecation_guidelines/index.md) + ## Documentation guides - [Writing documentation](documentation/index.md) diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md index 92e6add9f17..bf2d6400f56 100644 --- a/doc/development/api_graphql_styleguide.md +++ b/doc/development/api_graphql_styleguide.md @@ -36,6 +36,19 @@ can be shared. It is also possible to add a `private_token` to the querystring, or add a `HTTP_PRIVATE_TOKEN` header. +## Global IDs + +GitLab's GraphQL API uses Global IDs (i.e: `"gid://gitlab/MyObject/123"`) +and never database primary key IDs. + +Global ID is [a standard](https://graphql.org/learn/global-object-identification/) +used for caching and fetching in client-side libraries. + +See also: + +- [Exposing Global IDs](#exposing-global-ids). +- [Mutation arguments](#object-identifier-arguments). + ## Types We use a code-first schema, and we declare what type everything is in Ruby. @@ -106,18 +119,28 @@ Further reading: ### Exposing Global IDs -When exposing an `ID` field on a type, we will by default try to -expose a global ID by calling `to_global_id` on the resource being -rendered. +In keeping with GitLab's use of [Global IDs](#global-ids), always convert +database primary key IDs into Global IDs when you expose them. + +All fields named `id` are +[converted automatically](https://gitlab.com/gitlab-org/gitlab/-/blob/b0f56e7/app/graphql/types/base_object.rb#L11-14) +into the object's Global ID. + +Fields that are not named `id` need to be manually converted. We can do this using +[`Gitlab::GlobalID.build`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/global_id.rb), +or by calling `#to_global_id` on an object that has mixed in the +`GlobalID::Identification` module. -To override this behavior, you can implement an `id` method on the -type for which you are exposing an ID. Please make sure that when -exposing a `GraphQL::ID_TYPE` using a custom method that it is -globally unique. +Using an example from +[`Types::Notes::DiscussionType`](https://gitlab.com/gitlab-org/gitlab/-/blob/3c95bd9/app/graphql/types/notes/discussion_type.rb#L24-26): -The records that are exposing a `full_path` as an `ID_TYPE` are one of -these exceptions. Since the full path is a unique identifier for a -`Project` or `Namespace`. +```ruby +field :reply_id, GraphQL::ID_TYPE + +def reply_id + ::Gitlab::GlobalId.build(object, id: object.reply_id) +end +``` ### Connection Types @@ -429,6 +452,52 @@ module Types end ``` +## JSON + +When data to be returned by GraphQL is stored as +[JSON](migration_style_guide.md#storing-json-in-database), we should continue to use +GraphQL types whenever possible. Avoid using the `GraphQL::Types::JSON` type unless +the JSON data returned is _truly_ unstructured. + +If the structure of the JSON data varies, but will be one of a set of known possible +structures, use a +[union](https://graphql-ruby.org/type_definitions/unions.html). +An example of the use of a union for this purpose is +[!30129](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30129). + +Field names can be mapped to hash data keys using the `hash_key:` keyword if needed. + +For example, given the following simple JSON data: + +```json +{ + "title": "My chart", + "data": [ + { "x": 0, "y": 1 }, + { "x": 1, "y": 1 }, + { "x": 2, "y": 2 } + ] +} +``` + +We can use GraphQL types like this: + +```ruby +module Types + class ChartType < BaseObject + field :title, GraphQL::STRING_TYPE, null: true, description: 'Title of the chart' + field :data, [Types::ChartDatumType], null: true, description: 'Data of the chart' + end +end + +module Types + class ChartDatumType < BaseObject + field :x, GraphQL::INT_TYPE, null: true, description: 'X-axis value of the chart datum' + field :y, GraphQL::INT_TYPE, null: true, description: 'Y-axis value of the chart datum' + end +end +``` + ## Descriptions All fields and arguments @@ -608,15 +677,8 @@ the objects in question. To find objects to display in a field, we can add resolvers to `app/graphql/resolvers`. -Arguments can be defined within the resolver, those arguments will be -made available to the fields using the resolver. When exposing a model -that had an internal ID (`iid`), prefer using that in combination with -the namespace path as arguments in a resolver over a database -ID. Otherwise use a [globally unique ID](#exposing-global-ids). - -We already have a `FullPathLoader` that can be included in other -resolvers to quickly find Projects and Namespaces which will have a -lot of dependent objects. +Arguments can be defined within the resolver in the same way as in a mutation. +See the [Mutation arguments](#object-identifier-arguments) section. To limit the amount of queries performed, we can use `BatchLoader`. @@ -705,10 +767,6 @@ actions. In the same way a GET-request should not modify data, we cannot modify data in a regular GraphQL-query. We can however in a mutation. -To find objects for a mutation, arguments need to be specified. As with -[resolvers](#resolvers), prefer using internal ID or, if needed, a -global ID rather than the database ID. - ### Building Mutations Mutations live in `app/graphql/mutations` ideally grouped per @@ -763,10 +821,34 @@ If you need advice for mutation naming, canvass the Slack `#graphql` channel for ### Arguments -Arguments required by the mutation can be defined as arguments -required for a field. These will be wrapped up in an input type for -the mutation. For example, the `Mutations::MergeRequests::SetWip` -with GraphQL-name `MergeRequestSetWip` defines these arguments: +Arguments for a mutation are defined using `argument`. + +Example: + +```ruby +argument :my_arg, GraphQL::STRING_TYPE, + required: true, + description: "A description of the argument" +``` + +Each GraphQL `argument` defined will be passed to the `#resolve` method +of a mutation as keyword arguments. + +Example: + +```ruby +def resolve(my_arg:) + # Perform mutation ... +end +``` + +`graphql-ruby` will automatically wrap up arguments into an +[input type](https://graphql.org/learn/schema/#input-types). + +For example, the +[`mergeRequestSetWip` mutation](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/mutations/merge_requests/set_wip.rb) +defines these arguments (some +[through inheritance](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/mutations/merge_requests/base.rb)): ```ruby argument :project_path, GraphQL::ID_TYPE, @@ -786,12 +868,19 @@ argument :wip, DESC ``` -This would automatically generate an input type called +These arguments automatically generate an input type called `MergeRequestSetWipInput` with the 3 arguments we specified and the `clientMutationId`. -These arguments are then passed to the `resolve` method of a mutation -as keyword arguments. +### Object identifier arguments + +In keeping with GitLab's use of [Global IDs](#global-ids), mutation +arguments should use Global IDs to identify an object and never database +primary key IDs. + +Where an object has an `iid`, prefer to use the `full_path` or `group_path` +of its parent in combination with its `iid` as arguments to identify an +object rather than its `id`. ### Fields @@ -1204,3 +1293,7 @@ See the [schema reference](../api/graphql/reference/index.md) for details. This generated GraphQL documentation needs to be updated when the schema changes. For information on generating GraphQL documentation and schema files, see [updating the schema documentation](rake_tasks.md#update-graphql-documentation-and-schema-definitions). + +To help our readers, you should also add a new page to our [GraphQL API](../api/graphql/index.md) documentation. +For guidance, see the [GraphQL API](documentation/styleguide.md#graphql-api) section +of our documentation style guide. diff --git a/doc/development/api_styleguide.md b/doc/development/api_styleguide.md index 327f919d7f4..06b05f49b12 100644 --- a/doc/development/api_styleguide.md +++ b/doc/development/api_styleguide.md @@ -13,7 +13,7 @@ Always use an [Entity](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/ ## Documentation -API endpoints must come with [documentation](documentation/styleguide.md#api), unless it is internal or behind a feature flag. +API endpoints must come with [documentation](documentation/styleguide.md#restful-api), unless it is internal or behind a feature flag. The docs should be in the same merge request, or, if strictly necessary, in a follow-up with the same milestone as the original merge request. @@ -85,7 +85,7 @@ User.create(params) # imagine the user submitted `admin=1`... :) User.create(declared(params, include_parent_namespaces: false).to_h) ``` ->**Note:** +NOTE: **Note:** `declared(params)` return a `Hashie::Mash` object, on which you will have to call `.to_h`. @@ -173,7 +173,8 @@ guide on how you can add a new custom validator. validates the parameter value for different cases. Mainly, it checks whether a path is relative and does it contain `../../` relative traversal using `File::Separator` or not, and whether the path is absolute, for example - `/etc/passwd/`. + `/etc/passwd/`. By default, absolute paths are not allowed. However, you can optionally pass in an allowlist for allowed absolute paths in the following way: + `requires :file_path, type: String, file_path: { allowlist: ['/foo/bar/', '/home/foo/', '/app/home'] }` - `Git SHA`: diff --git a/doc/development/architecture.md b/doc/development/architecture.md index 8b28dd03017..963e1e618a1 100644 --- a/doc/development/architecture.md +++ b/doc/development/architecture.md @@ -46,69 +46,101 @@ https://docs.google.com/drawings/d/1fBzAyklyveF-i-2q-OHUIqDkYfjjxC4mq5shwKSZHLs/ ```mermaid graph TB - HTTP[HTTP/HTTPS] -- TCP 80, 443 --> NGINX[NGINX] - SSH -- TCP 22 --> GitLabShell[GitLab Shell] - SMTP[SMTP Gateway] - Geo[GitLab Geo Node] -- TCP 22, 80, 443 --> NGINX - - GitLabShell --TCP 8080 -->Unicorn["Unicorn (GitLab Rails)"] - GitLabShell --> Praefect - GitLabShell --> Redis - Unicorn --> PgBouncer[PgBouncer] - Unicorn --> Redis - Unicorn --> Praefect - Sidekiq --> Redis - Sidekiq --> PgBouncer - Sidekiq --> Praefect - GitLabWorkhorse[GitLab Workhorse] --> Unicorn - GitLabWorkhorse --> Redis - GitLabWorkhorse --> Praefect - Praefect --> Gitaly - NGINX --> GitLabWorkhorse - NGINX -- TCP 8090 --> GitLabPages[GitLab Pages] - NGINX --> Grafana[Grafana] - Grafana -- TCP 9090 --> Prometheus[Prometheus] - Prometheus -- TCP 80, 443 --> Unicorn - RedisExporter[Redis Exporter] --> Redis - Prometheus -- TCP 9121 --> RedisExporter - PostgreSQLExporter[PostgreSQL Exporter] --> PostgreSQL - PgBouncerExporter[PgBouncer Exporter] --> PgBouncer - Prometheus -- TCP 9187 --> PostgreSQLExporter - Prometheus -- TCP 9100 --> NodeExporter[Node Exporter] - Prometheus -- TCP 9168 --> GitLabExporter[GitLab Exporter] - Prometheus -- TCP 9127 --> PgBouncerExporter - GitLabExporter --> PostgreSQL - GitLabExporter --> GitLabShell - GitLabExporter --> Sidekiq - PgBouncer --> Consul - PostgreSQL --> Consul - PgBouncer --> PostgreSQL - NGINX --> Registry - Unicorn --> Registry - NGINX --> Mattermost - Mattermost --- Unicorn - Prometheus --> Alertmanager - Migrations --> PostgreSQL - Runner -- TCP 443 --> NGINX - Unicorn -- TCP 9200 --> Elasticsearch - Sidekiq -- TCP 9200 --> Elasticsearch - Sidekiq -- TCP 80, 443 --> Sentry - Unicorn -- TCP 80, 443 --> Sentry - Sidekiq -- UDP 6831 --> Jaeger - Unicorn -- UDP 6831 --> Jaeger - Gitaly -- UDP 6831 --> Jaeger - GitLabShell -- UDP 6831 --> Jaeger - GitLabWorkhorse -- UDP 6831 --> Jaeger - Alertmanager -- TCP 25 --> SMTP - Sidekiq -- TCP 25 --> SMTP - Unicorn -- TCP 25 --> SMTP - Unicorn -- TCP 369 --> LDAP - Sidekiq -- TCP 369 --> LDAP - Unicorn -- TCP 443 --> ObjectStorage["Object Storage"] - Sidekiq -- TCP 443 --> ObjectStorage - GitLabWorkhorse -- TCP 443 --> ObjectStorage - Registry -- TCP 443 --> ObjectStorage - Geo -- TCP 5432 --> PostgreSQL +HTTP[HTTP/HTTPS] -- TCP 80, 443 --> NGINX[NGINX] +SSH -- TCP 22 --> GitLabShell[GitLab Shell] +SMTP[SMTP Gateway] +Geo[GitLab Geo Node] -- TCP 22, 80, 443 --> NGINX + +GitLabShell --TCP 8080 -->Unicorn["Unicorn (GitLab Rails)"] +GitLabShell --> Praefect +Unicorn --> PgBouncer[PgBouncer] +Unicorn --> Redis +Unicorn --> Praefect +Sidekiq --> Redis +Sidekiq --> PgBouncer +Sidekiq --> Praefect +GitLabWorkhorse[GitLab Workhorse] --> Unicorn +GitLabWorkhorse --> Redis +GitLabWorkhorse --> Praefect +Praefect --> Gitaly +NGINX --> GitLabWorkhorse +NGINX -- TCP 8090 --> GitLabPages[GitLab Pages] +NGINX --> Grafana[Grafana] +Grafana -- TCP 9090 --> Prometheus[Prometheus] +Prometheus -- TCP 80, 443 --> Unicorn +RedisExporter[Redis Exporter] --> Redis +Prometheus -- TCP 9121 --> RedisExporter +PostgreSQLExporter[PostgreSQL Exporter] --> PostgreSQL +PgBouncerExporter[PgBouncer Exporter] --> PgBouncer +Prometheus -- TCP 9187 --> PostgreSQLExporter +Prometheus -- TCP 9100 --> NodeExporter[Node Exporter] +Prometheus -- TCP 9168 --> GitLabExporter[GitLab Exporter] +Prometheus -- TCP 9127 --> PgBouncerExporter +GitLabExporter --> PostgreSQL +GitLabExporter --> GitLabShell +GitLabExporter --> Sidekiq +PgBouncer --> Consul +PostgreSQL --> Consul +PgBouncer --> PostgreSQL +NGINX --> Registry +Unicorn --> Registry +NGINX --> Mattermost +Mattermost --- Unicorn +Prometheus --> Alertmanager +Migrations --> PostgreSQL +Runner -- TCP 443 --> NGINX +Unicorn -- TCP 9200 --> Elasticsearch +Sidekiq -- TCP 9200 --> Elasticsearch +Sidekiq -- TCP 80, 443 --> Sentry +Unicorn -- TCP 80, 443 --> Sentry +Sidekiq -- UDP 6831 --> Jaeger +Unicorn -- UDP 6831 --> Jaeger +Gitaly -- UDP 6831 --> Jaeger +GitLabShell -- UDP 6831 --> Jaeger +GitLabWorkhorse -- UDP 6831 --> Jaeger +Alertmanager -- TCP 25 --> SMTP +Sidekiq -- TCP 25 --> SMTP +Unicorn -- TCP 25 --> SMTP +Unicorn -- TCP 369 --> LDAP +Sidekiq -- TCP 369 --> LDAP +Unicorn -- TCP 443 --> ObjectStorage["Object Storage"] +Sidekiq -- TCP 443 --> ObjectStorage +GitLabWorkhorse -- TCP 443 --> ObjectStorage +Registry -- TCP 443 --> ObjectStorage +Geo -- TCP 5432 --> PostgreSQL + +click Alertmanager "./architecture.html#alertmanager" +click Praefect "./architecture.html#praefect" +click Geo "./architecture.html#gitlab-geo" +click NGINX "./architecture.html#nginx" +click Runner "./architecture.html#gitlab-runner" +click Registry "./architecture.html#registry" +click ObjectStorage "./architecture.html#minio" +click Mattermost "./architecture.html#mattermost" +click Gitaly "./architecture.html#gitaly" +click Jaeger "./architecture.html#jaeger" +click GitLabWorkhorse "./architecture.html#gitlab-workhorse" +click LDAP "./architecture.html#ldap-authentication" +click Unicorn "./architecture.html#unicorn" +click GitLabShell "./architecture.html#gitlab-shell" +click SSH "./architecture.html#ssh-request-22" +click Sidekiq "./architecture.html#sidekiq" +click Sentry "./architecture.html#sentry" +click GitLabExporter "./architecture.html#gitlab-exporter" +click Elasticsearch "./architecture.html#elasticsearch" +click Migrations "./architecture.html#database-migrations" +click PostgreSQL "./architecture.html#postgresql" +click Consul "./architecture.html#consul" +click PgBouncer "./architecture.html#pgbouncer" +click PgBouncerExporter "./architecture.html#pgbouncer-exporter" +click RedisExporter "./architecture.html#redis-exporter" +click Redis "./architecture.html#redis" +click Prometheus "./architecture.html#prometheus" +click Grafana "./architecture.html#grafana" +click GitLabPages "./architecture.html#gitlab-pages" +click PostgreSQLExporter "./architecture.html#postgresql-exporter" +click SMTP "./architecture.html#outbound-email" +click NodeExporter "./architecture.html#node-exporter" ``` ### Component legend @@ -215,7 +247,7 @@ GitLab can be considered to have two layers from a process perspective: - [Project page](https://github.com/hashicorp/consul/blob/master/README.md) - Configuration: - - [Omnibus](../administration/high_availability/consul.md) + - [Omnibus](../administration/consul.md) - [Charts](https://docs.gitlab.com/charts/installation/deployment.html#postgresql) - Layer: Core Service (Data) - GitLab.com: [Consul](../user/gitlab_com/index.md#consul) @@ -435,7 +467,7 @@ NGINX has an Ingress port for all HTTP requests and routes them to the appropria - [Project page](https://github.com/pgbouncer/pgbouncer/blob/master/README.md) - Configuration: - - [Omnibus](../administration/high_availability/pgbouncer.md) + - [Omnibus](../administration/postgresql/pgbouncer.md) - [Charts](https://docs.gitlab.com/charts/installation/deployment.html#postgresql) - Layer: Core Service (Data) - GitLab.com: [Database Architecture](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#database-architecture) @@ -554,7 +586,7 @@ An external registry can also be configured to use GitLab as an auth endpoint. Sentry fundamentally is a service that helps you monitor and fix crashes in real time. The server is in Python, but it contains a full API for sending events from any language, in any application. -For monitoring deployed apps, see the [Sentry integration docs](../user/project/operations/error_tracking.md) +For monitoring deployed apps, see the [Sentry integration docs](../operations/error_tracking.md) #### Sidekiq diff --git a/doc/development/auto_devops.md b/doc/development/auto_devops.md index 7d0c020ef96..6bdc77fff63 100644 --- a/doc/development/auto_devops.md +++ b/doc/development/auto_devops.md @@ -1,3 +1,9 @@ +--- +stage: Configure +group: Configure +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- + # Auto DevOps development guide This document provides a development guide for contributors to diff --git a/doc/development/background_migrations.md b/doc/development/background_migrations.md index d9e06206961..4b58758b5c7 100644 --- a/doc/development/background_migrations.md +++ b/doc/development/background_migrations.md @@ -29,10 +29,10 @@ Some examples where background migrations can be useful: - Populating one column based on JSON stored in another column. - Migrating data that depends on the output of external services (e.g. an API). -> **Note:** -> If the background migration is part of an important upgrade, make sure it's announced -> in the release post. Discuss with your Project Manager if you're not sure the migration falls -> into this category. +NOTE: **Note:** +If the background migration is part of an important upgrade, make sure it's announced +in the release post. Discuss with your Project Manager if you're not sure the migration falls +into this category. ## Isolation @@ -123,7 +123,7 @@ once. ## Cleaning Up ->**Note:** +NOTE: **Note:** Cleaning up any remaining background migrations _must_ be done in either a major or minor release, you _must not_ do this in a patch release. diff --git a/doc/development/build_test_package.md b/doc/development/build_test_package.md index 858ff41b685..e99915a24d0 100644 --- a/doc/development/build_test_package.md +++ b/doc/development/build_test_package.md @@ -1,3 +1,9 @@ +--- +stage: Enablement +group: Distribution +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- + # Building a package for testing While developing a new feature or modifying an existing one, it is helpful if an diff --git a/doc/development/changelog.md b/doc/development/changelog.md index 00a0573a8ba..e83ce40ef60 100644 --- a/doc/development/changelog.md +++ b/doc/development/changelog.md @@ -37,6 +37,8 @@ the `author` field. GitLab team members **should not**. - Any user-facing change **should** have a changelog entry. Example: "GitLab now uses system fonts for all text." - Performance improvements **should** have a changelog entry. +- Changes that need to be documented in the Telemetry [Event Dictionary](telemetry/event_dictionary.md) + also require a changelog entry. - _Any_ contribution from a community member, no matter how small, **may** have a changelog entry regardless of these guidelines if the contributor wants one. Example: "Fixed a typo on the search results page." diff --git a/doc/development/chatops_on_gitlabcom.md b/doc/development/chatops_on_gitlabcom.md index a3a4f1d7adc..0dd916c37fd 100644 --- a/doc/development/chatops_on_gitlabcom.md +++ b/doc/development/chatops_on_gitlabcom.md @@ -1,3 +1,9 @@ +--- +stage: Configure +group: Configure +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- + # Chatops on GitLab.com ChatOps on GitLab.com allows GitLab team members to run various automation tasks on GitLab.com using Slack. diff --git a/doc/development/cicd/img/ci_architecture.png b/doc/development/cicd/img/ci_architecture.png index b888f2f07aa..0dd8ba57f51 100644 Binary files a/doc/development/cicd/img/ci_architecture.png and b/doc/development/cicd/img/ci_architecture.png differ diff --git a/doc/development/cicd/img/ci_template_selection_v13_1.png b/doc/development/cicd/img/ci_template_selection_v13_1.png index af9f6dd1a90..32de35f5c1f 100644 Binary files a/doc/development/cicd/img/ci_template_selection_v13_1.png and b/doc/development/cicd/img/ci_template_selection_v13_1.png differ diff --git a/doc/development/cicd/index.md b/doc/development/cicd/index.md index e0cca00fd69..5b598a19a6e 100644 --- a/doc/development/cicd/index.md +++ b/doc/development/cicd/index.md @@ -1,3 +1,10 @@ +--- +stage: Verify +group: Continuous Integration +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +type: index, concepts, howto +--- + # CI/CD development documentation Development guides that are specific to CI/CD are listed here. diff --git a/doc/development/cicd/templates.md b/doc/development/cicd/templates.md index 904e7adffe2..0169ca42ac6 100644 --- a/doc/development/cicd/templates.md +++ b/doc/development/cicd/templates.md @@ -1,3 +1,10 @@ +--- +stage: Release +group: Progressive Delivery +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +type: index, concepts, howto +--- + # Development guide for GitLab CI/CD templates This document explains how to develop [GitLab CI/CD templates](../../ci/examples/README.md). @@ -8,6 +15,7 @@ All template files reside in the `lib/gitlab/ci/templates` directory, and are ca | Sub-directroy | Content | [Selectable in UI](#make-sure-the-new-template-can-be-selected-in-ui) | |---------------|--------------------------------------------------------------|-----------------------------------------------------------------------| +| `/AWS/*` | Cloud Deployment (AWS) related jobs | No | | `/Jobs/*` | Auto DevOps related jobs | Yes | | `/Pages/*` | Static site generators for GitLab Pages (for example Jekyll) | Yes | | `/Security/*` | Security related jobs | Yes | @@ -25,9 +33,37 @@ Also, all templates must be named with the `*.gitlab-ci.yml` suffix. ### Backward compatibility A template might be dynamically included with the `include:template:` keyword. If -you make a change to an *existing* template, you must make sure that it won't break +you make a change to an *existing* template, you **must** make sure that it won't break CI/CD in existing projects. +For example, changing a job name in a template could break pipelines in an existing project. +Let's say there is a template named `Performance.gitlab-ci.yml` with the following content: + +```yaml +performance: + image: registry.gitlab.com/gitlab-org/verify-tools/performance:v0.1.0 + script: ./performance-test $TARGET_URL +``` + +and users include this template with passing an argument to the `performance` job. +This can be done by specifying the environment variable `TARGET_URL` in _their_ `.gitlab-ci.yml`: + +```yaml +include: + template: Performance.gitlab-ci.yml + +performance: + variables: + TARGET_URL: https://awesome-app.com +``` + +If the job name `performance` in the template is renamed to `browser-performance`, +user's `.gitlab-ci.yml` will immediately cause a lint error because there +are no such jobs named `performance` in the included template anymore. Therefore, +users have to fix their `.gitlab-ci.yml` that could annoy their workflow. + +Please read [versioning](#versioning) section for introducing breaking change safely. + ## Testing Each CI/CD template must be tested in order to make sure that it's safe to be published. @@ -64,3 +100,13 @@ You should write an RSpec test to make sure that pipeline jobs will be generated A template could contain malicious code. For example, a template that contains the `export` shell command in a job might accidentally expose project secret variables in a job log. If you're unsure if it's secure or not, you need to ask security experts for cross-validation. + +## Versioning + +Versioning allows you to introduce a new template without modifying the existing +one. This is useful process especially when we need to introduce a breaking change, +but don't want to affect the existing projects that depends on the current template. + +There is an [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/17716) for +introducing versioning concept in GitLab Ci Template. Please follow the issue for +checking the progress. diff --git a/doc/development/code_review.md b/doc/development/code_review.md index fd53ce79534..2159f7a9ed5 100644 --- a/doc/development/code_review.md +++ b/doc/development/code_review.md @@ -230,7 +230,7 @@ Instead these should be sent to the [Release Manager](https://about.gitlab.com/c - Ask for clarification. ("I didn't understand. Can you clarify?") - Avoid selective ownership of code. ("mine", "not mine", "yours") - Avoid using terms that could be seen as referring to personal traits. ("dumb", - "stupid"). Assume everyone is attractive, intelligent, and well-meaning. + "stupid"). Assume everyone is intelligent and well-meaning. - Be explicit. Remember people don't always understand your intentions online. - Be humble. ("I'm not sure - let's look it up.") - Don't use hyperbole. ("always", "never", "endlessly", "nothing") @@ -281,12 +281,16 @@ first time. ### Assigning a merge request for a review When you are ready to have your merge request reviewed, -you should default to assigning it to a reviewer from your group or team for the first review, -however, you can also assign it to any reviewer. The list of reviewers can be found on [Engineering projects](https://about.gitlab.com/handbook/engineering/projects/) page. +you should request an initial review by assigning it to a reviewer from your group or team. +However, you can also assign it to any reviewer. The list of reviewers can be found on [Engineering projects](https://about.gitlab.com/handbook/engineering/projects/) page. You can also use `workflow::ready for review` label. That means that your merge request is ready to be reviewed and any reviewer can pick it. It is recommended to use that label only if there isn't time pressure and make sure the merge request is assigned to a reviewer. -When your merge request was reviewed and can be passed to a maintainer, you should default to choosing a maintainer with [domain expertise](#domain-experts), and otherwise follow the Reviewer Roulette recommendation or use the label `ready for merge`. +When your merge request receives an approval from the first reviewer it can be passed to a maintainer. You should default to choosing a maintainer with [domain expertise](#domain-experts), and otherwise follow the Reviewer Roulette recommendation or use the label `ready for merge`. + +Sometimes, a maintainer may not be available for review. They could be out of the office or [at capacity](#review-response-slo). +You can and should check the maintainer’s availability in their profile. If the maintainer recommended by +the roulette is not available, choose someone else from that list. It is responsibility of the author of a merge request that the merge request is reviewed. If it stays in `ready for review` state too long it is recommended to assign it to a specific reviewer. diff --git a/doc/development/contributing/issue_workflow.md b/doc/development/contributing/issue_workflow.md index 9feaa485bd2..76175cb7b66 100644 --- a/doc/development/contributing/issue_workflow.md +++ b/doc/development/contributing/issue_workflow.md @@ -49,8 +49,8 @@ Most issues will have labels for at least one of the following: - Team: `~"Technical Writing"`, `~Delivery` - Specialization: `~frontend`, `~backend`, `~documentation` - Release Scoping: `~Deliverable`, `~Stretch`, `~"Next Patch Release"` -- Priority: `~P1`, `~P2`, `~P3`, `~P4` -- Severity: ~`S1`, `~S2`, `~S3`, `~S4` +- Priority: `~P::1`, `~P::2`, `~P::3`, `~P::4` +- Severity: ~`S::1`, `~S::2`, `~S::3`, `~S::4` All labels, their meaning and priority are defined on the [labels page](https://gitlab.com/gitlab-org/gitlab/-/labels). @@ -275,10 +275,10 @@ or ~"Stretch". Any open issue for a previous milestone should be labeled We have the following priority labels: -- ~P1 -- ~P2 -- ~P3 -- ~P4 +- ~P::1 +- ~P::2 +- ~P::3 +- ~P::4 Please refer to the issue triage [priority label](https://about.gitlab.com/handbook/engineering/quality/issue-triage/#priority) section in our handbook to see how it's used. @@ -286,10 +286,10 @@ Please refer to the issue triage [priority label](https://about.gitlab.com/handb We have the following severity labels: -- ~S1 -- ~S2 -- ~S3 -- ~S4 +- ~S::1 +- ~S::2 +- ~S::3 +- ~S::4 Please refer to the issue triage [severity label](https://about.gitlab.com/handbook/engineering/quality/issue-triage/#severity) section in our handbook to see how it's used. diff --git a/doc/development/contributing/style_guides.md b/doc/development/contributing/style_guides.md index ed254052180..f6e64c1f1e6 100644 --- a/doc/development/contributing/style_guides.md +++ b/doc/development/contributing/style_guides.md @@ -10,26 +10,23 @@ we suggest investigating to see if a plugin exists. For instance here is the ## Pre-commit static analysis -You're strongly advised to install -[Overcommit](https://github.com/sds/overcommit) to automatically check for +You should install [`overcommit`](https://github.com/sds/overcommit) to automatically check for static analysis offenses before committing locally. -In your GitLab source directory run: +After installing `overcommit`, run the following in your GitLab source directory: ```shell make -C tooling/overcommit ``` -Then before a commit is created, Overcommit will automatically check for -RuboCop (and other checks) offenses on every modified file. +Then before a commit is created, `overcommit` automatically checks for RuboCop (and other checks) +offenses on every modified file. -This saves you time as you don't have to wait for the same errors to be detected -by the CI. +This saves you time as you don't have to wait for the same errors to be detected by CI/CD. -Overcommit relies on a pre-commit hook to prevent commits that violate its ruleset. -If you wish to override this behavior, it can be done by passing the ENV variable -`OVERCOMMIT_DISABLE`; i.e. `OVERCOMMIT_DISABLE=1 git rebase master` to rebase while -disabling the Git hook. +`overcommit` relies on a pre-commit hook to prevent commits that violate its ruleset. To override +this behavior, pass the `OVERCOMMIT_DISABLE` environment variable. For example, +`OVERCOMMIT_DISABLE=1 git rebase master` to rebase while disabling the Git hook. ## Ruby, Rails, RSpec diff --git a/doc/development/dangerbot.md b/doc/development/dangerbot.md index 93434479846..6fda394c10d 100644 --- a/doc/development/dangerbot.md +++ b/doc/development/dangerbot.md @@ -136,7 +136,7 @@ at GitLab so far: - Their availability: - No "OOO"/"PTO"/"Parental Leave" in their GitLab or Slack status. - No `:red_circle:`/`:palm_tree:`/`:beach:`/`:beach_umbrella:`/`:beach_with_umbrella:` emojis in GitLab or Slack status. - - [Experimental] Their timezone: people for which the local hour is between + - (Experimental) Their timezone: people for which the local hour is between 6 AM and 2 PM are eligible to be picked. This is to ensure they have a good chance to get to perform a review during their current work day. The experimentation is tracked in [this issue](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/563) diff --git a/doc/development/database_debugging.md b/doc/development/database_debugging.md index 6da0455f392..25b62e0d693 100644 --- a/doc/development/database_debugging.md +++ b/doc/development/database_debugging.md @@ -11,7 +11,7 @@ Available `RAILS_ENV`: - `development` (this is your main GDK db). - `test` (used for tests like RSpec). -## Nuke everything and start over +## Delete everything and start over If you just want to delete everything and start over with an empty DB (approximately 1 minute): diff --git a/doc/development/database_review.md b/doc/development/database_review.md index 967df411db5..f56ffdbad21 100644 --- a/doc/development/database_review.md +++ b/doc/development/database_review.md @@ -78,7 +78,8 @@ the following preparations into account. #### Preparation when adding migrations -- Ensure `db/structure.sql` is updated as [documented](migration_style_guide.md#schema-changes). +- Ensure `db/structure.sql` is updated as [documented](migration_style_guide.md#schema-changes), and additionally ensure that the relevant version files under +`db/schema_migrations` were added or removed. - Make migrations reversible by using the `change` method or include a `down` method when using `up`. - Include either a rollback procedure or describe how to rollback changes. - Add the output of both migrating and rolling back for all migrations into the MR description. @@ -149,6 +150,7 @@ test its execution using `CREATE INDEX CONCURRENTLY` in the `#database-lab` Slac - Ensure it was added in a post-migration. - Maintainer: After the merge request is merged, notify Release Managers about it on `#f_upcoming_release` Slack channel. - Check consistency with `db/structure.sql` and that migrations are [reversible](migration_style_guide.md#reversibility) + - Check that the relevant version files under `db/schema_migrations` were added or removed. - Check queries timing (If any): Queries executed in a migration need to fit comfortably within `15s` - preferably much less than that - on GitLab.com. - For column removals, make sure the column has been [ignored in a previous release](what_requires_downtime.md#dropping-columns) diff --git a/doc/development/deleting_migrations.md b/doc/development/deleting_migrations.md index 8aa16710d55..b8f23019ac2 100644 --- a/doc/development/deleting_migrations.md +++ b/doc/development/deleting_migrations.md @@ -23,7 +23,7 @@ Migrations can be disabled if: In order to disable a migration, the following steps apply to all types of migrations: 1. Turn the migration into a no-op by removing the code inside `#up`, `#down` - or `#perform` methods, and adding `#no-op` comment instead. + or `#perform` methods, and adding `# no-op` comment instead. 1. Add a comment explaining why the code is gone. Disabling migrations requires explicit approval of Database Maintainer. diff --git a/doc/development/deprecation_guidelines/index.md b/doc/development/deprecation_guidelines/index.md new file mode 100644 index 00000000000..1ee22644bbc --- /dev/null +++ b/doc/development/deprecation_guidelines/index.md @@ -0,0 +1,23 @@ +# Deprecation guidelines + +This page includes information about how and when to remove or make breaking +changes to GitLab features. + +## Terminology + +It's important to understand the difference between **deprecation** and +**removal**: + +**Deprecation** is the process of flagging/marking/announcing that a feature +will be removed in a future version of GitLab. + +**Removal** is the process of actually removing a feature that was previously +deprecated. + +## When can a feature be deprecated? + +A feature can be deprecated at any time, provided there is a viable alternative. + +## When can a feature be removed/changed? + +See our [Release and Maintenance policy](../../policy/maintenance.md). diff --git a/doc/development/diffs.md b/doc/development/diffs.md index e065e0acc6f..eb070cbf4d7 100644 --- a/doc/development/diffs.md +++ b/doc/development/diffs.md @@ -93,7 +93,8 @@ Gitlab::Git::DiffCollection.collection_limits[:max_bytes] = Gitlab::Git::DiffCol No more files will be rendered at all if 5 megabytes have already been rendered. -*Note:* All collection limit parameters are currently sent and applied on Gitaly. That is, once the limit is surpassed, +NOTE: **Note:** +All collection limit parameters are currently sent and applied on Gitaly. That is, once the limit is surpassed, Gitaly will only return the safe amount of data to be persisted on `merge_request_diff_files`. ### Individual diff file limits @@ -107,7 +108,8 @@ That is, it's equivalent to 10kb if the maximum allowed value is 100kb. The diff will still be persisted and expandable if the patch size doesn't surpass `ApplicationSettings#diff_max_patch_bytes`. -*Note:* Although this nomenclature (Collapsing) is also used on Gitaly, this limit is only used on GitLab (hardcoded - not sent to Gitaly). +NOTE: **Note:** +Although this nomenclature (Collapsing) is also used on Gitaly, this limit is only used on GitLab (hardcoded - not sent to Gitaly). Gitaly will only return `Diff.Collapsed` (RPC) when surpassing collection limits. #### Not expandable patches (too large) @@ -121,7 +123,8 @@ Commit::DIFF_SAFE_LINES = Gitlab::Git::DiffCollection::DEFAULT_LIMITS[:max_lines File diff will be suppressed (technically different from collapsed, but behaves the same, and is expandable) if it has more than 5000 lines. -*Note:* This limit is currently hardcoded and only applied on GitLab. +NOTE: **Note:** +This limit is currently hardcoded and only applied on GitLab. ## Viewers diff --git a/doc/development/distributed_tracing.md b/doc/development/distributed_tracing.md index 15b3b8ba755..cbbeae47a41 100644 --- a/doc/development/distributed_tracing.md +++ b/doc/development/distributed_tracing.md @@ -1,3 +1,9 @@ +--- +stage: Monitor +group: APM +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- + # Distributed Tracing - development guidelines GitLab is instrumented for distributed tracing. diff --git a/doc/development/doc_styleguide.md b/doc/development/doc_styleguide.md index 7d84f8ca86a..4a9f2a626f7 100644 --- a/doc/development/doc_styleguide.md +++ b/doc/development/doc_styleguide.md @@ -1,3 +1,5 @@ --- redirect_to: 'documentation/styleguide.md' --- + +This document was moved to [another location](documentation/styleguide.md). diff --git a/doc/development/documentation/feature_flags.md b/doc/development/documentation/feature_flags.md index f3ce9ce3a83..e2fbf25eb8a 100644 --- a/doc/development/documentation/feature_flags.md +++ b/doc/development/documentation/feature_flags.md @@ -56,7 +56,7 @@ not ready for production use: > - [Introduced](link-to-issue) in GitLab 12.0. > - It's deployed behind a feature flag, disabled by default. > - It's disabled on GitLab.com. -> - It's able to be enabled or disabled per-project +> - It's able to be enabled or disabled per-project. > - It's not recommended for production use. > - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#anchor-to-section). **(CORE ONLY)** @@ -67,7 +67,7 @@ not ready for production use: is under development and not ready for production use. It is deployed behind a feature flag that is **disabled by default**. [GitLab administrators with access to the GitLab Rails console](../path/to/administration/feature_flags.md) -can enable it for your instance. can be enabled or disabled per-project +can enable it for your instance. can be enabled or disabled per-project. To enable it: @@ -109,7 +109,7 @@ For example, for a feature initially deployed disabled by default, that became e > - It was deployed behind a feature flag, disabled by default. > - [Became enabled by default](link-to-issue) on GitLab 12.1. > - It's enabled on GitLab.com. -> - It's not able to be enabled or disabled per-project +> - It's not able to be enabled or disabled per-project. > - It's recommended for production use. > - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#anchor-to-section). **(CORE ONLY)** @@ -155,7 +155,7 @@ For example, for a feature enabled by default, enabled on GitLab.com, cannot be > - [Introduced](link-to-issue) in GitLab 12.0. > - It's deployed behind a feature flag, enabled by default. > - It's enabled on GitLab.com. -> - It's not able to be enabled or disabled per-project +> - It's not able to be enabled or disabled per-project. > - It's recommended for production use. > - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#anchor-to-section). **(CORE ONLY)** diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md index 2ea26985fcf..283060ba8d4 100644 --- a/doc/development/documentation/index.md +++ b/doc/development/documentation/index.md @@ -445,8 +445,8 @@ In case the review app URL returns 404, follow these steps to debug: If you want to know the in-depth details, here's what's really happening: 1. You manually run the `review-docs-deploy` job in a merge request. -1. The job runs the [`scripts/trigger-build-docs`](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/trigger-build-docs) - script with the `deploy` flag, which in turn: +1. The job runs the [`scripts/trigger-build`](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/trigger-build) + script with the `docs deploy` flag, which in turn: 1. Takes your branch name and applies the following: - The `docs-preview-` prefix is added. - The product slug is used to know the project the review app originated @@ -481,7 +481,7 @@ We treat documentation as code, and so use tests in our CI pipeline to maintain standards and quality of the docs. The current tests, which run in CI jobs when a merge request with new or changed docs is submitted, are: -- [`docs lint`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/docs.gitlab-ci.yml#L48): +- [`docs lint`](https://gitlab.com/gitlab-org/gitlab/-/blob/0b562014f7b71f98540e682c8d662275f0011f2f/.gitlab/ci/docs.gitlab-ci.yml#L41): Runs several tests on the content of the docs themselves: - [`lint-doc.sh` script](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/lint-doc.sh) runs the following checks and linters: @@ -492,33 +492,20 @@ merge request with new or changed docs is submitted, are: - [markdownlint](#markdownlint). - [Vale](#vale). - Nanoc tests: - - [`internal_links`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/docs.gitlab-ci.yml#L67) + - [`internal_links`](https://gitlab.com/gitlab-org/gitlab/-/blob/0b562014f7b71f98540e682c8d662275f0011f2f/.gitlab/ci/docs.gitlab-ci.yml#L58) checks that all internal links (ex: `[link](../index.md)`) are valid. - - [`internal_anchors`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/docs.gitlab-ci.yml#L69) + - [`internal_anchors`](https://gitlab.com/gitlab-org/gitlab/-/blob/0b562014f7b71f98540e682c8d662275f0011f2f/.gitlab/ci/docs.gitlab-ci.yml#L60) checks that all internal anchors (ex: `[link](../index.md#internal_anchor)`) are valid. + - [`ui-docs-links lint`](https://gitlab.com/gitlab-org/gitlab/-/blob/0b562014f7b71f98540e682c8d662275f0011f2f/.gitlab/ci/docs.gitlab-ci.yml#L62) + checks that all links to docs from UI elements (`app/views` files, for example) + are linking to valid docs and anchors. -### Running tests +### Run tests locally Apart from [previewing your changes locally](#previewing-the-changes-live), you can also run all lint checks and Nanoc tests locally. -#### Nanoc tests - -To execute Nanoc tests locally: - -1. Navigate to the [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs) directory. -1. Run: - - ```shell - # Check for broken internal links - bundle exec nanoc check internal_links - - # Check for broken external links (might take a lot of time to complete). - # This test is set to be allowed to fail and is run only in the gitlab-docs project CI - bundle exec nanoc check internal_anchors - ``` - #### Lint checks Lint checks are performed by the [`lint-doc.sh`](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/lint-doc.sh) @@ -550,6 +537,57 @@ The output should be similar to: Note that this requires you to either have the required lint tools installed on your machine, or a working Docker installation, in which case an image with these tools pre-installed will be used. +#### Nanoc tests + +To execute Nanoc tests locally: + +1. Navigate to the [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs) directory. +1. Run: + + ```shell + # Check for broken internal links + bundle exec nanoc check internal_links + + # Check for broken external links (might take a lot of time to complete). + # This test is set to be allowed to fail and is run only in the gitlab-docs project CI + bundle exec nanoc check internal_anchors + ``` + +#### `ui-docs-links` test + +The `ui-docs-links lint` job uses `haml-lint` to test that all links to docs from +UI elements (`app/views` files, for example) are linking to valid docs and anchors. + +To run the `ui-docs-links` test locally: + +1. Open the `gitlab` directory in a terminal window. +1. Run: + + ```shell + bundle exec haml-lint -i DocumentationLinks + ``` + +If you receive an error the first time you run this test, run `bundle install`, which +installs GitLab's dependencies, and try again. + +If you don't want to install all of GitLab's dependencies to test the links, you can: + +1. Open the `gitlab` directory in a terminal window. +1. Install `haml-lint`: + + ```shell + gem install haml_lint + ``` + +1. Run: + + ```shell + haml-lint -i DocumentationLinks + ``` + +If you manually install `haml-lint` with this process, it will not update automatically +and you should make sure your version matches the version used by GitLab. + ### Local linters To help adhere to the [documentation style guidelines](styleguide.md), and improve the content @@ -586,6 +624,7 @@ You can use markdownlint: - [On the command line](https://github.com/igorshubovych/markdownlint-cli#markdownlint-cli--). - [Within a code editor](#configure-editors). +- [In a `pre-commit` hook](#configure-pre-commit-hooks). #### Vale @@ -612,6 +651,9 @@ You can use Vale: - [On the command line](https://errata-ai.gitbook.io/vale/getting-started/usage). - [Within a code editor](#configure-editors). +- [In a `pre-commit` hook](#configure-pre-commit-hooks). Vale only reports errors in the + `pre-commit` hook (the same configuration as the CI/CD pipelines), and does not report suggestions + or warnings. #### Install linters @@ -655,14 +697,32 @@ To configure markdownlint within your editor, install one of the following as ap - [Sublime Text](https://packagecontrol.io/packages/SublimeLinter-contrib-markdownlint) - [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint) - [Atom](https://atom.io/packages/linter-node-markdownlint) +- [Vim](https://github.com/dense-analysis/ale) To configure Vale within your editor, install one of the following as appropriate: - The Sublime Text [`SublimeLinter-contrib-vale` plugin](https://packagecontrol.io/packages/SublimeLinter-contrib-vale) - The Visual Studio Code [`testthedocs.vale` extension](https://marketplace.visualstudio.com/items?itemName=testthedocs.vale) +- [Vim](https://github.com/dense-analysis/ale) We don't use [Vale Server](https://errata-ai.github.io/vale/#using-vale-with-a-text-editor-or-another-third-party-application). +#### Configure pre-commit hooks + +Git [pre-commit hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) allow Git users to +run tests or other processes before committing to a branch, with the ability to not commit to the branch if +failures occur with these tests. + +[`overcommit`](https://github.com/sds/overcommit) is a Git hooks manager, making configuring, +installing, and removing Git hooks easy. + +Sample configuration for `overcommit` is available in the +[`.overcommit.yml.example`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.overcommit.yml.example) +file for the [`gitlab`](https://gitlab.com/gitlab-org/gitlab) project. + +To set up `overcommit` for documentation linting, see +[Pre-commit static analysis](../contributing/style_guides.md#pre-commit-static-analysis). + #### Disable Vale tests You can disable a specific Vale linting rule or all Vale linting rules for any portion of a diff --git a/doc/development/documentation/site_architecture/deployment_process.md b/doc/development/documentation/site_architecture/deployment_process.md new file mode 100644 index 00000000000..00cdc69d422 --- /dev/null +++ b/doc/development/documentation/site_architecture/deployment_process.md @@ -0,0 +1,58 @@ +# Documentation deployment process + +The [`dockerfiles` directory](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/) +contains all needed Dockerfiles to build and deploy . It +is heavily inspired by Docker's +[Dockerfile](https://github.com/docker/docker.github.io/blob/06ed03db13895bfe867761b6fc2ad40acf6026dd/Dockerfile). + +The following Dockerfiles are used. + +| Dockerfile | Docker image | Description | +| ---------- | ------------ | ----------- | +| [`Dockerfile.bootstrap`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/Dockerfile.bootstrap) | `gitlab-docs:bootstrap` | Contains all the dependencies that are needed to build the website. If the gems are updated and `Gemfile{,.lock}` changes, the image must be rebuilt. | +| [`Dockerfile.builder.onbuild`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/Dockerfile.builder.onbuild) | `gitlab-docs:builder-onbuild` | Base image to build the docs website. It uses `ONBUILD` to perform all steps and depends on `gitlab-docs:bootstrap`. | +| [`Dockerfile.nginx.onbuild`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/Dockerfile.nginx.onbuild) | `gitlab-docs:nginx-onbuild` | Base image to use for building documentation archives. It uses `ONBUILD` to perform all required steps to copy the archive, and relies upon its parent `Dockerfile.builder.onbuild` that is invoked when building single documentation archives (see the `Dockerfile` of each branch. | +| [`Dockerfile.archives`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/Dockerfile.archives) | `gitlab-docs:archives` | Contains all the versions of the website in one archive. It copies all generated HTML files from every version in one location. | + +## How to build the images + +Although build images are built automatically via GitLab CI/CD, you can build +and tag all tooling images locally: + +1. Make sure you have [Docker installed](https://docs.docker.com/install/). +1. Make sure you're in the `dockerfiles/` directory of the `gitlab-docs` repository. +1. Build the images: + + ```shell + docker build -t registry.gitlab.com/gitlab-org/gitlab-docs:bootstrap -f Dockerfile.bootstrap ../ + docker build -t registry.gitlab.com/gitlab-org/gitlab-docs:builder-onbuild -f Dockerfile.builder.onbuild ../ + docker build -t registry.gitlab.com/gitlab-org/gitlab-docs:nginx-onbuild -f Dockerfile.nginx.onbuild ../ + ``` + +For each image, there's a manual job under the `images` stage in +[`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/.gitlab-ci.yml) which can be invoked at will. + +## Update an old Docker image with new upstream docs content + +If there are any changes to any of the stable branches of the products that are +not included in the single Docker image, just rerun the pipeline (`https://gitlab.com/gitlab-org/gitlab-docs/pipelines/new`) +for the version in question. + +## Porting new website changes to old versions + +CAUTION: **Warning:** +Porting changes to older branches can have unintended effects as we're constantly +changing the backend of the website. Use only when you know what you're doing +and make sure to test locally. + +The website will keep changing and being improved. In order to consolidate +those changes to the stable branches, we'd need to pick certain changes +from time to time. + +If this is not possible or there are many changes, merge master into them: + +```shell +git branch 12.0 +git fetch origin master +git merge origin/master +``` diff --git a/doc/development/documentation/site_architecture/global_nav.md b/doc/development/documentation/site_architecture/global_nav.md index 2625fbe0415..22d97a9e2cf 100644 --- a/doc/development/documentation/site_architecture/global_nav.md +++ b/doc/development/documentation/site_architecture/global_nav.md @@ -304,9 +304,9 @@ Examples: # does not include index.html at the end docs: - - doc_title: Service Desk - doc_url: 'user/project/service_desk.html' - ee_only: false + - doc_title: Container Scanning + doc_url: 'user/application_security/container_scanning/' + ee_only: true # note that the URL above ends in html and, as the # document is EE-only, the attribute ee_only is set to true. ``` diff --git a/doc/development/documentation/site_architecture/index.md b/doc/development/documentation/site_architecture/index.md index 60e6d4bcb13..63cd9959985 100644 --- a/doc/development/documentation/site_architecture/index.md +++ b/doc/development/documentation/site_architecture/index.md @@ -138,6 +138,8 @@ If you need to build and deploy the site immediately (must have maintainer level 1. In [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs), go to **{rocket}** **CI / CD > Schedules**. 1. For the `Build docs.gitlab.com every 4 hours` scheduled pipeline, click the **play** (**{play}**) button. +Read more about the [deployment process](deployment_process.md). + ## Using YAML data files The easiest way to achieve something similar to diff --git a/doc/development/documentation/site_architecture/release_process.md b/doc/development/documentation/site_architecture/release_process.md index d100ab8afa8..d04d34ff786 100644 --- a/doc/development/documentation/site_architecture/release_process.md +++ b/doc/development/documentation/site_architecture/release_process.md @@ -1,51 +1,21 @@ # GitLab Docs monthly release process -The [`dockerfiles` directory](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/) -contains all needed Dockerfiles to build and deploy the versioned website. It -is heavily inspired by Docker's -[Dockerfile](https://github.com/docker/docker.github.io/blob/06ed03db13895bfe867761b6fc2ad40acf6026dd/Dockerfile). - -The following Dockerfiles are used. - -| Dockerfile | Docker image | Description | -| ---------- | ------------ | ----------- | -| [`Dockerfile.bootstrap`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/Dockerfile.bootstrap) | `gitlab-docs:bootstrap` | Contains all the dependencies that are needed to build the website. If the gems are updated and `Gemfile{,.lock}` changes, the image must be rebuilt. | -| [`Dockerfile.builder.onbuild`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/Dockerfile.builder.onbuild) | `gitlab-docs:builder-onbuild` | Base image to build the docs website. It uses `ONBUILD` to perform all steps and depends on `gitlab-docs:bootstrap`. | -| [`Dockerfile.nginx.onbuild`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/Dockerfile.nginx.onbuild) | `gitlab-docs:nginx-onbuild` | Base image to use for building documentation archives. It uses `ONBUILD` to perform all required steps to copy the archive, and relies upon its parent `Dockerfile.builder.onbuild` that is invoked when building single documentation archives (see the `Dockerfile` of each branch. | -| [`Dockerfile.archives`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/dockerfiles/Dockerfile.archives) | `gitlab-docs:archives` | Contains all the versions of the website in one archive. It copies all generated HTML files from every version in one location. | - -## How to build the images - -Although build images are built automatically via GitLab CI/CD, you can build -and tag all tooling images locally: - -1. Make sure you have [Docker installed](https://docs.docker.com/install/). -1. Make sure you're in the `dockerfiles/` directory of the `gitlab-docs` repository. -1. Build the images: - - ```shell - docker build -t registry.gitlab.com/gitlab-org/gitlab-docs:bootstrap -f Dockerfile.bootstrap ../ - docker build -t registry.gitlab.com/gitlab-org/gitlab-docs:builder-onbuild -f Dockerfile.builder.onbuild ../ - docker build -t registry.gitlab.com/gitlab-org/gitlab-docs:nginx-onbuild -f Dockerfile.nginx.onbuild ../ - ``` - -For each image, there's a manual job under the `images` stage in -[`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/.gitlab-ci.yml) which can be invoked at will. - -## Monthly release process - When a new GitLab version is released on the 22nd, we need to create the respective single Docker image, and update some files so that the dropdown works correctly. -### 1. Add the chart version +## 1. Add the chart version Since the charts use a different version number than all the other GitLab products, we need to add a [version mapping](https://docs.gitlab.com/charts/installation/version_mappings.html): -1. Check that there is a [stable branch created](https://gitlab.com/gitlab-org/charts/gitlab/-/branches) - for the new chart version. If you're unsure or can't find it, drop a line in - the `#g_delivery` channel. +NOTE: **Note:** +The charts stable branch is not created automatically like the other products. +There's an [issue to track this](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/1442). +It is usually created on the 21st or the 22nd. + +To add a new charts version: + 1. Make sure you're in the root path of the `gitlab-docs` repository. 1. Open `content/_data/chart_versions.yaml` and add the new stable branch version using the version mapping. Note that only the `major.minor` version is needed. @@ -56,7 +26,7 @@ It can be handy to create the future mappings since they are pretty much known. In that case, when a new GitLab version is released, you don't have to repeat this first step. -### 2. Create an image for a single version +## 2. Create an image for a single version The single docs version must be created before the release merge request, but this needs to happen when the stable branches for all products have been created. @@ -89,7 +59,7 @@ docker run -it --rm -p 4000:4000 docs:12.0 Visit `http://localhost:4000/12.0/` to see if everything works correctly. -### 3. Create the release merge request +## 3. Create the release merge request NOTE: **Note:** To be [automated](https://gitlab.com/gitlab-org/gitlab-docs/-/issues/750). @@ -135,7 +105,7 @@ version and rotates the old one: git push origin release-12-0 ``` -### 4. Update the dropdown for all online versions +## 4. Update the dropdown for all online versions The versions dropdown is in a way "hardcoded". When the site is built, it looks at the contents of `content/_data/versions.yaml` and based on that, the dropdown @@ -144,14 +114,18 @@ dropdown will list one or more releases behind. Remember that the new changes of the dropdown are included in the unmerged `release-X-Y` branch. The content of `content/_data/versions.yaml` needs to change for all online -versions: +versions (stable branches `X.Y` of the `gitlab-docs` project): 1. Run the Rake task that will create all the respective merge requests needed to update the dropdowns and will be set to automatically be merged when their - pipelines succeed. The `release-X-Y` branch needs to be present locally, - and you need to have switched to it, otherwise the Rake task will fail: + pipelines succeed: + + NOTE: **Note:** + The `release-X-Y` branch needs to be present locally, + and you need to have switched to it, otherwise the Rake task will fail. ```shell + git checkout release-X-Y ./bin/rake release:dropdowns ``` @@ -162,46 +136,22 @@ versions: TIP: **Tip:** In case a pipeline fails, see [troubleshooting](#troubleshooting). -### 5. Merge the release merge request +## 5. Merge the release merge request The dropdown merge requests should have now been merged into their respective -version (stable branch), which will trigger another pipeline. At this point, +version (stable `X.Y` branch), which will trigger another pipeline. At this point, you need to only babysit the pipelines and make sure they don't fail: -1. Check the pipelines page: `https://gitlab.com/gitlab-org/gitlab-docs/pipelines` +1. Check the [pipelines page](https://gitlab.com/gitlab-org/gitlab-docs/pipelines) and make sure all stable branches have green pipelines. 1. After all the pipelines of the online versions succeed, merge the release merge request. -1. Finally, from `https://gitlab.com/gitlab-org/gitlab-docs/pipeline_schedules` run - the `Build docker images weekly` pipeline that will build the `:latest` and `:archives` Docker images. +1. Finally, run the + [`Build docker images weekly` pipeline](https://gitlab.com/gitlab-org/gitlab-docs/pipeline_schedules) + that will build the `:latest` and `:archives` Docker images. Once the scheduled pipeline succeeds, the docs site will be deployed with all new versions online. -## Update an old Docker image with new upstream docs content - -If there are any changes to any of the stable branches of the products that are -not included in the single Docker image, just rerun the pipeline (`https://gitlab.com/gitlab-org/gitlab-docs/pipelines/new`) -for the version in question. - -## Porting new website changes to old versions - -CAUTION: **Warning:** -Porting changes to older branches can have unintended effects as we're constantly -changing the backend of the website. Use only when you know what you're doing -and make sure to test locally. - -The website will keep changing and being improved. In order to consolidate -those changes to the stable branches, we'd need to pick certain changes -from time to time. - -If this is not possible or there are many changes, merge master into them: - -```shell -git branch 12.0 -git fetch origin master -git merge origin/master -``` - ## Troubleshooting Releasing a new version is a long process that involves many moving parts. diff --git a/doc/development/documentation/structure.md b/doc/development/documentation/structure.md index 4cfc57aa57b..e13b2f4d031 100644 --- a/doc/development/documentation/structure.md +++ b/doc/development/documentation/structure.md @@ -27,7 +27,7 @@ be used. There is no need to add a title called "Introduction" or "Overview," be search for these terms. Just put this information after the title. - **Use cases**: describes real use case scenarios for that feature/configuration. - **Requirements**: describes what software, configuration, account, or knowledge is required. -- **Instructions**: One or more sets of detailed instructions to follow. +- **Instructions**: one or more sets of detailed instructions to follow. - **Troubleshooting** guide (recommended but not required). For additional details on each, see the [template for new docs](#template-for-new-docs), @@ -42,40 +42,48 @@ To start a new document, respect the file tree and file name guidelines, as well as the style guidelines. Use the following template: ```markdown - + --- -description: "Short document description." # Up to ~200 chars long. They will be displayed in Google Search snippets. It may help to write the page intro first, and then reuse it here. +description: "Short document description." # Up to ~200 chars long. They will be displayed +in Google Search snippets. It may help to write the page intro first, and then reuse it here. stage: "Add the stage name here, and remove the quotation marks" group: "Add the group name here, and remove the quotation marks" -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +info: To determine the technical writer assigned to the Stage/Group associated with this page, +see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers --- # Feature Name or Use Case Name **[TIER]** (1) - + - + > [Introduced](link_to_issue_or_mr) in GitLab (Tier) X.Y (2). An introduction -- without its own additional header -- goes here. Offer a description of the feature or use case, and what to expect on this page. -(You can reuse this content, or part of it, for the front matter's `description` at the top of this file). +(You can reuse this content, or part of it, for the front matter's `description` at the top +of this file). The introduction should answer the following questions: - What is this feature or use case? - Who is it for? - What is the context in which it is used and are there any prerequisites/requirements? -- What can the audience do with this? (Be sure to consider all applicable audiences, like GitLab admin and developer-user.) +- What can the audience do with this? (Be sure to consider all applicable audiences, like + GitLab admin and developer-user.) - What are the benefits to using this over any alternatives? ## Use cases Describe some use cases, typically in bulleted form. Include real-life examples for each. -If the page itself is dedicated to a use case, this section can usually include more specific scenarios -for use (e.g. variations on the main use case), but if that's not applicable, the section can be omitted. +If the page itself is dedicated to a use case, this section can usually include more specific +scenarios for use (for example, variations on the main use case), but if that's not applicable, +the section can be omitted. Examples of use cases on feature pages: - CE and EE: [Issues](../../user/project/issues/index.md#use-cases) @@ -88,27 +96,60 @@ Examples of use cases on feature pages: State any requirements for using the feature and/or following along with the instructions. These can include both: -- technical requirements (e.g. an account on a third party service, an amount of storage space, prior configuration of another feature) -- prerequisite knowledge (e.g. familiarity with certain GitLab features, cloud technologies) +- technical requirements (for example, an account on a third party service, an amount of storage space, + prior configuration of another feature) +- prerequisite knowledge (for example, familiarity with certain GitLab features, cloud technologies) Link each one to an appropriate place for more information. ## Instructions -"Instructions" is usually not the name of the heading. -This is the part of the document where you can include one or more sets of instructions, each to accomplish a specific task. -Headers should describe the task the reader will achieve by following the instructions within, typically starting with a verb. +This is the part of the document where you can include one or more sets of instructions. +Each topic should help users accomplish a specific task. + +Headers should describe the task the reader will achieve by following the instructions within, +typically starting with a verb. For example, `Create a package` or `Configure a pipeline`. + Larger instruction sets may have subsections covering specific phases of the process. -Where appropriate, provide examples of code or configuration files to better clarify intended usage. +Where appropriate, provide examples of code or configuration files to better clarify +intended usage. - Write a step-by-step guide, with no gaps between the steps. -- Include example code or configurations as part of the relevant step. Use appropriate Markdown to [wrap code blocks with syntax highlighting](../../user/markdown.md#colored-code-and-syntax-highlighting). +- Include example code or configurations as part of the relevant step. + Use appropriate Markdown to wrap code blocks with + [syntax highlighting](../../user/markdown.md#colored-code-and-syntax-highlighting). - Start with an h2 (`##`), break complex steps into small steps using -subheadings h3 > h4 > h5 > h6. _Never skip a hierarchy level, such -as h2 > h4_, as it will break the TOC and may affect the breadcrumbs. + subheadings h3 > h4 > h5 > h6. _Never skip a hierarchy level, such + as h2 > h4_, as it will break the TOC and may affect the breadcrumbs. - Use short and descriptive headings (up to ~50 chars). You can use one -single heading like `## Configure X` for instructions when the feature -is simple and the document is short. + single heading like `## Configure X` for instructions when the feature + is simple and the document is short. + +Example topic: + +## Create a teddy bear + +Start by writing a sentence or two about _why_ someone would want to perform this task. +It's not always possible, but is a good practice. For example: + +Create a teddy bear when you need something to hug. + +Follow this information with the task steps. + +To create a teddy bear: + +1. Go to **Settings > CI/CD**. +1. Expand **This** and click **This**. +1. Do another step. + +After the numbered list, add a sentence with the expected result, if it +is not obvious, and any next steps. For example: + +The teddy bear is now in the kitchen, in the cupboard above the sink. + +You can retrieve the teddy bear and put it on the couch with the other animals. + +Screenshots are not necessary. They are difficult to keep up-to-date and can clutter the page. @@ -127,7 +168,8 @@ but commented out to help encourage others to add to it in the future. --> Notes: - (1): Apply the [tier badges](styleguide.md#product-badges) accordingly -- (2): Apply the correct format for the [GitLab version introducing the feature](styleguide.md#gitlab-versions-and-tiers) +- (2): Apply the correct format for the + [GitLab version that introduces the feature](styleguide.md#gitlab-versions-and-tiers) ``` ## Help and feedback section @@ -167,3 +209,28 @@ Disqus, therefore, don't add both keys to the same document. The click events in the feedback section are tracked with Google Tag Manager. The conversions can be viewed on Google Analytics by navigating to **Behavior > Events > Top events > docs**. + +## Guidelines for good practices + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36576/) in GitLab 13.2 as GitLab Development documentation. + +"Good practice" examples demonstrate encouraged ways of writing code while comparing with examples of practices to avoid. +These examples are labeled as "Bad" or "Good". +In GitLab development guidelines, when presenting the cases, it is recommended +to follow a **first-bad-then-good** strategy. First demonstrate the "Bad" practice (how things _could_ be done, which is often still working code), +and then how things _should_ be done better, using a "Good" example. This is typically an improved example of the same code. + +Consider the following guidelines when offering examples: + +- First, offer the "Bad" example, then the "Good" one. +- When only one bad case and one good case is given, use the same code block. +- When more than one bad case or one good case is offered, use separated code blocks for each. +With many examples being presented, a clear separation helps the reader to go directly to the good part. +Consider offering an explanation (for example, a comment, a link to a resource, etc.) on why something is bad practice. +- Better and best cases can be considered part of the good case(s) code block. +In the same code block, precede each with comments: `# Better` and `# Best`. + +NOTE: **Note:** +While the bad-then-good approach is acceptable for the GitLab development guidelines, do not use it +for user documentation. For user documentation, use "Do" and "Don't." For example, see the +[Pajamas Design System](https://design.gitlab.com/content/punctuation/). diff --git a/doc/development/documentation/styleguide.md b/doc/development/documentation/styleguide.md index f2c90e71bd5..c252f6425d0 100644 --- a/doc/development/documentation/styleguide.md +++ b/doc/development/documentation/styleguide.md @@ -13,6 +13,8 @@ For programmatic help adhering to the guidelines, see [Testing](index.md#testing See the GitLab handbook for further [writing style guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines) that apply to all GitLab content, not just documentation. +View [a list of recent style guide updates](https://gitlab.com/dashboard/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&label_name[]=tw-style¬[label_name][]=docs%3A%3Afix). + ## Documentation is the single source of truth (SSOT) ### Why a single source of truth @@ -249,7 +251,7 @@ GitLab documentation should be clear and easy to understand. - Be clear, concise, and stick to the goal of the documentation. - Write in US English with US grammar. (Tested in [`British.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/British.yml).) -- Use inclusive language. +- Use [inclusive language](#inclusive-language). ### Point of view @@ -261,37 +263,117 @@ because it’s friendly and easy to understand. ### Capitalization -- Capitalize "G" and "L" in GitLab. -- Use sentence case for: - - Titles. - - Labels. - - Menu items. - - Buttons. - - Headings. Don't capitalize other words in the title, unless - it refers to a product feature. For example: - - Capitalizing "issues" is acceptable in - `## What you can do with GitLab Issues`, but not in `## Closing multiple issues`. -- Use title case when referring to: - - [GitLab Features](https://about.gitlab.com/features/). For example, Issue Board, - Geo, and Runner. - - GitLab [product tiers](https://about.gitlab.com/pricing/). For example, GitLab Core - and GitLab Ultimate. (Tested in [`BadgeCapitalization.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/BadgeCapitalization.yml).) - - Third-party products. For example, Prometheus, Kubernetes, and Git. - - Methods or methodologies. For example, Continuous Integration, Continuous - Deployment, Scrum, and Agile. - (Tested in [`.markdownlint.json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.markdownlint.json).) - - NOTE: **Note:** - Some features are also objects. For example, "GitLab's Merge Requests support X" and - "Create a new merge request for Z." +#### Headings + +Use sentence case. For example: + +- `# Use variables to configure pipelines` +- `## Use the To-Do List` + +#### UI text + +When referring to specific user interface text, like a button label or menu item, use the same capitalization that is displayed in the UI. +Standards for this content are listed in the [Pajamas Design System Content section](https://design.gitlab.com/content/punctuation/) and typically +match what is called for in this Documentation Style Guide. + +If you think there is a mistake in the way the UI text is styled, +create an issue or an MR to propose a change to the UI text. + +#### Feature names + +- **Feature names are typically lowercase**, like those describing actions and types of objects in GitLab. For example: + - epics + - issues + - issue weights + - merge requests + - milestones + - reorder issues + - runner, runners, shared runners +- **Some features are capitalized**, typically nouns naming GitLab-specific capabilities or tools. For example: + - GitLab CI/CD + - Repository Mirroring + - Value Stream Analytics + - the To-Do List + - the Web IDE + - Geo + - GitLab Runner (see [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/233529) for details) + +Document any exceptions in this style guide. If you're not sure, ask a GitLab Technical Writer so that they can help decide and document the result. + +Do not match the capitalization of terms or phrases on the [Features page](https://about.gitlab.com/features/) or [features.yml](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/features.yml) by default. + +#### Other terms + +Capitalize names of: + +- GitLab [product tiers](https://about.gitlab.com/pricing/). For example, GitLab Core + and GitLab Ultimate. (Tested in [`BadgeCapitalization.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/BadgeCapitalization.yml).) +- Third-party organizations, software, and products. For example, Prometheus, Kubernetes, Git, and The Linux Foundation. +- Methods or methodologies. For example, Continuous Integration, Continuous Deployment, Scrum, and Agile. (Tested in [`.markdownlint.json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.markdownlint.json).) + +Follow the capitalization style listed at the [authoritative source](#links-to-external-documentation) for the entity, which may use non-standard case styles. For example: GitLab and npm. + +### Inclusive language + +We strive to create documentation that is inclusive. This section includes guidance and examples in the +following categories: + +- [Gender-specific wording](#avoid-gender-specific-wording). +- [Ableist language](#avoid-ableist-language). +- [Cultural sensitivity](#culturally-sensitive-language). + +We write our developer documentation with inclusivity and diversity in mind. This page is not an exhaustive reference, but describes some general guidelines and examples that illustrate some best practices to follow. + +#### Avoid gender-specific wording + +When possible, use gender-neutral pronouns. For example, you can use a singular +[they](https://developers.google.com/style/pronouns#gender-neutral-pronouns) as a gender-neutral +pronoun. + +Avoid the use of gender-specific pronouns, unless referring to a specific person. + +| Use | Avoid | +|-----------------------------------|-----------------| +| People, humanity | Mankind | +| GitLab Team Members | Manpower | +| You can install; They can install | He can install; She can install | + +If you need to set up [Fake user information](#fake-user-information), use diverse or non-gendered +names with common surnames. + +#### Avoid ableist language + +Avoid terms that are also used in negative stereotypes for different groups. + +| Use | Avoid | +|------------------------|----------------------| +| Check for completeness | Sanity check | +| Uncertain outliers | Crazy outliers | +| Slows the service | Cripples the service | +| Placeholder variable | Dummy variable | +| Active/Inactive | Enabled/Disabled | +| On/Off | Enabled/Disabled | + +Credit: [Avoid ableist language](https://developers.google.com/style/inclusive-documentation#ableist-language) in the Google Developer Style Guide. + +#### Culturally sensitive language + +Avoid terms that reflect negative cultural stereotypes and history. In most cases, you can replace terms such as `master` and `slave` with terms that are more precise and functional, such as `primary` and `secondary`. + +| Use | Avoid | +|----------------------|-----------------------| +| Primary / secondary | Master / slave | +| Allowlist / denylist | Blacklist / whitelist | + +For more information see the following [Internet Draft specification](https://tools.ietf.org/html/draft-knodel-terminology-02). ### Language to avoid When creating documentation, limit or avoid the use of the following verb tenses, words, and phrases: -- Avoid jargon. -- Avoid uncommon words. +- Avoid jargon when possible, and when not possible, define the term or [link to a definition](#links-to-external-documentation). +- Avoid uncommon words when a more-common alternative is possible, ensuring that content is accessible to more readers. - Don't write in the first person singular. (Tested in [`FirstPerson.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FirstPerson.yml).) - Instead of "I" or "me," use "we," "you," "us," or "one." @@ -431,6 +513,7 @@ tenses, words, and phrases: Check the general punctuation rules for the GitLab documentation on the table below. Check specific punctuation rules for [lists](#lists) below. +Additional examples are available in the [Pajamas guide for punctuation](https://design.gitlab.com/content/punctuation/). | Rule | Example | | ---- | ------- | @@ -806,9 +889,40 @@ Using the Markdown extension is necessary for the [`/help`](index.md#gitlab-help ### Links to external documentation When describing interactions with external software, it's often helpful to include links to external -documentation. When possible, make sure that you are linking to an **authoritative** source. +documentation. When possible, make sure that you're linking to an [**authoritative** source](#authoritative-sources). For example, if you're describing a feature in Microsoft's Active Directory, include a link to official Microsoft documentation. +### Authoritative sources + +When citing external information, use sources that are written by the people who created +the item or product in question. These sources are the most likely to +be accurate and remain up to date. + +Examples of authoritative sources include: + +- Specifications, such as a [Request for Comments](https://www.ietf.org/standards/rfcs/) document +from the Internet Engineering Task Force. +- Official documentation for a product. For example, if you're setting up an interface with the +Google OAuth 2 authorization server, include a link to Google's documentation. +- Official documentation for a project. For example, if you're citing NodeJS functionality, +refer directly to [NodeJS documentation](https://nodejs.org/en/docs/). +- Books from an authoritative publisher. + +Examples of sources to avoid include: + +- Personal blog posts. +- Wikipedia. +- Non-trustworthy articles. +- Discussions on forums such as Stack Overflow. +- Documentation from a company that describes another company's product. + +While many of these sources to avoid can help you learn skills and or features, they can become +obsolete quickly. Nobody is obliged to maintain any of these sites. Therefore, we should avoid using them as reference literature. + +NOTE: **Note:** +Non-authoritative sources are acceptable only if there is no equivalent authoritative source. +Even then, focus on non-authoritative sources that are extensively cited or peer-reviewed. + ### Links requiring permissions Don't link directly to: @@ -1135,48 +1249,39 @@ Usage examples: [Bootstrap utility class](https://getbootstrap.com/docs/4.4/utilities/float/): `**{tanuki, 32, float-right}**` renders as: **{tanuki, 32, float-right}** -### Use GitLab SVGs to describe UI elements +### When to use icons -When using GitLab SVGs to describe screen elements, also include the name or tooltip of the element as text. +Icons should be used sparingly, and only in ways that aid and do not hinder the readability of the +text. -For example, for references to the Admin Area: +For example, the following adds little to the accompanying text: -- Correct: `**{admin}** **Admin Area > Settings**` (**{admin}** **Admin Area > Settings**) -- Incorrect: `**{admin}** **> Settings**` (**{admin}** **> Settings**) +```markdown +1. Go to **{home}** **Project overview > Details** +``` -This will ensure that the source Markdown remains readable and should help with accessibility. +1. Go to **{home}** **Project overview > Details** -The following are examples of source Markdown for menu items with their published output: +However, the following might help the reader connect the text to the user interface: ```markdown -1. Go to **{home}** **Project overview > Details** -1. Go to **{doc-text}** **Repository > Branches** -1. Go to **{issues}** **Issues > List** -1. Go to **{merge-request}** **Merge Requests** -1. Go to **{rocket}** **CI/CD > Pipelines** -1. Go to **{shield}** **Security & Compliance > Configuration** -1. Go to **{cloud-gear}** **Operations > Metrics** -1. Go to **{package}** **Packages > Container Registry** -1. Go to **{chart}** **Project Analytics > Code Review** -1. Go to **{book}** **Wiki** -1. Go to **{snippet}** **Snippets** -1. Go to **{users}** **Members** -1. Select the **More actions** **{ellipsis_v}** icon > **Hide stage** +| Section | Description | +|:-------------------------|:----------------------------------------------------------------------------------------------------------------------------| +| **{overview}** Overview | View your GitLab Dashboard, and administer projects, users, groups, jobs, Runners, and Gitaly servers. | +| **{monitor}** Monitoring | View GitLab system information, and information on background jobs, logs, health checks, requests profiles, and audit logs. | +| **{messages}** Messages | Send and manage broadcast messages for your users. | ``` -1. Go to **{home}** **Project overview > Details** -1. Go to **{doc-text}** **Repository > Branches** -1. Go to **{issues}** **Issues > List** -1. Go to **{merge-request}** **Merge Requests** -1. Go to **{rocket}** **CI/CD > Pipelines** -1. Go to **{shield}** **Security & Compliance > Configuration** -1. Go to **{cloud-gear}** **Operations > Metrics** -1. Go to **{package}** **Packages > Container Registry** -1. Go to **{chart}** **Project Analytics > Code Review** -1. Go to **{book}** **Wiki** -1. Go to **{snippet}** **Snippets** -1. Go to **{users}** **Members** -1. Select the **More actions** **{ellipsis_v}** icon > **Hide stage** +| Section | Description | +|:-------------------------|:----------------------------------------------------------------------------------------------------------------------------| +| **{overview}** Overview | View your GitLab Dashboard, and administer projects, users, groups, jobs, Runners, and Gitaly servers. | +| **{monitor}** Monitoring | View GitLab system information, and information on background jobs, logs, health checks, requests profiles, and audit logs. | +| **{messages}** Messages | Send and manage broadcast messages for your users. | + +Use an icon when you find youself having to describe an interface element. For example: + +- Do: Click the Admin Area icon ( **{admin}** ). +- Don't: Click the Admin Area icon (the wrench icon). ## Alert boxes @@ -1294,21 +1399,20 @@ Which renders to: To maintain consistency through GitLab documentation, the following guides documentation authors on agreed styles and usage of terms. -### Merge Requests (MRs) +### Merge requests (MRs) Merge requests allow you to exchange changes you made to source code and collaborate with other people on the same project. You'll see this term used in the following ways: -- If you're referring to the feature, use **Merge Request**. -- In any other context, use **merge request**. +- Use lowercase **merge requests** regardless of whether referring to the feature or individual merge requests. -As noted in our corporate [Writing Style Guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines), +As noted in the GitLab [Writing Style Guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines), if you use the **MR** acronym, expand it at least once per document page. -For example, the first time you specify a MR, specify either _Merge Request (MR)_ or _merge request (MR)_. +Typically, the first use would be phrased as _merge request (MR)_ with subsequent instances being _MR_. Examples: -- "We prefer GitLab Merge Requests". +- "We prefer GitLab merge requests". - "Open a merge request to fix a broken link". - "After you open a merge request (MR), submit your MR for review and approval". @@ -1476,43 +1580,43 @@ GitLab Community Edition), don't split the product or feature name across lines. ### Product badges -When a feature is available in EE-only tiers, add the corresponding tier according to the -feature availability: +When a feature is available in paid tiers, add the corresponding tier to the +header or other page element according to the feature's availability: -- For GitLab Core and GitLab.com Free: `**(CORE)**`. -- For GitLab Starter and GitLab.com Bronze: `**(STARTER)**`. -- For GitLab Premium and GitLab.com Silver: `**(PREMIUM)**`. -- For GitLab Ultimate and GitLab.com Gold: `**(ULTIMATE)**`. +| Tier in which feature is available | Tier markup | +|:-----------------------------------------------------------------------|:----------------------| +| GitLab Core and GitLab.com Free, and their higher tiers | `**(CORE)**` | +| GitLab Starter and GitLab.com Bronze, and their higher tiers | `**(STARTER)**` | +| GitLab Premium and GitLab.com Silver, and their higher tiers | `**(PREMIUM)**` | +| GitLab Ultimate and GitLab.com Gold | `**(ULTIMATE)**` | +| *Only* GitLab Core and higher tiers (no GitLab.com-based tiers) | `**(CORE ONLY)**` | +| *Only* GitLab Starter and higher tiers (no GitLab.com-based tiers) | `**(STARTER ONLY)**` | +| *Only* GitLab Premium and higher tiers (no GitLab.com-based tiers) | `**(PREMIUM ONLY)**` | +| *Only* GitLab Ultimate (no GitLab.com-based tiers) | `**(ULTIMATE ONLY)**` | +| *Only* GitLab.com Free and higher tiers (no self-managed instances) | `**(FREE ONLY)**` | +| *Only* GitLab.com Bronze and higher tiers (no self-managed instances) | `**(BRONZE ONLY)**` | +| *Only* GitLab.com Silver and higher tiers (no self-managed instances) | `**(SILVER ONLY)**` | +| *Only* GitLab.com Gold (no self-managed instances) | `**(GOLD ONLY)**` | -To exclude GitLab.com tiers (when the feature is not available in GitLab.com), add the -keyword "only": +For clarity, all page title headers (H1s) must be have a tier markup for +the lowest tier that has information on the documentation page. -- For GitLab Core: `**(CORE ONLY)**`. -- For GitLab Starter: `**(STARTER ONLY)**`. -- For GitLab Premium: `**(PREMIUM ONLY)**`. -- For GitLab Ultimate: `**(ULTIMATE ONLY)**`. +If sections of a page apply to higher tier levels, they can be separately +labeled with their own tier markup. -For GitLab.com only tiers (when the feature is not available for self-managed instances): +#### Product badge display behavior -- For GitLab Free and higher tiers: `**(FREE ONLY)**`. -- For GitLab Bronze and higher tiers: `**(BRONZE ONLY)**`. -- For GitLab Silver and higher tiers: `**(SILVER ONLY)**`. -- For GitLab Gold: `**(GOLD ONLY)**`. +When using the tier markup with headers, the documentation page will +display the full tier badge with the header line. -The tier should be ideally added to headers, so that the full badge will be displayed. -However, it can be also mentioned from paragraphs, list items, and table cells. For these cases, -the tier mention will be represented by an orange info icon **(information)** that will show the tiers on hover. - -Use the lowest tier at the page level, even if higher-level tiers exist on the page. For example, you might have a page that is marked as Starter but a section badged as Premium. - -For example: +You can also use the tier markup with paragraphs, list items, +and table cells. For these cases, the tier mention will be represented by an +orange info icon **{information}** that will display the tiers when visitors +point to the icon. For example: -- `**(STARTER)**` renders as **(STARTER)** -- `**(STARTER ONLY)**` renders as **(STARTER ONLY)** -- `**(SILVER ONLY)**` renders as **(SILVER ONLY)** - -The absence of tiers' mentions mean that the feature is available in GitLab Core, -GitLab.com Free, and all higher tiers. +- `**(STARTER)**` displays as **(STARTER)** +- `**(STARTER ONLY)**` displays as **(STARTER ONLY)** +- `**(SILVER ONLY)**` displays as **(SILVER ONLY)** #### How it works @@ -1622,10 +1726,10 @@ Learn how to [document features deployed behind flags](feature_flags.md). For guidance on developing GitLab with feature flags, see [Feature flags in development of GitLab](../feature_flags/index.md). -## API +## RESTful API -Here is a list of must-have items. Use them in the exact order that appears -on this document. Further explanation is given below. +Here is a list of must-have items for RESTful API documentation. Use them in the +exact order that appears on this document. Further explanation is given below. - Every method must have the REST API request. For example: @@ -1776,7 +1880,8 @@ curl --data "name=foo" --header "PRIVATE-TOKEN: " "https://gi #### Post data using JSON content -> **Note:** In this example we create a new group. Watch carefully the single +NOTE: **Note:** +In this example we create a new group. Watch carefully the single and double quotes. ```shell @@ -1816,3 +1921,80 @@ exclude specific users when requesting a list of users for a project, you would ```shell curl --request PUT --header "PRIVATE-TOKEN: " --data "skip_users[]=" --data "skip_users[]=" https://gitlab.example.com/api/v4/projects//users ``` + +## GraphQL API + +GraphQL APIs are different from [RESTful APIs](#restful-api). Reference information is +generated automatically in our [GraphQL reference](../../api/graphql/reference/index.md). + +However, it's helpful to include examples on how to use GraphQL for different "use cases", +with samples that readers can use directly in the [GraphiQL explorer](../api_graphql_styleguide.md#graphiql). + +This section describes the steps required to add your GraphQL examples to GitLab documentation. + +### Add a dedicated GraphQL page + +To create a dedicated GraphQL page, create a new `.md` file in the `doc/api/graphql/` directory. +Give that file a functional name, such as `import_from_specific_location.md`. + +### Start the page with an explanation + +Include a page title that describes the GraphQL functionality in a few words, such as: + +```markdown +# Search for [substitute kind of data] +``` + +Describe the search. One sentence may be all you need. More information may help +readers learn how to use the example for their GitLab deployments. + +### Include a procedure using the GraphiQL explorer + +The GraphiQL explorer can help readers test queries with working deployments. Set up the section with the following: + +- Use the following title: + + ```markdown + ## Set up the GraphiQL explorer + ``` + +- Include a code block with the query that anyone can include in their instance of + the GraphiQL explorer: + + ````markdown + ```graphql + query { + + } + ``` + ```` + +- Tell the user what to do: + + ```markdown + 1. Open the GraphiQL explorer tool in the following URL: `https://gitlab.com/-/graphql-explorer`. + 1. Paste the `query` listed above into the left window of your GraphiQL explorer tool. + 1. Click Play to get the result shown here: + ``` + +- Include a screenshot of the result in the GraphiQL explorer. Follow the naming + convention described in the [Save the image](#save-the-image) section. +- Follow up with an example of what you can do with the output. + Make sure the example is something that readers can do on their own deployments. +- Include a link to the [GraphQL API resources](../../api/graphql/reference/index.md). + +### Add the GraphQL example to the Table of Contents + +You'll need to open a second MR, against the [GitLab Docs repository](https://gitlab.com/gitlab-org/gitlab-docs/). + +We store our Table of Contents in the `default-nav.yaml` file, in the `content/_data` +subdirectory. You can find the GraphQL section under the following line: + +```yaml + - category_title: GraphQL +``` + +Be aware that CI tests for that second MR will fail with a bad link until the main MR +that adds the new GraphQL page is merged. + +And that's all you need! diff --git a/doc/development/ee_features.md b/doc/development/ee_features.md index ac544113cbd..e7954fa910b 100644 --- a/doc/development/ee_features.md +++ b/doc/development/ee_features.md @@ -56,6 +56,12 @@ This works because for every path that is present in CE's eager-load/auto-load paths, we add the same `ee/`-prepended path in [`config/application.rb`](https://gitlab.com/gitlab-org/gitlab/blob/925d3d4ebc7a2c72964ce97623ae41b8af12538d/config/application.rb#L42-52). This also applies to views. +#### Testing EE-only features + +To test an EE class that doesn't exist in CE, create the spec file as you normally +would in the `ee/spec` directory, but without the second `ee/` subdirectory. +For example, a class `ee/app/models/vulnerability.rb` would have its tests in `ee/spec/models/vulnerability_spec.rb`. + ### EE features based on CE features For features that build on existing CE features, write a module in the `EE` @@ -96,6 +102,21 @@ This is also not just applied to models. Here's a list of other examples: - `ee/app/validators/ee/foo_attr_validator.rb` - `ee/app/workers/ee/foo_worker.rb` +#### Testing EE features based on CE features + +To test an `EE` namespaced module that extends a CE class with EE features, +create the spec file as you normally would in the `ee/spec` directory, including the second `ee/` subdirectory. +For example, an extension `ee/app/models/ee/user.rb` would have its tests in `ee/app/models/ee/user_spec.rb`. + +In the `RSpec.describe` call, use the CE class name where the EE module would be used. +For example, in `ee/app/models/ee/user_spec.rb`, the test would start with: + +```ruby +RSpec.describe User do + describe 'ee feature added through extension' +end +``` + #### Overriding CE methods To override a method present in the CE codebase, use `prepend`. It @@ -904,7 +925,7 @@ export default { - Please do not use mixins unless ABSOLUTELY NECESSARY. Please try to find an alternative pattern. -##### Reccomended alternative approach (named/scoped slots) +##### Recommended alternative approach (named/scoped slots) - We can use slots and/or scoped slots to achieve the same thing as we did with mixins. If you only need an EE component there is no need to create the CE component. diff --git a/doc/development/elasticsearch.md b/doc/development/elasticsearch.md index 90debab3b5c..2f01692e944 100644 --- a/doc/development/elasticsearch.md +++ b/doc/development/elasticsearch.md @@ -1,3 +1,9 @@ +--- +stage: Enablement +group: Global Search +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- + # Elasticsearch knowledge **(STARTER ONLY)** This area is to maintain a compendium of useful information when working with Elasticsearch. @@ -121,6 +127,9 @@ Patterns: ## Zero downtime reindexing with multiple indices +NOTE: **Note:** +This is not applicable yet as multiple indices functionality is not fully implemented. + Currently GitLab can only handle a single version of setting. Any setting/schema changes would require reindexing everything from scratch. Since reindexing can take a long time, this can cause search functionality downtime. To avoid downtime, GitLab is working to support multiple indices that diff --git a/doc/development/fe_guide/frontend_faq.md b/doc/development/fe_guide/frontend_faq.md index 3c0845a9aaa..71436a7c7fb 100644 --- a/doc/development/fe_guide/frontend_faq.md +++ b/doc/development/fe_guide/frontend_faq.md @@ -163,3 +163,33 @@ To return to the normal development mode: 1. Run `yarn clean` to remove the production assets and free some space (optional). 1. Start webpack again: `gdk start webpack`. 1. Restart GDK: `gdk-restart rails-web`. + +### 8. Babel polyfills + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/28837) in GitLab 12.8. + +GitLab has enabled the Babel `preset-env` option +[`useBuiltIns: 'usage'`](https://babeljs.io/docs/en/babel-preset-env#usebuiltins-usage), +which adds the appropriate `core-js` polyfills once for each JavaScript feature +we're using that our target browsers don't support. You don't need to add `core-js` +polyfills manually. + +NOTE: **Note:** +GitLab still manually adds non-`core-js` polyfills for extending browser features +(such as GitLab's SVG polyfill) that allow us reference SVGs by using ``. +These polyfills should be added to `app/assets/javascripts/commons/polyfills.js`. + +To see what polyfills are being used: + +1. Navigate to your merge request. +1. In the secondary menu below the title of the merge request, click **Pipelines**, then + click the pipeline you want to view, to display the jobs in that pipeline. +1. Click the [`compile-production-assets`](https://gitlab.com/gitlab-org/gitlab/-/jobs/641770154) job. +1. In the right-hand sidebar, scroll to **Job Artifacts**, and click **Browse**. +1. Click the **webpack-report** folder to open it, and click **index.html**. +1. In the upper left corner of the page, click the right arrow **{angle-right}** + to display the explorer. +1. In the **Search modules** field, enter `gitlab/node_modules/core-js` to see + which polyfills are being loaded and where: + + ![Image of webpack report](img/webpack_report_v12_8.png) diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md index 3d74ec94ae4..f5e16d377f1 100644 --- a/doc/development/fe_guide/graphql.md +++ b/doc/development/fe_guide/graphql.md @@ -75,7 +75,7 @@ their execution by clicking **Execute query** button on the top left: ## Apollo Client To save duplicated clients getting created in different apps, we have a -[default client](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/javascripts/lib/graphql.js) that should be used. This setups the +[default client](https://gitlab.com/gitlab-org/gitlab/blob/master/app/assets/javascripts/lib/graphql.js) that should be used. This sets up the Apollo client with the correct URL and also sets the CSRF headers. Default client accepts two parameters: `resolvers` and `config`. @@ -85,6 +85,7 @@ Default client accepts two parameters: `resolvers` and `config`. - `cacheConfig` field accepts an optional object of settings to [customize Apollo cache](https://www.apollographql.com/docs/react/caching/cache-configuration/#configuring-the-cache) - `baseUrl` allows us to pass a URL for GraphQL endpoint different from our main endpoint (i.e.`${gon.relative_url_root}/api/graphql`) - `assumeImmutableResults` (set to `false` by default) - this setting, when set to `true`, will assume that every single operation on updating Apollo Cache is immutable. It also sets `freezeResults` to `true`, so any attempt on mutating Apollo Cache will throw a console warning in development environment. Please ensure you're following the immutability pattern on cache update operations before setting this option to `true`. + - `fetchPolicy` determines how you want your component to interact with the Apollo cache. Defaults to "cache-first". ## GraphQL Queries @@ -167,9 +168,7 @@ import VueApollo from 'vue-apollo'; import createDefaultClient from '~/lib/graphql'; Vue.use(VueApollo); -const defaultClient = createDefaultClient({ - resolvers: {} -}); +const defaultClient = createDefaultClient(); defaultClient.cache.writeData({ data: { @@ -257,10 +256,7 @@ We need to pass resolvers object to our existing Apollo Client: import createDefaultClient from '~/lib/graphql'; import resolvers from './graphql/resolvers'; -const defaultClient = createDefaultClient( - {}, - resolvers, -); +const defaultClient = createDefaultClient(resolvers); ``` Now every single time on attempt to fetch a version, our client will fetch `id` and `sha` from the remote API endpoint and will assign our hardcoded values to `author` and `createdAt` version properties. With this data, frontend developers are able to work on UI part without being blocked by backend. When actual response is added to the API, a custom local resolver can be removed fast and the only change to query/fragment is `@client` directive removal. @@ -470,6 +466,28 @@ fetchNextPage() { Please note we don't have to save `pageInfo` one more time; `fetchMore` triggers a query `result` hook as well. +### Managing performance + +The Apollo client will batch queries by default. This means that if you have 3 queries defined, +Apollo will group them into one request, send the single request off to the server and only +respond once all 3 queries have completed. + +If you need to have queries sent as individual requests, additional context can be provided +to tell Apollo to do this. + +```javascript +export default { + apollo: { + user: { + query: QUERY_IMPORT, + context: { + isSingleRequest: true, + } + } + }, +}; +``` + ### Testing #### Mocking response as component data @@ -501,6 +519,7 @@ If we need to test how our component renders when results from the GraphQL API a designs: { loading, }, + }, }; wrapper = shallowMount(Index, { @@ -595,7 +614,7 @@ These errors are located at the "top level" of a GraphQL response. These are non #### Handling top-level errors -Apollo is aware of top-level errors, so we are able to leverage Apollo's various error-handling mechanisms to handle these errors (e.g. handling Promise rejections after invoking the [`mutate`](https://www.apollographql.com/docs/react/api/apollo-client/#ApolloClient.mutate) method, or handling the `error` event emitted from the [`ApolloMutation`](https://apollo.vuejs.org/api/apollo-mutation.html#events) component). +Apollo is aware of top-level errors, so we are able to leverage Apollo's various error-handling mechanisms to handle these errors (e.g. handling Promise rejections after invoking the [`mutate`](https://www.apollographql.com/docs/react/api/core/ApolloClient/#ApolloClient.mutate) method, or handling the `error` event emitted from the [`ApolloMutation`](https://apollo.vuejs.org/api/apollo-mutation.html#events) component). Because these errors are not intended for users, error messages for top-level errors should be defined client-side. diff --git a/doc/development/fe_guide/icons.md b/doc/development/fe_guide/icons.md index 7078b5e9b2f..b539293e9cf 100644 --- a/doc/development/fe_guide/icons.md +++ b/doc/development/fe_guide/icons.md @@ -76,6 +76,89 @@ export default { Please use the following function inside JS to render an icon: `gl.utils.spriteIcon(iconName)` +## Loading icon + +### Usage in HAML/Rails + +DANGER: **Danger:** +Do not use the `spinner` or `icon('spinner spin')` rails helpers to insert +loading icons. These helpers rely on the Font Awesome icon library which is +deprecated. + +To insert a loading spinner in HAML or Rails use the `loading_icon` helper: + +```haml += loading_icon +``` + +You can include one or more of the following properties with the `loading_icon` helper, as demonstrated +by the examples that follow: + +- `container` (optional): wraps the loading icon in a container, which centers the loading icon using the `text-center` CSS property. +- `color` (optional): either `orange` (default), `light`, or `dark`. +- `size` (optional): either `sm` (default), `md`, `lg`, or `xl`. +- `css_class` (optional): defaults to an empty string, but can be useful for utility classes to fine-tune alignment or spacing. + +**Example 1:** + +The following HAML expression generates a loading icon’s markup and +centers the icon by wrapping it in a `gl-spinner-container` element. + +```haml += loading_icon(container: true) +``` + +**Output from example 1:** + +```html +
+ +
+``` + +**Example 2:** + +The following HAML expression generates a loading icon’s markup +with a custom size. It also appends a margin utility class. + +```haml += loading_icon(size: 'lg', css_class: 'gl-mr-2') +``` + +**Output from example 2:** + +```html + +``` + +### Usage in Vue + +The [GitLab UI](https://gitlab-org.gitlab.io/gitlab-ui/) components library provides a +`GlLoadingIcon` component. See the component’s +[storybook](https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/base-loading-icon--default) +for more information about its usage. + +**Example:** + +The following code snippet demonstrates how to use `GlLoadingIcon` in +a Vue component. + +```html +