Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-05-07 09:09:45 +00:00
parent 1f956dde28
commit aaeaab23bf
28 changed files with 327 additions and 316 deletions

View File

@ -851,7 +851,7 @@ export default {
<gl-link
v-if="issuable.state === $options.STATUS_OPEN && isMergeRequestBroken(issuable)"
v-gl-tooltip
:href="issuable.webUrl"
:href="issuable.webPath"
:title="__('Cannot be merged automatically')"
data-testid="merge-request-cannot-merge"
>

View File

@ -12,7 +12,7 @@ fragment MergeRequestFragment on MergeRequest {
upvotes
resolvedDiscussionsCount @include(if: $isSignedIn)
resolvableDiscussionsCount @include(if: $isSignedIn)
webUrl
webPath
assignees @skip(if: $hideUsers) {
nodes {
...User

View File

@ -1,10 +1,9 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
import { engineeringNotation } from '@gitlab/ui/src/utils/number_utils';
import { GlLineChart } from '@gitlab/ui/dist/charts';
import { s__ } from '~/locale';
import { localeDateFormat } from '~/lib/utils/datetime/locale_dateformat';
import { formatPipelineDuration } from '../format_utils';
import { formatPipelineDuration, formatPipelineDurationForAxis } from '../format_utils';
export default {
components: {
@ -55,12 +54,7 @@ export default {
type: 'value',
axisLabel: {
formatter: (seconds) => {
const minutes = seconds / 60;
// using engineering notation for small amounts is strange, as we'd render "milliminutes"
if (minutes < 1) {
return minutes.toFixed(2).replace(/\.?0*$/, '');
}
return engineeringNotation(minutes, 2);
return formatPipelineDurationForAxis(seconds);
},
},
},

View File

@ -1,3 +1,4 @@
import { engineeringNotation } from '@gitlab/ui/src/utils/number_utils';
import { SUPPORTED_FORMATS, getFormatter } from '~/lib/utils/unit_format';
import { stringifyTime, parseSeconds } from '~/lib/utils/datetime/date_format_utility';
import { formatNumber } from '~/locale';
@ -34,3 +35,15 @@ export const formatPipelineDuration = (seconds) => {
}
return '-';
};
export const formatPipelineDurationForAxis = (seconds) => {
if (!Number.isFinite(seconds)) {
return '-';
}
const minutes = seconds / 60;
// using engineering notation for small amounts is strange, as we'd render "milliminutes"
if (minutes < 1) {
return minutes.toFixed(2).replace(/\.?0*$/, '');
}
return engineeringNotation(minutes, 2);
};

View File

@ -2,6 +2,9 @@
module EventForward
class EventForwardController < BaseActionController
DEDICATED_SUFFIX = 'dedicated'
SELF_MANAGED_SUFFIX = 'sm'
def forward
if ::Feature.enabled?(:collect_product_usage_events, :instance)
process_events
@ -25,14 +28,32 @@ module EventForward
end
events_to_forward.each do |event|
update_app_id(event)
tracker.emit_event_payload(event)
end
logger.info("Enqueued events for forwarding. Count: #{events_to_forward.size}")
end
def update_app_id(event)
app_id = event['aid']
return unless app_id
return if app_id.ends_with?(suffix)
event['aid'] = "#{app_id}#{suffix}"
end
def logger
@logger ||= EventForward::Logger.build
end
def suffix
@suffix ||= if ::Gitlab::CurrentSettings.gitlab_dedicated_instance?
"_#{DEDICATED_SUFFIX}"
else
"_#{SELF_MANAGED_SUFFIX}"
end
end
end
end

View File

@ -568,6 +568,7 @@ module ProjectsHelper
cicd_catalog_path: cicd_catalog_path,
is_project_archived: project.archived.to_s,
is_project_empty: project.empty_repo?.to_s,
is_project_marked_for_deletion: project.marked_for_deletion?.to_s,
project_avatar: project.avatar_url,
project_name: project.name,
project_id: project.id,

View File

@ -1184,6 +1184,12 @@ class Group < Namespace
::Clusters::Agent.for_projects(all_projects)
end
def pending_delete?
return false unless deletion_schedule
deletion_schedule.marked_for_deletion_on.future?
end
private
def feature_flag_enabled_for_self_or_ancestor?(feature_flag, type: :development)

View File

@ -1,5 +0,0 @@
= render Pajamas::ButtonComponent.new(href: project,
method: :delete,
category: :tertiary,
icon: 'remove',
button_options: { class: 'has-tooltip', title: _('Delete'), data: { confirm: remove_project_message(project), confirm_btn_variant: 'danger' } })

View File

@ -10,5 +10,6 @@ description: When a project is first forked, a row is created in this table. Als
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3098
milestone: '10.1'
gitlab_schema: gitlab_main_cell
sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/490480
sharding_key:
organization_id: organizations
table_size: small

View File

@ -18,4 +18,4 @@ desired_sharding_key:
sharding_key: target_project_id
belongs_to: merge_request
desired_sharding_key_migration_job_name: BackfillMergeRequestAssignmentEventsProjectId
table_size: small
table_size: medium

View File

@ -10,4 +10,4 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/31b0e53015e38e5
milestone: '8.7'
gitlab_schema: gitlab_main_cell
sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/514596
table_size: small
table_size: medium

View File

@ -344,6 +344,8 @@ If you have any `geo_secondary[]` configuration options enabled in your `gitlab.
file, comment them out or remove them, and then [reconfigure GitLab](../../restart_gitlab.md#reconfigure-a-linux-package-installation)
for the changes to take effect.
At this point, your promoted site is a normal GitLab site without Geo configured. Optionally, you can [bring the old site back as a secondary](bring_primary_back.md#configure-the-former-primary-site-to-be-a-secondary-site).
## Promoting secondary Geo replica in multi-secondary configurations
If you have more than one **secondary** site and you need to promote one of them, we suggest you follow

View File

@ -2,7 +2,7 @@
stage: Verify
group: Pipeline Execution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
title: Use kaniko to build Docker images
title: Use kaniko to build Docker images (removed)
---
{{< details >}}
@ -12,248 +12,6 @@ title: Use kaniko to build Docker images
{{< /details >}}
[kaniko](https://github.com/GoogleContainerTools/kaniko) is a tool to build
container images from a Dockerfile, inside a container or Kubernetes cluster.
kaniko solves two problems with using the
[Docker-in-Docker build](using_docker_build.md#use-docker-in-docker)
method:
- Docker-in-Docker requires [privileged mode](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities)
to function, which is a significant security concern.
- Docker-in-Docker generally incurs a performance penalty and can be slow.
## Prerequisites
To use kaniko with GitLab, [a runner](https://docs.gitlab.com/runner/) with one
of the following executors is required:
- [Kubernetes](https://docs.gitlab.com/runner/executors/kubernetes/).
- [Docker](https://docs.gitlab.com/runner/executors/docker.html).
- [Docker Machine](https://docs.gitlab.com/runner/executors/docker_machine.html).
## Authentication with registries
Authentication is required when building and pushing images with kaniko:
- For the GitLab container registry, authentication happens automatically without any manual configuration.
- For pulling images through the GitLab dependency proxy, additional configuration is required.
For more information on how authentication works, see [access an image from a private container registry](using_docker_images.md#access-an-image-from-a-private-container-registry).
For more information on authentication with other registries,
see [pushing to different registries](https://github.com/GoogleContainerTools/kaniko?tab=readme-ov-file#pushing-to-different-registries).
### Authenticate with the container registry
When pushing to the GitLab container registry, authentication happens automatically without requiring any manual configuration:
- GitLab CI/CD generates authentication credentials from the `CI_REGISTRY`, `CI_REGISTRY_USER`, and `CI_REGISTRY_PASSWORD` predefined CI/CD variables.
- These credentials are stored in the `DOCKER_AUTH_CONFIG` environment variable as a JSON object that contains base64-encoded authentication strings:
```json
{
"auths": {
"registry.example.com:5000": {
"auth": "bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ="
}
}
}
```
- The contents of the `DOCKER_AUTH_CONFIG` variable is automatically copied from the `$HOME/.docker/config.json` file before kaniko runs.
- kaniko automatically detects and uses this file for authentication with the registry.
- If the `DOCKER_AUTH_CONFIG` variable is empty or misconfigured, authentication fails.
See [debug authentication issues](#debug-authentication-issues) for troubleshooting steps.
{{< alert type="note" >}}
The configuration file is hidden when inspecting the container because GitLab CI/CD manages it internally.
Manually creating or modifying this file might cause authentication issues.
{{< /alert >}}
### Authenticate with the dependency proxy
If you need to pull images through the dependency proxy,
you must add the corresponding CI/CD variables for authentication to the `config.json` file:
```yaml
build:
script:
# Create a config.json with authentication for both the GitLab container registry and dependency proxy
- |
echo "{
\"auths\": {
\"${CI_REGISTRY}\": {
\"auth\": \"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"
},
\"$(echo -n $CI_DEPENDENCY_PROXY_SERVER | awk -F[:] '{print $1}')\": {
\"auth\": \"$(printf "%s:%s" ${CI_DEPENDENCY_PROXY_USER} "${CI_DEPENDENCY_PROXY_PASSWORD}" | base64 | tr -d '\n')\"
}
}
}" > /kaniko/.docker/config.json
```
This configuration strips the port, for example `:443`, from `CI_DEPENDENCY_PROXY_SERVER` so you don't have to include it when referencing images.
For more information, see [authenticate within CI/CD](../../user/packages/dependency_proxy/_index.md#authenticate-within-cicd).
## Build and push an image
When building an image with kaniko and GitLab CI/CD, you should be aware of a
few important details:
- The kaniko debug image is recommended (`gcr.io/kaniko-project/executor:debug`)
because it has a shell, and a shell is required for an image to be used with
GitLab CI/CD.
- The entrypoint needs to be [overridden](using_docker_images.md#override-the-entrypoint-of-an-image),
otherwise the build script doesn't run.
In the following example, kaniko is used to:
1. Build a Docker image.
1. Push it to [GitLab container registry](../../user/packages/container_registry/_index.md).
The job runs only when a tag is pushed.
In the last step, kaniko uses the `Dockerfile` under the
root directory of the project, builds the Docker image and pushes it to the
project's container registry while tagging it with the Git tag:
```yaml
build:
stage: build
image:
name: gcr.io/kaniko-project/executor:v1.23.2-debug
entrypoint: [""]
script:
- /kaniko/executor
--context "${CI_PROJECT_DIR}"
--dockerfile "${CI_PROJECT_DIR}/Dockerfile"
--destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}"
rules:
- if: $CI_COMMIT_TAG
```
### Build an image behind a proxy
If you use a custom GitLab Runner behind an http(s) proxy, kaniko needs to be set
up accordingly. This means:
- Passing the `http_proxy` environment variables as build arguments so the Dockerfile
instructions can use the proxy when building the image.
The previous example can be extended as follows:
```yaml
build:
stage: build
variables:
http_proxy: <your-proxy>
https_proxy: <your-proxy>
no_proxy: <your-no-proxy>
image:
name: gcr.io/kaniko-project/executor:v1.23.2-debug
entrypoint: [""]
script:
- /kaniko/executor
--context "${CI_PROJECT_DIR}"
--build-arg http_proxy=$http_proxy
--build-arg https_proxy=$https_proxy
--build-arg no_proxy=$no_proxy
--dockerfile "${CI_PROJECT_DIR}/Dockerfile"
--destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}"
rules:
- if: $CI_COMMIT_TAG
```
## Build a multi-arch image
You can build [multi-arch images](https://www.docker.com/blog/multi-arch-build-and-images-the-simple-way/)
inside a container by using [`manifest-tool`](https://github.com/estesp/manifest-tool).
For a detailed guide on how to build a multi-arch image, see
[Building a multi-arch container image in unprivileged containers](https://blog.siemens.com/2022/07/building-a-multi-arch-container-image-in-unprivileged-containers/).
## Use a registry with a custom certificate
When trying to push to a Docker registry that uses a certificate that is signed
by a custom CA, you might get the following error:
```shell
$ /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --no-push
INFO[0000] Downloading base image registry.gitlab.example.com/group/docker-image
error building image: getting stage builder for stage 0: Get https://registry.gitlab.example.com/v2/: x509: certificate signed by unknown authority
```
This can be solved by adding your CA's certificate to the kaniko certificate
store:
```yaml
before_script:
- |
echo "-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----" >> /kaniko/ssl/certs/ca-certificates.crt
```
## Video walkthrough of a working example
The [Least Privilege Container Builds with Kaniko on GitLab](https://www.youtube.com/watch?v=d96ybcELpFs)
video is a walkthrough of the [Kaniko Docker Build](https://gitlab.com/guided-explorations/containers/kaniko-docker-build)
Guided Exploration project pipeline. It was tested on:
- [GitLab.com instance runners](../runners/_index.md)
- [The Kubernetes runner executor](https://docs.gitlab.com/runner/executors/kubernetes/)
The example can be copied to your own group or instance for testing. More details
on what other GitLab CI patterns are demonstrated are available at the project page.
## Troubleshooting
### Debug authentication issues
To debug authentication issues with kaniko:
- [Enable debug logging](../variables/_index.md#enable-debug-logging) by adding `CI_DEBUG_TRACE: "true"` to your job variables.
{{< alert type="warning" >}}
Debug logging exposes sensitive information including authentication tokens in your job logs.
Enable it temporarily and only when needed for troubleshooting.
{{< /alert >}}
In the debug logs, examine the `DOCKER_AUTH_CONFIG` variable.
- To isolate authentication issues, [configure credentials per job](using_docker_images.md#configure-a-job).
- If you're using Docker-in-Docker, see [authenticate with registry in Docker-in-Docker](authenticate_registry.md).
### 403 error: "error checking push permissions"
If you receive this error, it might be due to an outside proxy. Setting the `http_proxy`
and `https_proxy` [environment variables](../../administration/packages/container_registry_troubleshooting.md#running-the-docker-daemon-with-a-proxy)
can fix the problem.
### Error: kaniko should only be run inside of a container
There is a known incompatibility introduced by Docker Engine 20.10
When the host uses Docker Engine 20.10 or newer, then the `gcr.io/kaniko-project/executor:debug` image in a version
older than v1.9.0 does not work as expected.
When you try to build the image, Kaniko fails with:
```plaintext
kaniko should only be run inside of a container, run with the --force flag if you are sure you want to continue
```
To resolve this issue, update the `gcr.io/kaniko-project/executor:debug` container to version at least v1.9.0,
for example `gcr.io/kaniko-project/executor:v1.23.2-debug`.
The opposite configuration (`gcr.io/kaniko-project/executor:v1.23.2-debug` image and Docker Engine
on the host in version 19.06.x or older) works without problems. For the best strategy, you should
frequently test and update job environment versions to the newest. This brings new features, improved
security and - for this specific case - makes the upgrade on underlying Docker Engine on the runner's
host transparent for the job.
[kaniko](https://github.com/GoogleContainerTools/kaniko) is no longer a maintained project.
For more information, see [issue 3348](https://github.com/GoogleContainerTools/kaniko/issues/3348).
Use [Docker to build Docker images](using_docker_build.md), [Buildah](using_docker_build.md#buildah-example), [Podman to run Docker commands](https://docs.gitlab.com/runner/executors/docker/#use-podman-to-run-docker-commands), or [Podman with GitLab Runner on Kubernetes](https://docs.gitlab.com/runner/executors/kubernetes/use_podman_with_kubernetes/) instead.

View File

@ -2886,7 +2886,6 @@ test-job:
- [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27919) in GitLab 16.7. Requires GitLab Runner 16.7 or later.
- `user` input option [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/137907) in GitLab 16.8.
- `user` input option [applied to the Kubernetes executor](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/5469) in GitLab 17.11.
{{< /history >}}
@ -2921,6 +2920,50 @@ arm-sql-job:
- `image:docker:platform` maps to the [`docker pull --platform` option](https://docs.docker.com/reference/cli/docker/image/pull/#options).
- `image:docker:user` maps to the [`docker run --user` option](https://docs.docker.com/reference/cli/docker/container/run/#options).
#### `image:kubernetes`
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/38451) in GitLab 18.0. Requires GitLab Runner 17.11 or later.
- `user` input option [introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/5469) in GitLab Runner 17.11.
- `user` input option [extended to support `uid:gid` format](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/5540) in GitLab 18.0.
{{< /history >}}
Use `image:kubernetes` to pass options to the GitLab Runner [Kubernetes executor](https://docs.gitlab.com/runner/executors/kubernetes/).
This keyword does not work with other executor types.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
[`default` section](#default).
**Supported values**:
A hash of options for the Kubernetes executor, which can include:
- `user`: Specify the username or UID to use when the container runs. You can also use it to set GID by using the `UID:GID` format.
**Example of `image:kubernetes` with only UID**:
```yaml
arm-sql-job:
script: echo "Run sql tests"
image:
name: super/sql:experimental
kubernetes:
user: "1001"
```
**Example of `image:kubernetes` with both UID and GID**:
```yaml
arm-sql-job:
script: echo "Run sql tests"
image:
name: super/sql:experimental
kubernetes:
user: "1001:1001"
```
#### `image:pull_policy`
{{< history >}}
@ -5399,6 +5442,51 @@ arm-sql-job:
- `services:docker:platform` maps to the [`docker pull --platform` option](https://docs.docker.com/reference/cli/docker/image/pull/#options).
- `services:docker:user` maps to the [`docker run --user` option](https://docs.docker.com/reference/cli/docker/container/run/#options).
#### `services:kubernetes`
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/38451) in GitLab 18.0. Requires GitLab Runner 17.11 or later.
- `user` input option [introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/5469) in GitLab Runner 17.11.
- `user` input option [extended to support `uid:gid` format](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/5540) in GitLab 18.0.
{{< /history >}}
Use `services:kubernetes` to pass options to the GitLab Runner [Kubernetes executor](https://docs.gitlab.com/runner/executors/kubernetes/).
**Keyword type**: Job keyword. You can use it only as part of a job or in the
[`default` section](#default).
**Supported values**:
A hash of options for the Kubernetes executor, which can include:
- `user`: Specify the username or UID to use when the container runs. You can also use it to set GID by using the `UID:GID` format.
**Example of `services:kubernetes` with only UID**:
```yaml
arm-sql-job:
script: echo "Run sql tests"
image: ruby:2.6
services:
- name: super/sql:experimental
kubernetes:
user: "1001"
```
**Example of `services:kubernetes` with both UID and GID**:
```yaml
arm-sql-job:
script: echo "Run sql tests"
image: ruby:2.6
services:
- name: super/sql:experimental
kubernetes:
user: "1001:1001"
```
#### `services:pull_policy`
{{< history >}}

View File

@ -43,6 +43,17 @@ To configure the Language Server to use a proxy:
## Troubleshooting
### Update your editor extension
The Language Server is bundled with each editor extension for GitLab. To ensure you have the latest features and bug fixes
available, update to the latest version of your extension:
- Update instructions [for Eclipse](../eclipse/_index.md#update-the-plugin)
- Update instructions [for JetBrains IDEs](../jetbrains_ide/_index.md#update-the-extension)
- Update instructions [for Neovim](../neovim/_index.md#update-the-extension)
- Update instructions [for Visual Studio](../visual_studio/_index.md#update-the-extension)
- Update instructions [for Visual Studio Code](../visual_studio_code/_index.md#update-the-extension)
### Enable proxy authentication
You might encounter a `407 Access Denied (authentication_failed)` error when using an authenticated proxy:

View File

@ -42,7 +42,7 @@ After you set up everything, the two teams will be able to hand off issues from
1. A product designer on the UX team:
1. Checks the `Workflow::Ready for design` list on the **UX workflow** board and decides to work on the profile page redesign.
![Issue board called "UX workflow" with three columns and three issues](img/ux_board_filled_v16_0.png)
!["UX workflow" issue board with three issues across three workflow columns](img/ux_board_filled_v16_0.png)
1. Assigns themselves to the **Redesign user profile page** issue.
1. Drags the issue card to the `Workflow::Design` list. The previous workflow label is automatically removed.
@ -53,7 +53,7 @@ After you set up everything, the two teams will be able to hand off issues from
1. A developer on the Frontend team:
1. Checks the `Workflow::Ready for development` list on the **Frontend workflow** board and chooses an issue to work on.
![Issue board called "Frontend workflow" with three columns and three issues](img/frontend_board_filled_v16_0.png)
!["Frontend workflow" issue board with two issues from "UX workflow" board in "Ready for development" column](img/frontend_board_filled_v16_0.png)
1. Assigns themselves to the **Redesign user profile page** issue.
1. Drags the issue card to the `Workflow::In development` list. The previous workflow label is automatically removed.
@ -142,7 +142,7 @@ To create the **UX workflow** issue board:
1. Select **Add to board**.
1. Repeat the previous step for labels `Workflow::Design` and `Workflow::Ready for development`.
![Issue board called "UX workflow" with three columns and no issues](img/ux_board_empty_v16_0.png)
![Empty "UX workflow" issue board with three workflow columns](img/ux_board_empty_v16_0.png)
To create the **Frontend workflow** board:
@ -159,7 +159,7 @@ To create the **Frontend workflow** board:
1. Select **Add to board**.
1. Repeat the previous step for labels `Workflow::In development` and `Workflow::Complete`.
![Issue board called "Frontend workflow" with three columns and no issues](img/frontend_board_empty_v16_0.png)
![Empty "Frontend workflow" issue board with three workflow columns](img/frontend_board_empty_v16_0.png)
For now, lists in both your boards should be empty. Next, you'll populate them with some issues.

View File

@ -157,7 +157,7 @@ To prioritize a label:
1. Prioritize all the labels you created previously.
Make sure that labels of higher priority and severity are higher on the list than the lower values.
![List of priority labels](img/priority_labels_v16_3.png)
![List of eleven prioritized scoped labels](img/priority_labels_v16_3.png)
## Create an issue triage board
@ -221,7 +221,7 @@ Your first triage issue board is ready!
Try it out by dragging some issues from the **Open** list to one of the label lists to add one of
the severity labels.
![Triage issue board with example issues](img/triage_board_v16_3.png)
![Issue board with unlabeled issues and prioritized "severity" labels for labeling issues](img/triage_board_v16_3.png)
## Next steps
@ -242,7 +242,7 @@ Next, you can:
- Create policies that help automate issue triage in a project with the [`gitlab-triage` gem](https://gitlab.com/gitlab-org/ruby/gems/gitlab-triage).
Generate summary reports with heatmaps like the following:
![Example triage report heatmap](img/triage_report_v16_3.png)
![Diagonal heatmap for issues with "priority" and "severity" labels](img/triage_report_v16_3.png)
To learn more about issue triage at GitLab, see [Issue Triage](https://handbook.gitlab.com/handbook/engineering/infrastructure/engineering-productivity/issue-triage/)
and [Triage Operations](https://handbook.gitlab.com/handbook/engineering/infrastructure/engineering-productivity/triage-operations/).

View File

@ -168,7 +168,7 @@ To prioritize labels:
1. Prioritize all the labels you previously created.
Make sure that labels of higher priority and severity are higher on the list than those of lower values.
![List of priority labels](img/priority_labels_v16_3.png)
![List of eleven prioritized scoped labels](img/priority_labels_v16_3.png)
## Create a group issue triage board
@ -238,7 +238,7 @@ Your first triage issue board is ready!
Try it out by dragging some issues from the **Open** list to one of the label lists to add one of
the severity labels.
![Triage issue board with example issues](img/triage_board_v16_3.png)
![Issue board with unlabeled issues and prioritized "severity" labels for labeling issues](img/triage_board_v16_3.png)
## Next steps
@ -259,7 +259,7 @@ Next, you can:
- Create policies that help automate issue triage in a project with the [`gitlab-triage` gem](https://gitlab.com/gitlab-org/ruby/gems/gitlab-triage).
Generate summary reports with heatmaps like the following:
![Example triage report heatmap](img/triage_report_v16_3.png)
![Diagonal heatmap for issues with "priority" and "severity" labels](img/triage_report_v16_3.png)
To learn more about issue triage at GitLab, see [Issue Triage](https://handbook.gitlab.com/handbook/engineering/infrastructure/engineering-productivity/issue-triage/)
and [Triage Operations](https://handbook.gitlab.com/handbook/engineering/infrastructure/engineering-productivity/triage-operations/).

View File

@ -55,6 +55,7 @@ To see how your language is best supported, review the
{{< history >}}
- Python support [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/301111) in GitLab 17.9.
- .Net/C# support [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/372243) in GitLab 18.0.
{{< /history >}}
@ -65,6 +66,7 @@ in your `.gitlab-ci.yml` file. The component supports these languages:
- TypeScript or JavaScript.
- Java 8, 11, 17, and 21.
- Python
- .Net/C#
To contribute more languages to the component, open a merge request in the
[Code intelligence component project](https://gitlab.com/components/code-intelligence).

View File

@ -249,16 +249,14 @@ To star a project:
{{< history >}}
- Default deletion behavior for projects on the Premium and Ultimate tier changed to [delayed project deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/389557) in GitLab 16.0.
- Default deletion behavior changed to delayed deletion on the Premium and Ultimate tier [on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/393622) and [on GitLab Self-Managed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119606) in GitLab 16.0.
- Default behavior [changed](https://gitlab.com/gitlab-org/gitlab/-/issues/389557) to delayed project deletion for Premium and Ultimate tiers on [GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/393622) and [GitLab Self-Managed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119606) in 16.0.
- Default behavior changed to delayed project deletion for [GitLab Free](https://gitlab.com/groups/gitlab-org/-/epics/17208) and [personal projects](https://gitlab.com/gitlab-org/gitlab/-/issues/536244) in 18.0.
{{< /history >}}
You can mark a project to be deleted.
After you delete a project:
- Projects in personal namespaces are deleted immediately.
- Projects in groups are deleted after a retention period.
After you delete a project for the first time, it enters a pending deletion state.
If you delete a project a second time, it is removed permanently.
Prerequisites:
@ -270,10 +268,10 @@ To delete a project:
1. On the left sidebar, select **Search or go to** and find your project.
1. Select **Settings > General**.
1. Expand **Advanced**.
1. In the **Delete this project** section, select **Delete project**.
1. In the **Delete project** section, select **Delete project**.
1. On the confirmation dialog, enter the project name and select **Yes, delete project**.
This action deletes the project and all associated resources (such as issues and merge requests).
This action marks the project for deletion and places it in a pending deletion state.
You can also [delete projects using the Rails console](troubleshooting.md#delete-a-project-using-console).
@ -285,6 +283,7 @@ You can also [delete projects using the Rails console](troubleshooting.md#delete
- [Disabled for projects in personal namespaces](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95495) in GitLab 15.3.
- Enabled delayed deletion by default and removed the option to delete immediately [on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/393622) and [on GitLab Self-Managed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119606) in GitLab 16.0.
- [Moved](https://gitlab.com/groups/gitlab-org/-/epics/17208) from GitLab Premium to GitLab Free in 18.0.
- [Enabled for projects in personal namespaces](https://gitlab.com/gitlab-org/gitlab/-/issues/536244) in GitLab 18.0.
{{< /history >}}
@ -292,7 +291,7 @@ Prerequisites:
- You must have the Owner role for the project.
Projects in a group (not a personal namespace) can be deleted after a delay period.
Projects enter a pending deletion state when deleted for the first time.
On GitLab Self-Managed instances, group administrators can define a deletion delay period of between 1 and 90 days.
On SaaS, there is a non-adjustable default retention period of seven days.
@ -327,14 +326,14 @@ If during this delayed deletion time you run a second deletion cycle, the projec
Prerequisites:
- You must have the Owner role for the project.
- The project must be [marked for deletion](#delete-a-project).
- The project must be [pending deletion](#delete-a-project).
To immediately delete a project marked for deletion:
To immediately delete a project pending deletion:
1. On the left sidebar, select **Search or go to** and find your project.
1. Select **Settings > General**.
1. Expand **Advanced**.
1. In the **Delete this project** section, select **Delete project**.
1. In the **Delete project** section, select **Delete project**.
1. On the confirmation dialog, enter the project name and select **Yes, delete project**.
### View projects pending deletion
@ -344,6 +343,7 @@ To immediately delete a project marked for deletion:
- [Changed](https://gitlab.com/groups/gitlab-org/-/epics/13066) tab label from "Pending deletion" to "Inactive" in GitLab 17.9 [with a flag](../../administration/feature_flags.md) named `your_work_projects_vue`. Disabled by default.
- [Changed tab label generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/465889) in GitLab 17.10. Feature flag `your_work_projects_vue` removed.
- [Moved](https://gitlab.com/groups/gitlab-org/-/epics/17208) from GitLab Premium to GitLab Free in 18.0.
- [Enabled for projects in personal namespaces](https://gitlab.com/gitlab-org/gitlab/-/issues/536244) in GitLab 18.0.
{{< /history >}}
@ -351,13 +351,7 @@ To view a list of all projects that are pending deletion:
1. On the left sidebar, select **Search or go to**.
1. Select **View all my projects**.
1. Select the **Pending deletion** tab.
{{< alert type="note" >}}
This tab appears as **Inactive** when the `your_work_projects_vue` feature flag is enabled.
{{< /alert >}}
1. Select the **Inactive** tab.
Each project in the list shows:
@ -368,17 +362,24 @@ Each project in the list shows:
## Restore a project
{{< history >}}
- [Moved](https://gitlab.com/groups/gitlab-org/-/epics/17208) from GitLab Premium to GitLab Free in 18.0.
- [Enabled for projects in personal namespaces](https://gitlab.com/gitlab-org/gitlab/-/issues/536244) in GitLab 18.0.
{{< /history >}}
Prerequisites:
- You must have the Owner role for the project.
- The project must be marked for deletion.
- The project must be [pending deletion](#delete-a-project).
To restore a project marked for deletion:
To restore a project pending deletion:
1. On the left sidebar, select **Search or go to** and find your project.
1. Select **Settings > General**.
1. Expand **Advanced**.
1. In the Restore project section, select **Restore project**.
1. In the **Restore project** section, select **Restore project**.
## Archive a project

View File

@ -306,7 +306,7 @@
"swagger-cli": "^4.0.4",
"tailwindcss": "^3.4.1",
"timezone-mock": "^1.0.8",
"vite": "^6.3.4",
"vite": "^6.3.5",
"vite-plugin-ruby": "^5.1.1",
"vue-loader-vue3": "npm:vue-loader@17.4.2",
"vue-test-utils-compat": "0.0.14",

View File

@ -25,7 +25,7 @@ export const getQueryResponse = {
upvotes: 3,
resolvedDiscussionsCount: 4,
resolvableDiscussionsCount: 4,
webUrl: 'project/-/merge_requests/789',
webPath: 'project/-/merge_requests/789',
assignees: {
nodes: [
{

View File

@ -54,12 +54,8 @@ describe('PipelineDurationChart', () => {
it('formats seconds in y axis labels as minutes', () => {
const { formatter } = findLineChart().props('option').yAxis.axisLabel;
expect(formatter(0)).toBe('0');
expect(formatter(1)).toBe('0.02');
expect(formatter(60)).toBe('1');
expect(formatter(3600)).toBe('60');
expect(formatter(60 * 10 ** 3)).toBe('1k');
expect(formatter(3600 * 10 ** 4)).toBe('600k');
});
it('displays chart with data', () => {

View File

@ -2,6 +2,7 @@ import {
formatPipelineCount,
formatPipelineCountPercentage,
formatPipelineDuration,
formatPipelineDurationForAxis,
} from '~/projects/pipelines/charts/format_utils';
const largeNumber = '12345678901234567890'; // Larger than MAX_SAFE_INTEGER
@ -71,4 +72,20 @@ describe('Stats formatting utilities', () => {
expect(formatPipelineDuration(input)).toBe(output);
});
});
describe('formatPipelineDurationForAxis', () => {
it.each`
input | output
${1} | ${'0.02'}
${60 * 10} | ${'10'}
${3600} | ${'60'}
${60 * 10 ** 3} | ${'1k'}
${3600 * 10 ** 4} | ${'600k'}
${0} | ${'0'}
${NaN} | ${'-'}
${'60000'} | ${'-'}
`('formats $input to "$output"', ({ input, output }) => {
expect(formatPipelineDurationForAxis(input)).toBe(output);
});
});
});

View File

@ -1292,6 +1292,26 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
it { is_expected.to include(expected) }
end
context "when project is not marked for deletion" do
before do
allow(project).to receive(:marked_for_deletion?).and_return(false)
end
subject { helper.home_panel_data_attributes }
it { is_expected.to include({ is_project_marked_for_deletion: "false" }) }
end
context "when project is marked for deletion" do
before do
allow(project).to receive(:marked_for_deletion?).and_return(true)
end
subject { helper.home_panel_data_attributes }
it { is_expected.to include({ is_project_marked_for_deletion: "true" }) }
end
end
shared_examples 'configure import method modal' do

View File

@ -3058,6 +3058,36 @@ RSpec.describe Group, feature_category: :groups_and_projects do
end
end
describe '#pending_delete?' do
context 'when deletion_schedule is not present' do
it 'returns false' do
expect(group).not_to be_pending_delete
end
end
context 'when deletion_schedule is present' do
context 'when marked_for_deletion_on is from past' do
before do
create(:group_deletion_schedule, group: group, marked_for_deletion_on: 1.day.ago)
end
it 'returns false' do
expect(group).not_to be_pending_delete
end
end
context 'when marked_for_deletion_on is in future' do
before do
create(:group_deletion_schedule, group: group, marked_for_deletion_on: 2.days.from_now)
end
it 'returns true' do
expect(group).to be_pending_delete
end
end
end
end
describe '#highest_group_member' do
let(:nested_group) { create(:group, parent: group) }
let(:nested_group_2) { create(:group, parent: nested_group) }

View File

@ -6,11 +6,13 @@ RSpec.describe EventForward::EventForwardController, feature_category: :product_
let(:tracker) { instance_double(Gitlab::Tracking::Destinations::Snowplow) }
let(:event_eligibility_checker) { instance_double(Gitlab::Tracking::EventEligibilityChecker) }
let(:logger) { instance_double(Logger) }
let(:event_1) { { 'se_ac' => 'event_1', 'aid' => 'app_id_1' } }
let(:event_2) { { 'se_ac' => 'event_2', 'aid' => 'app_id_2' } }
let(:payload) do
{
'data' => [
{ 'se_ac' => 'event_1' },
{ 'se_ac' => 'event_2' }
event_1,
event_2
]
}
end
@ -28,12 +30,36 @@ RSpec.describe EventForward::EventForwardController, feature_category: :product_
describe 'POST #forward' do
let(:request) { post event_forwarding_path, params: payload, as: :json }
it 'forwards each event to the Snowplow tracker' do
payload['data'].each do |event|
expect(tracker).to receive(:emit_event_payload).with(event)
context 'when instance type is dedicated' do
before do
stub_application_setting(gitlab_dedicated_instance?: true)
end
request
it 'forwards each event to the Snowplow tracker with updated app_id' do
payload['data'].each do |event|
expected_event = event.merge('aid' => "#{event['aid']}_dedicated")
expect(tracker).to receive(:emit_event_payload).with(expected_event)
end
request
end
end
context 'when instance type is self-managed' do
before do
stub_application_setting(gitlab_dedicated_instance?: false)
end
it 'forwards each event to the Snowplow tracker with updated app_id' do
payload['data'].each do |event|
expected_event = event.merge('aid' => "#{event['aid']}_sm")
expect(tracker).to receive(:emit_event_payload).with(expected_event)
end
request
end
end
it 'logs the number of enqueued events' do
@ -67,11 +93,14 @@ RSpec.describe EventForward::EventForwardController, feature_category: :product_
before do
allow(event_eligibility_checker).to receive(:eligible?).with("event_1").and_return(true)
allow(event_eligibility_checker).to receive(:eligible?).with("event_2").and_return(false)
stub_application_setting(gitlab_dedicated_instance?: true)
end
it 'forwards only eligible events to the Snowplow tracker' do
expect(tracker).to receive(:emit_event_payload).with(payload['data'][0])
expect(tracker).not_to receive(:emit_event_payload).with(payload['data'][1])
it 'forwards only eligible events to the Snowplow tracker with updated app_id' do
expected_event = event_1.merge('aid' => 'app_id_1_dedicated')
expect(tracker).to receive(:emit_event_payload).with(expected_event)
expect(tracker).not_to receive(:emit_event_payload).with(event_2)
request
end
@ -102,5 +131,31 @@ RSpec.describe EventForward::EventForwardController, feature_category: :product_
request
end
end
context 'when events have no app_id' do
let(:event_1) { { 'se_ac' => 'event_1' } }
let(:event_2) { { 'se_ac' => 'event_2' } }
it 'forwards each event to the Snowplow tracker' do
payload['data'].each do |event|
expect(tracker).to receive(:emit_event_payload).with(event)
end
request
end
end
context 'when app_id already has the suffix' do
let(:event_1) { { 'se_ac' => 'event_1', 'aid' => 'app_id_sm' } }
let(:event_2) { { 'se_ac' => 'event_2', 'aid' => 'app_id_sm' } }
it 'forwards each event to the Snowplow tracker' do
payload['data'].each do |event|
expect(tracker).to receive(:emit_event_payload).with(event)
end
request
end
end
end
end

View File

@ -15048,10 +15048,10 @@ vite-plugin-ruby@^5.1.1:
debug "^4.3.4"
fast-glob "^3.3.2"
vite@^6.3.4:
version "6.3.4"
resolved "https://registry.yarnpkg.com/vite/-/vite-6.3.4.tgz#d441a72c7cd9a93b719bb851250a4e6c119c9cff"
integrity sha512-BiReIiMS2fyFqbqNT/Qqt4CVITDU9M9vE+DKcVAsB+ZV0wvTKd+3hMbkpxz1b+NmEDMegpVbisKiAZOnvO92Sw==
vite@^6.3.5:
version "6.3.5"
resolved "https://registry.yarnpkg.com/vite/-/vite-6.3.5.tgz#fec73879013c9c0128c8d284504c6d19410d12a3"
integrity sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==
dependencies:
esbuild "^0.25.0"
fdir "^6.4.4"