diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-01-24 15:09:24 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-01-24 15:09:24 +0300 |
commit | 17c1c66eefd05243dd8ed2c8fd49d17ab1a52522 (patch) | |
tree | a6f7c103902284c8245bc1991769916139f60aa9 | |
parent | 3a4363e0098b1ff7689247e55da416848ac51050 (diff) |
Add latest changes from gitlab-org/gitlab@master
38 files changed, 490 insertions, 296 deletions
diff --git a/app/assets/javascripts/blob/components/table_contents.vue b/app/assets/javascripts/blob/components/table_contents.vue index b3410b94b98..28e81b83713 100644 --- a/app/assets/javascripts/blob/components/table_contents.vue +++ b/app/assets/javascripts/blob/components/table_contents.vue @@ -1,5 +1,5 @@ <script> -import { GlDropdown, GlDropdownItem } from '@gitlab/ui'; +import { GlDisclosureDropdown } from '@gitlab/ui'; function getHeaderNumber(el) { return parseInt(el.tagName.match(/\d+/)[0], 10); @@ -7,8 +7,7 @@ function getHeaderNumber(el) { export default { components: { - GlDropdown, - GlDropdownItem, + GlDisclosureDropdown, }, data() { return { @@ -43,33 +42,40 @@ export default { } }, methods: { + close() { + this.$refs.disclosureDropdown?.close(); + }, generateHeaders() { + const BASE_PADDING = 16; const headers = [...this.blobViewer.querySelectorAll('h1,h2,h3,h4,h5,h6')]; - if (headers.length) { - const firstHeader = getHeaderNumber(headers[0]); - - this.items = headers.map((el) => ({ - text: el.textContent.trim(), - anchor: el.querySelector('a').getAttribute('id'), - spacing: Math.max((getHeaderNumber(el) - firstHeader) * 8, 0), - })); + if (headers.length === 0) { + return; } + + const firstHeader = getHeaderNumber(headers[0]); + + this.items = headers.map((el) => ({ + text: el.textContent.trim(), + href: `#${el.querySelector('a').getAttribute('id')}`, + extraAttrs: { + style: { + paddingLeft: `${BASE_PADDING + Math.max((getHeaderNumber(el) - firstHeader) * 8, 0)}px`, + }, + }, + })); }, }, }; </script> <template> - <gl-dropdown v-if="!isHidden && items.length" icon="list-bulleted" class="gl-mr-2" lazy> - <gl-dropdown-item v-for="(item, index) in items" :key="index" :href="`#${item.anchor}`"> - <span - :style="{ 'padding-left': `${item.spacing}px` }" - class="gl-display-block" - data-testid="tableContentsLink" - > - {{ item.text }} - </span> - </gl-dropdown-item> - </gl-dropdown> + <gl-disclosure-dropdown + v-if="!isHidden && items.length" + ref="disclosureDropdown" + icon="list-bulleted" + class="gl-mr-2" + :items="items" + @action="close" + /> </template> diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 1c26a8a0af3..47375eb7bcf 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -65,6 +65,7 @@ class Projects::IssuesController < Projects::ApplicationController push_frontend_feature_flag(:epic_widget_edit_confirmation, project) push_frontend_feature_flag(:use_iid_in_work_items_path, project&.group) push_force_frontend_feature_flag(:work_items_create_from_markdown, project&.work_items_create_from_markdown_feature_flag_enabled?) + push_frontend_feature_flag(:incident_event_tags, project) end around_action :allow_gitaly_ref_name_caching, only: [:discussions] diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 7fd14363377..04190bc442b 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -304,11 +304,7 @@ module ProjectsHelper current_page?(starred_explore_projects_path) end - def show_merge_request_count?(disabled: false, compact_mode: false) - !disabled && !compact_mode - end - - def show_issue_count?(disabled: false, compact_mode: false) + def show_count?(disabled: false, compact_mode: false) !disabled && !compact_mode end @@ -439,6 +435,10 @@ module ProjectsHelper project.merge_requests_enabled? && can?(user, :read_merge_request, project) end + def able_to_see_forks_count?(project, user) + project.forking_enabled? && can?(user, :read_code, project) + end + def fork_button_disabled_tooltip(project) return unless current_user diff --git a/app/views/shared/projects/_list.html.haml b/app/views/shared/projects/_list.html.haml index 813d8c5ed2b..09d63347ed6 100644 --- a/app/views/shared/projects/_list.html.haml +++ b/app/views/shared/projects/_list.html.haml @@ -37,7 +37,7 @@ - css_class = (i >= projects_limit) || project.pending_delete? ? 'hide' : nil = render "shared/projects/project", project: project, skip_namespace: skip_namespace, avatar: avatar, stars: stars, css_class: css_class, use_creator_avatar: use_creator_avatar, - forks: project.forking_enabled?, show_last_commit_as_description: show_last_commit_as_description, + forks: able_to_see_forks_count?(project, user), show_last_commit_as_description: show_last_commit_as_description, user: user, merge_requests: able_to_see_merge_requests?(project, user), issues: able_to_see_issues?(project, user), pipeline_status: pipeline_status, compact_mode: compact_mode = paginate_collection(projects, remote: remote) unless skip_pagination diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml index 40cd81ab3da..2adc7844a67 100644 --- a/app/views/shared/projects/_project.html.haml +++ b/app/views/shared/projects/_project.html.haml @@ -97,15 +97,15 @@ = link_to project_starrers_path(project), class: "#{css_metadata_classes} stars", title: _('Stars'), data: { container: 'body', placement: 'top' } do = sprite_icon('star-o', size: 14, css_class: 'gl-mr-2') = badge_count(project.star_count) - - if forks + - if show_count?(disabled: !forks, compact_mode: compact_mode) = link_to project_forks_path(project), class: "#{css_metadata_classes} forks", title: _('Forks'), data: { container: 'body', placement: 'top' } do = sprite_icon('fork', size: 14, css_class: 'gl-mr-2') = badge_count(project.forks_count) - - if show_merge_request_count?(disabled: !merge_requests, compact_mode: compact_mode) + - if show_count?(disabled: !merge_requests, compact_mode: compact_mode) = link_to project_merge_requests_path(project), class: "#{css_metadata_classes} merge-requests", title: _('Merge requests'), data: { container: 'body', placement: 'top' } do = sprite_icon('git-merge', size: 14, css_class: 'gl-mr-2') = badge_count(project.open_merge_requests_count) - - if show_issue_count?(disabled: !issues, compact_mode: compact_mode) + - if show_count?(disabled: !issues, compact_mode: compact_mode) = link_to project_issues_path(project), class: "#{css_metadata_classes} issues", title: _('Issues'), data: { container: 'body', placement: 'top' } do = sprite_icon('issues', size: 14, css_class: 'gl-mr-2') = badge_count(project.open_issues_count) diff --git a/db/post_migrate/20230118083437_redefine_foreign_key_on_ci_unit_test_failure.rb b/db/post_migrate/20230118083437_redefine_foreign_key_on_ci_unit_test_failure.rb new file mode 100644 index 00000000000..220da0908a9 --- /dev/null +++ b/db/post_migrate/20230118083437_redefine_foreign_key_on_ci_unit_test_failure.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +class RedefineForeignKeyOnCiUnitTestFailure < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + + SOURCE_TABLE_NAME = :ci_unit_test_failures + TARGET_TABLE_NAME = :ci_builds + COLUMN = :build_id + TARGET_COLUMN = :id + OLD_FK_NAME = :fk_0f09856e1f_p + PARTITION_COLUMN = :partition_id + + def up + add_concurrent_foreign_key( + SOURCE_TABLE_NAME, + TARGET_TABLE_NAME, + column: [PARTITION_COLUMN, COLUMN], + target_column: [PARTITION_COLUMN, TARGET_COLUMN], + validate: true, + reverse_lock_order: true, + name: new_foreign_key_name, + on_update: :cascade + ) + + with_lock_retries do + remove_foreign_key_if_exists(SOURCE_TABLE_NAME, name: OLD_FK_NAME) + end + end + + def down + add_concurrent_foreign_key( + SOURCE_TABLE_NAME, + TARGET_TABLE_NAME, + column: [PARTITION_COLUMN, COLUMN], + target_column: [PARTITION_COLUMN, TARGET_COLUMN], + validate: true, + reverse_lock_order: true, + name: OLD_FK_NAME + ) + + with_lock_retries do + remove_foreign_key_if_exists(SOURCE_TABLE_NAME, name: new_foreign_key_name) + end + end + + private + + def new_foreign_key_name + "#{concurrent_foreign_key_name(SOURCE_TABLE_NAME, [PARTITION_COLUMN, COLUMN])}_p" + end +end diff --git a/db/post_migrate/20230118083632_redefine_foreign_key_on_ci_build_pending_state.rb b/db/post_migrate/20230118083632_redefine_foreign_key_on_ci_build_pending_state.rb new file mode 100644 index 00000000000..002ec923989 --- /dev/null +++ b/db/post_migrate/20230118083632_redefine_foreign_key_on_ci_build_pending_state.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +class RedefineForeignKeyOnCiBuildPendingState < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + + SOURCE_TABLE_NAME = :ci_build_pending_states + TARGET_TABLE_NAME = :ci_builds + COLUMN = :build_id + TARGET_COLUMN = :id + OLD_FK_NAME = :fk_rails_0bbbfeaf9d_p + PARTITION_COLUMN = :partition_id + + def up + add_concurrent_foreign_key( + SOURCE_TABLE_NAME, + TARGET_TABLE_NAME, + column: [PARTITION_COLUMN, COLUMN], + target_column: [PARTITION_COLUMN, TARGET_COLUMN], + validate: true, + reverse_lock_order: true, + name: new_foreign_key_name, + on_update: :cascade + ) + + with_lock_retries do + remove_foreign_key_if_exists(SOURCE_TABLE_NAME, name: OLD_FK_NAME) + end + end + + def down + add_concurrent_foreign_key( + SOURCE_TABLE_NAME, + TARGET_TABLE_NAME, + column: [PARTITION_COLUMN, COLUMN], + target_column: [PARTITION_COLUMN, TARGET_COLUMN], + validate: true, + reverse_lock_order: true, + name: OLD_FK_NAME + ) + + with_lock_retries do + remove_foreign_key_if_exists(SOURCE_TABLE_NAME, name: new_foreign_key_name) + end + end + + private + + def new_foreign_key_name + "#{concurrent_foreign_key_name(SOURCE_TABLE_NAME, [PARTITION_COLUMN, COLUMN])}_p" + end +end diff --git a/db/post_migrate/20230118083748_redefine_foreign_key_on_ci_build_trace_chunk.rb b/db/post_migrate/20230118083748_redefine_foreign_key_on_ci_build_trace_chunk.rb new file mode 100644 index 00000000000..3474e672dfa --- /dev/null +++ b/db/post_migrate/20230118083748_redefine_foreign_key_on_ci_build_trace_chunk.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +class RedefineForeignKeyOnCiBuildTraceChunk < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + + SOURCE_TABLE_NAME = :ci_build_trace_chunks + TARGET_TABLE_NAME = :ci_builds + COLUMN = :build_id + TARGET_COLUMN = :id + OLD_FK_NAME = :fk_rails_1013b761f2_p + PARTITION_COLUMN = :partition_id + + def up + add_concurrent_foreign_key( + SOURCE_TABLE_NAME, + TARGET_TABLE_NAME, + column: [PARTITION_COLUMN, COLUMN], + target_column: [PARTITION_COLUMN, TARGET_COLUMN], + validate: true, + reverse_lock_order: true, + name: new_foreign_key_name, + on_update: :cascade + ) + + with_lock_retries do + remove_foreign_key_if_exists(SOURCE_TABLE_NAME, name: OLD_FK_NAME) + end + end + + def down + add_concurrent_foreign_key( + SOURCE_TABLE_NAME, + TARGET_TABLE_NAME, + column: [PARTITION_COLUMN, COLUMN], + target_column: [PARTITION_COLUMN, TARGET_COLUMN], + validate: true, + reverse_lock_order: true, + name: OLD_FK_NAME + ) + + with_lock_retries do + remove_foreign_key_if_exists(SOURCE_TABLE_NAME, name: new_foreign_key_name) + end + end + + private + + def new_foreign_key_name + "#{concurrent_foreign_key_name(SOURCE_TABLE_NAME, [PARTITION_COLUMN, COLUMN])}_p" + end +end diff --git a/db/schema_migrations/20230118083437 b/db/schema_migrations/20230118083437 new file mode 100644 index 00000000000..44a4ceb4e95 --- /dev/null +++ b/db/schema_migrations/20230118083437 @@ -0,0 +1 @@ +5d05a62784cc89c1c74531df16d0f4b47bbdba5e1c9f62434335e896a45e5784
\ No newline at end of file diff --git a/db/schema_migrations/20230118083632 b/db/schema_migrations/20230118083632 new file mode 100644 index 00000000000..ef6d72182c3 --- /dev/null +++ b/db/schema_migrations/20230118083632 @@ -0,0 +1 @@ +834f5888e949a3ba83b409d64f619329d32d8abb0202dd5aa2a5cec72a90c4c8
\ No newline at end of file diff --git a/db/schema_migrations/20230118083748 b/db/schema_migrations/20230118083748 new file mode 100644 index 00000000000..9b1965a625d --- /dev/null +++ b/db/schema_migrations/20230118083748 @@ -0,0 +1 @@ +69bc3d796516f6b2c4de3027be529ea4f366bb03db05d2bdc58faf7041ef173a
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 83e021bf7d9..adff1278af1 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -33366,9 +33366,6 @@ ALTER TABLE ONLY lists ALTER TABLE ONLY ci_unit_test_failures ADD CONSTRAINT fk_0f09856e1f FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE; -ALTER TABLE ONLY ci_unit_test_failures - ADD CONSTRAINT fk_0f09856e1f_p FOREIGN KEY (partition_id, build_id) REFERENCES ci_builds(partition_id, id) ON DELETE CASCADE; - ALTER TABLE ONLY deployment_approvals ADD CONSTRAINT fk_0f58311058 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; @@ -33780,6 +33777,9 @@ ALTER TABLE ONLY merge_request_diffs ALTER TABLE ONLY requirements ADD CONSTRAINT fk_85044baef0 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE; +ALTER TABLE ONLY ci_build_pending_states + ADD CONSTRAINT fk_861cd17da3_p FOREIGN KEY (partition_id, build_id) REFERENCES ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE; + ALTER TABLE ONLY geo_event_log ADD CONSTRAINT fk_86c84214ec FOREIGN KEY (repository_renamed_event_id) REFERENCES geo_repository_renamed_events(id) ON DELETE CASCADE; @@ -33801,6 +33801,9 @@ ALTER TABLE ONLY requirements_management_test_reports ALTER TABLE ONLY issues ADD CONSTRAINT fk_899c8f3231 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; +ALTER TABLE ONLY ci_build_trace_chunks + ADD CONSTRAINT fk_89e29fa5ee_p FOREIGN KEY (partition_id, build_id) REFERENCES ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE; + ALTER TABLE ONLY sbom_vulnerable_component_versions ADD CONSTRAINT fk_8a2a1197f9 FOREIGN KEY (sbom_component_version_id) REFERENCES sbom_component_versions(id) ON DELETE CASCADE; @@ -33861,6 +33864,9 @@ ALTER TABLE ONLY epics ALTER TABLE ONLY user_group_callouts ADD CONSTRAINT fk_9dc8b9d4b2 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE; +ALTER TABLE ONLY ci_unit_test_failures + ADD CONSTRAINT fk_9e0fc58930_p FOREIGN KEY (partition_id, build_id) REFERENCES ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE; + ALTER TABLE ONLY protected_environments ADD CONSTRAINT fk_9e112565b7 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE; @@ -34320,9 +34326,6 @@ ALTER TABLE ONLY related_epic_links ALTER TABLE ONLY ci_build_pending_states ADD CONSTRAINT fk_rails_0bbbfeaf9d FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE; -ALTER TABLE ONLY ci_build_pending_states - ADD CONSTRAINT fk_rails_0bbbfeaf9d_p FOREIGN KEY (partition_id, build_id) REFERENCES ci_builds(partition_id, id) ON DELETE CASCADE; - ALTER TABLE ONLY audit_events_external_audit_event_destinations ADD CONSTRAINT fk_rails_0bc80a4edc FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE; @@ -34353,9 +34356,6 @@ ALTER TABLE ONLY merge_request_context_commits ALTER TABLE ONLY ci_build_trace_chunks ADD CONSTRAINT fk_rails_1013b761f2 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE; -ALTER TABLE ONLY ci_build_trace_chunks - ADD CONSTRAINT fk_rails_1013b761f2_p FOREIGN KEY (partition_id, build_id) REFERENCES ci_builds(partition_id, id) ON DELETE CASCADE; - ALTER TABLE ONLY vulnerability_exports ADD CONSTRAINT fk_rails_1019162882 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE; diff --git a/doc/administration/auth/oidc.md b/doc/administration/auth/oidc.md index 22eabe167d6..7a2a136187e 100644 --- a/doc/administration/auth/oidc.md +++ b/doc/administration/auth/oidc.md @@ -118,7 +118,7 @@ The OpenID Connect provides you with a client's details and secret for you to us If you do not provide this value, or the field with the configured value is missing from the `user_info.raw_attributes` details, `uid` uses the `sub` field. - `send_scope_to_token_endpoint` is `true` by default, so the `scope` parameter - is normally included in requests to the token endpoint. + is usually included in requests to the token endpoint. However, if your OpenID Connect provider does not accept the `scope` parameter in such requests, set this to `false`. - `client_options` are the OpenID Connect client-specific options. Specifically: diff --git a/doc/administration/logs/log_parsing.md b/doc/administration/logs/log_parsing.md index 0439d4967cb..84c517e6120 100644 --- a/doc/administration/logs/log_parsing.md +++ b/doc/administration/logs/log_parsing.md @@ -120,6 +120,12 @@ jq 'select(.queue_duration_s > 10000)' <FILE> jq -s 'map(select(.gitaly_calls != null)) | sort_by(-.gitaly_calls) | limit(10; .[])' <FILE> ``` +#### Output a specific time range + +```shell +jq 'select(.time >= "2023-01-10T00:00:00Z" and .time <= "2023-01-10T12:00:00Z")' <FILE> +``` + ### Parsing `gitlab-rails/production_json.log` #### Print the top three controller methods by request volume and their three longest durations diff --git a/doc/administration/package_information/signed_packages.md b/doc/administration/package_information/signed_packages.md index e4566be7534..638dd7820b8 100644 --- a/doc/administration/package_information/signed_packages.md +++ b/doc/administration/package_information/signed_packages.md @@ -6,8 +6,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Package Signatures **(FREE SELF)** -As of the release of GitLab 9.5 on August 22, 2017, GitLab provides signed Omnibus GitLab packages for RPM and DEB based distributions. This means that all packages provided on <https://packages.gitlab.com> are signed, starting with `9.5.0`, and all future versions of supported branches (for example `9.3.x` and `9.4.x` after August 22, 2017). Any package version prior to August 22, 2017, will not be signed. Pass the appropriate argument to your package manager. (Example: `yum --nogpgcheck`) - Omnibus GitLab packages produced by GitLab are created via the [Omnibus](https://github.com/chef/omnibus) tool, for which GitLab has added DEB signing via `debsigs` in [our own fork](https://gitlab.com/gitlab-org/omnibus). This addition, combined with the existing functionality of RPM signing, allows GitLab to provide signed packages for all supported distributions using DEB or RPM. These packages are produced by the GitLab CI process, as found in the [Omnibus GitLab project](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/.gitlab-ci.yml), prior to their delivery to <https://packages.gitlab.com> to ensure provide assurance that the packages are not altered prior to delivery to our community. diff --git a/doc/api/projects.md b/doc/api/projects.md index bd3b13f517c..5b9ce203141 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -6,20 +6,14 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Projects API **(FREE)** -Interact with [projects](../user/project/index.md) using the REST API. +Interact with [projects](../user/project/index.md) by using the REST API. ## Project visibility level A project in GitLab can be private, internal, or public. The visibility level is determined by the `visibility` field in the project. -Values for the project visibility level are: - -- `private`: project access must be granted explicitly to each user. -- `internal`: the project can be cloned by any authenticated user except [external users](../user/admin_area/external_users.md). -- `public`: the project can be accessed without any authentication. - -For more, read [Project visibility](../user/public_access.md). +For details, see [Project visibility](../user/public_access.md). ## Project merge method diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md index 20bdd059a85..2d5e3d5a26f 100644 --- a/doc/ci/docker/using_docker_build.md +++ b/doc/ci/docker/using_docker_build.md @@ -369,7 +369,7 @@ are done to the services as well, making these incompatible. #### Use the Docker executor with Docker socket binding -To make Docker available in the context of the image, you will need to mount +To make Docker available in the context of the image, you need to mount `/var/run/docker.sock` into the launched containers. To do this with the Docker executor, you need to add `"/var/run/docker.sock:/var/run/docker.sock"` to the [Volumes in the `[runners.docker]` section](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#volumes-in-the-runnersdocker-section). diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md index 0ba510acdbc..022aa7c3093 100644 --- a/doc/ci/docker/using_docker_images.md +++ b/doc/ci/docker/using_docker_images.md @@ -158,7 +158,7 @@ a useless shell layer. However, that does not work for all Docker versions. - For Docker 17.03 and earlier, the `entrypoint` can be set to `/bin/sh -c`, `/bin/bash -c`, or an equivalent shell available in the image. -The syntax of `image:entrypoint` is similar to [Dockerfile's `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint). +The syntax of `image:entrypoint` is similar to [Dockerfile `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint). Let's assume you have a `super/sql:experimental` image with a SQL database in it. You want to use it as a base image for your job because you @@ -453,7 +453,7 @@ registries to the `"credHelpers"` hash. ### Use checksum to keep your image secure -We recommend using the image checksum in your job definition in your `.gitlab-ci.yml` file to verify the integrity of the image. A failed image integrity verification will prevent you from using a modified container. +We recommend using the image checksum in your job definition in your `.gitlab-ci.yml` file to verify the integrity of the image. A failed image integrity verification prevents you from using a modified container. To use the image checksum you have to append the checksum at the end: diff --git a/doc/ci/resource_groups/index.md b/doc/ci/resource_groups/index.md index b46008abb07..7cf71f2a3ea 100644 --- a/doc/ci/resource_groups/index.md +++ b/doc/ci/resource_groups/index.md @@ -235,7 +235,7 @@ If the process mode is `oldest_first`, it executes the jobs from the oldest pipe However, a child pipeline also requires a resource from the `production` resource group. Because the child pipeline is newer than the parent pipeline, the child pipeline -waits until the `deploy` job is finished, something that will never happen. +waits until the `deploy` job is finished, something that never happens. In this case, you should specify the `resource_group` keyword in the parent pipeline configuration instead: diff --git a/doc/install/postgresql_extensions.md b/doc/install/postgresql_extensions.md index 2d6a9411f25..ea6de690426 100644 --- a/doc/install/postgresql_extensions.md +++ b/doc/install/postgresql_extensions.md @@ -24,14 +24,14 @@ extensions into all secondary tracking databases (defaults to `gitlabhq_geo_prod |--------------|------------------------| | `plpgsql` | 9.0 | -In order to install extensions, PostgreSQL requires the user to have superuser privileges. +To install extensions, PostgreSQL requires the user to have superuser privileges. Typically, the GitLab database user is not a superuser. Therefore, regular database migrations cannot be used in installing extensions and instead, extensions have to be installed manually prior to upgrading GitLab to a newer version. ## Installing PostgreSQL extensions manually -In order to install a PostgreSQL extension, this procedure should be followed: +To install a PostgreSQL extension, this procedure should be followed: 1. Connect to the GitLab PostgreSQL database using a superuser, for example: diff --git a/doc/integration/glab/index.md b/doc/integration/glab/index.md index e71f49905c8..621472a2083 100644 --- a/doc/integration/glab/index.md +++ b/doc/integration/glab/index.md @@ -17,7 +17,7 @@ switching between windows and browser tabs. ![command example](img/glabgettingstarted.gif) The GitLab CLI uses commands structured like `glab <command> <subcommand> [flags]` -to perform many of the actions you normally do from the GitLab user interface: +to perform many of the actions you usually do from the GitLab user interface: ```shell # Sign in diff --git a/doc/integration/jira/connect-app.md b/doc/integration/jira/connect-app.md index 9e75e248d23..04fd36079ec 100644 --- a/doc/integration/jira/connect-app.md +++ b/doc/integration/jira/connect-app.md @@ -88,7 +88,9 @@ To create an OAuth application: 1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Applications** (`/admin/applications`). 1. Select **New application**. -1. In **Redirect URI**, enter `https://gitlab.com/-/jira_connect/oauth_callbacks`. +1. In **Redirect URI**: + - If you're installing the app from the official marketplace listing, enter `https://gitlab.com/-/jira_connect/oauth_callbacks`. + - If you're installing the app manually, enter `<instance_url>/-/jira_connect/oauth_callbacks` and replace `<instance_url>` with the URL of your instance. 1. Clear the **Confidential** checkbox. <!-- markdownlint-disable MD044 --> 1. In **Scopes**, select the **api** checkbox only. diff --git a/doc/integration/mattermost/index.md b/doc/integration/mattermost/index.md index df6130a7540..42592a0dff2 100644 --- a/doc/integration/mattermost/index.md +++ b/doc/integration/mattermost/index.md @@ -307,7 +307,7 @@ These settings can also be configured in `/var/opt/gitlab/mattermost/config.json Enabling this feature allows users to control how often they receive email notifications. -Email batching can be enabled in the Mattermost **System Console** by going to the **Environment > SMTP** tab, and setting the **Enable Email Batching** setting to **True**. +Email batching can be enabled in the Mattermost **System Console** by navigating to the **Environment > SMTP** tab, and setting the **Enable Email Batching** setting to **True**. This setting can also be configured in `/var/opt/gitlab/mattermost/config.json`. @@ -360,7 +360,7 @@ When upgrading the Mattermost version, it is essential to check the for Mattermost to address any changes or migrations that need to be performed. Starting with GitLab 11.0, GitLab Mattermost can be upgraded through the regular Omnibus GitLab update process. When upgrading previous versions of -GitLab, the update process can only be used if Mattermost configuration settings have not been changed outside of GitLab. That is, no changes to Mattermost's `config.json` +GitLab, the update process can only be used if Mattermost configuration settings have not been changed outside of GitLab. That is, no changes to the Mattermost `config.json` file have been made - either directly or via the Mattermost **System Console**, which saves changes to `config.json`. If you are upgrading to at least GitLab 11.0 or have only configured Mattermost using `gitlab.rb`, you can upgrade GitLab using Omnibus and then run `gitlab-ctl reconfigure` to upgrade GitLab Mattermost to the latest version. @@ -402,7 +402,7 @@ generates the `config.json` file, and instead passes limited configuration setti The settings that continue to be supported in `gitlab.rb` can be found in [`gitlab.rb.template`](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template). -From GitLab 11.0, other Mattermost settings can be configured through Mattermost's System Console, +From GitLab 11.0, other Mattermost settings can be configured through the Mattermost System Console, by editing `/var/opt/gitlab/mattermost/config.json`, or by using `mattermost['env']` in `gitlab.rb`. If you would like to keep configuring Mattermost using `gitlab.rb`, you can take the following actions @@ -490,9 +490,9 @@ If you encounter any issues [visit the GitLab Mattermost troubleshooting forum]( If you choose to upgrade Mattermost outside of the Omnibus GitLab automation, [follow this guide](https://docs.mattermost.com/administration/upgrade.html). -## OAuth2 sequence diagram +## OAuth 2.0 sequence diagram -The following image is a sequence diagram for how GitLab works as an OAuth2 +The following image is a sequence diagram for how GitLab works as an OAuth 2.0 provider for Mattermost. You can use this to troubleshoot errors in getting the integration to work: @@ -520,7 +520,7 @@ sequenceDiagram ## Community support resources -For help and support around your GitLab Mattermost deployment please see: +For help and support around your GitLab Mattermost deployment, see: - [Troubleshooting Mattermost issues](https://docs.mattermost.com/install/troubleshooting.html). - [Mattermost GitLab Issues Support Handbook](https://docs.mattermost.com/process/support.html?highlight=omnibus#gitlab-issues). diff --git a/doc/raketasks/backup_gitlab.md b/doc/raketasks/backup_gitlab.md index ffa67c6b4a9..fd88529807f 100644 --- a/doc/raketasks/backup_gitlab.md +++ b/doc/raketasks/backup_gitlab.md @@ -216,7 +216,7 @@ To ensure the generated archive is transferable by rsync, you can set the `GZIP_ option. This sets the `--rsyncable` option to `gzip`, which is useful only in combination with setting [the Backup filename option](#backup-filename). -Note that the `--rsyncable` option in `gzip` isn't guaranteed to be available +The `--rsyncable` option in `gzip` isn't guaranteed to be available on all distributions. To verify that it's available in your distribution, run `gzip --help` or consult the man pages. @@ -468,7 +468,7 @@ gitlab_rails['backup_upload_storage_options'] = { ##### SSE-KMS -To enable SSE-KMS, you'll need the +To enable SSE-KMS, you need the [KMS key via its Amazon Resource Name (ARN) in the `arn:aws:kms:region:acct-id:key/key-id` format](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingKMSEncryption.html). Under the `backup_upload_storage_options` configuration setting, set: diff --git a/doc/user/analytics/value_streams_dashboard.md b/doc/user/analytics/value_streams_dashboard.md index 1de26749deb..f8cfb1bf06b 100644 --- a/doc/user/analytics/value_streams_dashboard.md +++ b/doc/user/analytics/value_streams_dashboard.md @@ -16,6 +16,9 @@ The Value Streams Dashboard is a customizable dashboard to enable decision-maker This page is a work in progress, and we're updating the information as we add more features. For more information, see the [Value Stream Management category direction page](https://about.gitlab.com/direction/plan/value_stream_management/). +After the feature flag is enabled, to open the new page, append this path `/analytics/dashboards` to the group URL +(for example, `https://gitlab.com/groups/gitlab-org/-/analytics/dashboards`). + ## Initial use case Our initial use case is focused on providing the ability to compare software delivery metrics. @@ -59,3 +62,16 @@ For example, the parameter `query=gitlab-org/gitlab-foss,gitlab-org/gitlab,gitla - `gitlab-org` group - `gitlab-ui` project - `gitlab-org/plan-stage` subgroup + +## Dashboard metrics and drill-down reports + +| Metric | Description | Drill-down report | Documentation page | +| ------ | ----------- | --------------- | ------------------ | +| Deployment frequency | Average number of deployments to production per day. This metric measures how often value is delivered to end users. | [Deployment frequency tab](https://gitlab.com/groups/gitlab-org/-/analytics/ci_cd?tab=deployment-frequency) | [Deployment frequency](dora_metrics.md#deployment-frequency) | +| Lead time for changes | The time to successfully deliver a commit into production. This metric reflects the efficiency of CI/CD pipelines. | [Lead time tab](https://gitlab.com/groups/gitlab-org/-/analytics/ci_cd?tab=lead-time) | [Lead time for changes](dora_metrics.md#lead-time-for-changes) | +| Time to restore service | The time it takes an organization to recover from a failure in production. | [Time to restore service tab](https://gitlab.com/groups/gitlab-org/-/analytics/ci_cd?tab=time-to-restore-service) | [Time to restore service](dora_metrics.md#time-to-restore-service) | +| Change failure rate | Percentage of deployments that cause an incident in production. | [Change failure rate tab](https://gitlab.com/groups/gitlab-org/-/analytics/ci_cd?tab=change-failure-rate) | [Change failure rate](dora_metrics.md#change-failure-rate) | +| VSA Lead time | Median time from issue created to issue closed. | [Value Stream Analytics](https://gitlab.com/groups/gitlab-org/-/analytics/value_stream_analytics) | [View the lead time and cycle time for issues](value_stream_analytics.md#view-the-lead-time-and-cycle-time-for-issues) | +| VSA Cycle time | Median time from the earliest commit of a linked issue's merge request to when that issue is closed. | [VSA overview](https://gitlab.com/groups/gitlab-org/-/analytics/value_stream_analytics) | [View the lead time and cycle time for issues](value_stream_analytics.md#view-the-lead-time-and-cycle-time-for-issues) | +| New issues | Number of new issues created. | [Issue Analytics](https://gitlab.com/groups/gitlab-org/-/issues_analytics) | Issue analytics [for projects](issue_analytics.md) and [for groups](../../user/group/issues_analytics/index.md) | +| Number of deploys | Total number of deploys to production. | [Merge Request Analytics](https://gitlab.com/gitlab-org/gitlab/-/analytics/merge_request_analytics) | [Merge request analytics](merge_request_analytics.md) | diff --git a/doc/user/application_security/dast_api/index.md b/doc/user/application_security/dast_api/index.md index 4c324033140..0144c37c3ff 100644 --- a/doc/user/application_security/dast_api/index.md +++ b/doc/user/application_security/dast_api/index.md @@ -5,13 +5,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w type: reference, howto --- -# DAST API **(ULTIMATE)** +# DAST API analyzer **(ULTIMATE)** > DAST API analyzer [became the default analyzer for on-demand DAST API scans](https://gitlab.com/groups/gitlab-org/-/epics/4254) in GitLab 15.6. Perform Dynamic Application Security Testing (DAST) of web APIs to help discover bugs and potential security issues that other QA processes may miss. Use DAST API tests in addition to -[GitLab Secure](../index.md)'s other security scanners and your own test processes. You can run DAST +other [GitLab Secure](../index.md) security scanners and your own test processes. You can run DAST API tests either as part your CI/CD workflow, [on-demand](../dast/proxy-based.md#on-demand-scans), or both. WARNING: diff --git a/doc/user/product_analytics/index.md b/doc/user/product_analytics/index.md index 46f8b57a64c..de4e9c3d36c 100644 --- a/doc/user/product_analytics/index.md +++ b/doc/user/product_analytics/index.md @@ -6,7 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Product analytics **(ULTIMATE)** -> Introduced in GitLab 15.4 as an [Alpha](../../policy/alpha-beta-support.md#alpha-features) feature [with a flag](../../administration/feature_flags.md) named `cube_api_proxy`. Disabled by default. +> - Introduced in GitLab 15.4 as an [Alpha](../../policy/alpha-beta-support.md#alpha-features) feature [with a flag](../../administration/feature_flags.md) named `cube_api_proxy`. Disabled by default. +> - `cube_api_proxy` revised to only reference the [Product Analytics API](../../api/product_analytics.md) in GitLab 15.6. FLAG: On self-managed GitLab, by default this feature is not available. To make it available per project or for your entire instance, ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `cube_api_proxy`. @@ -16,8 +17,45 @@ This feature is not ready for production use. This page is a work in progress, and we're updating the information as we add more features. For more information, visit the [Product Analytics group direction page](https://about.gitlab.com/direction/analytics/product-analytics/). +## How Product Analytics works + +```mermaid +--- +title: Product Analytics flow +--- +flowchart TB + subgraph Adding data + A([SDK]) --Send user data--> B[Analytics Proxy] + B --Transform data and pass it through--> C[Jitsu] + C --Pass the data to the associated database--> D([Clickhouse]) + end + subgraph Showing dashboards + E([Dashboards]) --Generated from the YAML definition--> F[Dashboard] + F --Request data--> G[Product Analytics API] + G --Run Cube queries with pre-aggregations--> H[Cube.js] + H --Get data from database--> D + D --Return results--> H + H --> G + G --Transform data to be rendered--> F + end +``` + +Product Analytics uses several tools: + +- [**Jitsu**](https://jitsu.com/docs) - A web and app event collection platform that provides a consistent API to collect user data and pass it through to Clickhouse. +- [**Clickhouse**](https://clickhouse.com/docs) - A database suited to store, query, and retrieve analytical data. +- [**Cube.js**](https://cube.dev/docs/) - An analytical graphing library that provides an API to run queries against the data stored in Clickhouse. + ## Enable product analytics +> - Introduced in GitLab 15.6 behind the [feature flag](../../administration/feature_flags.md) named `cube_api_proxy`. Disabled by default. +> - Moved to be behind the [feature flag](../../administration/feature_flags.md) named `product_analytics_admin_settings` in GitLab 15.7. Disabled by default. + +FLAG: +On self-managed GitLab, by default this feature is not available. To make it available per project or for your entire instance, ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `cube_api_proxy`. +On GitLab.com, this feature is not available. +This feature is not ready for production use. + You can enable and configure product analytics to track events within your project applications on a self-managed instance. @@ -45,6 +83,13 @@ Prerequisite: ## Product analytics dashboards +> Introduced in GitLab 15.5 behind the [feature flag](../../administration/feature_flags.md) named `product_analytics_internal_preview`. Disabled by default. + +FLAG: +On self-managed GitLab, by default this feature is not available. To make it available per project or for your entire instance, ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `cube_api_proxy`. +On GitLab.com, this feature is not available. +This feature is not ready for production use. + Each project can define an unlimited number of dashboards. These dashboards are defined using our YAML schema and stored in the `.gitlab/product_analytics/dashboards/` directory of a project repository. The name of the file is the name of the dashboard, and visualizations are shared across dashboards. diff --git a/doc/user/public_access.md b/doc/user/public_access.md index 773c14c9ec8..2a9a9fb84fe 100644 --- a/doc/user/public_access.md +++ b/doc/user/public_access.md @@ -7,63 +7,49 @@ type: reference # Project and group visibility **(FREE)** -If you have the Owner role, you can set a project's or group's visibility as: +A project in GitLab can be private, internal, or public. -- **Public** -- **[Internal](#internal-projects-and-groups)** -- **Private** - -These visibility levels affect who can see the project in the public access directory -(for example, <https://gitlab.com/public>). - -For more granular control, you can determine -[which features in a project are visible](project/working_with_projects.md#change-the-visibility-of-individual-features-in-a-project). - -The visibility setting of a project must be at least as restrictive -as the visibility of its parent group. -For example, a private group can include only private projects, -while a public group can include private, internal, and public projects. - -## Public projects and groups - -Public projects can be cloned **without any** authentication over HTTPS. +## Private projects and groups -They are listed in the public access directory (`/public`) for all users. +For private projects, only project members can: -Public groups can have public, internal, or private subgroups. +- Clone the project. +- View the public access directory (`/public`). -**Any authenticated user** has the Guest role on the repository. +Users with the Guest role cannot clone the project. -NOTE: -By default, `/public` is visible to unauthenticated users. However, if the -[**Public** visibility level](admin_area/settings/visibility_and_access_controls.md#restrict-visibility-levels) -is restricted, `/public` is visible only to authenticated users. +Private groups can have private subgroups only. ## Internal projects and groups **(FREE SELF)** -Internal projects can be cloned by any authenticated user except -[external users](admin_area/external_users.md). +For internal projects, **any authenticated user**, including users with the Guest role, can: -They are also listed in the public access directory (`/public`), but only for authenticated users. +- Clone the project. +- View the public access directory (`/public`). -Internal groups can have internal or private subgroups. +[External users](admin_area/external_users.md) cannot clone the project. -Any signed-in users except [external users](admin_area/external_users.md) have the -Guest role on the repository. +Internal groups can have internal or private subgroups. NOTE: From July 2019, the `Internal` visibility setting is disabled for new projects, groups, and snippets on GitLab.com. Existing projects, groups, and snippets using the `Internal` -visibility setting keep this setting. You can read more about the change in the -[relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/12388). +visibility setting keep this setting. For more information, see +[issue 12388](https://gitlab.com/gitlab-org/gitlab/-/issues/12388). -## Private projects and groups +## Public projects and groups -Private projects can only be cloned and viewed by project members (except for guests). +For public projects, **users who are not authenticated**, including users with the Guest role, can: -They appear in the public access directory (`/public`) for project members only. +- Clone the project. +- View the public access directory (`/public`). -Private groups can only have private subgroups. +Public groups can have public, internal, or private subgroups. + +NOTE: +If an administrator restricts the +[**Public** visibility level](admin_area/settings/visibility_and_access_controls.md#restrict-visibility-levels), +then `/public` is visible only to authenticated users. ## Change project visibility @@ -77,6 +63,8 @@ Prerequisite: 1. On the left sidebar, select **Settings > General**. 1. Expand **Visibility, project features, permissions**. 1. Change **Project visibility** to either **Private**, **Internal**, or **Public**. + The visibility setting for a project must be at least as restrictive + as the visibility of its parent group. 1. Select **Save changes**. ## Change group visibility @@ -94,15 +82,21 @@ Prerequisites: 1. On the left sidebar, select **Settings > General**. 1. Expand **Naming, visibility**. 1. Under **Visibility level** select either **Private**, **Internal**, or **Public**. + The visibility setting for a project must be at least as restrictive + as the visibility of its parent group. 1. Select **Save changes**. ## Restrict use of public or internal projects **(FREE SELF)** -You can restrict the use of visibility levels for users when they create a project or a snippet. -This is useful to prevent users from publicly exposing their repositories by accident. The -restricted visibility settings do not apply to administrators. +Administrators can restrict which visibility levels users can choose when they create a project or a snippet. +This setting can help prevent users from publicly exposing their repositories by accident. + +For more information, see [Restrict visibility levels](admin_area/settings/visibility_and_access_controls.md#restrict-visibility-levels). + +## Related topics -For details, see [Restricted visibility levels](admin_area/settings/visibility_and_access_controls.md#restrict-visibility-levels). +- For more granular control of project features, you can + [change the visibility of features](project/working_with_projects.md#change-the-visibility-of-individual-features-in-a-project). <!-- ## Troubleshooting diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 5417d393ae8..4f89fd54904 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -273,6 +273,11 @@ msgid_plural "%d groups" msgstr[0] "" msgstr[1] "" +msgid "%d group found" +msgid_plural "%d groups found" +msgstr[0] "" +msgstr[1] "" + msgid "%d hour" msgid_plural "%d hours" msgstr[0] "" @@ -37250,9 +37255,6 @@ msgstr "" msgid "Search for Namespace" msgstr "" -msgid "Search for a LDAP group" -msgstr "" - msgid "Search for a group" msgstr "" @@ -38478,6 +38480,9 @@ msgstr "" msgid "Select Profile" msgstr "" +msgid "Select a LDAP group" +msgstr "" + msgid "Select a branch" msgstr "" @@ -42812,6 +42817,9 @@ msgstr "" msgid "There was an error resetting user pipeline minutes." msgstr "" +msgid "There was an error retrieving LDAP groups. Please try again." +msgstr "" + msgid "There was an error retrieving the Jira users." msgstr "" diff --git a/package.json b/package.json index ad83155725b..b3e16fc79c0 100644 --- a/package.json +++ b/package.json @@ -57,8 +57,8 @@ "@gitlab/at.js": "1.5.7", "@gitlab/favicon-overlay": "2.0.0", "@gitlab/fonts": "^1.1.2", - "@gitlab/svgs": "3.17.0", - "@gitlab/ui": "53.0.0", + "@gitlab/svgs": "3.18.0", + "@gitlab/ui": "53.2.0", "@gitlab/visual-review-tools": "1.7.3", "@gitlab/web-ide": "0.0.1-dev-20230120231236", "@rails/actioncable": "6.1.4-7", diff --git a/spec/features/incidents/incident_timeline_events_spec.rb b/spec/features/incidents/incident_timeline_events_spec.rb index 45518671c57..ffab23c58bc 100644 --- a/spec/features/incidents/incident_timeline_events_spec.rb +++ b/spec/features/incidents/incident_timeline_events_spec.rb @@ -4,171 +4,101 @@ require 'spec_helper' RSpec.describe 'Incident timeline events', :js, feature_category: :incident_management do let_it_be(:project) { create(:project) } - let_it_be(:developer) { create(:user) } + let_it_be(:user) { create(:user, developer_projects: [project]) } let_it_be(:incident) { create(:incident, project: project) } - before_all do - project.add_developer(developer) - end - - before do - sign_in(developer) - - visit incident_project_issues_path(project, incident) - wait_for_requests - click_link s_('Incident|Timeline') - end - - context 'when add event is clicked' do - it 'submits event data when save is clicked' do - click_button s_('Incident|Add new timeline event') - - expect(page).to have_selector('.common-note-form') - - fill_in _('Description'), with: 'Event note goes here' - fill_in 'timeline-input-hours', with: '07' - fill_in 'timeline-input-minutes', with: '25' - - click_button _('Save') + shared_examples 'add, edit, and delete timeline events' do + it 'submits event data on save' do + # Add event + click_button(s_('Incident|Add new timeline event')) + complete_form('Event note goes here', '07', '25') expect(page).to have_selector('.incident-timeline-events') - page.within '.timeline-event-note' do expect(page).to have_content('Event note goes here') expect(page).to have_content('07:25') end - end - end - - context 'when add event is clicked and feature flag enabled' do - before do - stub_feature_flags(incident_event_tags: true) - end - - it 'submits event data with tags when save is clicked' do - click_button s_('Incident|Add new timeline event') - - expect(page).to have_selector('.common-note-form') - fill_in _('Description'), with: 'Event note goes here' - fill_in 'timeline-input-hours', with: '07' - fill_in 'timeline-input-minutes', with: '25' - - click_button _('Select tags') - - page.within '.gl-dropdown-inner' do - expect(page).to have_content(_('Start time')) - page.find('.gl-dropdown-item-text-wrapper', text: _('Start time')).click - end - - click_button _('Save') - - expect(page).to have_selector('.incident-timeline-events') + # Edit event + trigger_dropdown_action(_('Edit')) + complete_form('Edited event note goes here', '08', '30') page.within '.timeline-event-note' do - expect(page).to have_content('Event note goes here') - expect(page).to have_content('07:25') - expect(page).to have_content('Start time') + expect(page).to have_content('Edited event note goes here') + expect(page).to have_content('08:30') end - end - end - context 'when edit is clicked' do - before do - click_button 'Add new timeline event' - fill_in 'Description', with: 'Event note to edit' - click_button _('Save') - end + # Delete event + trigger_dropdown_action(_('Delete')) - it 'shows the confirmation modal and edits the event' do - click_button _('More actions') - - page.within '.gl-dropdown-contents' do - expect(page).to have_content(_('Edit')) - page.find('.gl-dropdown-item-text-primary', text: _('Edit')).click + page.within '.modal' do + expect(page).to have_content(s_('Incident|Delete event')) end - expect(page).to have_selector('.common-note-form') - - fill_in _('Description'), with: 'Event note goes here' - fill_in 'timeline-input-hours', with: '07' - fill_in 'timeline-input-minutes', with: '25' - - click_button _('Save') - + click_button s_('Incident|Delete event') wait_for_requests - page.within '.timeline-event-note' do - expect(page).to have_content('Event note goes here') - expect(page).to have_content('07:25') - end + expect(page).to have_content(s_('Incident|No timeline items have been added yet.')) end - end - context 'when edit is clicked and feature flag enabled' do - before do + it 'submits event data on save with feature flag on' do stub_feature_flags(incident_event_tags: true) - click_button 'Add new timeline event' - fill_in 'Description', with: 'Event note to edit' - click_button _('Select tags') + # Add event + click_button(s_('Incident|Add new timeline event')) + + click_button _('Select tags') page.within '.gl-dropdown-inner' do + expect(page).to have_content(_('Start time')) page.find('.gl-dropdown-item-text-wrapper', text: _('Start time')).click end - click_button _('Save') - end - it 'shows the confirmation modal and edits the event tags' do - click_button _('More actions') + complete_form('Event note goes here', '07', '25') - page.within '.gl-dropdown-contents' do - expect(page).to have_content(_('Edit')) - page.find('.gl-dropdown-item-text-primary', text: _('Edit')).click + expect(page).to have_selector('.incident-timeline-events') + page.within '.timeline-event-note' do + expect(page).to have_content('Event note goes here') + expect(page).to have_content('07:25') + expect(page).to have_content('Start time') end - expect(page).to have_selector('.common-note-form') - - click_button s_('Start time') + # Edit event + trigger_dropdown_action(_('Edit')) + click_button _('Start time') page.within '.gl-dropdown-inner' do - expect(page).to have_content(_('Start time')) page.find('.gl-dropdown-item-text-wrapper', text: _('Start time')).click end - - click_button _('Save') - - wait_for_requests + complete_form('Edited event note goes here', '08', '30') page.within '.timeline-event-note' do + expect(page).to have_content('Edited event note goes here') + expect(page).to have_content('08:30') expect(page).not_to have_content('Start time') end end - end - context 'when delete is clicked' do - before do - click_button s_('Incident|Add new timeline event') - fill_in _('Description'), with: 'Event note to delete' + private + + def complete_form(title, hours, minutes) + fill_in _('Description'), with: title + fill_in 'timeline-input-hours', with: hours + fill_in 'timeline-input-minutes', with: minutes + click_button _('Save') + wait_for_requests end - it 'shows the confirmation modal and deletes the event' do + def trigger_dropdown_action(text) click_button _('More actions') page.within '.gl-dropdown-contents' do - expect(page).to have_content(_('Delete')) - page.find('.gl-dropdown-item-text-primary', text: 'Delete').click + page.find('.gl-dropdown-item', text: text).click end - - page.within '.modal' do - expect(page).to have_content(s_('Incident|Delete event')) - end - - click_button s_('Incident|Delete event') - - wait_for_requests - - expect(page).to have_content(s_('Incident|No timeline items have been added yet.')) end end + + it_behaves_like 'for each incident details route', + 'add, edit, and delete timeline events', + tab_text: s_('Incident|Timeline') end diff --git a/spec/frontend/blob/components/table_contents_spec.js b/spec/frontend/blob/components/table_contents_spec.js index 5fe328b65ff..6af9cdcae7d 100644 --- a/spec/frontend/blob/components/table_contents_spec.js +++ b/spec/frontend/blob/components/table_contents_spec.js @@ -1,4 +1,4 @@ -import { GlDropdownItem } from '@gitlab/ui'; +import { GlDisclosureDropdown } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import { nextTick } from 'vue'; import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; @@ -10,6 +10,8 @@ function createComponent() { wrapper = shallowMount(TableContents); } +const findDropdown = () => wrapper.findComponent(GlDisclosureDropdown); + async function setLoaded(loaded) { document.querySelector('.blob-viewer').dataset.loaded = loaded; @@ -20,10 +22,10 @@ describe('Markdown table of contents component', () => { beforeEach(() => { setHTMLFixture(` <div class="blob-viewer" data-type="rich" data-loaded="false"> - <h1><a href="#1"></a>Hello</h1> - <h2><a href="#2"></a>World</h2> - <h3><a href="#3"></a>Testing</h3> - <h2><a href="#4"></a>GitLab</h2> + <h1><a id="hello">$</a> Hello</h1> + <h2><a id="world">$</a> World</h2> + <h3><a id="hakuna">$</a> Hakuna</h3> + <h2><a id="matata">$</a> Matata</h2> </div> `); }); @@ -34,12 +36,10 @@ describe('Markdown table of contents component', () => { }); describe('not loaded', () => { - const findDropdownItem = () => wrapper.findComponent(GlDropdownItem); - it('does not populate dropdown', () => { createComponent(); - expect(findDropdownItem().exists()).toBe(false); + expect(findDropdown().exists()).toBe(false); }); it('does not show dropdown when loading blob content', async () => { @@ -47,7 +47,7 @@ describe('Markdown table of contents component', () => { await setLoaded(false); - expect(findDropdownItem().exists()).toBe(false); + expect(findDropdown().exists()).toBe(false); }); it('does not show dropdown when viewing non-rich content', async () => { @@ -57,7 +57,7 @@ describe('Markdown table of contents component', () => { await setLoaded(true); - expect(findDropdownItem().exists()).toBe(false); + expect(findDropdown().exists()).toBe(false); }); }); @@ -67,15 +67,25 @@ describe('Markdown table of contents component', () => { await setLoaded(true); - const dropdownItems = wrapper.findAllComponents(GlDropdownItem); + const dropdown = findDropdown(); - expect(dropdownItems.exists()).toBe(true); - expect(dropdownItems.length).toBe(4); + expect(dropdown.exists()).toBe(true); + expect(dropdown.props('items').length).toBe(4); // make sure that this only happens once await setLoaded(true); - expect(wrapper.findAllComponents(GlDropdownItem).length).toBe(4); + expect(dropdown.props('items').length).toBe(4); + }); + + it('generates proper anchor links', async () => { + createComponent(); + await setLoaded(true); + + const dropdown = findDropdown(); + const items = dropdown.props('items'); + const hrefs = items.map((item) => item.href); + expect(hrefs).toEqual(['#hello', '#world', '#hakuna', '#matata']); }); it('sets padding for dropdown items', async () => { @@ -83,12 +93,12 @@ describe('Markdown table of contents component', () => { await setLoaded(true); - const dropdownLinks = wrapper.findAll('[data-testid="tableContentsLink"]'); + const items = findDropdown().props('items'); - expect(dropdownLinks.at(0).element.style.paddingLeft).toBe('0px'); - expect(dropdownLinks.at(1).element.style.paddingLeft).toBe('8px'); - expect(dropdownLinks.at(2).element.style.paddingLeft).toBe('16px'); - expect(dropdownLinks.at(3).element.style.paddingLeft).toBe('8px'); + expect(items[0].extraAttrs.style.paddingLeft).toBe('16px'); + expect(items[1].extraAttrs.style.paddingLeft).toBe('24px'); + expect(items[2].extraAttrs.style.paddingLeft).toBe('32px'); + expect(items[3].extraAttrs.style.paddingLeft).toBe('24px'); }); }); }); diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb index 2da9f7b1ebc..477b5cd7753 100644 --- a/spec/helpers/projects_helper_spec.rb +++ b/spec/helpers/projects_helper_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe ProjectsHelper do +RSpec.describe ProjectsHelper, feature_category: :source_code_management do include ProjectForksHelper include AfterNextHelpers @@ -582,46 +582,24 @@ RSpec.describe ProjectsHelper do end end - describe '#show_merge_request_count' do + describe '#show_count?' do context 'enabled flag' do it 'returns true if compact mode is disabled' do - expect(helper.show_merge_request_count?).to be_truthy + expect(helper.show_count?).to be_truthy end it 'returns false if compact mode is enabled' do - expect(helper.show_merge_request_count?(compact_mode: true)).to be_falsey + expect(helper.show_count?(compact_mode: true)).to be_falsey end end context 'disabled flag' do it 'returns false if disabled flag is true' do - expect(helper.show_merge_request_count?(disabled: true)).to be_falsey + expect(helper.show_count?(disabled: true)).to be_falsey end it 'returns true if disabled flag is false' do - expect(helper.show_merge_request_count?).to be_truthy - end - end - end - - describe '#show_issue_count?' do - context 'enabled flag' do - it 'returns true if compact mode is disabled' do - expect(helper.show_issue_count?).to be_truthy - end - - it 'returns false if compact mode is enabled' do - expect(helper.show_issue_count?(compact_mode: true)).to be_falsey - end - end - - context 'disabled flag' do - it 'returns false if disabled flag is true' do - expect(helper.show_issue_count?(disabled: true)).to be_falsey - end - - it 'returns true if disabled flag is false' do - expect(helper.show_issue_count?).to be_truthy + expect(helper).to be_show_count end end end @@ -1050,6 +1028,28 @@ RSpec.describe ProjectsHelper do end end end + + describe '#able_to_see_forks_count?' do + subject { helper.able_to_see_forks_count?(project, user) } + + where(:can_read_code, :forking_enabled, :expected) do + false | false | false + true | false | false + false | true | false + true | true | true + end + + with_them do + before do + allow(project).to receive(:forking_enabled?).and_return(forking_enabled) + allow(helper).to receive(:can?).with(user, :read_code, project).and_return(can_read_code) + end + + it 'returns the correct response' do + expect(subject).to eq(expected) + end + end + end end describe '#fork_button_disabled_tooltip' do diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb index 3530d1b1a39..3403064bf0b 100644 --- a/spec/support/helpers/test_env.rb +++ b/spec/support/helpers/test_env.rb @@ -423,7 +423,7 @@ module TestEnv return if File.exist?(install_dir) && ci? if component_needs_update?(install_dir, version) - puts "==> Starting #{component} set up...\n" + puts "==> Starting #{component} (#{version}) set up...\n" # Cleanup the component entirely to ensure we start fresh FileUtils.rm_rf(install_dir) if fresh_install diff --git a/spec/support/shared_examples/features/incident_details_routing_shared_examples.rb b/spec/support/shared_examples/features/incident_details_routing_shared_examples.rb new file mode 100644 index 00000000000..dab125caa60 --- /dev/null +++ b/spec/support/shared_examples/features/incident_details_routing_shared_examples.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'for each incident details route' do |example, tab_text:| + before do + sign_in(user) + visit incident_path + end + + context 'for /-/issues/:id route' do + let(:incident_path) { project_issue_path(project, incident) } + + before do + page.within('[data-testid="incident-tabs"]') { click_link tab_text } + end + + it_behaves_like example + end + + context 'for /-/issues/incident/:id route' do + let(:incident_path) { incident_project_issues_path(project, incident) } + + before do + page.within('[data-testid="incident-tabs"]') { click_link tab_text } + end + + it_behaves_like example + end +end diff --git a/workhorse/go.mod b/workhorse/go.mod index 276d628b26d..c9b83553edb 100644 --- a/workhorse/go.mod +++ b/workhorse/go.mod @@ -7,7 +7,7 @@ require ( github.com/BurntSushi/toml v1.2.1 github.com/FZambia/sentinel v1.1.1 github.com/alecthomas/chroma/v2 v2.4.0 - github.com/aws/aws-sdk-go v1.44.180 + github.com/aws/aws-sdk-go v1.44.184 github.com/disintegration/imaging v1.6.2 github.com/getsentry/raven-go v0.2.0 github.com/golang-jwt/jwt/v4 v4.4.3 diff --git a/workhorse/go.sum b/workhorse/go.sum index eb40abdfc49..6cf889201bf 100644 --- a/workhorse/go.sum +++ b/workhorse/go.sum @@ -542,8 +542,8 @@ github.com/aws/aws-sdk-go v1.43.11/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4 github.com/aws/aws-sdk-go v1.43.31/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/aws/aws-sdk-go v1.44.128/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/aws/aws-sdk-go v1.44.151/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= -github.com/aws/aws-sdk-go v1.44.180 h1:VLZuAHI9fa/3WME5JjpVjcPCNfpGHVMiHx8sLHWhMgI= -github.com/aws/aws-sdk-go v1.44.180/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.184 h1:/MggyE66rOImXJKl1HqhLQITvWvqIV7w1Q4MaG6FHUo= +github.com/aws/aws-sdk-go v1.44.184/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/aws/aws-sdk-go-v2 v1.17.1 h1:02c72fDJr87N8RAC2s3Qu0YuvMRZKNZJ9F+lAehCazk= github.com/aws/aws-sdk-go-v2 v1.17.1/go.mod h1:JLnGeGONAyi2lWXI1p0PCIOIy333JMVK1U7Hf0aRFLw= diff --git a/yarn.lock b/yarn.lock index 59574b10bca..b1ebc904861 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1140,15 +1140,15 @@ stylelint-declaration-strict-value "1.8.0" stylelint-scss "4.2.0" -"@gitlab/svgs@3.17.0": - version "3.17.0" - resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.17.0.tgz#beeda4bd2b97ec2637bebe1760dbe283d6a599ef" - integrity sha512-+5wsh/FG7SSkUQjehROl+0nRgrg/XRNUa9h3LkxpksP0AXy4j6xuYuq+7xucDGJDdXo43tUftLc9w7u/SCmgQA== - -"@gitlab/ui@53.0.0": - version "53.0.0" - resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-53.0.0.tgz#bdd62cb7c2d5f028c4c6792b010a30566f6e29d4" - integrity sha512-kkvTbEbSf54CqFHGzlVSqqfEsfBXhaawuG3UxXDkxMU7fTONQf9WDtH+hGjBS5rOQrtD7A4sBHB/Jp5l2APsPw== +"@gitlab/svgs@3.18.0": + version "3.18.0" + resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.18.0.tgz#d89364feb42404a35824a54d518b51af8c1e900f" + integrity sha512-ni9TmhusXpt/3k/DZzovMEUeB/6UTXiDpuujI8HDBqR4Mwlah6FBco5ZfolkW6YjFL0YvtcLWhnwZA0iM3hfMw== + +"@gitlab/ui@53.2.0": + version "53.2.0" + resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-53.2.0.tgz#71e602ac8e6db4452e647ffcfd5892f636c7a6b4" + integrity sha512-9GwwBTj6TKqsEa83QCjzUe+ObLkALn/G+vvfkQ5UNJIu2PiDjTpAEtySEXEWz4sJoUPZLhxdVXWeukjyBGinAg== dependencies: "@popperjs/core" "^2.11.2" bootstrap-vue "2.20.1" |