diff options
44 files changed, 313 insertions, 168 deletions
diff --git a/app/assets/stylesheets/page_bundles/oncall_schedules.scss b/app/assets/stylesheets/page_bundles/oncall_schedules.scss index a6668f00147..5c9e84ab0af 100644 --- a/app/assets/stylesheets/page_bundles/oncall_schedules.scss +++ b/app/assets/stylesheets/page_bundles/oncall_schedules.scss @@ -37,6 +37,11 @@ &.gl-modal .modal-md { max-width: 640px; } + + .dropdown-menu { + max-height: $dropdown-max-height; + @include gl-overflow-y-auto; + } } //// Copied from roadmaps.scss - adapted for on-call schedules @@ -182,10 +187,3 @@ $column-right-gradient: linear-gradient(to right, $gradient-dark-gray 0%, $gradi transform: translateX(-50%); } } - -.gl-token { - .gl-avatar-labeled-label { - @include gl-text-white; - @include gl-font-weight-normal; - } -} diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb index 1707daff734..cef09c13dae 100644 --- a/app/services/merge_requests/update_service.rb +++ b/app/services/merge_requests/update_service.rb @@ -25,12 +25,14 @@ module MergeRequests update_task_event(merge_request) || update(merge_request) end + # rubocop:disable Metrics/AbcSize def handle_changes(merge_request, options) old_associations = options.fetch(:old_associations, {}) old_labels = old_associations.fetch(:labels, []) old_mentioned_users = old_associations.fetch(:mentioned_users, []) old_assignees = old_associations.fetch(:assignees, []) old_reviewers = old_associations.fetch(:reviewers, []) + changed_fields = merge_request.previous_changes.keys if has_changes?(merge_request, old_labels: old_labels, old_assignees: old_assignees, old_reviewers: old_reviewers) todo_service.resolve_todos_for_target(merge_request, current_user) @@ -52,15 +54,11 @@ module MergeRequests end handle_assignees_change(merge_request, old_assignees) if merge_request.assignees != old_assignees - handle_reviewers_change(merge_request, old_reviewers) if merge_request.reviewers != old_reviewers - - if merge_request.previous_changes.include?('target_branch') || - merge_request.previous_changes.include?('source_branch') - merge_request.mark_as_unchecked - end - handle_milestone_change(merge_request) + handle_draft_status_change(merge_request, changed_fields) + + track_title_and_desc_edits(changed_fields) added_labels = merge_request.labels - old_labels if added_labels.present? @@ -80,7 +78,17 @@ module MergeRequests current_user ) end + + # Since #mark_as_unchecked triggers an update action through the MR's + # state machine, we want to push this as far down in the process so we + # avoid resetting #ActiveModel::Dirty + # + if merge_request.previous_changes.include?('target_branch') || + merge_request.previous_changes.include?('source_branch') + merge_request.mark_as_unchecked + end end + # rubocop:enable Metrics/AbcSize def handle_task_changes(merge_request) todo_service.resolve_todos_for_target(merge_request, current_user) @@ -95,50 +103,46 @@ module MergeRequests MergeRequests::CloseService end - def before_update(issuable, skip_spam_check: false) - return unless issuable.changed? - - @issuable_changes = issuable.changes - end - def after_update(issuable) issuable.cache_merge_request_closes_issues!(current_user) + end - return unless @issuable_changes + private - %w(title description).each do |action| - next unless @issuable_changes.key?(action) + attr_reader :target_branch_was_deleted + + def track_title_and_desc_edits(changed_fields) + tracked_fields = %w(title description) + + return unless changed_fields.any? { |field| tracked_fields.include?(field) } + + tracked_fields.each do |action| + next unless changed_fields.include?(action) - # Track edits to title or description - # merge_request_activity_counter .public_send("track_#{action}_edit_action".to_sym, user: current_user) # rubocop:disable GitlabSecurity/PublicSend - - # Track changes to Draft/WIP status - # - if action == "title" - old_title, new_title = @issuable_changes["title"] - old_title_wip = MergeRequest.work_in_progress?(old_title) - new_title_wip = MergeRequest.work_in_progress?(new_title) - - if !old_title_wip && new_title_wip - # Marked as Draft/WIP - # - merge_request_activity_counter - .track_marked_as_draft_action(user: current_user) - elsif old_title_wip && !new_title_wip - # Unmarked as Draft/WIP - # - merge_request_activity_counter - .track_unmarked_as_draft_action(user: current_user) - end - end end end - private + def handle_draft_status_change(merge_request, changed_fields) + return unless changed_fields.include?("title") - attr_reader :target_branch_was_deleted + old_title, new_title = merge_request.previous_changes["title"] + old_title_wip = MergeRequest.work_in_progress?(old_title) + new_title_wip = MergeRequest.work_in_progress?(new_title) + + if !old_title_wip && new_title_wip + # Marked as Draft/WIP + # + merge_request_activity_counter + .track_marked_as_draft_action(user: current_user) + elsif old_title_wip && !new_title_wip + # Unmarked as Draft/WIP + # + merge_request_activity_counter + .track_unmarked_as_draft_action(user: current_user) + end + end def handle_milestone_change(merge_request) return if skip_milestone_email diff --git a/app/views/admin/users/_cohorts_table.html.haml b/app/views/admin/users/_cohorts_table.html.haml index bb6266b38f6..a92cfb5851a 100644 --- a/app/views/admin/users/_cohorts_table.html.haml +++ b/app/views/admin/users/_cohorts_table.html.haml @@ -2,7 +2,7 @@ .bs-callout.clearfix %p = s_("Cohorts|User cohorts are shown for the last %{months_included} months. Only users with activity are counted in the 'New users' column; inactive users are counted separately.") % { months_included: @cohorts[:months_included] } - = link_to sprite_icon('question-o'), help_page_path('user/admin_area/analytics/user_cohorts', anchor: 'cohorts'), title: 'About this feature', target: '_blank' + = link_to sprite_icon('question-o'), help_page_path('user/admin_area/user_cohorts', anchor: 'cohorts'), title: 'About this feature', target: '_blank' .table-holder.d-xl-table %table.table diff --git a/changelogs/unreleased/301056-make-the-geo-oauth-application-trusted-by-default.yml b/changelogs/unreleased/301056-make-the-geo-oauth-application-trusted-by-default.yml new file mode 100644 index 00000000000..4215b6620b1 --- /dev/null +++ b/changelogs/unreleased/301056-make-the-geo-oauth-application-trusted-by-default.yml @@ -0,0 +1,5 @@ +--- +title: Make the Geo OAuth application trusted by default +merge_request: 54079 +author: +type: changed diff --git a/changelogs/unreleased/add-environment-job-pipeline-hooks.yml b/changelogs/unreleased/add-environment-job-pipeline-hooks.yml new file mode 100644 index 00000000000..e138ea742ac --- /dev/null +++ b/changelogs/unreleased/add-environment-job-pipeline-hooks.yml @@ -0,0 +1,5 @@ +--- +title: Added environment details to Job Hook and Pipeline Hook +merge_request: 54480 +author: AdrianLC +type: changed diff --git a/changelogs/unreleased/gl-button-audit-events.yml b/changelogs/unreleased/gl-button-audit-events.yml new file mode 100644 index 00000000000..8a4989da2e3 --- /dev/null +++ b/changelogs/unreleased/gl-button-audit-events.yml @@ -0,0 +1,5 @@ +--- +title: Apply new GitLab UI for button in promotion link +merge_request: 54755 +author: Yogi (@yo) +type: changed diff --git a/changelogs/unreleased/sy-add-end-date-to-rotations.yml b/changelogs/unreleased/sy-add-end-date-to-rotations.yml new file mode 100644 index 00000000000..fb93c5d1d3d --- /dev/null +++ b/changelogs/unreleased/sy-add-end-date-to-rotations.yml @@ -0,0 +1,5 @@ +--- +title: Add suppport for an end time on on-call rotations +merge_request: 53675 +author: +type: added diff --git a/db/migrate/20210208200914_add_ends_at_to_oncall_rotations.rb b/db/migrate/20210208200914_add_ends_at_to_oncall_rotations.rb new file mode 100644 index 00000000000..5cd179c9a80 --- /dev/null +++ b/db/migrate/20210208200914_add_ends_at_to_oncall_rotations.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class AddEndsAtToOncallRotations < ActiveRecord::Migration[6.0] + DOWNTIME = false + + def change + add_column :incident_management_oncall_rotations, :ends_at, :datetime_with_timezone + end +end diff --git a/db/migrate/20210212153934_make_the_geo_oauth_application_trusted_by_default.rb b/db/migrate/20210212153934_make_the_geo_oauth_application_trusted_by_default.rb new file mode 100644 index 00000000000..ab0343887e4 --- /dev/null +++ b/db/migrate/20210212153934_make_the_geo_oauth_application_trusted_by_default.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class MakeTheGeoOauthApplicationTrustedByDefault < ActiveRecord::Migration[6.0] + DOWNTIME = false + + def up + execute(<<-SQL.squish) + UPDATE oauth_applications + SET confidential = true, trusted = true + WHERE id IN (SELECT oauth_application_id FROM geo_nodes); + SQL + end + + def down + # We won't be able to tell which trusted applications weren't + # confidential before the migration and setting all trusted + # applications are not confidential would introduce security + # issues. + end +end diff --git a/db/schema_migrations/20210208200914 b/db/schema_migrations/20210208200914 new file mode 100644 index 00000000000..10a98a3d6e2 --- /dev/null +++ b/db/schema_migrations/20210208200914 @@ -0,0 +1 @@ +e7a0121e8e21acd356daa882d8fe83242f4db180915dd0f3c25835c6c664ce0b
\ No newline at end of file diff --git a/db/schema_migrations/20210212153934 b/db/schema_migrations/20210212153934 new file mode 100644 index 00000000000..28ef55d012c --- /dev/null +++ b/db/schema_migrations/20210212153934 @@ -0,0 +1 @@ +233a976aab340f16ed1c896963580fb66f4c9b4dee6a34f9536a62a4f7688792
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index b69d70ee159..c2f007c3a84 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -13216,6 +13216,7 @@ CREATE TABLE incident_management_oncall_rotations ( length_unit smallint NOT NULL, starts_at timestamp with time zone NOT NULL, name text NOT NULL, + ends_at timestamp with time zone, CONSTRAINT check_5209fb5d02 CHECK ((char_length(name) <= 200)) ); diff --git a/doc/administration/index.md b/doc/administration/index.md index e5f20e3ba05..36adbf2c960 100644 --- a/doc/administration/index.md +++ b/doc/administration/index.md @@ -130,7 +130,7 @@ Learn how to install, configure, update, and maintain your GitLab instance. - [Kerberos authentication](../integration/kerberos.md). - See also other [authentication](../topics/authentication/index.md#gitlab-administrators) topics (for example, enforcing 2FA). - [Email users](../tools/email.md): Email GitLab users from within GitLab. -- [User Cohorts](../user/admin_area/analytics/user_cohorts.md): Display the monthly cohorts of new users and their activities over time. +- [User Cohorts](../user/admin_area/user_cohorts.md): Display the monthly cohorts of new users and their activities over time. - [Audit events](audit_events.md): View the changes made within the GitLab server for: - Groups and projects. - Instances. diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index c6ad2cb82c7..1bfd50e7246 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -2096,6 +2096,7 @@ Describes an incident management on-call rotation. | Field | Type | Description | | ----- | ---- | ----------- | +| `endsAt` | Time | End date and time of the on-call rotation. | | `id` | IncidentManagementOncallRotationID! | ID of the on-call rotation. | | `length` | Int | Length of the on-call schedule, in the units specified by lengthUnit. | | `lengthUnit` | OncallRotationUnitEnum | Unit of the on-call rotation length. | diff --git a/doc/api/group_repository_storage_moves.md b/doc/api/group_repository_storage_moves.md index 8a19a43d31f..f4d89c34f38 100644 --- a/doc/api/group_repository_storage_moves.md +++ b/doc/api/group_repository_storage_moves.md @@ -197,7 +197,7 @@ Supported attributes: | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | | `group_id` | integer | yes | ID of the group. | -| `destination_storage_name` | string | no | Name of the destination storage shard. In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitaly/-/issues/3209), the storage is selected automatically if not provided. | +| `destination_storage_name` | string | no | Name of the destination storage shard. In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitaly/-/issues/3209), the storage is selected [automatically based on storage weights](../administration/repository_storage_paths.md#configure-where-new-repositories-are-stored) if not provided. | Example request: @@ -236,7 +236,7 @@ Supported attributes: | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | | `source_storage_name` | string | yes | Name of the source storage shard. | -| `destination_storage_name` | string | no | Name of the destination storage shard. The storage is selected automatically if not provided. | +| `destination_storage_name` | string | no | Name of the destination storage shard. The storage is selected [automatically based on storage weights](../administration/repository_storage_paths.md#configure-where-new-repositories-are-stored) if not provided. | Example request: diff --git a/doc/api/project_repository_storage_moves.md b/doc/api/project_repository_storage_moves.md index be922b441d6..a7fe25d03cd 100644 --- a/doc/api/project_repository_storage_moves.md +++ b/doc/api/project_repository_storage_moves.md @@ -211,7 +211,7 @@ Parameters: | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | | `project_id` | integer | yes | ID of the project | -| `destination_storage_name` | string | no | Name of the destination storage shard. In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitaly/-/issues/3209), the storage is selected automatically if not provided | +| `destination_storage_name` | string | no | Name of the destination storage shard. In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitaly/-/issues/3209), the storage is selected [automatically based on storage weights](../administration/repository_storage_paths.md#configure-where-new-repositories-are-stored) if not provided | Example request: @@ -255,7 +255,7 @@ Parameters: | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | | `source_storage_name` | string | yes | Name of the source storage shard. | -| `destination_storage_name` | string | no | Name of the destination storage shard. The storage is selected automatically if not provided. | +| `destination_storage_name` | string | no | Name of the destination storage shard. The storage is selected [automatically based on storage weights](../administration/repository_storage_paths.md#configure-where-new-repositories-are-stored) if not provided. | Example request: diff --git a/doc/api/snippet_repository_storage_moves.md b/doc/api/snippet_repository_storage_moves.md index 393ca30c28d..80037dd7aa3 100644 --- a/doc/api/snippet_repository_storage_moves.md +++ b/doc/api/snippet_repository_storage_moves.md @@ -225,7 +225,7 @@ Supported attributes: | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | | `snippet_id` | integer | yes | ID of the snippet. | -| `destination_storage_name` | string | no | Name of the destination storage shard. In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitaly/-/issues/3209), the storage is selected automatically if not provided. | +| `destination_storage_name` | string | no | Name of the destination storage shard. In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitaly/-/issues/3209), the storage is selected [automatically based on storage weights](../administration/repository_storage_paths.md#configure-where-new-repositories-are-stored) if not provided. | Example request: @@ -274,7 +274,7 @@ Supported attributes: | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | | `source_storage_name` | string | yes | Name of the source storage shard. | -| `destination_storage_name` | string | no | Name of the destination storage shard. The storage is selected automatically if not provided. | +| `destination_storage_name` | string | no | Name of the destination storage shard. The storage is selected [automatically based on storage weights](../administration/repository_storage_paths.md#configure-where-new-repositories-are-stored) if not provided. | Example request: diff --git a/doc/development/integrations/jenkins.md b/doc/development/integrations/jenkins.md index 16aba023fab..f54abfd17fd 100644 --- a/doc/development/integrations/jenkins.md +++ b/doc/development/integrations/jenkins.md @@ -8,6 +8,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w This is a step by step guide on how to set up [Jenkins](https://www.jenkins.io/) on your local machine and connect to it from your GitLab instance. GitLab triggers webhooks on Jenkins, and Jenkins connects to GitLab using the API. By running both applications on the same machine, we can make sure they are able to access each other. +For configuring an existing Jenkins integration, read [Jenkins CI service](../../integration/jenkins.md). + ## Install Jenkins Install Jenkins and start the service using Homebrew. @@ -39,62 +41,20 @@ Jenkins uses the GitLab API and needs an access token. ## Configure Jenkins -Configure your GitLab API connection in Jenkins. - -1. Make sure the GitLab plugin is installed on Jenkins. You can manage plugins in **Manage Jenkins > Manage Plugins**. -1. Set up the GitLab connection: - 1. Go to **Manage Jenkins > Configure System**. - 1. Find the **GitLab** section and check the **Enable authentication for '/project' end-point** checkbox. -1. To add your credentials, click **Add** then choose **Jenkins Credential Provider**. -1. Choose **GitLab API token** as the type of token. -1. Paste your GitLab access token and click **Add**. -1. Choose your credentials from the dropdown menu. -1. Add your GitLab host URL. Normally `http://localhost:3000/`. -1. Click **Save Settings**. - -For more details, see [GitLab documentation about Jenkins CI](../../integration/jenkins.md). +To configure your GitLab API connection in Jenkins, read +[Configure the Jenkins server](../../integration/jenkins.md#configure-the-jenkins-server). ## Configure Jenkins Project -Set up the Jenkins project to run your build on. A **Freestyle** project is the easiest -option because the Jenkins plugin updates the build status on GitLab. In a **Pipeline** project, updating the status on GitLab needs to be configured in a script. - -1. On your Jenkins instance, go to **New Item**. -1. Pick a name, choose **Freestyle** or **Pipeline** and click **ok**. -1. Choose your GitLab connection from the dropdown. -1. Check the **Build when a change is pushed to GitLab** checkbox. -1. Check the following checkboxes: - - - **Accepted Merge Request Events** - - **Closed Merge Request Events** - -1. If you created a **Freestyle** project, choose **Publish build status to GitLab** in the **Post-build Actions** section. - - If you created a **Pipeline** project, updating the status on GitLab has to be done by the pipeline script. Add GitLab update steps as in this example: - - ```groovy - pipeline { - agent any - - stages { - stage('gitlab') { - steps { - echo 'Notify GitLab' - updateGitlabCommitStatus name: 'build', state: 'pending' - updateGitlabCommitStatus name: 'build', state: 'success' - } - } - } - } - ``` +To set up the Jenkins project you intend to run your build on, read +[Configure the Jenkins project](../../integration/jenkins.md#configure-the-jenkins-project). ## Configure your GitLab project -To activate the Jenkins service: +You can configure your integration between Jenkins and GitLab: -1. Go to your project's page, then **Settings > Integrations > Jenkins CI**. -1. Check the **Active** checkbox and the triggers for **Push** and **Merge request**. -1. Fill in your Jenkins host, project name, username and password and click **Test settings and save changes**. +- With the [recommended approach for Jenkins integration](../../integration/jenkins.md#recommended-jenkins-integration). +- [Using a webhook](../../integration/jenkins.md#webhook-integration). ## Test your setup diff --git a/doc/development/usage_ping.md b/doc/development/usage_ping.md index f75db08597e..130da059583 100644 --- a/doc/development/usage_ping.md +++ b/doc/development/usage_ping.md @@ -742,7 +742,7 @@ Arguments: - or a `block`: which is evaluated - `fallback: -1`: the common value used for any metrics that are failing. -Example of usage: +Usage: ```ruby alt_usage_data { Gitlab::VERSION } @@ -750,6 +750,17 @@ alt_usage_data { Gitlab::CurrentSettings.uuid } alt_usage_data(999) ``` +### Adding counters to build new metrics + +When adding the results of two counters, use the `add` usage data method that +handles fallback values and exceptions. It also generates a valid SQL export. + +Example usage: + +```ruby +add(User.active, User.bot) +``` + ### Prometheus Queries In those cases where operational metrics should be part of Usage Ping, a database or Redis query is unlikely diff --git a/doc/integration/jenkins.md b/doc/integration/jenkins.md index b51ce5de8d7..1250ddee584 100644 --- a/doc/integration/jenkins.md +++ b/doc/integration/jenkins.md @@ -31,7 +31,8 @@ the ['GitLab vs. Jenkins' comparison page](https://about.gitlab.com/devops-tools NOTE: This documentation focuses only on how to **configure** a Jenkins *integration* with -GitLab. Learn how to **migrate** from Jenkins to GitLab CI/CD in our +GitLab. Learn how to set up Jenkins [on your local machine](../development/integrations/jenkins.md) +in our developer documentation, and how to **migrate** from Jenkins to GitLab CI/CD in our [Migrating from Jenkins](../ci/migration/jenkins.md) documentation. ## Configure GitLab integration with Jenkins @@ -138,9 +139,11 @@ Set up the Jenkins project you intend to run your build on. ## Configure the GitLab project -Configure the GitLab integration with Jenkins. +Configure the GitLab integration with Jenkins in one of the following ways. -### Option 1: Jenkins integration (recommended) +### Recommended Jenkins integration + +GitLab recommends this approach for Jenkins integrations. 1. Create a new GitLab project or choose an existing one. 1. Go to **Settings > Integrations**, then select **Jenkins CI**. @@ -159,7 +162,7 @@ Configure the GitLab integration with Jenkins. authentication. 1. Click **Test settings and save changes**. GitLab tests the connection to Jenkins. -### Option 2: Webhook +### Webhook integration If you are unable to provide GitLab with your Jenkins server login, you can use this option to integrate GitLab and Jenkins. @@ -167,7 +170,8 @@ to integrate GitLab and Jenkins. 1. In the configuration of your Jenkins job, in the GitLab configuration section, click **Advanced**. 1. Click the **Generate** button under the **Secret Token** field. 1. Copy the resulting token, and save the job configuration. -1. In GitLab, create a webhook for your project, enter the trigger URL (such as `https://JENKINS_URL/project/YOUR_JOB`) and paste the token in the **Secret Token** field. +1. In GitLab, create a webhook for your project, enter the trigger URL + (such as `https://JENKINS_URL/project/YOUR_JOB`) and paste the token in the **Secret Token** field. 1. After you add the webhook, click the **Test** button, and it should succeed. ## Troubleshooting diff --git a/doc/user/admin_area/analytics/index.md b/doc/user/admin_area/analytics/index.md index 5cf5e33f2d2..bea22745e7b 100644 --- a/doc/user/admin_area/analytics/index.md +++ b/doc/user/admin_area/analytics/index.md @@ -14,4 +14,3 @@ There are several kinds of statistics: - [DevOps Report](dev_ops_report.md): Provides an overview of your entire instance's feature usage. **(FREE)** - [Usage Trends](usage_trends.md): Shows how much data your instance contains, and how that is changing. **(FREE)** -- [User Cohorts](user_cohorts.md): Display the monthly cohorts of new users and their activities over time. **(FREE)** diff --git a/doc/user/admin_area/analytics/user_cohorts.md b/doc/user/admin_area/analytics/user_cohorts.md index a7c93160b69..ca5dff85757 100644 --- a/doc/user/admin_area/analytics/user_cohorts.md +++ b/doc/user/admin_area/analytics/user_cohorts.md @@ -1,36 +1,8 @@ --- -stage: none -group: unassigned -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +redirect_to: '../user_cohorts.md' --- -# Cohorts **(FREE)** +This document was moved to [another location](../user_cohorts.md). -As a benefit of having the [usage ping active](../settings/usage_statistics.md), -you can analyze your users' GitLab activities over time. - -To see user cohorts, go to **Admin Area > Overview > Users**. - -## Overview - -How do you interpret the user cohorts table? Let's review an example with the -following user cohorts: - -![User cohort example](img/cohorts_v13_9.png) - -For the cohort of March 2020, three users were added to this server and have -been active since this month. One month later (April 2020), two users are still -active. Five months later (August 2020), one user from this cohort is still -active, or 33% of the original cohort of three that joined in March. - -The **Inactive users** column shows the number of users who were added during -the month, but who never had any activity in the instance. - -How do we measure the activity of users? GitLab considers a user active if: - -- The user signs in. -- The user has Git activity (whether push or pull). -- The user visits pages related to dashboards, projects, issues, or merge - requests ([introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/54947) in GitLab 11.8). -- The user uses the API. -- The user uses the GraphQL API. +<!-- This redirect file can be deleted after <2021-06-01>. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/user/admin_area/analytics/img/cohorts_v13_9.png b/doc/user/admin_area/img/cohorts_v13_9.png Binary files differindex 6a616b201c9..6a616b201c9 100644 --- a/doc/user/admin_area/analytics/img/cohorts_v13_9.png +++ b/doc/user/admin_area/img/cohorts_v13_9.png diff --git a/doc/user/admin_area/index.md b/doc/user/admin_area/index.md index 14a193322a5..40e0e2856bd 100644 --- a/doc/user/admin_area/index.md +++ b/doc/user/admin_area/index.md @@ -186,6 +186,10 @@ The following totals are also included: GitLab billing is based on the number of [**Billable users**](../../subscriptions/self_managed/index.md#billable-users). +### User cohorts + +The [Cohorts](user_cohorts.md) tab displays the monthly cohorts of new users and their activities over time. + ### Administering Groups You can administer all groups in the GitLab instance from the Admin Area's Groups page. diff --git a/doc/user/admin_area/user_cohorts.md b/doc/user/admin_area/user_cohorts.md new file mode 100644 index 00000000000..f3c913b409a --- /dev/null +++ b/doc/user/admin_area/user_cohorts.md @@ -0,0 +1,36 @@ +--- +stage: none +group: unassigned +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +--- + +# Cohorts **(FREE)** + +As a benefit of having the [usage ping active](settings/usage_statistics.md), +you can analyze your users' GitLab activities over time. + +To see user cohorts, go to **Admin Area > Overview > Users**. + +## Overview + +How do you interpret the user cohorts table? Let's review an example with the +following user cohorts: + +![User cohort example](img/cohorts_v13_9.png) + +For the cohort of March 2020, three users were added to this server and have +been active since this month. One month later (April 2020), two users are still +active. Five months later (August 2020), one user from this cohort is still +active, or 33% of the original cohort of three that joined in March. + +The **Inactive users** column shows the number of users who were added during +the month, but who never had any activity in the instance. + +How do we measure the activity of users? GitLab considers a user active if: + +- The user signs in. +- The user has Git activity (whether push or pull). +- The user visits pages related to dashboards, projects, issues, or merge + requests ([introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/54947) in GitLab 11.8). +- The user uses the API. +- The user uses the GraphQL API. diff --git a/doc/user/application_security/threat_monitoring/index.md b/doc/user/application_security/threat_monitoring/index.md index 13bde2ed38b..4d149382907 100644 --- a/doc/user/application_security/threat_monitoring/index.md +++ b/doc/user/application_security/threat_monitoring/index.md @@ -186,7 +186,7 @@ There are two ways to create policy alerts: Once added, the UI updates and displays a warning about the dangers of too many alerts. -#### Enable or disable Policy Alerts **(FREE SELF)** +#### Enable or disable Policy Alerts **(ULTIMATE)** Policy Alerts is under development but ready for production use. It is deployed behind a feature flag that is **enabled by default**. diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md index 0fd4ccfd869..eb9b1f69424 100644 --- a/doc/user/discussions/index.md +++ b/doc/user/discussions/index.md @@ -38,18 +38,19 @@ There is a limit of 5,000 comments for every object, for example: issue, epic, a > - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5022) in GitLab 8.11. > - Resolvable threads can be added only to merge request diffs. +> - Resolving comments individually was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/28750) in GitLab 13.6. Thread resolution helps keep track of progress during planning or code review. -Every standard comment or thread in merge requests, commits, commit diffs, and +Every thread in merge requests, commits, commit diffs, and snippets is initially displayed as unresolved. They can then be individually resolved by anyone with at least Developer access to the project or by the author of the change being reviewed. If the thread has been resolved and a non-member un-resolves their own response, this will also unresolve the discussion thread. If the non-member then resolves this same response, this will resolve the discussion thread. -The need to resolve all standard comments or threads prevents you from forgetting -to address feedback and lets you hide threads that are no longer relevant. +The need to resolve threads prevents you from forgetting to address feedback and lets you +hide threads that are no longer relevant. !["A thread between two people on a piece of code"](img/thread_view.png) diff --git a/doc/user/group/saml_sso/group_managed_accounts.md b/doc/user/group/saml_sso/group_managed_accounts.md index dd0888a610f..9f2cafd456b 100644 --- a/doc/user/group/saml_sso/group_managed_accounts.md +++ b/doc/user/group/saml_sso/group_managed_accounts.md @@ -37,17 +37,7 @@ Since use of the group-managed account requires the use of SSO, users of group-m - The user is unable to access the group (their credentials no longer work on the identity provider when prompted to use SSO). - Contributions in the group (for example, issues and merge requests) remains intact. -## Assertions - -When using group-managed accounts, the following user details need to be passed to GitLab as SAML -assertions to be able to create a user. - -| Field | Supported keys | -|-----------------|----------------| -| Email (required)| `email`, `mail` | -| Full Name | `name` | -| First Name | `first_name`, `firstname`, `firstName` | -| Last Name | `last_name`, `lastname`, `lastName` | +Please refer to our [SAML SSO for Groups page](../index.md) for information on how to configure SAML. ## Feature flag **(PREMIUM SELF)** diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md index 24216188c80..02c75a4deef 100644 --- a/doc/user/group/saml_sso/index.md +++ b/doc/user/group/saml_sso/index.md @@ -25,7 +25,8 @@ SAML SSO is only configurable at the top-level group. 1. Navigate to the group and select **Settings > SAML SSO**. 1. Configure your SAML server using the **Assertion consumer service URL**, **Identifier**, and **GitLab single sign-on URL**. Alternatively GitLab provides [metadata XML configuration](#metadata-configuration). See [specific identity provider documentation](#providers) for more details. 1. Configure the SAML response to include a NameID that uniquely identifies each user. -1. Configure [required assertions](group_managed_accounts.md#assertions) if using [Group Managed Accounts](group_managed_accounts.md). +1. Configure [required assertions](#assertions) at minimum containing + the user's email address. 1. While the default is enabled for most SAML providers, please ensure the app is set to have [Service Provider](#glossary) initiated calls in order to link existing GitLab accounts. 1. Once the identity provider is set up, move on to [configuring GitLab](#configuring-gitlab). @@ -53,6 +54,19 @@ Once users have signed into GitLab using the SSO SAML setup, changing the `NameI We recommend setting the NameID format to `Persistent` unless using a field (such as email) that requires a different format. +### Assertions + +For users to be created with the right information with the improved [user access and management](#user-access-and-management), +the following user details need to be passed to GitLab as SAML assertions. + +| Field | Supported keys | +|-----------------|----------------| +| Email (required)| `email`, `mail` | +| Username | `username`, `nickname` | +| Full Name | `name` | +| First Name | `first_name`, `firstname`, `firstName` | +| Last Name | `last_name`, `lastname`, `lastName` | + ### Metadata configuration GitLab provides metadata XML that can be used to configure your Identity Provider. diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md index 63f15b7b914..92e8c67c01c 100644 --- a/doc/user/project/integrations/webhooks.md +++ b/doc/user/project/integrations/webhooks.md @@ -1133,6 +1133,10 @@ X-Gitlab-Event: Pipeline Hook "artifacts_file":{ "filename": null, "size": null + }, + "environment": { + "name": "production", + "action": "start" } }, { @@ -1167,7 +1171,8 @@ X-Gitlab-Event: Pipeline Hook "artifacts_file":{ "filename": null, "size": null - } + }, + "environment": null }, { "id": 378, @@ -1200,7 +1205,8 @@ X-Gitlab-Event: Pipeline Hook "artifacts_file":{ "filename": null, "size": null - } + }, + "environment": null }, { "id": 376, @@ -1233,7 +1239,8 @@ X-Gitlab-Event: Pipeline Hook "artifacts_file":{ "filename": null, "size": null - } + }, + "environment": null }, { "id": 379, @@ -1257,6 +1264,10 @@ X-Gitlab-Event: Pipeline Hook "artifacts_file":{ "filename": null, "size": null + }, + "environment": { + "name": "staging", + "action": "start" } } ] @@ -1329,7 +1340,8 @@ X-Gitlab-Event: Job Hook "linux", "docker" ] - } + }, + "environment": null } ``` diff --git a/lib/gitlab/data_builder/build.rb b/lib/gitlab/data_builder/build.rb index e17bd25e57e..c4af5e6608e 100644 --- a/lib/gitlab/data_builder/build.rb +++ b/lib/gitlab/data_builder/build.rb @@ -62,7 +62,9 @@ module Gitlab git_http_url: project.http_url_to_repo, git_ssh_url: project.ssh_url_to_repo, visibility_level: project.visibility_level - } + }, + + environment: build_environment(build) } data @@ -86,6 +88,15 @@ module Gitlab tags: runner.tags&.map(&:name) } end + + def build_environment(build) + return unless build.has_environment? + + { + name: build.expanded_environment_name, + action: build.environment_action + } + end end end end diff --git a/lib/gitlab/data_builder/pipeline.rb b/lib/gitlab/data_builder/pipeline.rb index 3036bc57ca5..7fd1b9cd228 100644 --- a/lib/gitlab/data_builder/pipeline.rb +++ b/lib/gitlab/data_builder/pipeline.rb @@ -67,7 +67,8 @@ module Gitlab artifacts_file: { filename: build.artifacts_file&.filename, size: build.artifacts_size - } + }, + environment: environment_hook_attrs(build) } end @@ -80,6 +81,15 @@ module Gitlab tags: runner.tags&.map(&:name) } end + + def environment_hook_attrs(build) + return unless build.has_environment? + + { + name: build.expanded_environment_name, + action: build.environment_action + } + end end end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 72fe8763a82..126111a70d0 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -20733,6 +20733,12 @@ msgstr "" msgid "On-call schedules" msgstr "" +msgid "OnCallSchedules|1 day" +msgstr "" + +msgid "OnCallSchedules|2 weeks" +msgstr "" + msgid "OnCallSchedules|Add a rotation" msgstr "" @@ -20790,6 +20796,9 @@ msgstr "" msgid "OnCallSchedules|On-call schedule for the %{timezone}" msgstr "" +msgid "OnCallSchedules|Please note, rotations with shifts that are less than four hours are currently not supported in the weekly view." +msgstr "" + msgid "OnCallSchedules|Restrict to time intervals" msgstr "" @@ -35610,6 +35619,9 @@ msgstr "" msgid "must be a valid IPv4 or IPv6 address" msgstr "" +msgid "must be after start" +msgstr "" + msgid "must be greater than start date" msgstr "" diff --git a/qa/qa/resource/project_snippet.rb b/qa/qa/resource/project_snippet.rb index c262499664e..9ab4612d117 100644 --- a/qa/qa/resource/project_snippet.rb +++ b/qa/qa/resource/project_snippet.rb @@ -33,12 +33,16 @@ module QA end def api_get_path - "/projects/#{project.id}/snippets/#{snippet_id}" + "/projects/#{project.id}/snippets/#{id}" end def api_post_path "/projects/#{project.id}/snippets" end + + def api_delete_path + "/projects/#{project.id}/snippets/#{id}" + end end end end diff --git a/qa/qa/resource/snippet.rb b/qa/qa/resource/snippet.rb index 6fdcb1cd29b..253a3363511 100644 --- a/qa/qa/resource/snippet.rb +++ b/qa/qa/resource/snippet.rb @@ -3,7 +3,9 @@ module QA module Resource class Snippet < Base - attr_accessor :title, :description, :file_content, :visibility, :file_name, :snippet_id + attr_accessor :title, :description, :file_content, :visibility, :file_name + + attribute :id def initialize @title = 'New snippet title' @@ -44,7 +46,7 @@ module QA end def api_get_path - "/snippets/#{snippet_id}" + "/snippets/#{id}" end def api_post_path @@ -60,6 +62,10 @@ module QA } end + def api_delete_path + "/snippets/#{id}" + end + def all_file_contents @files.insert(0, { name: @file_name, content: @file_content }) @files.each do |file| diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb index a867d9cb973..6ab50ba56f2 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb @@ -23,6 +23,11 @@ module QA Flow::Login.sign_in end + after do + personal_snippet&.remove_via_api! + project_snippet&.remove_via_api! + end + shared_examples 'comments on snippets' do |snippet_type| it "adds, edits, and deletes a comment on a #{snippet_type}" do send(snippet_type) diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb index 604c98ca21e..7e2464b509a 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/add_file_to_snippet_spec.rb @@ -23,6 +23,11 @@ module QA Flow::Login.sign_in end + after do + personal_snippet&.remove_via_api! + project_snippet&.remove_via_api! + end + shared_examples 'adding file to snippet' do |snippet_type| it "adds second file to an existing #{snippet_type} to make it multi-file" do send(snippet_type).visit! diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb index 2940b2067a1..3164efe2212 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb @@ -66,6 +66,8 @@ module QA expect(repository.commits.first).to include('Update snippet') expect(repository.file_content(new_file)).to include("#{added_content}#{changed_content}") end + + snippet.remove_via_api! end it 'clones, pushes, and pulls a snippet over SSH, deletes via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/825' do diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb index b91424d5b65..8ae0a80dc14 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb @@ -67,6 +67,8 @@ module QA expect(repository.commits.first).to include 'Update snippet' expect(repository.file_content(new_file)).to include "#{added_content}#{changed_content}" end + + snippet.remove_via_api! end it 'clones, pushes, and pulls a project snippet over SSH, deletes via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/832' do diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb index 1670ba56064..29ddbb22a01 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb @@ -54,6 +54,11 @@ module QA Flow::Login.sign_in end + after do + personal_snippet&.remove_via_api! + project_snippet&.remove_via_api! + end + shared_examples 'copying snippet file contents' do |snippet_type| it "copies file contents of a multi-file #{snippet_type} to a comment and verifies them" do send(snippet_type).visit! diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb index 5c0983dabb6..99c44345105 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/delete_file_from_snippet_spec.rb @@ -31,6 +31,11 @@ module QA Flow::Login.sign_in end + after do + personal_snippet&.remove_via_api! + project_snippet&.remove_via_api! + end + shared_examples 'deleting file from snippet' do |snippet_type| it "deletes second file from an existing #{snippet_type} to make it single-file" do send(snippet_type).visit! diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb index 751424222ba..3973e0aacad 100644 --- a/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb @@ -16,6 +16,10 @@ module QA Flow::Login.sign_in end + after do + snippet&.remove_via_api! + end + context 'when the snippet is public' do it 'can be shared with not signed-in users', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1016' do snippet.visit! diff --git a/spec/lib/gitlab/data_builder/build_spec.rb b/spec/lib/gitlab/data_builder/build_spec.rb index 4242469b3db..ab1728414bb 100644 --- a/spec/lib/gitlab/data_builder/build_spec.rb +++ b/spec/lib/gitlab/data_builder/build_spec.rb @@ -38,6 +38,7 @@ RSpec.describe Gitlab::DataBuilder::Build do it { expect(data[:runner][:id]).to eq(build.runner.id) } it { expect(data[:runner][:tags]).to match_array(tag_names) } it { expect(data[:runner][:description]).to eq(build.runner.description) } + it { expect(data[:environment]).to be_nil } context 'commit author_url' do context 'when no commit present' do @@ -63,6 +64,13 @@ RSpec.describe Gitlab::DataBuilder::Build do expect(data[:commit][:author_url]).to eq(Gitlab::Routing.url_helpers.user_url(username: build.commit.author.username)) end end + + context 'with environment' do + let(:build) { create(:ci_build, :teardown_environment) } + + it { expect(data[:environment][:name]).to eq(build.expanded_environment_name) } + it { expect(data[:environment][:action]).to eq(build.environment_action) } + end end end end diff --git a/spec/lib/gitlab/data_builder/pipeline_spec.rb b/spec/lib/gitlab/data_builder/pipeline_spec.rb index fd7cadeb89e..cf04f560ceb 100644 --- a/spec/lib/gitlab/data_builder/pipeline_spec.rb +++ b/spec/lib/gitlab/data_builder/pipeline_spec.rb @@ -37,6 +37,7 @@ RSpec.describe Gitlab::DataBuilder::Pipeline do expect(build_data[:id]).to eq(build.id) expect(build_data[:status]).to eq(build.status) expect(build_data[:allow_failure]).to eq(build.allow_failure) + expect(build_data[:environment]).to be_nil expect(runner_data).to eq(nil) expect(project_data).to eq(project.hook_attrs(backward: false)) expect(data[:merge_request]).to be_nil @@ -115,5 +116,12 @@ RSpec.describe Gitlab::DataBuilder::Pipeline do expect(build_data[:id]).to eq(build.id) end end + + context 'build with environment' do + let!(:build) { create(:ci_build, :teardown_environment, pipeline: pipeline) } + + it { expect(build_data[:environment][:name]).to eq(build.expanded_environment_name) } + it { expect(build_data[:environment][:action]).to eq(build.environment_action) } + end end end |