diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-07-12 18:08:33 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-07-12 18:08:33 +0300 |
commit | 8562dfae56800770e729dcb8215ebf7e1e29a55f (patch) | |
tree | 638de2a4d4e8c959c46ac343eaea602771e0f39a | |
parent | 3d6dddf134ebb82f2a9894cad738c84ff9d6e723 (diff) |
Add latest changes from gitlab-org/gitlab@master
28 files changed, 440 insertions, 74 deletions
diff --git a/.gitlab/ci/review-apps/main.gitlab-ci.yml b/.gitlab/ci/review-apps/main.gitlab-ci.yml index 065a654eab2..f11cba97f63 100644 --- a/.gitlab/ci/review-apps/main.gitlab-ci.yml +++ b/.gitlab/ci/review-apps/main.gitlab-ci.yml @@ -49,7 +49,6 @@ review-build-cng: GITLAB_REPO_URL: ${CI_PROJECT_URL} GITLAB_IMAGE_REPOSITORY: "registry.gitlab.com/gitlab-org/build/cng-mirror" GITLAB_IMAGE_SUFFIX: "ee" - GITLAB_VERIFY_DEPLOY_TIMEOUT_MINUTES: 5 GITLAB_HELM_CHART_REF: "75b1486a9aec212d0f49ef1251526d8e51004bbc" # 7.0.1: https://gitlab.com/gitlab-org/charts/gitlab/-/commit/75b1486a9aec212d0f49ef1251526d8e51004bbc environment: name: review/${CI_COMMIT_REF_SLUG}${SCHEDULE_TYPE} # No separator for SCHEDULE_TYPE so it's compatible as before and looks nice without it diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml index d0ce284fcef..28467dca3d5 100644 --- a/.gitlab/ci/rules.gitlab-ci.yml +++ b/.gitlab/ci/rules.gitlab-ci.yml @@ -2527,6 +2527,10 @@ changes: - ".gitlab/ci/test-metadata.gitlab-ci.yml" - "scripts/rspec_helpers.sh" + - <<: *if-merge-request + changes: + - "gems/gitlab-rspec" + - "gems/rspec_flaky" ################### # workhorse rules # diff --git a/.gitlab/ci/test-metadata.gitlab-ci.yml b/.gitlab/ci/test-metadata.gitlab-ci.yml index 85d3ea11ac6..c890fb15a59 100644 --- a/.gitlab/ci/test-metadata.gitlab-ci.yml +++ b/.gitlab/ci/test-metadata.gitlab-ci.yml @@ -45,7 +45,7 @@ update-tests-metadata: - rspec-ee system pg14 - rspec-ee background_migration pg14 script: - - run_timed_command "retry gem install fog-aws mime-types activesupport rspec_profiling postgres-copy --no-document" + - run_timed_command "retry gem install fog-aws mime-types activesupport rspec rspec_profiling postgres-copy --no-document" - source ./scripts/rspec_helpers.sh - test -f "${FLAKY_RSPEC_SUITE_REPORT_PATH}" || echo -e "\e[31m" 'Consider add ~"pipeline:run-all-rspec" to run full rspec jobs' "\e[0m" - update_tests_metadata diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue b/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue index c4675c25df4..87a2eb362d5 100644 --- a/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue +++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue @@ -194,8 +194,6 @@ export default { </template> </title-area> - <gl-skeleton-loader v-if="$apollo.queries.group.loading" /> - <gl-form-group v-if="showDependencyProxyImagePrefix" :label="$options.i18n.proxyImagePrefix" @@ -225,6 +223,7 @@ export default { </span> </template> </gl-form-group> + <gl-skeleton-loader v-else-if="$apollo.queries.group.loading" /> <manifests-list :dependency-proxy-image-prefix="dependencyProxyImagePrefix" diff --git a/app/models/integrations/microsoft_teams.rb b/app/models/integrations/microsoft_teams.rb index d6cbe5760e8..a9ed0bd3da1 100644 --- a/app/models/integrations/microsoft_teams.rb +++ b/app/models/integrations/microsoft_teams.rb @@ -2,6 +2,24 @@ module Integrations class MicrosoftTeams < BaseChatNotification + undef :notify_only_broken_pipelines + + field :webhook, + section: SECTION_TYPE_CONNECTION, + help: 'https://outlook.office.com/webhook/…', + required: true + + field :notify_only_broken_pipelines, + type: 'checkbox', + section: SECTION_TYPE_CONFIGURATION, + help: 'If selected, successful pipelines do not trigger a notification event.' + + field :branches_to_be_notified, + type: 'select', + section: SECTION_TYPE_CONFIGURATION, + title: -> { s_('Integrations|Branches for which notifications are to be sent') }, + choices: -> { branch_choices } + def title 'Microsoft Teams notifications' end @@ -26,23 +44,8 @@ module Integrations pipeline wiki_page] end - def default_fields - [ - { type: 'text', section: SECTION_TYPE_CONNECTION, name: 'webhook', help: 'https://outlook.office.com/webhook/…', required: true }, - { - type: 'checkbox', - section: SECTION_TYPE_CONFIGURATION, - name: 'notify_only_broken_pipelines', - help: 'If selected, successful pipelines do not trigger a notification event.' - }, - { - type: 'select', - section: SECTION_TYPE_CONFIGURATION, - name: 'branches_to_be_notified', - title: s_('Integrations|Branches for which notifications are to be sent'), - choices: self.class.branch_choices - } - ] + def fields + self.class.fields + build_event_channels end def sections diff --git a/app/views/layouts/_img_loader.html.haml b/app/views/layouts/_img_loader.html.haml index 979ebeb0a02..c1fe3ae0924 100644 --- a/app/views/layouts/_img_loader.html.haml +++ b/app/views/layouts/_img_loader.html.haml @@ -13,6 +13,6 @@ img.removeAttribute('data-src'); img.classList.remove('lazy'); img.classList.add('js-lazy-loaded'); - img.dataset.qa_selector = 'js_lazy_loaded_content'; + img.dataset.testid = 'js_lazy_loaded_content'; }); } diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md index 3ea94f5e4be..69c97982562 100644 --- a/doc/administration/audit_events.md +++ b/doc/administration/audit_events.md @@ -405,6 +405,13 @@ The following user actions on a GitLab instance generate instance audit events: Instance events can also be accessed using the [Instance Audit Events API](../api/audit_events.md#instance-audit-events). +#### Application settings **(PREMIUM)** + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/282428) in GitLab 16.2. + +When a user changes an application setting in an instance, project, or group, +that change and the user that made the change are recorded in the audit log. + ### GitLab Runner events > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/335509) in GitLab 14.8, audit events for when a runner is registered. diff --git a/doc/development/ai_features.md b/doc/development/ai_features.md index 7c4035fc6e9..52dc37caec3 100644 --- a/doc/development/ai_features.md +++ b/doc/development/ai_features.md @@ -43,7 +43,7 @@ See the [feature flag tracker](https://gitlab.com/gitlab-org/gitlab/-/issues/405 ## Implement a new AI action -To implement a new AI action, connect to the OpenAI API. You can connect to this API using either the: +To implement a new AI action, connect to the preferred AI provider. You can connect to this API using either the: - Experimental REST API. - Abstraction layer. @@ -208,7 +208,7 @@ The experimental endpoint is only available to GitLab team members on production ### GraphQL API -To connect to the OpenAI API using the Abstraction Layer, use an extendable GraphQL API called +To connect to the AI provider API using the Abstraction Layer, use an extendable GraphQL API called [`aiAction`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/graphql/mutations/ai/action.rb). The `input` accepts key/value pairs, where the `key` is the action that needs to be performed. We only allow one AI action per mutation request. @@ -237,6 +237,8 @@ mutation { The GraphQL API then uses the [OpenAI Client](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/gitlab/llm/open_ai/client.rb) to send the response. +Remember that other clients are available and you should not use OpenAI. + #### How to receive a response As the OpenAI API requests are handled in a background job, we do not keep the request alive and @@ -256,6 +258,8 @@ You should only subscribe to the subscription once the mutation is sent. If mult #### Current abstraction layer flow +The following graph uses OpenAI as an example. You can use different providers. + ```mermaid flowchart TD A[GitLab frontend] -->B[AiAction GraphQL mutation] diff --git a/doc/tutorials/protected_workflow/img/approval_rules_v16_2.png b/doc/tutorials/protected_workflow/img/approval_rules_v16_2.png Binary files differnew file mode 100644 index 00000000000..a7db9488bad --- /dev/null +++ b/doc/tutorials/protected_workflow/img/approval_rules_v16_2.png diff --git a/doc/tutorials/protected_workflow/img/branch_is_protected_v16_2.png b/doc/tutorials/protected_workflow/img/branch_is_protected_v16_2.png Binary files differnew file mode 100644 index 00000000000..c4ea048a41e --- /dev/null +++ b/doc/tutorials/protected_workflow/img/branch_is_protected_v16_2.png diff --git a/doc/tutorials/protected_workflow/img/branch_list_v16_1.png b/doc/tutorials/protected_workflow/img/branch_list_v16_1.png Binary files differnew file mode 100644 index 00000000000..d557c4a9350 --- /dev/null +++ b/doc/tutorials/protected_workflow/img/branch_list_v16_1.png diff --git a/doc/tutorials/protected_workflow/img/new_file_v16_2.png b/doc/tutorials/protected_workflow/img/new_file_v16_2.png Binary files differnew file mode 100644 index 00000000000..d42b461f9c5 --- /dev/null +++ b/doc/tutorials/protected_workflow/img/new_file_v16_2.png diff --git a/doc/tutorials/protected_workflow/img/new_project_v16_2.png b/doc/tutorials/protected_workflow/img/new_project_v16_2.png Binary files differnew file mode 100644 index 00000000000..00effb87856 --- /dev/null +++ b/doc/tutorials/protected_workflow/img/new_project_v16_2.png diff --git a/doc/tutorials/protected_workflow/img/protections_in_place_v16_2.png b/doc/tutorials/protected_workflow/img/protections_in_place_v16_2.png Binary files differnew file mode 100644 index 00000000000..b21a714562e --- /dev/null +++ b/doc/tutorials/protected_workflow/img/protections_in_place_v16_2.png diff --git a/doc/tutorials/protected_workflow/img/search_engineering_v16_2.png b/doc/tutorials/protected_workflow/img/search_engineering_v16_2.png Binary files differnew file mode 100644 index 00000000000..ae69b41a665 --- /dev/null +++ b/doc/tutorials/protected_workflow/img/search_engineering_v16_2.png diff --git a/doc/tutorials/protected_workflow/img/subgroup_structure_v16_1.png b/doc/tutorials/protected_workflow/img/subgroup_structure_v16_1.png Binary files differnew file mode 100644 index 00000000000..3c4ee02d0f4 --- /dev/null +++ b/doc/tutorials/protected_workflow/img/subgroup_structure_v16_1.png diff --git a/doc/tutorials/protected_workflow/index.md b/doc/tutorials/protected_workflow/index.md new file mode 100644 index 00000000000..5245bdc5ba9 --- /dev/null +++ b/doc/tutorials/protected_workflow/index.md @@ -0,0 +1,290 @@ +--- +stage: Create +group: Code Review +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments" +--- + +<!-- vale gitlab.FutureTense = NO --> + +# Tutorial: Build a protected workflow for your project **(FREE)** + +When your team starts a new project, they need a workflow that balances efficiency +with appropriate reviews. In GitLab, you can create user groups, combine those +groups with branch protections, and then enforce those protections with approval rules. + +This tutorial sets up protections for Excelsior Project's `1.x` and `1.x.x` +release branches, and creates a minimal approval workflow for the project: + +1. [Create the `engineering` group](#create-the-engineering-group) +1. [Create subgroups in `engineering`](#create-subgroups-in-engineering) +1. [Add users to the subgroups](#add-users-to-the-subgroups) +1. [Create the Excelsior project](#create-the-excelsior-project) +1. [Add a basic CODEOWNERS file](#add-a-basic-codeowners-file) +1. [Configure approval rules](#configure-approval-rules) +1. [Enforce CODEOWNER approval on branches](#enforce-codeowner-approval-on-branches) +1. [Create the release branches](#create-the-release-branches) + +## Prerequisites + +- You must have the Maintainer or Owner role. +- You need a list of managers and their email addresses. +- You need a list of your backend and frontend engineers, and their email addresses. +- You understand [semantic versioning](https://semver.org/) for branch names. + +## Create the `engineering` group + +Before setting up Excelsior Project, you should create a group to own +the project. Here, you'll set up the Engineering group: + +1. On the left sidebar, at the top, select **Create new...** (**{plus}**) and **New group**. +1. Select **Create group**. +1. For **Group name**, enter `Engineering`. +1. For the **Group URL**, enter `engineering`. +1. Set the **Visibility level** to **Private**. +1. Personalize your experience so GitLab shows the most helpful information to you: + - For **Role**, select **System administrator**. + - For **Who will be using this group?** select **My company or team**. + - For **What will you use this group for?** select **I want to store my code**. +1. Skip inviting members to the group. You'll add users in a later section of this tutorial. +1. Select **Create group**. + +Next, you'll add subgroups to this `engineering` group for more granular control. + +## Create subgroups in `engineering` + +The `engineering` group is a good start, but Excelsior Project's +backend engineers, frontend engineers, and managers +have different tasks, and different areas of specialty. + +Here, you'll create three more granular subgroups in the Engineering group to +segment users by the type of work they do: `managers`, `frontend`, and `backend`. +Then you'll add these new groups as members of the `engineering` group. + +First, create the new subgroup: + +1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) + and search for `engineering`. Select the group named `Engineering`: + + ![The engineering group in search results](img/search_engineering_v16_2.png) + +1. On the overview page for the `engineering` group, in the upper-right corner, + select **New subgroup**. +1. For the **Subgroup name**, enter `Managers`. +1. Set the **Visibility level** to **Private**. +1. Select **Create subgroup**. + +Next, add the subgroup as a member of the `engineering` group: + +1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) + and search for `engineering`. Select the group named `Engineering`. +1. On the left sidebar, select **Manage > Members**. +1. On the top right, select **Invite a group**. +1. For **Select a group to invite**, select `Engineering / Managers`. +1. When adding the subgroups select the role **Maintainer**. + This configures the highest role a member of the subgroup can inherit when accessing the `engineering` group and its projects. +1. Optional. Select an expiration date. +1. Select **Invite**. + +Repeat this process to create subgroups for `backend` and `frontend`. When you're done, +search for the `engineering` group one more time. Its overview page should show +three subgroups, like this: + +![The engineering group has three subgroups](img/subgroup_structure_v16_1.png) + +## Add users to the subgroups + +In the previous step, when you added your subgroups to the parent group (`engineering`), you limited +members of the subgroups to the Maintainer role. This is the highest role they can inherit +for projects owned by `engineering`. As a result: + +- User 1 is added to the `manager` subgroup with the Guest role, and receives + the Guest role on `engineering` projects. +- User 2 is added to the `manager` group with the Owner role. This role is higher + than the maximum role (Maintainer) you set, so User 2 receives the Maintainer + role instead of Owner. + +To add a user to the `frontend` subgroup: + +1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) + and search for `frontend`. Select the `Frontend` group. +1. Select **Manage > Members**. +1. Select **Invite members**. +1. Fill in the fields. Select the **Developer** role by default, increasing it + to **Maintainer** if this user reviews the work of others. +1. Select **Invite**. +1. Repeat these steps until you've added all of the frontend engineers into the + `frontend` subgroup. + +Now do the same with the `backend` and `managers` groups. The same user can be a +member of multiple subgroups. + +## Create the Excelsior project + +Now that your group structure is in place, create the `excelsior` project +for the teams to work in. Because both frontend and backend engineers +are involved, `excelsior` should belong to `engineering` instead of any of the +smaller subgroups you just created. + +To create the new `excelsior` project: + +1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) and + search for `engineering`. Select the group named `Engineering`. +1. On the overview page for the `engineering` group, on the left sidebar, at the top, + select **Create new...** (**{plus}**) and **In this group > New project/repository**. +1. Select **Create blank project**. +1. Enter the project details: + - In the **Project name** field, enter `Excelsior`. The **Project slug** should + auto-populate with `excelsior`. + - For **Visibility Level**, select **Public**. + - Select **Initialize repository with a README** to add an initial file to the repository. +1. Select **Create project**. + +GitLab creates the `excelsior` project for you, and redirects you to its homepage. +It should look like this: + +![Your new, almost-empty excelsior project](img/new_project_v16_2.png) + +You'll use a feature on this page in the next step. + +## Add a basic CODEOWNERS file + +Add a CODEOWNERS file to the root directory of your project to route reviews to +the right subgroup. This example sets up four rules: + +- All changes should be reviewed by someone in the `engineering` group. +- A manager should review any change to the CODEOWNERS file itself. +- Frontend engineers should review changes to frontend files. +- Backend engineers should review changes to backend files. + +NOTE: +GitLab Free supports only optional reviews. To make reviews required, you need +GitLab Premium or Ultimate. + +To add a CODEOWNERS file to your `excelsior` project: + +1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) and + search for `Excelsior`. Select the project named `Excelsior`. +1. Next to the branch name, select the plus icon (**{plus}**), then **New file**: + ![Create a new file in the project](img/new_file_v16_2.png) +1. For **Filename**, enter `CODEOWNERS`. This will create a file named `CODEOWNERS` + in the root directory of your project. +1. Paste this example into the editing area, changing `@engineering/` if it + does not match your group structure: + + ```plaintext + # All changes should be reviewed by someone in the engineering group + * @engineering + + # A manager should review any changes to this file + CODEOWNERS @engineering/managers + + # Frontend files should be reviewed by FE engineers + [Frontend] @engineering/frontend + *.scss + *.js + + # Backend files should be reviewed by BE engineers + [Backend] @engineering/backend + *.rb + ``` + +1. For a **Commit message**, paste in: + + ```plaintext + Adds a new CODEOWNERS file + + Creates a small CODEOWNERS file to: + - Route backend and frontend changes to the right teams + - Route CODEOWNERS file changes to managers + - Request all changes be reviewed + ``` + +1. Select **Commit changes**. + +The CODEOWNERS file is now in place in the `main` branch of your project, and +available for all future branches created in this project. + +## Configure approval rules + +The CODEOWNERS file describes the appropriate reviewers for directories and +file types. Approval rules direct merge requests to those reviewers. +Here, you will set up an approval rule that uses the information in your new CODEOWNERS +file and adds protection for release branches: + +1. On the left sidebar, select **Settings > Merge requests**. +1. In the **Merge request approvals** section, scroll to **Approval rules**. +1. Select **Add approval rule**. +1. Create a rule named `Enforce CODEOWNERS`. +1. Select **All protected branches**. +1. To make the rule required in GitLab Premium and GitLab Ultimate, + set the **Approvals required** to `1`. +1. Add the `managers` group as approvers. +1. Select **Add approval rule**. +1. Scroll to **Approval settings** and make sure + **Prevent editing approval rules in merge requests** is selected. +1. Select **Save changes**. + +When added, the `Enforce CODEOWNERS` rule looks like this: + +![New approval rule in place](img/approval_rules_v16_2.png) + +## Enforce CODEOWNER approval on branches + +You've configured several protections for your project, and you're now ready to +combine those protections together to safeguard your project's important branches: + +- Your users are sorted into logical groups and subgroups. +- Your CODEOWNERS file describes the subject matter experts for file types and directories. +- Your approval rule encourages (in GitLab Free) or requires (in GitLab Premium and GitLab Ultimate) + the subject matter experts to review changes. + +Your `excelsior` project uses [semantic versioning](https://semver.org/) for +release branch names, so you know the release branches follow the pattern `1.x` +and `1.x.x`. You want all code added to these branches to be reviewed by subject +matter experts, and for managers to make the final decision on what work is merged +into the release branch. + +Rather than create protections for a branch at a time, configure wildcard branch rules +to protect multiple branches: + +1. On the left sidebar, select **Settings > Repository**. +1. Expand **Protected branches**. +1. From the **Branch** dropdown list, type `1.*`, and then select **Create wildcard `1.*`**. +1. To require everyone to submit merge requests, rather than pushing commits directly: + 1. Set **Allowed to merge** to **Maintainers**. + 1. Set **Allowed to push and merge** to **No one**. + 1. Leave **Allowed to force push** disabled. +1. In GitLab Premium and GitLab Ultimate, to require Code Owners to review changes + to files they work on, toggle **Require approval from code owners**. +1. Select **Protect**. +1. In the table of branches, find the rule marked as `Default`. (Depending on + your version of GitLab, this branch may be named `main` or `master`.) Set the + values for this branch to match the settings you used for the `1.*` rule. + +Your rules are now in place, even though no `1.*` branches exist yet: + +![main and 1.x are now protected](img/branch_list_v16_1.png) + +## Create the release branches + +Now that all branch protections in place, you're ready to create your 1.0.0 release branch: + +1. On the left sidebar, select **Code > Branches**. +1. On the top right, select **New branch**. Name it `1.0.0`. +1. Select **Create branch**. + +The branch protections are now visible in the UI: + +- On the left sidebar, select **Code > Branches**. In the list of branches, + branch `1.0.0` should be show that it is protected: + + ![List of branches, showing 1.0.0 is protected](img/branch_is_protected_v16_2.png) + +- On the left sidebar, select **Settings > Repository**, then expand **Branch rules** + to see details about all protected branches: + + ![List of protected branches and their protections](img/protections_in_place_v16_2.png) + +Congratulations! Your engineers can work independently in their feature branches, +and all code submitted for consideration for the 1.0.0 release branch will +be reviewed by subject matter experts. diff --git a/doc/user/project/ml/experiment_tracking/img/candidate_detail_ci_v16_12.png b/doc/user/project/ml/experiment_tracking/img/candidate_detail_ci_v16_12.png Binary files differnew file mode 100644 index 00000000000..fb4f8d5dc66 --- /dev/null +++ b/doc/user/project/ml/experiment_tracking/img/candidate_detail_ci_v16_12.png diff --git a/doc/user/project/ml/experiment_tracking/index.md b/doc/user/project/ml/experiment_tracking/index.md index 584a6c0df59..7fda6ef03a0 100644 --- a/doc/user/project/ml/experiment_tracking/index.md +++ b/doc/user/project/ml/experiment_tracking/index.md @@ -58,8 +58,8 @@ Some example parameters: ## Track new experiments and candidates Experiment and trials can only be tracked through the -[MLflow](https://www.mlflow.org/docs/latest/tracking.html) client integration. -See [MLflow client integration](../../integrations/mlflow_client.md) for more information +[MLflow](https://www.mlflow.org/docs/latest/tracking.html) client compatibility. +See [MLflow client compatibility](mlflow_client.md) for more information on how to use GitLab as a backend for the MLflow Client. ## Explore model candidates @@ -82,6 +82,14 @@ limitations. After an artifact is logged for a candidate, all artifacts logged f package registry. The package name for a candidate is `ml_experiment_<experiment_id>`, where the version is the candidate IID. The link to the artifacts can also be accessed from the **Experiment Candidates** list or **Candidate detail**. +## View CI information + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119788) in 16.1 + +Candidates can be associated to the CI job that created them, allowing quick links to the merge request, pipeline, and user that triggered the pipeline: + +![CI information in candidate detail](img/candidate_detail_ci_v16_12.png) + ## Related topics - Development details in [epic 8560](https://gitlab.com/groups/gitlab-org/-/epics/8560). diff --git a/doc/user/project/integrations/mlflow_client.md b/doc/user/project/ml/experiment_tracking/mlflow_client.md index 9d354c9a2d9..7fd5c7cca92 100644 --- a/doc/user/project/integrations/mlflow_client.md +++ b/doc/user/project/ml/experiment_tracking/mlflow_client.md @@ -4,17 +4,17 @@ group: Incubation info: Machine Learning Experiment Tracking is a GitLab Incubation Engineering program. No technical writer assigned to this group. --- -# MLflow client integration **(FREE)** +# MLflow client compatibility **(FREE)** -> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/8560) in GitLab 15.11 as an [Experiment](../../../policy/experiment-beta-support.md#experiment) release [with a flag](../../../administration/feature_flags.md) named `ml_experiment_tracking`. Disabled by default. +> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/8560) in GitLab 15.11 as an [Experiment](../../../../policy/experiment-beta-support.md#experiment) release [with a flag](../../../../administration/feature_flags.md) named `ml_experiment_tracking`. Disabled by default. NOTE: -Model experiment tracking is an [experimental feature](../../../policy/experiment-beta-support.md). +Model experiment tracking is an [experimental feature](../../../../policy/experiment-beta-support.md). Refer to <https://gitlab.com/gitlab-org/gitlab/-/issues/381660> for feedback and feature requests. [MLflow](https://mlflow.org/) is a popular open source tool for Machine Learning Experiment Tracking. -GitLab works as a backend to the MLflow Client, [logging experiments](../ml/experiment_tracking/index.md). -Setting up your integrations requires minimal changes to existing code. +GitLab [Model experiment tracking](index.md) is compatible with MLflow Client, +[logging experiments](index.md). The setup requires minimal changes to existing code. GitLab plays the role of a MLflow server. Running `mlflow server` is not necessary. @@ -22,12 +22,12 @@ GitLab plays the role of a MLflow server. Running `mlflow server` is not necessa Prerequisites: -- A [personal](../../../user/profile/personal_access_tokens.md), [project](../../../user/project/settings/project_access_tokens.md), or [group](../../../user/group/settings/group_access_tokens.md) access token with at least the Developer role and the `api` permission. +- A [personal](../../../../user/profile/personal_access_tokens.md), [project](../../../../user/project/settings/project_access_tokens.md), or [group](../../../../user/group/settings/group_access_tokens.md) access token with at least the Developer role and the `api` permission. - The project ID. To find the project ID: 1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project. 1. Select **Settings > General**. -To enable MLflow client integration: +To use MLflow client compatibility from a local environment: 1. Set the tracking URI and token environment variables on the host that runs the code. This can be your local environment, CI pipeline, or remote host. For example: @@ -53,18 +53,23 @@ Runs are registered as: > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119454) in GitLab 16.1. If your training code is being run from a CI/CD job, GitLab can use that information to enhance -candidate metadata. To do so, add the following snippet to your training code within the run -execution context: - -```python -with mlflow.start_run(run_name=f"Candidate {index}"): - # Your training code - - # Start of snippet to be included - if os.getenv('GITLAB_CI'): - mlflow.set_tag('gitlab.CI_JOB_ID', os.getenv('CI_JOB_ID')) - # End of snippet to be included -``` +candidate metadata. To associate a candidate to a CI/CD job: + +1. In the [Project CI variables](../../../../ci/variables/index.md), include the following variables: + - `MLFLOW_TRACKING_URI`: `"<your gitlab endpoint>/api/v4/projects/<your project id>/ml/mlflow"` + - `MLFLOW_TRACKING_TOKEN`: `<your_access_token>` + +1. In your training code within the run execution context, add the following code snippet: + + ```python + with mlflow.start_run(run_name=f"Candidate {index}"): + # Your training code + + # Start of snippet to be included + if os.getenv('GITLAB_CI'): + mlflow.set_tag('gitlab.CI_JOB_ID', os.getenv('CI_JOB_ID')) + # End of snippet to be included + ``` ## Supported MLflow client methods and caveats diff --git a/gems/rspec_flaky/lib/rspec_flaky/report.rb b/gems/rspec_flaky/lib/rspec_flaky/report.rb index 3c8e1c933e1..cc213d336ae 100644 --- a/gems/rspec_flaky/lib/rspec_flaky/report.rb +++ b/gems/rspec_flaky/lib/rspec_flaky/report.rb @@ -2,6 +2,7 @@ require 'json' require 'time' +require 'fileutils' require_relative 'config' require_relative 'flaky_examples_collection' diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb index 180ccf21264..fabc02af70a 100644 --- a/lib/gitlab/i18n.rb +++ b/lib/gitlab/i18n.rb @@ -44,30 +44,30 @@ module Gitlab TRANSLATION_LEVELS = { 'bg' => 0, 'cs_CZ' => 0, - 'da_DK' => 31, - 'de' => 97, + 'da_DK' => 30, + 'de' => 99, 'en' => 100, 'eo' => 0, - 'es' => 30, + 'es' => 29, 'fil_PH' => 0, - 'fr' => 98, + 'fr' => 99, 'gl_ES' => 0, 'id_ID' => 0, 'it' => 1, - 'ja' => 98, - 'ko' => 18, + 'ja' => 99, + 'ko' => 17, 'nb_NO' => 22, 'nl_NL' => 0, 'pl_PL' => 3, - 'pt_BR' => 56, - 'ro_RO' => 82, + 'pt_BR' => 57, + 'ro_RO' => 80, 'ru' => 23, 'si_LK' => 10, 'tr_TR' => 9, 'uk' => 53, 'zh_CN' => 98, 'zh_HK' => 1, - 'zh_TW' => 99 + 'zh_TW' => 100 }.freeze private_constant :TRANSLATION_LEVELS diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 4cdc81b693a..2f0b9362ab9 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -53796,6 +53796,9 @@ msgstr "" msgid "ciReport|%{sameNum} same" msgstr "" +msgid "ciReport|%{scanner} detected %{atleastStart}at least%{atleastEnd} %{number} new potential %{vulnStr}" +msgstr "" + msgid "ciReport|%{scanner} detected %{number} new potential %{vulnStr}" msgstr "" diff --git a/scripts/remote_development/run-smoke-test-suite.sh b/scripts/remote_development/run-smoke-test-suite.sh index a48b66d31ab..0db57e04317 100755 --- a/scripts/remote_development/run-smoke-test-suite.sh +++ b/scripts/remote_development/run-smoke-test-suite.sh @@ -42,6 +42,7 @@ ee/spec/finders/remote_development/workspaces_finder_spec.rb \ ee/spec/graphql/types/query_type_spec.rb \ ee/spec/graphql/types/remote_development/workspace_type_spec.rb \ ee/spec/graphql/types/subscription_type_spec.rb \ +ee/spec/lib/remote_development/agent_config/main_integration_spec.rb \ ee/spec/lib/remote_development/unmatched_result_error_spec.rb \ ee/spec/lib/remote_development/workspaces/create/create_processor_spec.rb \ ee/spec/lib/remote_development/workspaces/create/devfile_processor_spec.rb \ diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh index 7ba63a4464a..af6c2ec5383 100755 --- a/scripts/review_apps/review-apps.sh +++ b/scripts/review_apps/review-apps.sh @@ -395,8 +395,9 @@ function verify_deploy() { mkdir -p curl-logs/ - local max_try_times=${GITLAB_VERIFY_DEPLOY_TIMEOUT_MINUTES} * 60 / 5 - for i in {1..max_try_times}; do # try for GITLAB_VERIFY_DEPLOY_TIMEOUT_MINUTES minutes, default 5 minutes + # By default, try for 5 minutes, with 5 of sleep between attempts + local max_try_times=$((${GITLAB_VERIFY_DEPLOY_TIMEOUT_MINUTES:-5} * 60 / 5)) + for i in {1..$max_try_times}; do local now=$(date '+%H:%M:%S') echo "[${now}] Verifying deployment at ${CI_ENVIRONMENT_URL}/users/sign_in" log_name="curl-logs/${now}.log" diff --git a/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js b/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js index fd2220a20d2..f590cff0312 100644 --- a/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js +++ b/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js @@ -6,6 +6,7 @@ import { GlFormGroup, GlModal, GlSprintf, + GlSkeletonLoader, } from '@gitlab/ui'; import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; @@ -77,6 +78,7 @@ describe('DependencyProxyApp', () => { const findFormInputGroup = () => wrapper.findComponent(GlFormInputGroup); const findProxyCountText = () => wrapper.findByTestId('proxy-count'); const findManifestList = () => wrapper.findComponent(ManifestsList); + const findLoader = () => wrapper.findComponent(GlSkeletonLoader); const findClearCacheDropdownList = () => wrapper.findComponent(GlDropdown); const findClearCacheModal = () => wrapper.findComponent(GlModal); const findClearCacheAlert = () => wrapper.findComponent(GlAlert); @@ -100,9 +102,16 @@ describe('DependencyProxyApp', () => { describe('when the dependency proxy is available', () => { describe('when is loading', () => { - it('does not render a form group with label', () => { + beforeEach(() => { createComponent(); + }); + + it('renders loading component & sets loading prop', () => { + expect(findLoader().exists()).toBe(true); + expect(findManifestList().props('loading')).toBe(true); + }); + it('does not render a form group with label', () => { expect(findFormGroup().exists()).toBe(false); }); }); @@ -191,26 +200,58 @@ describe('DependencyProxyApp', () => { }); }); - it('prev-page event on list fetches the previous page', async () => { - findManifestList().vm.$emit('prev-page'); - await waitForPromises(); + describe('prev-page event on list', () => { + beforeEach(() => { + findManifestList().vm.$emit('prev-page'); + }); + + describe('while loading', () => { + it('does not render loading component & sets loading prop', () => { + expect(findLoader().exists()).toBe(false); + expect(findManifestList().props('loading')).toBe(true); + }); + + it('renders form group with label', () => { + expect(findFormGroup().exists()).toBe(true); + }); + }); - expect(resolver).toHaveBeenCalledWith({ - before: pagination().startCursor, - first: null, - fullPath: provideDefaults.groupPath, - last: GRAPHQL_PAGE_SIZE, + it('list fetches the previous page', async () => { + await waitForPromises(); + + expect(resolver).toHaveBeenCalledWith({ + before: pagination().startCursor, + first: null, + fullPath: provideDefaults.groupPath, + last: GRAPHQL_PAGE_SIZE, + }); }); }); - it('next-page event on list fetches the next page', async () => { - findManifestList().vm.$emit('next-page'); - await waitForPromises(); + describe('next-page event on list', () => { + beforeEach(() => { + findManifestList().vm.$emit('next-page'); + }); - expect(resolver).toHaveBeenCalledWith({ - after: pagination().endCursor, - first: GRAPHQL_PAGE_SIZE, - fullPath: provideDefaults.groupPath, + describe('while loading', () => { + it('does not render loading component & sets loading prop', () => { + expect(findLoader().exists()).toBe(false); + expect(findManifestList().props('loading')).toBe(true); + }); + + it('renders form group with label', () => { + expect(findFormGroup().exists()).toBe(true); + }); + }); + + it('fetches the next page', async () => { + await waitForPromises(); + + expect(resolver).toHaveBeenCalledWith({ + after: pagination().endCursor, + first: GRAPHQL_PAGE_SIZE, + fullPath: provideDefaults.groupPath, + }); }); }); diff --git a/spec/models/integrations/microsoft_teams_spec.rb b/spec/models/integrations/microsoft_teams_spec.rb index f1d9071d232..4f5b4daad42 100644 --- a/spec/models/integrations/microsoft_teams_spec.rb +++ b/spec/models/integrations/microsoft_teams_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Integrations::MicrosoftTeams do +RSpec.describe Integrations::MicrosoftTeams, feature_category: :integrations do it_behaves_like "chat integration", "Microsoft Teams" do let(:client) { ::MicrosoftTeams::Notifier } let(:client_arguments) { webhook_url } diff --git a/workhorse/.tool-versions b/workhorse/.tool-versions index e8249f49e4f..bf7f6cc9184 100644 --- a/workhorse/.tool-versions +++ b/workhorse/.tool-versions @@ -1 +1 @@ -golang 1.20.5 +golang 1.20.6 |