diff options
31 files changed, 284 insertions, 161 deletions
diff --git a/.gitignore b/.gitignore index 8a47cc8d20b..415f5dec1e6 100644 --- a/.gitignore +++ b/.gitignore @@ -62,6 +62,8 @@ eslint-report.html /public/assets/ /public/uploads.* /public/uploads/ +/public/sitemap.xml +/public/sitemap.xml.gz /shared/artifacts/ /spec/examples.txt /rails_best_practices_output.html diff --git a/.gitlab/ci/test-metadata.gitlab-ci.yml b/.gitlab/ci/test-metadata.gitlab-ci.yml index ba5b3f98689..eedcf44c63a 100644 --- a/.gitlab/ci/test-metadata.gitlab-ci.yml +++ b/.gitlab/ci/test-metadata.gitlab-ci.yml @@ -1,6 +1,4 @@ .tests-metadata-state: - variables: - TESTS_METADATA_S3_BUCKET: "gitlab-ce-cache" before_script: - source scripts/utils.sh artifacts: diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index eeeae75d501..f372807af9b 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -cf8e99ccc104f0a43f41e54896ee46a5e1b15a0a +dfdc9b7725eb710dab8ae9970e98cc5118e65c49 diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list.vue b/app/assets/javascripts/ide/components/commit_sidebar/list.vue index 6f49a694cc1..729ff7c74ec 100644 --- a/app/assets/javascripts/ide/components/commit_sidebar/list.vue +++ b/app/assets/javascripts/ide/components/commit_sidebar/list.vue @@ -1,8 +1,7 @@ <script> import { mapActions } from 'vuex'; -import { GlModal, GlIcon } from '@gitlab/ui'; +import { GlModal, GlIcon, GlTooltipDirective } from '@gitlab/ui'; import { __, sprintf } from '~/locale'; -import tooltip from '~/vue_shared/directives/tooltip'; import ListItem from './list_item.vue'; export default { @@ -12,7 +11,7 @@ export default { GlModal, }, directives: { - tooltip, + GlTooltip: GlTooltipDirective, }, props: { fileList: { @@ -73,7 +72,7 @@ export default { <div class="d-flex ml-auto"> <button v-if="!stagedList" - v-tooltip + v-gl-tooltip :title="__('Discard all changes')" :aria-label="__('Discard all changes')" :disabled="!filesLength" diff --git a/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue b/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue index 120512bf15e..4b6f52c09be 100644 --- a/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue +++ b/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue @@ -1,13 +1,13 @@ <script> +import { GlModal } from '@gitlab/ui'; import axios from '~/lib/utils/axios_utils'; import { deprecatedCreateFlash as createFlash } from '~/flash'; -import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue'; import { redirectTo } from '~/lib/utils/url_utility'; -import { s__ } from '~/locale'; +import { __, s__ } from '~/locale'; export default { components: { - GlModal: DeprecatedModal2, + GlModal, }, props: { url: { @@ -36,17 +36,24 @@ export default { }); }, }, + primaryAction: { + text: s__('AdminArea|Stop jobs'), + attributes: [{ variant: 'danger' }], + }, + cancelAction: { + text: __('Cancel'), + }, }; </script> <template> <gl-modal - id="stop-jobs-modal" - :header-title-text="s__('AdminArea|Stop all jobs?')" - :footer-primary-button-text="s__('AdminArea|Stop jobs')" - footer-primary-button-variant="danger" - @submit="onSubmit" + modal-id="stop-jobs-modal" + :action-primary="$options.primaryAction" + :action-cancel="$options.cancelAction" + @primary="onSubmit" > + <template #modal-title>{{ s__('AdminArea|Stop all jobs?') }}</template> {{ text }} </gl-modal> </template> diff --git a/app/assets/javascripts/pages/admin/jobs/index/index.js b/app/assets/javascripts/pages/admin/jobs/index/index.js index 5a4f8c6e745..4df210debb5 100644 --- a/app/assets/javascripts/pages/admin/jobs/index/index.js +++ b/app/assets/javascripts/pages/admin/jobs/index/index.js @@ -5,19 +5,24 @@ import stopJobsModal from './components/stop_jobs_modal.vue'; Vue.use(Translate); document.addEventListener('DOMContentLoaded', () => { - const stopJobsButton = document.getElementById('stop-jobs-button'); + const buttonId = 'js-stop-jobs-button'; + const modalId = 'stop-jobs-modal'; + const stopJobsButton = document.getElementById(buttonId); if (stopJobsButton) { // eslint-disable-next-line no-new new Vue({ - el: '#stop-jobs-modal', + el: `#js-${modalId}`, components: { stopJobsModal, }, mounted() { stopJobsButton.classList.remove('disabled'); + stopJobsButton.addEventListener('click', () => { + this.$root.$emit('bv::show::modal', modalId, `#${buttonId}`); + }); }, render(createElement) { - return createElement('stop-jobs-modal', { + return createElement(modalId, { props: { url: stopJobsButton.dataset.url, }, diff --git a/app/finders/group_projects_finder.rb b/app/finders/group_projects_finder.rb index 5f24b15156c..8362e782ad1 100644 --- a/app/finders/group_projects_finder.rb +++ b/app/finders/group_projects_finder.rb @@ -12,6 +12,7 @@ # only_owned: boolean # only_shared: boolean # limit: integer +# include_subgroups: boolean # params: # sort: string # visibility_level: int diff --git a/app/models/project.rb b/app/models/project.rb index 08a9843dbbd..c43f78f3db9 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -378,7 +378,7 @@ class Project < ApplicationRecord delegate :feature_available?, :builds_enabled?, :wiki_enabled?, :merge_requests_enabled?, :forking_enabled?, :issues_enabled?, - :pages_enabled?, :public_pages?, :private_pages?, + :pages_enabled?, :snippets_enabled?, :public_pages?, :private_pages?, :merge_requests_access_level, :forking_access_level, :issues_access_level, :wiki_access_level, :snippets_access_level, :builds_access_level, :repository_access_level, :pages_access_level, :metrics_dashboard_access_level, diff --git a/app/services/bulk_update_integration_service.rb b/app/services/bulk_update_integration_service.rb index bb9bddb5967..5ddfdd359c2 100644 --- a/app/services/bulk_update_integration_service.rb +++ b/app/services/bulk_update_integration_service.rb @@ -9,7 +9,7 @@ class BulkUpdateIntegrationService # rubocop: disable CodeReuse/ActiveRecord def execute Service.transaction do - batch.update_all(service_hash) + Service.where(id: batch.select(:id)).update_all(service_hash) if integration.data_fields_present? integration.data_fields.class.where(service_id: batch.select(:id)).update_all(data_fields_hash) diff --git a/app/views/admin/jobs/index.html.haml b/app/views/admin/jobs/index.html.haml index d482ae04c08..8eaf84c8df9 100644 --- a/app/views/admin/jobs/index.html.haml +++ b/app/views/admin/jobs/index.html.haml @@ -6,11 +6,9 @@ = render "shared/builds/tabs", build_path_proc: build_path_proc, all_builds: @all_builds, scope: @scope - if @all_builds.running_or_pending.any? - #stop-jobs-modal + #js-stop-jobs-modal .nav-controls - %button#stop-jobs-button.btn.gl-button.btn-danger{ data: { toggle: 'modal', - target: '#stop-jobs-modal', - url: cancel_all_admin_jobs_path } } + %button#js-stop-jobs-button.btn.gl-button.btn-danger{ data: { url: cancel_all_admin_jobs_path } } = s_('AdminArea|Stop all jobs') .row-content-block.second-block diff --git a/app/views/projects/_remove_fork.html.haml b/app/views/projects/_remove_fork.html.haml new file mode 100644 index 00000000000..2f85376876f --- /dev/null +++ b/app/views/projects/_remove_fork.html.haml @@ -0,0 +1,10 @@ +- return unless @project.forked? && can?(current_user, :remove_fork_project, @project) + +.sub-section + %h4.danger-title= _('Remove fork relationship') + %p= remove_fork_project_description_message(@project) + + = form_for @project, url: remove_fork_project_path(@project), method: :delete, remote: true, html: { class: 'transfer-project' } do |f| + %p + %strong= _('Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source.') + = button_to _('Remove fork relationship'), '#', class: "gl-button btn btn-danger js-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_warning_message(@project) } diff --git a/app/views/projects/_transfer.html.haml b/app/views/projects/_transfer.html.haml new file mode 100644 index 00000000000..eb7feb7bd3b --- /dev/null +++ b/app/views/projects/_transfer.html.haml @@ -0,0 +1,16 @@ +- return unless can?(current_user, :change_namespace, @project) + +.sub-section + %h4.danger-title= _('Transfer project') + = form_for @project, url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'js-project-transfer-form' } do |f| + .form-group + = label_tag :new_namespace_id, nil, class: 'label-bold' do + %span= _('Select a new namespace') + .form-group + = select_tag :new_namespace_id, namespaces_options(nil), include_blank: true, class: 'select2' + %ul + %li= _("Be careful. Changing the project's namespace can have unintended side effects.") + %li= _('You can only transfer the project to namespaces you manage.') + %li= _('You will need to update your local repositories to point to the new location.') + %li= _('Project visibility level will be changed to match namespace rules when transferring to a group.') + = f.submit 'Transfer project', class: "gl-button btn btn-danger js-confirm-danger qa-transfer-button", data: { "confirm-danger-message" => transfer_project_message(@project) } diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 63d571e718e..10dd80501e0 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -93,31 +93,9 @@ %li= _('Your deployment services will be broken, you will need to manually fix the services after renaming.') = f.submit _('Change path'), class: "btn btn-warning qa-change-path-button" - - if can?(current_user, :change_namespace, @project) - .sub-section - %h4.danger-title= _('Transfer project') - = form_for @project, url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'js-project-transfer-form' } do |f| - .form-group - = label_tag :new_namespace_id, nil, class: 'label-bold' do - %span= _('Select a new namespace') - .form-group - = select_tag :new_namespace_id, namespaces_options(nil), include_blank: true, class: 'select2' - %ul - %li= _("Be careful. Changing the project's namespace can have unintended side effects.") - %li= _('You can only transfer the project to namespaces you manage.') - %li= _('You will need to update your local repositories to point to the new location.') - %li= _('Project visibility level will be changed to match namespace rules when transferring to a group.') - = f.submit 'Transfer project', class: "gl-button btn btn-danger js-confirm-danger qa-transfer-button", data: { "confirm-danger-message" => transfer_project_message(@project) } - - - if @project.forked? && can?(current_user, :remove_fork_project, @project) - .sub-section - %h4.danger-title= _('Remove fork relationship') - %p= remove_fork_project_description_message(@project) - - = form_for @project, url: remove_fork_project_path(@project), method: :delete, remote: true, html: { class: 'transfer-project' } do |f| - %p - %strong= _('Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source.') - = button_to _('Remove fork relationship'), '#', class: "gl-button btn btn-danger js-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_warning_message(@project) } + = render 'transfer', project: @project + + = render 'remove_fork', project: @project = render 'remove', project: @project diff --git a/changelogs/unreleased/229701-aqualls-stop-jobs-modal.yml b/changelogs/unreleased/229701-aqualls-stop-jobs-modal.yml new file mode 100644 index 00000000000..f8c8582e833 --- /dev/null +++ b/changelogs/unreleased/229701-aqualls-stop-jobs-modal.yml @@ -0,0 +1,5 @@ +--- +title: Update stop all jobs modal to latest modal +merge_request: 46157 +author: +type: changed diff --git a/changelogs/unreleased/270051-fj-generate-sitmap-dot-com.yml b/changelogs/unreleased/270051-fj-generate-sitmap-dot-com.yml new file mode 100644 index 00000000000..c5715db77c3 --- /dev/null +++ b/changelogs/unreleased/270051-fj-generate-sitmap-dot-com.yml @@ -0,0 +1,5 @@ +--- +title: Add default sitemap generator for gitlab-org group +merge_request: 45645 +author: +type: added diff --git a/changelogs/unreleased/okr-components-tooltip-ide-commit-sidebar.yml b/changelogs/unreleased/okr-components-tooltip-ide-commit-sidebar.yml new file mode 100644 index 00000000000..0eb0b404fbf --- /dev/null +++ b/changelogs/unreleased/okr-components-tooltip-ide-commit-sidebar.yml @@ -0,0 +1,5 @@ +--- +title: "Migrate tooltip in app/assets/javascripts/ide/components/commit_sidebar/list.vue" +merge_request: 46148 +author: +type: other diff --git a/doc/api/groups.md b/doc/api/groups.md index be2d9993ca0..312688202f6 100644 --- a/doc/api/groups.md +++ b/doc/api/groups.md @@ -1119,7 +1119,7 @@ DELETE /groups/:id/hooks/:hook_id Group audit events can be accessed via the [Group Audit Events API](audit_events.md#group-audit-events) -## Sync group with LDAP **(STARTER)** +## Sync group with LDAP **(STARTER ONLY)** Syncs the group with its linked LDAP group. Only available to group owners and administrators. @@ -1139,7 +1139,7 @@ Please consult the [Group Members](members.md) documentation. List, add, and delete LDAP group links. -### List LDAP group links **(STARTER)** +### List LDAP group links **(STARTER ONLY)** Lists LDAP group links. @@ -1151,7 +1151,7 @@ GET /groups/:id/ldap_group_links | --------- | -------------- | -------- | ----------- | | `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) | -### Add LDAP group link with CN or filter **(STARTER)** +### Add LDAP group link with CN or filter **(STARTER ONLY)** Adds an LDAP group link using a CN or filter. Adding a group link by filter is only supported in the Premium tier and above. @@ -1170,7 +1170,7 @@ POST /groups/:id/ldap_group_links NOTE: **Note:** To define the LDAP group link, provide either a `cn` or a `filter`, but not both. -### Delete LDAP group link **(STARTER)** +### Delete LDAP group link **(STARTER ONLY)** Deletes an LDAP group link. Deprecated. Will be removed in a future release. @@ -1195,7 +1195,7 @@ DELETE /groups/:id/ldap_group_links/:provider/:cn | `cn` | string | yes | The CN of an LDAP group | | `provider` | string | yes | LDAP provider for the LDAP group link | -### Delete LDAP group link with CN or filter **(STARTER)** +### Delete LDAP group link with CN or filter **(STARTER ONLY)** Deletes an LDAP group link using a CN or filter. Deleting by filter is only supported in the Premium tier and above. diff --git a/doc/development/documentation/styleguide.md b/doc/development/documentation/styleguide.md index 128fd2fa9a0..b48c6915abf 100644 --- a/doc/development/documentation/styleguide.md +++ b/doc/development/documentation/styleguide.md @@ -557,12 +557,13 @@ tenses, words, and phrases: - Exceptions to this rule include commonly accepted technical terms, such as CI/CD and TCP/IP. - <!-- vale gitlab.LatinTerms = NO --> - We discourage use of Latin abbreviations, such as "e.g.," "i.e.," or "etc.," - as even native users of English might misunderstand them. - (Tested in [`LatinTerms.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/LatinTerms.yml).) - - Instead of "i.e.," use "that is." - - Instead of "e.g.," use "for example," "such as," "for instance," or "like." - - Instead of "etc.," either use "and so on" or consider editing it out, since + We discourage the use of Latin abbreviations and terms, such as _e.g._, + _i.e._, _etc._, or _via_, as even native users of English can misunderstand + those terms. (Tested in [`LatinTerms.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/LatinTerms.yml).) + - Instead of _i.e._, use _that is_. + - Instead of _via_, use _through_. + - Instead of _e.g._, use _for example_, _such as_, _for instance_, or _like_. + - Instead of _etc._, either use _and so on_ or consider editing it out, since it can be vague. <!-- vale gitlab.LatinTerms = YES --> - Avoid using the word *currently* when talking about the product or its @@ -740,8 +741,7 @@ This is a list of available features: - Don't add commas (`,`) or semicolons (`;`) to the ends of list items. - Only add periods to the end of a list item if the item consists of a complete - sentence. The [definition of full sentence](https://www.le.ac.uk/oerresources/ssds/grammarguides/page_02.htm) - is: _"a complete sentence always contains a verb, expresses a complete idea, and makes sense standing alone"_. + sentence (with a subject and a verb). - Be consistent throughout the list: if the majority of the items do not end in a period, do not end any of the items in a period, even if they consist of a complete sentence. The opposite is also valid: if the majority of the items diff --git a/doc/development/testing_guide/ci.md b/doc/development/testing_guide/ci.md index 8091142410c..0e292676c5a 100644 --- a/doc/development/testing_guide/ci.md +++ b/doc/development/testing_guide/ci.md @@ -6,7 +6,7 @@ Our current CI parallelization setup is as follows: 1. The `retrieve-tests-metadata` job in the `prepare` stage ensures we have a `knapsack/report-master.json` file: - - The `knapsack/report-master.json` file is fetched from S3, if it's not here + - The `knapsack/report-master.json` file is fetched from the latest `master` artifacts, if it's not here we initialize the file with `{}`. 1. Each `[rspec|rspec-ee] [unit|integration|system|geo] n m` job are run with `knapsack rspec` and should have an evenly distributed share of tests: @@ -19,7 +19,7 @@ Our current CI parallelization setup is as follows: 1. The `update-tests-metadata` job (which only runs on scheduled pipelines for [the canonical project](https://gitlab.com/gitlab-org/gitlab) takes all the `knapsack/rspec*_pg_*.json` files and merge them all together into a single - `knapsack/report-master.json` file that is then uploaded to S3. + `knapsack/report-master.json` file that is saved as artifact. After that, the next pipeline will use the up-to-date `knapsack/report-master.json` file. diff --git a/doc/university/training/topics/env_setup.md b/doc/university/training/topics/env_setup.md index be517032a1b..e99b8696189 100644 --- a/doc/university/training/topics/env_setup.md +++ b/doc/university/training/topics/env_setup.md @@ -6,22 +6,31 @@ comments: false ## Install -- **Windows** - - Install 'Git for Windows' from <https://gitforwindows.org> - +- **Windows** - Install 'Git for Windows' from [Git for Windows](https://gitforwindows.org). - **Mac** - Type '`git`' in the Terminal application. - If it's not installed, it will prompt you to install it. -- **Linux** - - ```shell - sudo yum install git-all - ``` - - ```shell - sudo apt-get install git-all - ``` +- **Linux** - Enter `which git` in the Terminal application and press <kbd>Enter</kbd> to + determine if Git is installed on your system. + + - If the output of that command gives you the path to the Git executable, similar to + `/usr/bin/git`, then Git is already installed on your system. + - If the output of the command displays "command not found" error, Git isn't installed on your system. + + GitLab recommends installing Git with the default package manager of your distribution. + The following commands install Git on various GNU/Linux distributions using their + default package managers. After you run the command corresponding to your distribution + and complete the installation process, Git should be available on your system: + + - **Arch Linux and its derivatives** - `sudo pacman -S git` + - **Fedora, RHEL, and CentOS** - For the `yum` package manager run `sudo yum install git-all`, + and for the `dnf` package manager run `sudo dnf install git`. + - **Debian/Ubuntu and their derivatives** - `sudo apt-get install git` + - **Gentoo** - `sudo emerge --ask --verbose dev-vcs/git` + - **openSUSE** - `sudo zypper install git` + - **FreeBSD** - `sudo pkg install git` + - **OpenBSD** - `doas pkg_add git` ## Configure Git diff --git a/doc/user/admin_area/appearance.md b/doc/user/admin_area/appearance.md index 55dabce7342..da1e4ca2581 100644 --- a/doc/user/admin_area/appearance.md +++ b/doc/user/admin_area/appearance.md @@ -76,7 +76,7 @@ to activate it in the GitLab instance. You can also click on the **Sign-in page* to review the saved appearance settings: NOTE: **Note:** -You can add also add a [customized help message](settings/help_page.md) below the sign in message. +You can add also add a [customized help message](settings/help_page.md) below the sign in message or add [a Sign in text message](settings/sign_in_restrictions.md#sign-in-information). ## New project pages diff --git a/doc/user/analytics/index.md b/doc/user/analytics/index.md index c26c3c3453a..0debb99f4f0 100644 --- a/doc/user/analytics/index.md +++ b/doc/user/analytics/index.md @@ -26,6 +26,7 @@ The following analytics features are available at the group level: - [Insights](../group/insights/index.md). **(ULTIMATE)** - [Issue](../group/issues_analytics/index.md). **(PREMIUM)** - [Productivity](productivity_analytics.md) **(PREMIUM)** +- [Repositories](../group/repositories_analytics/index.md) **(PREMIUM)** - [Value Stream](value_stream_analytics.md). **(PREMIUM)** ## Project-level analytics diff --git a/doc/user/project/clusters/add_remove_clusters.md b/doc/user/project/clusters/add_remove_clusters.md index 094f4bcf6ba..af870693f23 100644 --- a/doc/user/project/clusters/add_remove_clusters.md +++ b/doc/user/project/clusters/add_remove_clusters.md @@ -149,6 +149,9 @@ Amazon Elastic Kubernetes Service (EKS) at the project, group, or instance level - [Amazon EKS](add_eks_clusters.md#new-eks-cluster). - [Google GKE](add_gke_clusters.md#creating-the-cluster-on-gke). +After creating a cluster, you can install runners for it as described in +[GitLab Managed Apps](../../clusters/applications.md). + ## Add existing cluster If you have an existing Kubernetes cluster, you can add it to a project, group, @@ -158,6 +161,9 @@ Kubernetes integration isn't supported for arm64 clusters. See the issue [Helm Tiller fails to install on arm64 cluster](https://gitlab.com/gitlab-org/gitlab/-/issues/29838) for details. +After adding an existing cluster, you can install runners for it as described in +[GitLab Managed Apps](../../clusters/applications.md). + ### Existing Kubernetes cluster To add a Kubernetes cluster to your project, group, or instance: diff --git a/doc/user/project/import/index.md b/doc/user/project/import/index.md index a1c28cfa2b7..a113758495a 100644 --- a/doc/user/project/import/index.md +++ b/doc/user/project/import/index.md @@ -30,6 +30,11 @@ repository is too large the import can timeout. There is also the option of [connecting your external repository to get CI/CD benefits](../../../ci/ci_cd_for_external_repos/index.md). **(PREMIUM)** +## LFS authentication + +When importing a project that contains LFS objects, if the project has an [`.lfsconfig`](https://github.com/git-lfs/git-lfs/blob/master/docs/man/git-lfs-config.5.ronn) +file with a URL host (`lfs.url`) different from the repository URL host, LFS files are not downloaded. + ## Migrating from self-managed GitLab to GitLab.com If you only need to migrate Git repositories, you can [import each project by URL](repo_by_url.md). Issues and merge requests can't be imported. diff --git a/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml index c3a92b67a8b..6eab3557024 100644 --- a/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml @@ -1,3 +1,9 @@ +# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/api_fuzzing/ + +# Configure the scanning tool through the environment variables. +# List of the variables: https://docs.gitlab.com/ee/user/application_security/api_fuzzing/#available-variables +# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables + stages: - build - test @@ -7,7 +13,7 @@ stages: variables: FUZZAPI_PROFILE: Quick FUZZAPI_VERSION: latest - FUZZAPI_CONFIG: "/app/.gitlab-api-fuzzing.yml" + FUZZAPI_CONFIG: .gitlab-api-fuzzing.yml FUZZAPI_TIMEOUT: 30 FUZZAPI_REPORT: gl-api-fuzzing-report.xml # @@ -17,9 +23,53 @@ variables: # available (non 500 response to HTTP(s)) FUZZAPI_SERVICE_START_TIMEOUT: "300" # + FUZZAPI_IMAGE: registry.gitlab.com/gitlab-org/security-products/analyzers/api-fuzzing:${FUZZAPI_VERSION}-engine + # apifuzzer_fuzz: stage: fuzz + image: + name: $FUZZAPI_IMAGE + entrypoint: ["/bin/bash", "-l", "-c"] + variables: + FUZZAPI_PROJECT: $CI_PROJECT_PATH + FUZZAPI_API: http://apifuzzer:80 + TZ: America/Los_Angeles + services: + - name: $FUZZAPI_IMAGE + alias: apifuzzer + entrypoint: ["dotnet", "/peach/Peach.Web.dll"] + allow_failure: true + rules: + - if: $FUZZAPI_D_TARGET_IMAGE + when: never + - if: $FUZZAPI_D_WORKER_IMAGE + when: never + - if: $API_FUZZING_DISABLED + when: never + - if: $API_FUZZING_DISABLED_FOR_DEFAULT_BRANCH && + $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME + when: never + - if: $FUZZAPI_HAR == null && $FUZZAPI_OPENAPI == null + when: never + - if: $GITLAB_FEATURES =~ /\bapi_fuzzing\b/ + script: + # + # Run user provided pre-script + - sh -c "$FUZZAPI_PRE_SCRIPT" + # + # Start scanning + - worker-entry + # + # Run user provided post-script + - sh -c "$FUZZAPI_POST_SCRIPT" + # + artifacts: + reports: + junit: $FUZZAPI_REPORT + +apifuzzer_fuzz_dnd: + stage: fuzz image: docker:19.03.12 variables: DOCKER_DRIVER: overlay2 @@ -28,20 +78,21 @@ apifuzzer_fuzz: FUZZAPI_API: http://apifuzzer:80 allow_failure: true rules: + - if: $FUZZAPI_D_TARGET_IMAGE == null && $FUZZAPI_D_WORKER_IMAGE == null + when: never - if: $API_FUZZING_DISABLED when: never - if: $API_FUZZING_DISABLED_FOR_DEFAULT_BRANCH && - $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME + $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME when: never - - if: $FUZZAPI_HAR == null && - $FUZZAPI_OPENAPI == null && - $FUZZAPI_D_WORKER_IMAGE == null + - if: $FUZZAPI_HAR == null && $FUZZAPI_OPENAPI == null when: never - if: $GITLAB_FEATURES =~ /\bapi_fuzzing\b/ services: - docker:19.03.12-dind script: # + # - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY # - docker network create --driver bridge $FUZZAPI_D_NETWORK @@ -56,30 +107,13 @@ apifuzzer_fuzz: --network $FUZZAPI_D_NETWORK \ -e Proxy:Port=8000 \ -e TZ=America/Los_Angeles \ - -e FUZZAPI_API=http://127.0.0.1:80 \ - -e FUZZAPI_PROJECT \ - -e FUZZAPI_PROFILE \ - -e FUZZAPI_CONFIG \ - -e FUZZAPI_REPORT \ - -e FUZZAPI_HAR \ - -e FUZZAPI_OPENAPI \ - -e FUZZAPI_TARGET_URL \ - -e FUZZAPI_OVERRIDES_FILE \ - -e FUZZAPI_OVERRIDES_ENV \ - -e FUZZAPI_OVERRIDES_CMD \ - -e FUZZAPI_OVERRIDES_INTERVAL \ - -e FUZZAPI_TIMEOUT \ - -e FUZZAPI_VERBOSE \ - -e FUZZAPI_SERVICE_START_TIMEOUT \ - -e FUZZAPI_HTTP_USERNAME \ - -e FUZZAPI_HTTP_PASSWORD \ -e GITLAB_FEATURES \ - -v $CI_PROJECT_DIR:/app \ -p 80:80 \ -p 8000:8000 \ -p 514:514 \ --restart=no \ - registry.gitlab.com/gitlab-org/security-products/analyzers/api-fuzzing:${FUZZAPI_VERSION}-engine + $FUZZAPI_IMAGE \ + dotnet /peach/Peach.Web.dll # # Start target container - | @@ -94,7 +128,7 @@ apifuzzer_fuzz: $FUZZAPI_D_TARGET_IMAGE \ ; fi # - # Start worker container + # Start worker container if provided - | if [ "$FUZZAPI_D_WORKER_IMAGE" != "" ]; then \ echo "Starting worker image $FUZZAPI_D_WORKER_IMAGE" \ @@ -104,9 +138,20 @@ apifuzzer_fuzz: -e FUZZAPI_API=http://apifuzzer:80 \ -e FUZZAPI_PROJECT \ -e FUZZAPI_PROFILE \ - -e FUZZAPI_AUTOMATION_CMD \ -e FUZZAPI_CONFIG \ -e FUZZAPI_REPORT \ + -e FUZZAPI_HAR \ + -e FUZZAPI_OPENAPI \ + -e FUZZAPI_TARGET_URL \ + -e FUZZAPI_OVERRIDES_FILE \ + -e FUZZAPI_OVERRIDES_ENV \ + -e FUZZAPI_OVERRIDES_CMD \ + -e FUZZAPI_OVERRIDES_INTERVAL \ + -e FUZZAPI_TIMEOUT \ + -e FUZZAPI_VERBOSE \ + -e FUZZAPI_SERVICE_START_TIMEOUT \ + -e FUZZAPI_HTTP_USERNAME \ + -e FUZZAPI_HTTP_PASSWORD \ -e CI_COMMIT_BRANCH=${CI_COMMIT_BRANCH} \ $FUZZAPI_D_WORKER_ENV \ $FUZZAPI_D_WORKER_PORTS \ @@ -115,13 +160,43 @@ apifuzzer_fuzz: $FUZZAPI_D_WORKER_IMAGE \ ; fi # - # Wait for testing to complete if api fuzzer is scanning - - if [ "$FUZZAPI_HAR$FUZZAPI_OPENAPI" != "" ]; then echo "Waiting for API Fuzzer to exit"; docker wait apifuzzer; fi + # Start API Fuzzing provided worker if no other worker present + - | + if [ "$FUZZAPI_D_WORKER_IMAGE" == "" ]; then \ + docker run \ + --name worker \ + --network $FUZZAPI_D_NETWORK \ + -e TZ=America/Los_Angeles \ + -e FUZZAPI_API=http://apifuzzer:80 \ + -e FUZZAPI_PROJECT \ + -e FUZZAPI_PROFILE \ + -e FUZZAPI_CONFIG \ + -e FUZZAPI_REPORT \ + -e FUZZAPI_HAR \ + -e FUZZAPI_OPENAPI \ + -e FUZZAPI_TARGET_URL \ + -e FUZZAPI_OVERRIDES_FILE \ + -e FUZZAPI_OVERRIDES_ENV \ + -e FUZZAPI_OVERRIDES_CMD \ + -e FUZZAPI_OVERRIDES_INTERVAL \ + -e FUZZAPI_TIMEOUT \ + -e FUZZAPI_VERBOSE \ + -e FUZZAPI_SERVICE_START_TIMEOUT \ + -e FUZZAPI_HTTP_USERNAME \ + -e FUZZAPI_HTTP_PASSWORD \ + -v $CI_PROJECT_DIR:/app \ + -p 81:80 \ + -p 8001:8000 \ + -p 515:514 \ + --restart=no \ + $FUZZAPI_IMAGE \ + worker-entry \ + ; fi # - # Propagate exit code from api fuzzer (if any) - - if [[ $(docker inspect apifuzzer --format='{{.State.ExitCode}}') != "0" ]]; then echo "API Fuzzing exited with an error. Logs are available as job artifacts."; docker logs apifuzzer; exit 1; fi + # Propagate exit code from api fuzzing scanner (if any) + - if [[ $(docker inspect apifuzzer --format='{{.State.ExitCode}}') != "0" ]]; then echo "API Fuzzing scanner exited with an error. Logs are available as job artifacts."; exit 1; fi # - # Run user provided pre-script + # Run user provided post-script - sh -c "$FUZZAPI_POST_SCRIPT" # after_script: @@ -129,13 +204,13 @@ apifuzzer_fuzz: # Shutdown all containers - echo "Stopping all containers" - if [ "$FUZZAPI_D_TARGET_IMAGE" != "" ]; then docker stop target; fi - - if [ "$FUZZAPI_D_WORKER_IMAGE" != "" ]; then docker stop worker; fi + - docker stop worker - docker stop apifuzzer # # Save docker logs - docker logs apifuzzer &> gl-api_fuzzing-logs.log - if [ "$FUZZAPI_D_TARGET_IMAGE" != "" ]; then docker logs target &> gl-api_fuzzing-target-logs.log; fi - - if [ "$FUZZAPI_D_WORKER_IMAGE" != "" ]; then docker logs worker &> gl-api_fuzzing-worker-logs.log; fi + - docker logs worker &> gl-api_fuzzing-worker-logs.log # artifacts: when: always diff --git a/package.json b/package.json index 623cc9a969f..fc1c1dd40de 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "@babel/preset-env": "^7.10.1", "@gitlab/at.js": "1.5.5", "@gitlab/svgs": "1.174.0", - "@gitlab/ui": "21.38.0", + "@gitlab/ui": "21.41.0", "@gitlab/visual-review-tools": "1.6.1", "@rails/actioncable": "^6.0.3-3", "@rails/ujs": "^6.0.3-2", diff --git a/qa/qa/page/project/settings/advanced.rb b/qa/qa/page/project/settings/advanced.rb index 97519c3906c..757084fc5b9 100644 --- a/qa/qa/page/project/settings/advanced.rb +++ b/qa/qa/page/project/settings/advanced.rb @@ -11,6 +11,9 @@ module QA view 'app/views/projects/edit.html.haml' do element :project_path_field element :change_path_button + end + + view 'app/views/projects/_transfer.html.haml' do element :transfer_button end diff --git a/scripts/rspec_helpers.sh b/scripts/rspec_helpers.sh index 9fe7d089d93..9828fd94b69 100644 --- a/scripts/rspec_helpers.sh +++ b/scripts/rspec_helpers.sh @@ -4,11 +4,11 @@ function retrieve_tests_metadata() { mkdir -p knapsack/ rspec_flaky/ rspec_profiling/ if [[ ! -f "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" ]]; then - wget -O "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" "http://${TESTS_METADATA_S3_BUCKET}.s3.amazonaws.com/${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" || echo "{}" > "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" + wget -O "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" "https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/raw/${KNAPSACK_RSPEC_SUITE_REPORT_PATH}?job=retrieve-tests-metadata" || echo "{}" > "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" fi if [[ ! -f "${FLAKY_RSPEC_SUITE_REPORT_PATH}" ]]; then - wget -O "${FLAKY_RSPEC_SUITE_REPORT_PATH}" "http://${TESTS_METADATA_S3_BUCKET}.s3.amazonaws.com/${FLAKY_RSPEC_SUITE_REPORT_PATH}" || echo "{}" > "${FLAKY_RSPEC_SUITE_REPORT_PATH}" + wget -O "${FLAKY_RSPEC_SUITE_REPORT_PATH}" "https://gitlab.com/gitlab-org/gitlab/-/jobs/artifacts/master/raw/${FLAKY_RSPEC_SUITE_REPORT_PATH}?job=retrieve-tests-metadata" || echo "{}" > "${FLAKY_RSPEC_SUITE_REPORT_PATH}" fi } @@ -16,29 +16,11 @@ function update_tests_metadata() { echo "{}" > "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" scripts/merge-reports "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" knapsack/rspec*.json - if [[ -n "${TESTS_METADATA_S3_BUCKET}" ]]; then - if [[ "$CI_PIPELINE_SOURCE" == "schedule" ]]; then - scripts/sync-reports put "${TESTS_METADATA_S3_BUCKET}" "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" - else - echo "Not uplaoding report to S3 as the pipeline is not a scheduled one." - fi - fi - rm -f knapsack/rspec*.json - scripts/merge-reports "${FLAKY_RSPEC_SUITE_REPORT_PATH}" rspec_flaky/all_*.json - export FLAKY_RSPEC_GENERATE_REPORT="true" + scripts/merge-reports "${FLAKY_RSPEC_SUITE_REPORT_PATH}" rspec_flaky/all_*.json scripts/flaky_examples/prune-old-flaky-examples "${FLAKY_RSPEC_SUITE_REPORT_PATH}" - - if [[ -n ${TESTS_METADATA_S3_BUCKET} ]]; then - if [[ "$CI_PIPELINE_SOURCE" == "schedule" ]]; then - scripts/sync-reports put "${TESTS_METADATA_S3_BUCKET}" "${FLAKY_RSPEC_SUITE_REPORT_PATH}" - else - echo "Not uploading report to S3 as the pipeline is not a scheduled one." - fi - fi - rm -f rspec_flaky/all_*.json rspec_flaky/new_*.json if [[ "$CI_PIPELINE_SOURCE" == "schedule" ]]; then diff --git a/spec/features/admin/admin_builds_spec.rb b/spec/features/admin/admin_builds_spec.rb index 85f0c44ed9c..166fde0f37a 100644 --- a/spec/features/admin/admin_builds_spec.rb +++ b/spec/features/admin/admin_builds_spec.rb @@ -12,7 +12,7 @@ RSpec.describe 'Admin Builds' do context 'All tab' do context 'when have jobs' do - it 'shows all jobs' do + it 'shows all jobs', :js do create(:ci_build, pipeline: pipeline, status: :pending) create(:ci_build, pipeline: pipeline, status: :running) create(:ci_build, pipeline: pipeline, status: :success) @@ -24,6 +24,10 @@ RSpec.describe 'Admin Builds' do expect(page).to have_selector('.row-content-block', text: 'All jobs') expect(page.all('.build-link').size).to eq(4) expect(page).to have_button 'Stop all jobs' + + click_button 'Stop all jobs' + expect(page).to have_button 'Stop jobs' + expect(page).to have_content 'Stop all jobs?' end end diff --git a/spec/services/bulk_update_integration_service_spec.rb b/spec/services/bulk_update_integration_service_spec.rb index d6022ba5b59..e7944f07bb7 100644 --- a/spec/services/bulk_update_integration_service_spec.rb +++ b/spec/services/bulk_update_integration_service_spec.rb @@ -10,60 +10,69 @@ RSpec.describe BulkUpdateIntegrationService do end let(:excluded_attributes) { %w[id project_id group_id inherit_from_id instance template created_at updated_at] } + let(:batch) do + Service.inherited_descendants_from_self_or_ancestors_from(subgroup_integration).where(id: group_integration.id..integration.id) + end let_it_be(:group) { create(:group) } + let_it_be(:subgroup) { create(:group, parent: group) } let_it_be(:group_integration) do JiraService.create!( group: group, - active: true, - push_events: true, - url: 'http://update-jira.instance.com', - username: 'user', - password: 'secret' + url: 'http://group.jira.com' ) end let_it_be(:subgroup_integration) do JiraService.create!( inherit_from_id: group_integration.id, - group: create(:group, parent: group), - active: true, - push_events: true, - url: 'http://update-jira.instance.com', - username: 'user', - password: 'secret' + group: subgroup, + url: 'http://subgroup.jira.com', + push_events: true + ) + end + + let_it_be(:excluded_integration) do + JiraService.create!( + group: create(:group), + url: 'http://another.jira.com', + push_events: false ) end let_it_be(:integration) do JiraService.create!( - project: create(:project), - instance: false, - active: true, - push_events: false, - url: 'http://jira.instance.com', - username: 'user', - password: 'secret' + project: create(:project, group: subgroup), + inherit_from_id: subgroup_integration.id, + url: 'http://project.jira.com', + push_events: false ) end context 'with inherited integration' do - it 'updates the integration' do - described_class.new(subgroup_integration, Service.where.not(project: nil)).execute + it 'updates the integration', :aggregate_failures do + described_class.new(subgroup_integration, batch).execute expect(integration.reload.inherit_from_id).to eq(group_integration.id) - expect(integration.attributes.except(*excluded_attributes)) + expect(integration.reload.attributes.except(*excluded_attributes)) .to eq(subgroup_integration.attributes.except(*excluded_attributes)) + + expect(excluded_integration.reload.inherit_from_id).not_to eq(group_integration.id) + expect(excluded_integration.reload.attributes.except(*excluded_attributes)) + .not_to eq(subgroup_integration.attributes.except(*excluded_attributes)) end context 'with integration with data fields' do let(:excluded_attributes) { %w[id service_id created_at updated_at] } - it 'updates the data fields from the integration' do - described_class.new(subgroup_integration, Service.where.not(project: nil)).execute + it 'updates the data fields from the integration', :aggregate_failures do + described_class.new(subgroup_integration, batch).execute - expect(integration.reload.data_fields.attributes.except(*excluded_attributes)) + expect(integration.data_fields.attributes.except(*excluded_attributes)) .to eq(subgroup_integration.data_fields.attributes.except(*excluded_attributes)) + + expect(integration.data_fields.attributes.except(*excluded_attributes)) + .not_to eq(excluded_integration.data_fields.attributes.except(*excluded_attributes)) end end end diff --git a/yarn.lock b/yarn.lock index d896bad4d8e..9395e8a9ec7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -866,10 +866,10 @@ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.174.0.tgz#954b4d908a6188a2fcc45f00f748beeb23f054b0" integrity sha512-CgnZvO2miZkWxANhFdaK+2S4qRgkrMRE3vh3Xxwc+hIV9ki9KavlAAez9MNIs0Um/SJ1UpfmqKoM/dMyZX7K/w== -"@gitlab/ui@21.38.0": - version "21.38.0" - resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-21.38.0.tgz#ff67908cdb4cb5efb84138842a181640d75b1524" - integrity sha512-T1Bvts25s+OS+v5/z6rL24whjGjO8b4KOBZy1+bp3UcQFLC/+gwJAimtiCsILPojlf7WJAPDK1KqJiDciy8gWg== +"@gitlab/ui@21.41.0": + version "21.41.0" + resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-21.41.0.tgz#185f5a534d6cd038f48588f432a25576d08c5780" + integrity sha512-Jl0OcEMQ+GKB9wTnZH9rU6YmL3rVDMHkEZc7Sa5QvNvP6A1Se/UEKbzhLi9rdyAoKpvrm3++tYg3ZJklIRZIsg== dependencies: "@babel/standalone" "^7.0.0" "@gitlab/vue-toasted" "^1.3.0" |