diff --git a/.gitlab/merge_request_templates/Deprecations.md b/.gitlab/merge_request_templates/Deprecations.md index f8803768d88..fc803152efb 100644 --- a/.gitlab/merge_request_templates/Deprecations.md +++ b/.gitlab/merge_request_templates/Deprecations.md @@ -1,6 +1,7 @@ /label ~"release post" ~"release post item" ~"Technical Writing" ~devops:: ~group:: ~"release post item::deprecation" +/label ~"type::maintenance" /milestone % /assign `@EM/PM` (choose the DRI; remove backticks here, and below) diff --git a/.gitlab/merge_request_templates/Removals.md b/.gitlab/merge_request_templates/Removals.md index c169cd87ac7..9d3738f63b5 100644 --- a/.gitlab/merge_request_templates/Removals.md +++ b/.gitlab/merge_request_templates/Removals.md @@ -1,6 +1,7 @@ /label ~"release post" ~"release post item" ~"Technical Writing" ~devops:: ~group:: ~"release post item::removal" +/label ~"type::maintenance" /milestone % /assign `@EM/PM` (choose the DRI; remove backticks here, and below) diff --git a/app/assets/javascripts/issues/show/components/description.vue b/app/assets/javascripts/issues/show/components/description.vue index 3f42f825866..bcbcb04132b 100644 --- a/app/assets/javascripts/issues/show/components/description.vue +++ b/app/assets/javascripts/issues/show/components/description.vue @@ -95,7 +95,7 @@ export default { this.renderGFM(); this.updateTaskStatusText(); - if (this.workItemsEnabled) { + if (this.workItemsEnabled && this.$el) { this.renderTaskActions(); } }, @@ -174,8 +174,11 @@ export default { ); button.id = `js-task-button-${index}`; this.taskButtons.push(button.id); - button.innerHTML = - ''; + button.innerHTML = ` + + + + `; item.prepend(button); }); }, @@ -191,7 +194,7 @@ export default { const taskBadge = document.createElement('span'); taskBadge.innerHTML = ` - + ${__('Task')} @@ -245,7 +248,7 @@ export default { modal-id="create-task-modal" :title="s__('WorkItem|New Task')" hide-footer - body-class="gl-py-0!" + body-class="gl-p-0!" > { const el = document.querySelector('#js-work-items'); + const { fullPath } = el.dataset; return new Vue({ el, router: createRouter(el.dataset.fullPath), apolloProvider: createApolloProvider(), + provide: { + fullPath, + }, render(createElement) { return createElement(App); }, diff --git a/app/assets/javascripts/work_items/pages/create_work_item.vue b/app/assets/javascripts/work_items/pages/create_work_item.vue index 2b9db3e3db5..6c3bcf8f6a8 100644 --- a/app/assets/javascripts/work_items/pages/create_work_item.vue +++ b/app/assets/javascripts/work_items/pages/create_work_item.vue @@ -1,6 +1,8 @@ - {{ - __('Something went wrong when creating a work item. Please try again') - }} - + {{ error }} + + + + + + + + {{ type.name }} + + + + + 0 ? m : nil } diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb index 11c6cc360de..95093b88155 100644 --- a/app/services/issuable_base_service.rb +++ b/app/services/issuable_base_service.rb @@ -494,7 +494,7 @@ class IssuableBaseService < ::BaseProjectService def handle_move_between_ids(issuable_position) return unless params[:move_between_ids] - after_id, before_id = params.delete(:move_between_ids) + before_id, after_id = params.delete(:move_between_ids) positioning_scope = issuable_position.class.relative_positioning_query_base(issuable_position) diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb index 37d667d4be8..7f4ae60602a 100644 --- a/app/services/issues/base_service.rb +++ b/app/services/issues/base_service.rb @@ -2,6 +2,7 @@ module Issues class BaseService < ::IssuableBaseService + extend ::Gitlab::Utils::Override include IncidentManagement::UsageData include IssueTypeHelpers @@ -61,6 +62,23 @@ module Issues issue.system_note_timestamp = params[:created_at] || params[:updated_at] end + override :handle_move_between_ids + def handle_move_between_ids(issue) + issue.check_repositioning_allowed! if params[:move_between_ids] + + super + + rebalance_if_needed(issue) + end + + def issuable_for_positioning(id, positioning_scope) + return unless id + + issue = positioning_scope.find(id) + + issue if can?(current_user, :update_issue, issue) + end + def create_assignee_note(issue, old_assignees) SystemNoteService.change_issuable_assignees( issue, issue.project, current_user, old_assignees) diff --git a/app/services/issues/create_service.rb b/app/services/issues/create_service.rb index e29bcf4a453..7fbf7c6af58 100644 --- a/app/services/issues/create_service.rb +++ b/app/services/issues/create_service.rb @@ -21,6 +21,8 @@ module Issues def execute(skip_system_notes: false) @issue = @build_service.execute + handle_move_between_ids(@issue) + filter_resolve_discussion_params create(@issue, skip_system_notes: skip_system_notes) diff --git a/app/services/issues/reorder_service.rb b/app/services/issues/reorder_service.rb index 8be4f530dac..5443d41ac30 100644 --- a/app/services/issues/reorder_service.rb +++ b/app/services/issues/reorder_service.rb @@ -21,7 +21,7 @@ module Issues def move_between_ids strong_memoize(:move_between_ids) do - ids = [params[:move_after_id], params[:move_before_id]] + ids = [params[:move_before_id], params[:move_after_id]] .map(&:to_i) .map { |m| m > 0 ? m : nil } diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb index 4dc6294490f..8372cd919e5 100644 --- a/app/services/issues/update_service.rb +++ b/app/services/issues/update_service.rb @@ -2,8 +2,6 @@ module Issues class UpdateService < Issues::BaseService - extend ::Gitlab::Utils::Override - # NOTE: For Issues::UpdateService, we default the spam_params to nil, because spam_checking is not # necessary in many cases, and we don't want to require every caller to explicitly pass it as nil # to disable spam checking. @@ -92,14 +90,6 @@ module Issues todo_service.update_issue(issuable, current_user) end - def handle_move_between_ids(issue) - issue.check_repositioning_allowed! if params[:move_between_ids] - - super - - rebalance_if_needed(issue) - end - # rubocop: disable CodeReuse/ActiveRecord def change_issue_duplicate(issue) canonical_issue_id = params.delete(:canonical_issue_id) @@ -217,14 +207,6 @@ module Issues ).execute end - def issuable_for_positioning(id, positioning_scope) - return unless id - - issue = positioning_scope.find(id) - - issue if can?(current_user, :update_issue, issue) - end - def create_confidentiality_note(issue) SystemNoteService.change_issue_confidentiality(issue, issue.project, current_user) end diff --git a/app/views/projects/ci/lints/show.html.haml b/app/views/projects/ci/lints/show.html.haml index 4463220e951..b48e69c2c23 100644 --- a/app/views/projects/ci/lints/show.html.haml +++ b/app/views/projects/ci/lints/show.html.haml @@ -3,4 +3,4 @@ %h4.pt-3.pb-3= _("Validate your GitLab CI configuration") -#js-ci-lint{ data: { endpoint: project_ci_lint_path(@project), pipeline_simulation_help_page_path: help_page_path('ci/lint', anchor: 'pipeline-simulation') , lint_help_page_path: help_page_path('ci/lint', anchor: 'validate-basic-logic-and-syntax') } } +#js-ci-lint{ data: { endpoint: project_ci_lint_path(@project), pipeline_simulation_help_page_path: help_page_path('ci/lint', anchor: 'simulate-a-pipeline') , lint_help_page_path: help_page_path('ci/lint', anchor: 'check-cicd-syntax') } } diff --git a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml index f6a0638ccd0..908de68f825 100644 --- a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml +++ b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml @@ -36,5 +36,5 @@ = link_to edit_pipeline_schedule_path(pipeline_schedule), title: _('Edit'), class: 'btn gl-button btn-default btn-icon' do = sprite_icon('pencil') - if can?(current_user, :admin_pipeline_schedule, pipeline_schedule) - = link_to pipeline_schedule_path(pipeline_schedule), title: _('Delete'), method: :delete, class: 'btn gl-button btn-danger btn-icon', data: { confirm: _("Are you sure you want to delete this pipeline schedule?") } do + = link_to pipeline_schedule_path(pipeline_schedule), title: _('Delete'), method: :delete, class: 'btn gl-button btn-danger btn-icon', aria: { label: _('Delete pipeline schedule') }, data: { confirm: _("Are you sure you want to delete this pipeline schedule?"), confirm_btn_variant: 'danger' } do = sprite_icon('remove') diff --git a/app/views/shared/issue_type/_details_content.html.haml b/app/views/shared/issue_type/_details_content.html.haml index 0bf002fbbc5..e5197acf06f 100644 --- a/app/views/shared/issue_type/_details_content.html.haml +++ b/app/views/shared/issue_type/_details_content.html.haml @@ -3,7 +3,7 @@ .issue-details.issuable-details .detail-page-description.content-block - #js-issuable-app{ data: { initial: issuable_initial_data(issuable).to_json} } + #js-issuable-app{ data: { initial: issuable_initial_data(issuable).to_json, full_path: @project.full_path } } .title-container %h2.title= markdown_field(issuable, :title) - if issuable.description.present? diff --git a/doc/administration/get_started.md b/doc/administration/get_started.md index 3be3c11947e..f3b4400c8c3 100644 --- a/doc/administration/get_started.md +++ b/doc/administration/get_started.md @@ -62,7 +62,7 @@ You may need to import projects from external sources like GitHub, Bitbucket, or ### Popular project imports -- [GitHub Enterprise to self-managed GitLab](../integration/github.md#enabling-github-oauth): Enabling OAuth makes it easier for developers to find and import their projects. +- [GitHub Enterprise to self-managed GitLab](../integration/github.md): Enabling OAuth makes it easier for developers to find and import their projects. - [Bitbucket Server](../user/project/import/bitbucket_server.md#limitations): There are certain data limitations. For assistance with these data types, contact your GitLab account manager or GitLab Support about our professional migration services. diff --git a/doc/api/container_registry.md b/doc/api/container_registry.md index 4d4aaf5610b..0a1983b6b33 100644 --- a/doc/api/container_registry.md +++ b/doc/api/container_registry.md @@ -426,3 +426,29 @@ Examples: curl --request DELETE --data 'name_regex_delete=.*' --data 'older_than=1month' \ --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/5/registry/repositories/2/tags" ``` + +## Instance-wide endpoints + +Beside the group- and project-specific GitLab APIs explained above, +the Container Registry has its own endpoints. +To query those, follow the Registry's built-in mechanism to obtain and use an +[authentication token](https://docs.docker.com/registry/spec/auth/token/). + +NOTE: +These are different from project or personal access tokens in the GitLab application. + +### Listing all container repositories + +```plaintext +GET /v2/_catalogue +``` + +To list all container repositories on your GitLab instance, admin credentials are required: + +```shell +$ curl --request GET --user ":" "https://gitlab.example.com/jwt/auth?service=container_registry&scope=registry:catalog:*" +{"token":" ... "} + +$ curl --header "Authorization: Bearer " https://gitlab.example.com:5050/v2/_catalog +{"repositories":["user/project1", "group/subgroup/project2", ... ]} +``` diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 3bbaef72fea..298762a9d5d 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -1420,6 +1420,8 @@ Input type: `CreateIssueInput` | `locked` | [`Boolean`](#boolean) | Indicates discussion is locked on the issue. | | `mergeRequestToResolveDiscussionsOf` | [`MergeRequestID`](#mergerequestid) | IID of a merge request for which to resolve discussions. | | `milestoneId` | [`MilestoneID`](#milestoneid) | ID of the milestone to assign to the issue. On update milestone will be removed if set to null. | +| `moveAfterId` | [`IssueID`](#issueid) | Global ID of issue that should be placed after the current issue. | +| `moveBeforeId` | [`IssueID`](#issueid) | Global ID of issue that should be placed before the current issue. | | `projectPath` | [`ID!`](#id) | Project full path the issue is associated with. | | `title` | [`String!`](#string) | Title of the issue. | | `type` | [`IssueType`](#issuetype) | Type of the issue. | diff --git a/doc/api/lint.md b/doc/api/lint.md index e5b5e0e2be8..f8d871d070d 100644 --- a/doc/api/lint.md +++ b/doc/api/lint.md @@ -169,7 +169,7 @@ POST /projects/:id/ci/lint | Attribute | Type | Required | Description | | ---------- | ------- | -------- | -------- | | `content` | string | yes | The CI/CD configuration content. | -| `dry_run` | boolean | no | Run [pipeline creation simulation](../ci/lint.md#pipeline-simulation), or only do static check. This is false by default. | +| `dry_run` | boolean | no | Run [pipeline creation simulation](../ci/lint.md#simulate-a-pipeline), or only do static check. This is false by default. | | `include_jobs` | boolean | no | If the list of jobs that would exist in a static check or pipeline simulation should be included in the response. This is false by default. | Example request: 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 4e4b7420697..a906f213626 100644 --- a/doc/ci/ci_cd_for_external_repos/github_integration.md +++ b/doc/ci/ci_cd_for_external_repos/github_integration.md @@ -16,7 +16,7 @@ Watch a video on [Using GitLab CI/CD pipelines with GitHub repositories](https:/ NOTE: Because of [GitHub limitations](https://gitlab.com/gitlab-org/gitlab/-/issues/9147), -[GitHub OAuth](../../integration/github.md#enabling-github-oauth) +[GitHub OAuth](../../integration/github.md#enable-github-oauth-in-gitlab) cannot be used to authenticate with GitHub as an external CI/CD repository. ## Connect with Personal Access Token diff --git a/doc/ci/img/ci_lint.png b/doc/ci/img/ci_lint.png deleted file mode 100644 index fdc3868cdce..00000000000 Binary files a/doc/ci/img/ci_lint.png and /dev/null differ diff --git a/doc/ci/img/ci_lint_dry_run.png b/doc/ci/img/ci_lint_dry_run.png deleted file mode 100644 index 61d6379f70e..00000000000 Binary files a/doc/ci/img/ci_lint_dry_run.png and /dev/null differ diff --git a/doc/ci/lint.md b/doc/ci/lint.md index e58907ee0bd..c0df0b2a439 100644 --- a/doc/ci/lint.md +++ b/doc/ci/lint.md @@ -4,48 +4,54 @@ group: Pipeline Authoring 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/#assignments --- -# Validate `.gitlab-ci.yml` syntax with the CI Lint tool **(FREE)** +# Validate GitLab CI/CD configuration **(FREE)** -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. +Use the CI Lint tool to check the validity of GitLab CI/CD configuration. +You can validate the syntax from a `.gitlab-ci.yml` file or any other sample CI/CD configuration. +This tool checks for syntax and logic errors, and can simulate pipeline +creation to try to find more complicated configuration problems. -To access the CI Lint tool, navigate to **CI/CD > Pipelines** or **CI/CD > Jobs** -in your project and click **CI lint**. +If you use the [pipeline editor](pipeline_editor/index.md), it verifies configuration +syntax automatically. -If you use VS Code, you can also validate your CI/CD configuration with the +If you use VS Code, you can validate your CI/CD configuration with the [GitLab Workflow VS Code extension](../user/project/repository/vscode.md). -## Validate basic logic and syntax +## Check CI/CD syntax -By default, the CI lint checks the syntax of your CI YAML configuration and also runs -some basic logical validations. Configuration added with the [`includes` keyword](yaml/index.md#include), -is also validated. +The CI lint tool checks the syntax of GitLab CI/CD configuration, including +configuration added with the [`includes` keyword](yaml/index.md#include). -To use the CI lint, paste a complete CI configuration (`.gitlab-ci.yml` for example) -into the text box and click **Validate**: +To check CI/CD configuration with the CI lint tool: -![CI Lint](img/ci_lint.png) +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select one of: + - **CI/CD > Pipelines** + - **CI/CD > Jobs** +1. In the top right, select **CI lint**. +1. Paste a copy of the CI/CD configuration you want to check into the text box. +1. Select **Validate**. -## Pipeline simulation +## Simulate a pipeline > [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. +You can simulate the creation of a GitLab CI/CD pipeline to find more complicated issues, +including problems with [`needs`](yaml/index.md#needs) and [`rules`](yaml/index.md#rules) +configuration. A simulation runs as a Git `push` event on the default branch. -To validate the configuration by running a pipeline simulation: +Prerequisites: -1. Paste the GitLab CI configuration to verify into the text box. -1. Select the **Simulate pipeline creation for the default branch** checkbox. +- You must have [permissions](../user/permissions.md#project-members-permissions) + to create pipelines on this branch to validate with a simulation. + +To simulate a pipeline: + +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select one of: + - **CI/CD > Pipelines** + - **CI/CD > Jobs** +1. In the top right, select **CI lint**. +1. Paste a copy of the CI/CD configuration you want to check into the text box. +1. Select **Simulate pipeline creation for the default branch**. 1. Select **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/troubleshooting.md b/doc/ci/troubleshooting.md index 62913c56853..853d2f953fb 100644 --- a/doc/ci/troubleshooting.md +++ b/doc/ci/troubleshooting.md @@ -36,7 +36,7 @@ file is correct. Paste in full `.gitlab-ci.yml` files or individual jobs configu to verify the basic syntax. When a `.gitlab-ci.yml` file is present in a project, you can also use the CI Lint -tool to [simulate the creation of a full pipeline](lint.md#pipeline-simulation). +tool to [simulate the creation of a full pipeline](lint.md#simulate-a-pipeline). It does deeper verification of the configuration syntax. ## Verify variables diff --git a/doc/development/documentation/structure.md b/doc/development/documentation/structure.md index 6ecffce01b4..21368098f39 100644 --- a/doc/development/documentation/structure.md +++ b/doc/development/documentation/structure.md @@ -5,10 +5,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w description: What to include in GitLab documentation pages. --- -# Documentation topic types +# Documentation topic types (CTRT) At GitLab, we have not traditionally used types for our content. However, we are starting to -move in this direction, and we now use four primary topic types: +move in this direction, and we now use four primary topic types (CTRT): - [Concept](#concept) - [Task](#task) @@ -154,7 +154,7 @@ If multiple causes or workarounds exist, consider putting them into a table form ## Other types of content There are other types of content in the GitLab documentation that don't -classify as one of the four primary [topic types](#documentation-topic-types). +classify as one of the four primary [topic types](#documentation-topic-types-ctrt). These include: - [Tutorials](#tutorials) @@ -174,7 +174,7 @@ In general, you might consider using a tutorial when: Tutorials are learning aids that complement our core documentation. They do not introduce new features. -Always use the primary [topic types](#documentation-topic-types) to document new features. +Always use the primary [topic types](#documentation-topic-types-ctrt) to document new features. Tutorials should be in this format: diff --git a/doc/development/sidekiq/idempotent_jobs.md b/doc/development/sidekiq/idempotent_jobs.md index 40cdff7bb94..4b201e22ca9 100644 --- a/doc/development/sidekiq/idempotent_jobs.md +++ b/doc/development/sidekiq/idempotent_jobs.md @@ -185,30 +185,6 @@ end Duplicate jobs can happen when the TTL is reached, so make sure you lower this only for jobs that can tolerate some duplication. -## Deduplication with load balancing - -> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/6763) in GitLab 14.4. - -Jobs that declare either `:sticky` or `:delayed` data consistency -are eligible for database load-balancing. -In both cases, jobs are [scheduled in the future](#scheduling-jobs-in-the-future) with a short delay (1 second). -This minimizes the chance of replication lag after a write. - -If you really want to deduplicate jobs eligible for load balancing, -specify `including_scheduled: true` argument when defining deduplication strategy: - -```ruby -class DelayedIdempotentWorker - include ApplicationWorker - data_consistency :delayed - - deduplicate :until_executing, including_scheduled: true - idempotent! - - # ... -end -``` - ### Preserve the latest WAL location for idempotent jobs > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69372) in GitLab 14.3. diff --git a/doc/development/sidekiq/worker_attributes.md b/doc/development/sidekiq/worker_attributes.md index dbae0b03eab..d681e17a053 100644 --- a/doc/development/sidekiq/worker_attributes.md +++ b/doc/development/sidekiq/worker_attributes.md @@ -259,10 +259,11 @@ these scenarios, since `:always` should be considered the exception, not the rul To allow for reads to be served from replicas, we added two additional consistency modes: `:sticky` and `:delayed`. When you declare either `:sticky` or `:delayed` consistency, workers become eligible for database -load-balancing. In both cases, jobs are enqueued with a short delay. -This minimizes the likelihood of replication lag after a write. +load-balancing. -The difference is in what happens when there is replication lag after the delay: `sticky` workers +In both cases, if the replica is not up-to-date and the time from scheduling the job was less than the minimum delay interval, + the jobs sleep up to the minimum delay interval (0.8 seconds). This gives the replication process time to finish. +The difference is in what happens when there is still replication lag after the delay: `sticky` workers switch over to the primary right away, whereas `delayed` workers fail fast and are retried once. If they still encounter replication lag, they also switch to the primary instead. **If your worker never performs any writes, it is strongly advised to apply one of these consistency settings, diff --git a/doc/integration/github.md b/doc/integration/github.md index d8877e069b8..412ddf0225e 100644 --- a/doc/integration/github.md +++ b/doc/integration/github.md @@ -4,116 +4,117 @@ group: Integrations 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/#assignments --- -# Integrate your GitLab instance with GitHub **(FREE SELF)** +# Use GitHub as an authentication provider **(FREE SELF)** -You can integrate your GitLab instance with GitHub.com and GitHub Enterprise. This integration -enables users to import projects from GitHub, or sign in to your GitLab instance -with their GitHub account. +You can integrate your GitLab instance with GitHub.com and GitHub Enterprise. +You can import projects from GitHub, or sign in to GitLab +with your GitHub credentials. -## Security check +## Create an OAuth app in GitHub -Some integrations risk compromising GitLab accounts. To help mitigate this -[OAuth 2 covert redirect](https://oauth.net/advisories/2014-1-covert-redirect/) -vulnerability, append `/users/auth` to the end of the authorization callback URL. +To enable the GitHub OmniAuth provider, you need an OAuth 2.0 client ID and client +secret from GitHub: + +1. Sign in to GitHub. +1. [Create an OAuth App](https://docs.github.com/en/developers/apps/building-oauth-apps/creating-an-oauth-app) + and provide the following information: + - The URL of your GitLab instance, such as `https://gitlab.example.com`. + - The authorization callback URL, such as, `https://gitlab.example.com/users/auth`. + Include the port number if your GitLab instance uses a non-default port. + +### Check for security vulnerabilities + +For some integrations, the [OAuth 2 covert redirect](https://oauth.net/advisories/2014-1-covert-redirect/) +vulnerability can compromise GitLab accounts. +To mitigate this vulnerability, append `/users/auth` to the authorization +callback URL. However, as far as we know, GitHub does not validate the subdomain part of the `redirect_uri`. -This means that a subdomain takeover, an XSS, or an open redirect on any subdomain of +Therefore, a subdomain takeover, an XSS, or an open redirect on any subdomain of your website could enable the covert redirect attack. -## Enabling GitHub OAuth +## Enable GitHub OAuth in GitLab -To enable the GitHub OmniAuth provider, you need an OAuth 2 Client ID and Client Secret from GitHub. To get these credentials, sign into GitHub and follow their procedure for [Creating an OAuth App](https://docs.github.com/en/developers/apps/building-oauth-apps/creating-an-oauth-app). +1. [Configure the initial settings](omniauth.md#configure-initial-settings) in GitLab. -When you create an OAuth 2 app in GitHub, you need the following information: +1. Edit the GitLab configuration file using the following information: -- The URL of your GitLab instance, such as `https://gitlab.example.com`. -- The authorization callback URL; in this case, `https://gitlab.example.com/users/auth`. Include the port number if your GitLab instance uses a non-default port. + | GitHub setting | Value in the GitLab configuration file | Description | + |----------------|----------------------------------------|-------------------------| + | Client ID | `YOUR_APP_ID` | OAuth 2.0 client ID | + | Client secret | `YOUR_APP_SECRET` | OAuth 2.0 client secret | + | URL | `https://github.example.com/` | GitHub deployment URL | -See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings. + - **For Omnibus installations** -After you have configured the GitHub provider, you need the following information. You must substitute that information in the GitLab configuration file in these next steps. + 1. Open the `/etc/gitlab/gitlab.rb` file. -| Setting from GitHub | Substitute in the GitLab configuration file | Description | -|:---------------------|:---------------------------------------------|:------------| -| Client ID | `YOUR_APP_ID` | OAuth 2 Client ID | -| Client Secret | `YOUR_APP_SECRET` | OAuth 2 Client Secret | -| URL | `https://github.example.com/` | GitHub Deployment URL | + For GitHub.com, update the following section: -Follow these steps to incorporate the GitHub OAuth 2 app in your GitLab server: + ```ruby + gitlab_rails['omniauth_providers'] = [ + { + name: "github", + # label: "Provider name", # optional label for login button, defaults to "GitHub" + app_id: "YOUR_APP_ID", + app_secret: "YOUR_APP_SECRET", + args: { scope: "user:email" } + } + ] + ``` -**For Omnibus installations** + For GitHub Enterprise, update the following section and replace + `https://github.example.com/` with your GitHub URL: -1. Edit `/etc/gitlab/gitlab.rb`: + ```ruby + gitlab_rails['omniauth_providers'] = [ + { + name: "github", + # label: "Provider name", # optional label for login button, defaults to "GitHub" + app_id: "YOUR_APP_ID", + app_secret: "YOUR_APP_SECRET", + url: "https://github.example.com/", + args: { scope: "user:email" } + } + ] + ``` - For GitHub.com: + 1. Save the file and [reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) + GitLab. - ```ruby - gitlab_rails['omniauth_providers'] = [ - { - name: "github", - # label: "Provider name", # optional label for login button, defaults to "GitHub" - app_id: "YOUR_APP_ID", - app_secret: "YOUR_APP_SECRET", - args: { scope: "user:email" } - } - ] - ``` + - **For installations from source** - For GitHub Enterprise: + 1. Open the `config/gitlab.yml` file. - ```ruby - gitlab_rails['omniauth_providers'] = [ - { - name: "github", - # label: "Provider name", # optional label for login button, defaults to "GitHub" - app_id: "YOUR_APP_ID", - app_secret: "YOUR_APP_SECRET", - url: "https://github.example.com/", - args: { scope: "user:email" } - } - ] - ``` + For GitHub.com, update the following section: - **Replace `https://github.example.com/` with your GitHub URL.** + ```yaml + - { name: 'github', + # label: 'Provider name', # optional label for login button, defaults to "GitHub" + app_id: 'YOUR_APP_ID', + app_secret: 'YOUR_APP_SECRET', + args: { scope: 'user:email' } } + ``` -1. Save the file and [reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) GitLab for the changes to take effect. + For GitHub Enterprise, update the following section and replace + `https://github.example.com/` with your GitHub URL: ---- + ```yaml + - { name: 'github', + # label: 'Provider name', # optional label for login button, defaults to "GitHub" + app_id: 'YOUR_APP_ID', + app_secret: 'YOUR_APP_SECRET', + url: "https://github.example.com/", + args: { scope: 'user:email' } } + ``` -**For installations from source** + 1. Save the file and [restart](../administration/restart_gitlab.md#installations-from-source) + GitLab. -1. Navigate to your repository and edit `config/gitlab.yml`: +1. Refresh the GitLab sign-in page. A GitHub icon should display below the + sign-in form. - For GitHub.com: - - ```yaml - - { name: 'github', - # label: 'Provider name', # optional label for login button, defaults to "GitHub" - app_id: 'YOUR_APP_ID', - app_secret: 'YOUR_APP_SECRET', - args: { scope: 'user:email' } } - ``` - - For GitHub Enterprise: - - ```yaml - - { name: 'github', - # label: 'Provider name', # optional label for login button, defaults to "GitHub" - app_id: 'YOUR_APP_ID', - app_secret: 'YOUR_APP_SECRET', - url: "https://github.example.com/", - args: { scope: 'user:email' } } - ``` - - **Replace `https://github.example.com/` with your GitHub URL.** - -1. Save the file and [restart](../administration/restart_gitlab.md#installations-from-source) GitLab for the changes to take effect. - ---- - -1. Refresh the GitLab sign in page. You should now see a GitHub icon below the regular sign in form. - -1. Click the icon to begin the authentication process. GitHub asks the user to sign in and authorize the GitLab application. +1. Select the icon. Sign in to GitHub and authorize the GitLab application. ## GitHub Enterprise with self-signed Certificate diff --git a/doc/user/clusters/agent/index.md b/doc/user/clusters/agent/index.md index 975681aa798..3fb141e402f 100644 --- a/doc/user/clusters/agent/index.md +++ b/doc/user/clusters/agent/index.md @@ -8,79 +8,67 @@ info: To determine the technical writer assigned to the Stage/Group associated w > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/223061) in GitLab 13.4. > - Support for `grpcs` [introduced](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/issues/7) in GitLab 13.6. -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/300960) in GitLab 13.10, KAS became available on GitLab.com under `wss://kas.gitlab.com` through an Early Adopter Program. -> - Introduced in GitLab 13.11, the GitLab Agent became available to every project on GitLab.com. +> - Agent Server [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/300960) on GitLab.com under `wss://kas.gitlab.com` through an Early Adopter Program in GitLab 13.10. +> - The agent became available to every project on GitLab.com in GitLab 13.11. > - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) from GitLab Premium to GitLab Free in 14.5. -> - [Renamed](https://gitlab.com/groups/gitlab-org/-/epics/7167) from "GitLab Kubernetes Agent" to "GitLab Agent for Kubernetes" in GitLab 14.6. +> - [Renamed](https://gitlab.com/groups/gitlab-org/-/epics/7167) from "GitLab Kubernetes Agent" to "GitLab agent for Kubernetes" in GitLab 14.6. -The [GitLab Agent for Kubernetes](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent) ("Agent", for short) -is an active in-cluster component for connecting Kubernetes clusters to GitLab safely to support cloud-native deployment, management, and monitoring. +You can connect your Kubernetes cluster with GitLab to deploy, manage, +and monitor your cloud-native solutions. You can choose from two primary workflows. -The Agent is installed into the cluster through code, providing you with a fast, safe, stable, and scalable solution. +In a **GitOps workflow**, you keep your Kubernetes manifests in GitLab. You install a GitLab agent in your cluster, and +any time you update your manifests, the agent updates the cluster. This workflow is fully driven with Git and is considered pull-based, +because the cluster is pulling updates from your GitLab repository. -With GitOps, you can manage containerized clusters and applications from a Git repository that: +In a **CI/CD** workflow, you use GitLab CI/CD to query and update your cluster by using the Kubernetes API. +This workflow is considered push-based, because GitLab is pushing requests from GitLab CI/CD to your cluster. -- Is the single source of truth of your system. -- Is the single place where you operate your system. -- Is a single resource to monitor your system. - -By combining GitLab, Kubernetes, and GitOps, it results in a robust infrastructure: - -- GitLab as the GitOps operator. -- Kubernetes as the automation and convergence system. -- GitLab CI/CD as the Continuous Integration and Continuous Deployment engine. - -Beyond that, you can use all the features offered by GitLab as -the all-in-one DevOps platform for your product and your team. +Both of these workflows require you to [install an agent in your cluster](install/index.md). ## Supported cluster versions -GitLab is committed to support at least two production-ready Kubernetes minor -versions at any given time. We regularly review the versions we support, and -provide a three-month deprecation period before we remove support of a specific -version. The range of supported versions is based on the evaluation of: - -- The versions supported by major managed Kubernetes providers. -- The versions [supported by the Kubernetes community](https://kubernetes.io/releases/version-skew-policy/#supported-versions). - -GitLab supports the following Kubernetes versions, and you can upgrade your -Kubernetes version to any supported version at any time: +GitLab supports the following Kubernetes versions. You can upgrade your +Kubernetes version to a supported version at any time: - 1.20 (support ends on July 22, 2022) - 1.19 (support ends on February 22, 2022) - 1.18 (support ends on November 22, 2021) - 1.17 (support ends on September 22, 2021) -[Adding support to other versions of Kubernetes is managed under this epic](https://gitlab.com/groups/gitlab-org/-/epics/4827). +GitLab supports at least two production-ready Kubernetes minor +versions at any given time. GitLab regularly reviews the supported versions and +provides a three-month deprecation period before removing support for a specific +version. The list of supported versions is based on: -Some GitLab features may support versions outside the range provided here. +- The versions supported by major managed Kubernetes providers. +- The versions [supported by the Kubernetes community](https://kubernetes.io/releases/version-skew-policy/#supported-versions). -## Agent's features +[This epic](https://gitlab.com/groups/gitlab-org/-/epics/4827) tracks support for other Kubernetes versions. -By using the Agent, you can: +Some GitLab features might work on versions not listed here. -- Connect GitLab with a Kubernetes cluster behind a firewall or a -Network Address Translation (NAT). -- Have real-time access to API endpoints in your cluster from GitLab CI/CD. -- Use GitOps to configure your cluster through the [Agent's repository](repository.md). -- Perform pull-based or push-based GitOps deployments. -- Configure [Network Security Alerts](#kubernetes-network-security-alerts) -based on [Container Network Policies](../../application_security/policies/index.md#container-network-policy). -- Track objects applied to your cluster through [inventory objects](../../infrastructure/clusters/deploy/inventory_object.md). -- Use the [CI/CD Tunnel](ci_cd_tunnel.md) to access Kubernetes clusters -from GitLab CI/CD jobs while keeping the cluster's APIs safe and unexposed -to the internet. -- [Deploy the GitLab Runner in a Kubernetes cluster](https://docs.gitlab.com/runner/install/kubernetes-agent.html). -- [Scan your Kubernetes cluster for vulnerabilities](../../application_security/cluster_image_scanning/index.md). +## Using Kubernetes with GitOps **(PREMIUM)** -See the [Agent roadmap](https://gitlab.com/groups/gitlab-org/-/epics/3329) to track its development. +With GitOps, you can manage containerized clusters and applications from a Git repository that: -To contribute to the Agent, see the [Agent's development documentation](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/tree/master/doc). +- Is the single source of truth of your system. +- Is the single place where you operate your system. -## Agent's GitOps workflow **(PREMIUM)** +By combining GitLab, Kubernetes, and GitOps, you can have: -The Agent uses multiple GitLab projects to provide a flexible workflow +- GitLab as the GitOps operator. +- Kubernetes as the automation and convergence system. +- GitLab CI/CD for Continuous Integration and the agent for Continuous Deployment. + +Beyond that, you can use all the features offered by GitLab as +the all-in-one DevOps platform for your product and your team. + +### GitOps workflow **(PREMIUM)** + +The agent uses multiple GitLab projects to provide a flexible workflow that can suit various needs. This diagram shows these repositories and the main +The agent uses multiple GitLab projects to provide a flexible workflow. +This diagram shows these repositories and the main actors involved in a deployment: ```mermaid @@ -88,7 +76,7 @@ sequenceDiagram participant D as Developer participant A as Application code repository participant M as Manifest repository - participant K as GitLab Agent + participant K as GitLab agent participant C as Agent configuration repository loop Regularly K-->>C: Grab the configuration @@ -101,68 +89,28 @@ sequenceDiagram end ``` -For more details, refer to our [architecture documentation](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/architecture.md#high-level-architecture) in the Agent project. +For details, view the [architecture documentation](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/architecture.md#high-level-architecture). -## Install the Agent in your cluster +To perform GitOps deployments, you need: -To connect your cluster to GitLab, [install the Agent on your cluster](install/index.md). +- A properly-configured Kubernetes cluster where the GitLab agent is running. +- A project that contains the agent's configuration file (`config.yaml`) in the repository. + This file tells the agent which repositories to synchronize with the cluster. +- A project that contains Kubernetes manifests. Any changes to manifests are applied to the cluster. -## GitOps deployments **(PREMIUM)** +You can keep the agent's configuration file and Kubernetes manifests in one project, or you can use multiple. -To perform GitOps deployments with the Agent, you need: +- One GitLab project (recommended): When you use one project for both the Kubernetes manifests + and the agent's configuration file, the projects can be either private or public. +- Two GitLab projects: When you use two different GitLab projects (one for Kubernetes + manifests and another for the agent's configuration file), the project with Kubernetes manifests must + be public. The project with the agent's configuration file can be either private or public. -- A properly-configured Kubernetes cluster where the Agent is running. -- A [configuration repository](repository.md) that contains a -`config.yaml` file, which tells the Agent the repositories to synchronize -with the cluster. -- A manifest repository that contains manifest files. Any changes to manifest files are applied to the cluster. - -You can use a single GitLab project or different projects for the Agent -configuration and manifest files, as follows: - -- Single GitLab project (recommended): When you use a single repository to hold - both the manifest and the configuration files, these projects can be either - private or public. -- Two GitLab projects: When you use two different GitLab projects (one for - manifest files and another for configuration files), the manifests project must - be public, while the configuration project can be either private or public. - -Support for separated private manifest and configuration repositories is tracked in this [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/220912). - -## Kubernetes Network Security Alerts **(ULTIMATE)** - -> [Deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476) in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477) in GitLab 15.0. - -WARNING: -Cilium integration is in its end-of-life process. It's [deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476) -for use in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477) -in GitLab 15.0. - -The GitLab Agent also provides an integration with Cilium. This integration provides a simple way to -generate network policy-related alerts and to surface those alerts in GitLab. - -There are several components that work in concert for the Agent to generate the alerts: - -- A working Kubernetes cluster. -- Cilium integration through either of these options: - - Installation through [cluster management template](../../project/clusters/protect/container_network_security/quick_start_guide.md#use-the-cluster-management-template-to-install-cilium). - - Enablement of [hubble-relay](https://docs.cilium.io/en/v1.8/concepts/overview/#hubble) on an - existing installation. -- One or more network policies through any of these options: - - Use the [Container Network Policy editor](../../application_security/policies/index.md#container-network-policy-editor) to create and manage policies. - - Use an [AutoDevOps](../../application_security/policies/index.md#container-network-policy) configuration. - - Add the required labels and annotations to existing network policies. -- A configuration repository with [Cilium configured in `config.yaml`](repository.md#surface-network-security-alerts-from-cluster-to-gitlab) - -The setup process follows the same [Agent's installation steps](install/index.md), -with the following differences: - -- When you define a configuration repository, you must do so with [Cilium settings](repository.md#surface-network-security-alerts-from-cluster-to-gitlab). -- You do not need to specify the `gitops` configuration section. +Support for separate private projects is tracked in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/283885). ## Remove an agent -You can remove an agent using the [GitLab UI](#remove-an-agent-through-the-gitlab-ui) or through the [GraphQL API](#remove-an-agent-with-the-gitlab-graphql-api). +You can remove an agent by using the [GitLab UI](#remove-an-agent-through-the-gitlab-ui) or the [GraphQL API](#remove-an-agent-with-the-gitlab-graphql-api). ### Remove an agent through the GitLab UI @@ -170,16 +118,16 @@ You can remove an agent using the [GitLab UI](#remove-an-agent-through-the-gitla To remove an agent from the UI: -1. Go to your agent's configuration repository. -1. From your project's sidebar, select **Infrastructure > Kubernetes clusters**. -1. Select your agent from the table, and then in the **Options** column, click the vertical ellipsis -(**{ellipsis_v}**) button and select **Delete agent**. +1. On the top bar, select **Menu > Projects** and find the project that contains the agent's configuration file. +1. From the left sidebar, select **Infrastructure > Kubernetes clusters**. +1. In the table, in the row for your agent, in the **Options** column, select the vertical ellipsis (**{ellipsis_v}**). +1. Select **Delete agent**. ### Remove an agent with the GitLab GraphQL API 1. Get the `` from a query in the interactive GraphQL explorer. -For GitLab.com, go to to open GraphQL Explorer. -For self-managed GitLab instances, go to `https://gitlab.example.com/-/graphql-explorer`, replacing `gitlab.example.com` with your own instance's URL. + - For GitLab.com, go to to open GraphQL Explorer. + - For self-managed GitLab, go to `https://gitlab.example.com/-/graphql-explorer`, replacing `gitlab.example.com` with your instance's URL. ```graphql query{ @@ -225,16 +173,48 @@ For self-managed GitLab instances, go to `https://gitlab.example.com/-/graphql-e } ``` -1. Delete the Agent in your cluster: +1. Delete the agent in your cluster: ```shell kubectl delete -n gitlab-kubernetes-agent -f ./resources.yml ``` -## Migrating to the GitLab Agent from the legacy certificate-based integration +## Migrating to the agent from the legacy certificate-based integration -Find out how to [migrate to the GitLab Agent for Kubernetes](../../infrastructure/clusters/migrate_to_gitlab_agent.md) from the certificate-based integration depending on the features you use. +Find out how to [migrate to the agent for Kubernetes](../../infrastructure/clusters/migrate_to_gitlab_agent.md) from the certificate-based integration. + +## Kubernetes network security alerts **(ULTIMATE)** + +> [Deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476) in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477) in GitLab 15.0. + +WARNING: +Cilium integration is in its end-of-life process. It's [deprecated](https://gitlab.com/groups/gitlab-org/-/epics/7476) +for use in GitLab 14.8, and planned for [removal](https://gitlab.com/groups/gitlab-org/-/epics/7477) +in GitLab 15.0. + +The agent for Kubernetes also provides an integration with Cilium. This integration provides a simple way to +generate network policy-related alerts and to surface those alerts in GitLab. + +Several components work in concert for the agent to generate the alerts: + +- A working Kubernetes cluster. +- Cilium integration through either of these options: + - Installation through [cluster management template](../../project/clusters/protect/container_network_security/quick_start_guide.md#use-the-cluster-management-template-to-install-cilium). + - Enablement of [hubble-relay](https://docs.cilium.io/en/v1.8/concepts/overview/#hubble) on an + existing installation. +- One or more network policies through any of these options: + - Use the [Container Network Policy editor](../../application_security/policies/index.md#container-network-policy-editor) to create and manage policies. + - Use an [AutoDevOps](../../application_security/policies/index.md#container-network-policy) configuration. + - Add the required labels and annotations to existing network policies. +- A configuration repository with [Cilium configured in `config.yaml`](repository.md#surface-network-security-alerts-from-cluster-to-gitlab) + +The setup process follows the same [agent's installation steps](install/index.md), +with the following differences: + +- When you define a configuration repository, you must do so with [Cilium settings](repository.md#surface-network-security-alerts-from-cluster-to-gitlab). +- You do not need to specify the `gitops` configuration section. ## Related topics - [Troubleshooting](troubleshooting.md) +- [Contribute to the GitLab agent's development](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/tree/master/doc) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 84d1210488d..690b63ee745 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -11630,6 +11630,9 @@ msgstr "" msgid "Delete pipeline" msgstr "" +msgid "Delete pipeline schedule" +msgstr "" + msgid "Delete project" msgstr "" @@ -33809,9 +33812,6 @@ msgstr "" msgid "Something went wrong trying to load issue contacts." msgstr "" -msgid "Something went wrong when creating a work item. Please try again" -msgstr "" - msgid "Something went wrong when reordering designs. Please try again" msgstr "" @@ -41093,6 +41093,15 @@ msgstr "" msgid "WorkItem|New Task" msgstr "" +msgid "WorkItem|Something went wrong when creating a work item. Please try again" +msgstr "" + +msgid "WorkItem|Something went wrong when fetching work item types. Please try again" +msgstr "" + +msgid "WorkItem|Type" +msgstr "" + msgid "WorkItem|Work Items" msgstr "" diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb index be54081c925..d76dfb295a0 100644 --- a/qa/qa/page/merge_request/show.rb +++ b/qa/qa/page/merge_request/show.rb @@ -263,7 +263,8 @@ module QA # status as unmerged, the test will fail. # Revisit after merge page re-architect is done https://gitlab.com/groups/gitlab-org/-/epics/5598 # To remove page refresh logic if possible - retry_until(max_attempts: 3, reload: true) do + # We don't raise on failure because this method is used as a predicate matcher + retry_until(max_attempts: 3, reload: true, raise_on_failure: false) do has_element?(:merged_status_content, text: 'The changes were merged into', wait: 20) end end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb index e0520655542..178615f23f1 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb @@ -88,7 +88,7 @@ module QA mr.wait_until_ready_to_merge(transient_test: transient_test) mr.retry_until(reload: true, message: 'Wait until ready to click MWPS') do - merge_request = merge_request.reload! + merge_request.reload! # Don't try to click MWPS if the MR is merged or the pipeline is complete break if merge_request.state == 'merged' || mr.wait_until { project.pipelines.last }[:status] == 'success' @@ -102,8 +102,10 @@ module QA end aggregate_failures do - expect(mr.merged?).to be_truthy, "Expected content 'The changes were merged' but it did not appear." + expect { mr.merged? }.to eventually_be_truthy.within(max_duration: 60), "Expected content 'The changes were merged' but it did not appear." expect(merge_request.reload!.merge_when_pipeline_succeeds).to be_truthy + expect(merge_request.state).to eq('merged') + expect(project.pipelines.last[:status]).to eq('success') end end end diff --git a/spec/frontend/work_items/mock_data.js b/spec/frontend/work_items/mock_data.js index 9741a193258..a98722bc465 100644 --- a/spec/frontend/work_items/mock_data.js +++ b/spec/frontend/work_items/mock_data.js @@ -34,3 +34,17 @@ export const updateWorkItemMutationResponse = { }, }, }; + +export const projectWorkItemTypesQueryResponse = { + data: { + workspace: { + id: '1', + workItemTypes: { + nodes: [ + { id: 'work-item-1', name: 'Issue' }, + { id: 'work-item-2', name: 'Incident' }, + ], + }, + }, + }, +}; diff --git a/spec/frontend/work_items/pages/create_work_item_spec.js b/spec/frontend/work_items/pages/create_work_item_spec.js index 00571c1f5c8..b9fef0eaa6a 100644 --- a/spec/frontend/work_items/pages/create_work_item_spec.js +++ b/spec/frontend/work_items/pages/create_work_item_spec.js @@ -1,12 +1,14 @@ import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; -import { GlAlert } from '@gitlab/ui'; +import { GlAlert, GlDropdown, GlDropdownItem } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; import CreateWorkItem from '~/work_items/pages/create_work_item.vue'; import ItemTitle from '~/work_items/components/item_title.vue'; import { resolvers } from '~/work_items/graphql/resolvers'; +import projectWorkItemTypesQuery from '~/work_items/graphql/project_work_item_types.query.graphql'; +import { projectWorkItemTypesQueryResponse } from '../mock_data'; Vue.use(VueApollo); @@ -14,13 +16,20 @@ describe('Create work item component', () => { let wrapper; let fakeApollo; + const querySuccessHandler = jest.fn().mockResolvedValue(projectWorkItemTypesQueryResponse); + const findAlert = () => wrapper.findComponent(GlAlert); const findTitleInput = () => wrapper.findComponent(ItemTitle); + const findDropdown = () => wrapper.findComponent(GlDropdown); + const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem); + const findCreateButton = () => wrapper.find('[data-testid="create-button"]'); const findCancelButton = () => wrapper.find('[data-testid="cancel-button"]'); + const findContent = () => wrapper.find('[data-testid="content"]'); + const findLoadingTypesIcon = () => wrapper.find('[data-testid="loading-types"]'); - const createComponent = ({ data = {}, props = {} } = {}) => { - fakeApollo = createMockApollo([], resolvers); + const createComponent = ({ data = {}, props = {}, queryHandler = querySuccessHandler } = {}) => { + fakeApollo = createMockApollo([[projectWorkItemTypesQuery, queryHandler]], resolvers); wrapper = shallowMount(CreateWorkItem, { apolloProvider: fakeApollo, data() { @@ -37,6 +46,9 @@ describe('Create work item component', () => { push: jest.fn(), }, }, + provide: { + fullPath: 'full-path', + }, }); }; @@ -84,6 +96,10 @@ describe('Create work item component', () => { it('does not add right margin for cancel button', () => { expect(findCancelButton().classes()).not.toContain('gl-mr-3'); }); + + it('does not add padding for content', () => { + expect(findContent().classes('gl-px-5')).toBe(false); + }); }); describe('when displayed in a modal', () => { @@ -118,6 +134,44 @@ describe('Create work item component', () => { it('adds right margin for cancel button', () => { expect(findCancelButton().classes()).toContain('gl-mr-3'); }); + + it('adds padding for content', () => { + expect(findContent().classes('gl-px-5')).toBe(true); + }); + }); + + it('displays a loading icon inside dropdown when work items query is loading', () => { + createComponent(); + + expect(findLoadingTypesIcon().exists()).toBe(true); + }); + + it('displays an alert when work items query is rejected', async () => { + createComponent({ queryHandler: jest.fn().mockRejectedValue('Houston, we have a problem') }); + await waitForPromises(); + + expect(findAlert().exists()).toBe(true); + expect(findAlert().text()).toContain('fetching work item types'); + }); + + describe('when work item types are fetched', () => { + beforeEach(() => { + createComponent(); + return waitForPromises(); + }); + + it('displays a list of work item types', () => { + expect(findDropdownItems()).toHaveLength(2); + expect(findDropdownItems().at(0).text()).toContain('Issue'); + }); + + it('selects a work item type on click', async () => { + expect(findDropdown().props('text')).toBe('Type'); + findDropdownItems().at(0).vm.$emit('click'); + await nextTick(); + + expect(findDropdown().props('text')).toBe('Issue'); + }); }); it('hides the alert on dismissing the error', async () => { diff --git a/spec/frontend/work_items/router_spec.js b/spec/frontend/work_items/router_spec.js index 6017c9d9dbb..c583b5a5d4f 100644 --- a/spec/frontend/work_items/router_spec.js +++ b/spec/frontend/work_items/router_spec.js @@ -15,6 +15,16 @@ describe('Work items router', () => { wrapper = mount(App, { router, + provide: { + fullPath: 'full-path', + }, + mocks: { + $apollo: { + queries: { + workItemTypes: {}, + }, + }, + }, }); }; diff --git a/spec/requests/api/graphql/mutations/issues/create_spec.rb b/spec/requests/api/graphql/mutations/issues/create_spec.rb index 6baed352b37..3d81b456c9c 100644 --- a/spec/requests/api/graphql/mutations/issues/create_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/create_spec.rb @@ -52,5 +52,22 @@ RSpec.describe 'Create an issue' do it_behaves_like 'has spam protection' do let(:mutation_class) { ::Mutations::Issues::Create } end + + context 'when position params are provided' do + let(:existing_issue) { create(:issue, project: project, relative_position: 50) } + + before do + input.merge!( + move_after_id: existing_issue.to_global_id.to_s + ) + end + + it 'sets the correct position' do + post_graphql_mutation(mutation, current_user: current_user) + + expect(response).to have_gitlab_http_status(:success) + expect(mutation_response['issue']['relativePosition']).to be < existing_issue.relative_position + end + end end end diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb index 4494c1acaf7..90bab5bf76a 100644 --- a/spec/services/issues/create_service_spec.rb +++ b/spec/services/issues/create_service_spec.rb @@ -92,6 +92,23 @@ RSpec.describe Issues::CreateService do end end + context 'when setting a position' do + let(:issue_before) { create(:issue, project: project, relative_position: 10) } + let(:issue_after) { create(:issue, project: project, relative_position: 50) } + + before do + project.add_reporter(user) + + opts.merge!(move_between_ids: [issue_before.id, issue_after.id]) + end + + it 'sets the correct relative position' do + expect(issue).to be_persisted + expect(issue.relative_position).to be_present + expect(issue.relative_position).to be_between(issue_before.relative_position, issue_after.relative_position) + end + end + it_behaves_like 'not an incident issue' context 'when issue is incident type' do