diff --git a/data/deprecations/18-2-gitaly-bin-path.yml b/data/deprecations/18-2-gitaly-bin-path.yml
new file mode 100644
index 00000000000..70ff84e2f6a
--- /dev/null
+++ b/data/deprecations/18-2-gitaly-bin-path.yml
@@ -0,0 +1,16 @@
+- title: "`bin_path` and `use_bundled_binaries` configuration options in Gitaly"
+ removal_milestone: "19.0"
+ announcement_milestone: "18.2"
+ breaking_change: true
+ reporter: divya_gitlab
+ stage: data-access
+ issue_url: https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/9181
+ impact: low
+ scope: project
+ resolution_role: Admin
+ manual_task: false
+ body: |
+ Support for using `bin_path` and `use_bundled_binaries` configuration options in Gitaly is deprecated and will be
+ removed in GitLab 19.0.
+
+ The Git binaries provided by Gitaly will be the only supported way to execute Git.
diff --git a/doc/administration/postgresql/upgrading_os.md b/doc/administration/postgresql/upgrading_os.md
index 7277af63bd4..3bffc2c4a97 100644
--- a/doc/administration/postgresql/upgrading_os.md
+++ b/doc/administration/postgresql/upgrading_os.md
@@ -114,7 +114,7 @@ Disadvantages:
To update the system catalog to record the current collation version:
```sql
- ALTER COLLATION REFRESH VERSION;
+ ALTER DATABASE gitlabhq_production REFRESH COLLATION VERSION;
```
1. In all nodes, start GitLab.
@@ -154,7 +154,7 @@ Disadvantages:
To update the system catalog to record the current collation version:
```sql
- ALTER COLLATION REFRESH VERSION;
+ ALTER DATABASE REFRESH COLLATION VERSION;
```
1. If the secondary sites receive traffic from users, then let the read-replica databases catch up
@@ -190,7 +190,7 @@ different types of indexes were handled, see the blog post about
record the current collation version:
```sql
- ALTER COLLATION REFRESH VERSION;
+ ALTER DATABASE REFRESH COLLATION VERSION;
```
1. In all nodes, start GitLab.
@@ -231,7 +231,7 @@ Disadvantages:
record the current collation version:
```sql
- ALTER COLLATION REFRESH VERSION;
+ ALTER DATABASE REFRESH COLLATION VERSION;
```
1. The existing PostgreSQL streaming replication should replicate the reindex changes to the
diff --git a/doc/api/group_service_accounts.md b/doc/api/group_service_accounts.md
index 21ed374de5a..0a1d7929e39 100644
--- a/doc/api/group_service_accounts.md
+++ b/doc/api/group_service_accounts.md
@@ -1,415 +1,13 @@
---
-stage: Software Supply Chain Security
-group: Authentication
-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: Group service accounts API
+redirect_to: 'service_accounts.md'
+remove_date: '2025-10-16'
---
-{{< details >}}
+
-- Tier: Premium, Ultimate
-- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
+This document was moved to [another location](service_accounts.md).
-{{< /details >}}
-
-Use this API to interact with group service accounts. Group service accounts are owned by
-a specific top-level group and can inherit membership to subgroups and projects like a human user.
-For more information, see [service accounts](../user/profile/service_accounts.md).
-
-Prerequisites:
-
-- On GitLab.com, you must have the Owner role for the group.
-- On GitLab Self-Managed or GitLab Dedicated you must either:
- - Be an administrator for the instance.
- - Have the Owner role in a top-level group and be [allowed to create service accounts](../administration/settings/account_and_limit_settings.md#allow-top-level-group-owners-to-create-service-accounts).
-
-## List all group service accounts
-
-{{< history >}}
-
-- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/416729) in GitLab 17.1.
-
-{{< /history >}}
-
-Lists all service accounts in a specified top-level group.
-
-Use the `page` and `per_page` [pagination parameters](rest/_index.md#offset-based-pagination) to filter the results.
-
-```plaintext
-GET /groups/:id/service_accounts
-```
-
-Parameters:
-
-| Attribute | Type | Required | Description |
-| ---------- | -------------- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the target group](rest/_index.md#namespaced-paths). |
-| `order_by` | string | no | Orders list of users by `username` or `id`. Default is `id`. |
-| `sort` | string | no | Specifies sorting by `asc` or `desc`. Default is `desc`. |
-
-Example request:
-
-```shell
-curl --request GET --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/345/service_accounts"
-```
-
-Example response:
-
-```json
-[
-
- {
- "id": 57,
- "username": "service_account_group_345_",
- "name": "Service account user",
- "email": "service_account_group_345_@noreply.gitlab.example.com"
- },
- {
- "id": 58,
- "username": "service_account_group_346_",
- "name": "Service account user",
- "email": "service_account_group_346_@noreply.gitlab.example.com",
- "unconfirmed_email": "custom_email@example.com"
- }
-]
-```
-
-## Create a group service account
-
-{{< history >}}
-
-- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/407775) in GitLab 16.1.
-- `username` and `name` attributes [added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144841) in GitLab 16.10.
-- `email` attribute [added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/181456) in GitLab 17.9 [with a flag](../administration/feature_flags/_index.md) named `group_service_account_custom_email`.
-- `email` attribute [generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/186476) in GitLab 17.11. Feature flag `group_service_account_custom_email` removed.
-
-{{< /history >}}
-
-Creates a service account in a specified top-level group.
-
-{{< alert type="note" >}}
-
-This endpoint only works on top-level groups.
-
-{{< /alert >}}
-
-```plaintext
-POST /groups/:id/service_accounts
-```
-
-Supported attributes:
-
-| Attribute | Type | Required | Description |
-| ---------- | -------------- | -------- | ----------- |
-| `id` | integer/string | yes | ID or [URL-encoded path](rest/_index.md#namespaced-paths) of a top-level group. |
-| `name` | string | no | User account name. If not specified, uses `Service account user`. |
-| `username` | string | no | User account username. If not specified, generates a name prepended with `service_account_group_`. |
-| `email` | string | no | Email of the user account. If not specified, generates an email prepended with `service_account_group_`. Custom email addresses require confirmation, unless the group has a matching [verified domain](../user/enterprise_user/_index.md#verified-domains-for-groups) or email confirmation settings are [turned off](../administration/settings/sign_up_restrictions.md#confirm-user-email). |
-
-Example request:
-
-```shell
-curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/345/service_accounts" --data "email=custom_email@example.com"
-```
-
-Example response:
-
-```json
-{
- "id": 57,
- "username": "service_account_group_345_6018816a18e515214e0c34c2b33523fc",
- "name": "Service account user",
- "email": "custom_email@example.com"
-}
-```
-
-## Update a group service account
-
-{{< history >}}
-
-- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/182607/) in GitLab 17.10.
-- Add custom email address [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/196309) in GitLab 18.2.
-
-{{< /history >}}
-
-Updates a service account in a specified top-level group.
-
-{{< alert type="note" >}}
-
-This endpoint only works on top-level groups.
-
-{{< /alert >}}
-
-```plaintext
-PATCH /groups/:id/service_accounts/:user_id
-```
-
-Parameters:
-
-| Attribute | Type | Required | Description |
-| ---------- | -------------- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the target group](rest/_index.md#namespaced-paths). |
-| `user_id` | integer | yes | The ID of the service account. |
-| `name` | string | no | Name of the user. |
-| `username` | string | no | Username of the user. |
-| `email` | string | no | Email of the user account. Custom email addresses require confirmation, unless the group has a matching [verified domain](../user/enterprise_user/_index.md#verified-domains-for-groups) or email confirmation settings are [turned off](../administration/settings/sign_up_restrictions.md#confirm-user-email). |
-
-Example request:
-
-```shell
-curl --request PATCH --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/345/service_accounts/57" --data "name=Updated Service Account email=updated_email@example.com"
-```
-
-Example response:
-
-```json
-{
- "id": 57,
- "username": "service_account_group_345_6018816a18e515214e0c34c2b33523fc",
- "name": "Updated Service Account",
- "email": "service_account_group_345_@noreply.gitlab.example.com",
- "unconfirmed_email": "custom_email@example.com"
-}
-```
-
-## Delete a group service account
-
-{{< history >}}
-
-- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/416729) in GitLab 17.1.
-
-{{< /history >}}
-
-Deletes a service account from a specified top-level group.
-
-{{< alert type="note" >}}
-
-This endpoint only works on top-level groups.
-
-{{< /alert >}}
-
-```plaintext
-DELETE /groups/:id/service_accounts/:user_id
-```
-
-Parameters:
-
-| Attribute | Type | Required | Description |
-| ------------- | -------------- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the target group](rest/_index.md#namespaced-paths). |
-| `user_id` | integer | yes | The ID of a service account. |
-| `hard_delete` | boolean | no | If true, contributions that would usually be [moved to a Ghost User](../user/profile/account/delete_account.md#associated-records) are instead deleted, as well as groups owned solely by this service account. |
-
-Example request:
-
-```shell
-curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/345/service_accounts/181"
-```
-
-## List all personal access tokens for a group service account
-
-{{< history >}}
-
-- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/526924) in GitLab 17.11.
-
-{{< /history >}}
-
-Lists all personal access tokens for a service account in a top-level group.
-
-```plaintext
-GET /groups/:id/service_accounts/:user_id/personal_access_tokens
-```
-
-Supported attributes:
-
-| Attribute | Type | Required | Description |
-| ------------------ | ------------------- | -------- | ----------- |
-| `id` | integer/string | yes | ID or [URL-encoded path](rest/_index.md#namespaced-paths) of a top-level group. |
-| `user_id` | integer | yes | ID of service account. |
-| `created_after` | datetime (ISO 8601) | no | If defined, returns tokens created after the specified time. |
-| `created_before` | datetime (ISO 8601) | no | If defined, returns tokens created before the specified time. |
-| `expires_after` | date (ISO 8601) | no | If defined, returns tokens that expire after the specified time. |
-| `expires_before` | date (ISO 8601) | no | If defined, returns tokens that expire before the specified time. |
-| `last_used_after` | datetime (ISO 8601) | no | If defined, returns tokens last used after the specified time. |
-| `last_used_before` | datetime (ISO 8601) | no | If defined, returns tokens last used before the specified time. |
-| `revoked` | boolean | no | If `true`, only returns revoked tokens. |
-| `search` | string | no | If defined, returns tokens that include the specified value in the name. |
-| `sort` | string | no | If defined, sorts the results by the specified value. Possible values: `created_asc`, `created_desc`, `expires_asc`, `expires_desc`, `last_used_asc`, `last_used_desc`, `name_asc`, `name_desc`. |
-| `state` | string | no | If defined, returns tokens with the specified state. Possible values: `active` and `inactive`. |
-
-Example request:
-
-```shell
-curl --request GET \
- --header "PRIVATE-TOKEN: " \
- --url "https://gitlab.example.com/api/v4/groups/187/service_accounts/195/personal_access_tokens?sort=id_desc&search=token2b&created_before=2025-03-27"
-```
-
-Example response:
-
-```json
-[
- {
- "id": 187,
- "name": "service_accounts_token2b",
- "revoked": false,
- "created_at": "2025-03-26T14:42:51.084Z",
- "description": null,
- "scopes": [
- "api"
- ],
- "user_id": 195,
- "last_used_at": null,
- "active": true,
- "expires_at": null
- }
-]
-```
-
-Example of unsuccessful responses:
-
-- `401: Unauthorized`
-- `404 Group Not Found`
-
-## Create a personal access token for a group service account
-
-{{< history >}}
-
-- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/406781) in GitLab 16.1.
-
-{{< /history >}}
-
-Creates a personal access token for an existing service account in a specified top-level group.
-
-```plaintext
-POST /groups/:id/service_accounts/:user_id/personal_access_tokens
-```
-
-Parameters:
-
-| Attribute | Type | Required | Description |
-| ------------- | -------------- | -------- | ----------- |
-| `id` | integer/string | yes | ID or [URL-encoded path](rest/_index.md#namespaced-paths) of a top-level group. |
-| `user_id` | integer | yes | ID of service account. |
-| `name` | string | yes | Name of personal access token. |
-| `description` | string | no | Description of personal access token. |
-| `scopes` | array | yes | Array of approved scopes. For a list of possible values, see [Personal access token scopes](../user/profile/personal_access_tokens.md#personal-access-token-scopes). |
-| `expires_at` | date | no | Expiration date of the access token in ISO format (`YYYY-MM-DD`). If not specified, the date is set to the [maximum allowable lifetime limit](../user/profile/personal_access_tokens.md#access-token-expiration). |
-
-Example request:
-
-```shell
-curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/35/service_accounts/71/personal_access_tokens" --data "scopes[]=api,read_user,read_repository" --data "name=service_accounts_token"
-```
-
-Example response:
-
-```json
-{
- "id":6,
- "name":"service_accounts_token",
- "revoked":false,
- "created_at":"2023-06-13T07:47:13.900Z",
- "scopes":["api"],
- "user_id":71,
- "last_used_at":null,
- "active":true,
- "expires_at":"2024-06-12",
- "token":""
-}
-```
-
-## Revoke a personal access token for a group service account
-
-{{< history >}}
-
-- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/184287) in GitLab 17.11
-
-{{< /history >}}
-
-Revokes a personal access token for an existing service account in a specified top-level group.
-
-{{< alert type="note" >}}
-
-This endpoint only works on top-level groups.
-
-{{< /alert >}}
-
-```plaintext
-DELETE /groups/:id/service_accounts/:user_id/personal_access_tokens/:token_id
-```
-
-Parameters:
-
-| Attribute | Type | Required | Description |
-| ---------- | -------------- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the target group](rest/_index.md#namespaced-paths). |
-| `user_id` | integer | yes | The ID of the service account. |
-| `token_id` | integer | yes | The ID of the token. |
-
-Example request:
-
-```shell
-curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/35/service_accounts/71/personal_access_tokens/6"
-```
-
-If successful, returns `204: No Content`.
-
-Other possible responses:
-
-- `400: Bad Request` if not revoked successfully.
-- `401: Unauthorized` if the request is not authorized.
-- `403: Forbidden` if the request is not allowed.
-- `404: Not Found` if the access token does not exist.
-
-## Rotate a personal access token for a group service account
-
-{{< history >}}
-
-- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/406781) in GitLab 16.1.
-
-{{< /history >}}
-
-Rotates a personal access token for an existing service account in a specified top-level group. This creates a new token valid for one week and revokes any existing tokens.
-
-{{< alert type="note" >}}
-
-This endpoint only works on top-level groups.
-
-{{< /alert >}}
-
-```plaintext
-POST /groups/:id/service_accounts/:user_id/personal_access_tokens/:token_id/rotate
-```
-
-Parameters:
-
-| Attribute | Type | Required | Description |
-| ------------ | -------------- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the target group](rest/_index.md#namespaced-paths). |
-| `user_id` | integer | yes | The ID of the service account. |
-| `token_id` | integer | yes | The ID of the token. |
-| `expires_at` | date | no | Expiration date of the access token in ISO format (`YYYY-MM-DD`). [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/505671) in GitLab 17.9. If the token requires an expiration date, defaults to one week. If not required, defaults to the [maximum allowable lifetime limit](../user/profile/personal_access_tokens.md#access-token-expiration). |
-
-Example request:
-
-```shell
-curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/35/service_accounts/71/personal_access_tokens/6/rotate"
-```
-
-Example response:
-
-```json
-{
- "id":7,
- "name":"service_accounts_token",
- "revoked":false,
- "created_at":"2023-06-13T07:54:49.962Z",
- "scopes":["api"],
- "user_id":71,
- "last_used_at":null,
- "active":true,
- "expires_at":"2023-06-20",
- "token":""
-}
-```
+
+
+
+
diff --git a/doc/api/groups.md b/doc/api/groups.md
index c342cd95ab5..548a1ac1440 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -931,7 +931,7 @@ Example response:
{{< alert type="warning" >}}
This endpoint is scheduled for removal in GitLab 18.3 (August 11th, 2025).
-Use [`GET /groups/:id/saml_users`](#list-all-saml-users) and [`GET /groups/:id/service_accounts`](group_service_accounts.md#list-all-group-service-accounts) instead.
+Use [`GET /groups/:id/saml_users`](#list-all-saml-users) and [`GET /groups/:id/service_accounts`](service_accounts.md#list-all-group-service-accounts) instead.
{{< /alert >}}
diff --git a/doc/api/service_accounts.md b/doc/api/service_accounts.md
new file mode 100644
index 00000000000..808f24bb6e5
--- /dev/null
+++ b/doc/api/service_accounts.md
@@ -0,0 +1,567 @@
+---
+stage: Software Supply Chain Security
+group: Authentication
+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: Service accounts API
+---
+
+{{< details >}}
+
+- Tier: Premium, Ultimate
+- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
+
+{{< /details >}}
+
+Use this API to interact with [service accounts](../user/profile/service_accounts.md).
+
+You can also interact with service accounts through the [users API](users.md).
+
+## Instance service accounts
+
+{{< details >}}
+
+- Offering: GitLab Self-Managed, GitLab Dedicated
+
+{{< /details >}}
+
+Instance service accounts are available to an entire GitLab instance, but must still be added
+to groups and projects like a human user.
+
+Prerequisites:
+
+- You must have administrator access to the instance.
+
+### List all instance service accounts
+
+{{< history >}}
+
+- List all service accounts [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/416729) in GitLab 17.1.
+
+{{< /history >}}
+
+Lists all instance service accounts.
+
+Use the `page` and `per_page` [pagination parameters](rest/_index.md#offset-based-pagination) to filter the results.
+
+```plaintext
+GET /service_accounts
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+| ---------- | ------ | -------- | ----------- |
+| `order_by` | string | no | Attribute to order results by. Possible values: `id` or `username`. Default value: `id`. |
+| `sort` | string | no | Direction to sort results by. Possible values: `desc` or `asc`. Default value: `desc`. |
+
+Example request:
+
+```shell
+curl --request GET --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/service_accounts"
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 114,
+ "username": "service_account_33",
+ "name": "Service account user"
+ },
+ {
+ "id": 137,
+ "username": "service_account_34",
+ "name": "john doe"
+ }
+]
+```
+
+### Create an instance service account
+
+{{< history >}}
+
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/406782) in GitLab 16.1
+- `username` and `name` attributes [added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144841) in GitLab 16.10.
+- `email` attribute [added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/178689) in GitLab 17.9.
+
+{{< /history >}}
+
+Creates an instance service account.
+
+```plaintext
+POST /service_accounts
+POST /service_accounts?email=custom_email@gitlab.example.com
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+| ---------- | ------ | -------- | ----------- |
+| `name` | string | no | Name of the user. If not set, uses `Service account user`. |
+| `username` | string | no | Username of the user account. If undefined, generates a name prepended with `service_account_`. |
+| `email` | string | no | Email of the user account. If undefined, generates a no-reply email address. Custom email addresses require confirmation, unless the email confirmation settings are [turned off](../administration/settings/sign_up_restrictions.md#confirm-user-email). |
+
+Example request:
+
+```shell
+curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/service_accounts"
+```
+
+Example response:
+
+```json
+{
+ "id": 57,
+ "username": "service_account_6018816a18e515214e0c34c2b33523fc",
+ "name": "Service account user",
+ "email": "service_account_6018816a18e515214e0c34c2b33523fc@noreply.gitlab.example.com"
+}
+```
+
+If the email address defined by the `email` attribute is already in use by another user,
+returns a `400 Bad request` error.
+
+### Update an instance service account
+
+{{< history >}}
+
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/196309/) in GitLab 18.2.
+
+{{< /history >}}
+
+Updates a specified instance service account.
+
+```plaintext
+PATCH /service_accounts/:id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+|:-----------|:---------------|:---------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `id` | integer | yes | ID of the service account. |
+| `name` | string | no | Name of the user. |
+| `username` | string | no | Username of the user account. |
+| `email` | string | no | Email of the user account. Custom email addresses require confirmation, unless the email confirmation settings are [turned off](../administration/settings/sign_up_restrictions.md#confirm-user-email). |
+
+Example request:
+
+```shell
+curl --request PATCH --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/service_accounts/57" --data "name=Updated Service Account email=updated_email@example.com"
+```
+
+Example response:
+
+```json
+{
+ "id": 57,
+ "username": "service_account_6018816a18e515214e0c34c2b33523fc",
+ "name": "Updated Service Account",
+ "email": "service_account_@noreply.gitlab.example.com",
+ "unconfirmed_email": "custom_email@example.com"
+}
+```
+
+## Group service accounts
+
+Group service accounts are owned by a specific top-level group and can inherit membership to
+subgroups and projects like a human user.
+
+Prerequisites:
+
+- On GitLab.com, you must have the Owner role for the group.
+- On GitLab Self-Managed or GitLab Dedicated you must either:
+ - Be an administrator for the instance.
+ - Have the Owner role in a top-level group and be [allowed to create service accounts](../administration/settings/account_and_limit_settings.md#allow-top-level-group-owners-to-create-service-accounts).
+
+### List all group service accounts
+
+{{< history >}}
+
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/416729) in GitLab 17.1.
+
+{{< /history >}}
+
+Lists all service accounts in a specified top-level group.
+
+Use the `page` and `per_page` [pagination parameters](rest/_index.md#offset-based-pagination) to filter the results.
+
+```plaintext
+GET /groups/:id/service_accounts
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| ---------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the target group](rest/_index.md#namespaced-paths). |
+| `order_by` | string | no | Orders list of users by `username` or `id`. Default is `id`. |
+| `sort` | string | no | Specifies sorting by `asc` or `desc`. Default is `desc`. |
+
+Example request:
+
+```shell
+curl --request GET --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/345/service_accounts"
+```
+
+Example response:
+
+```json
+[
+
+ {
+ "id": 57,
+ "username": "service_account_group_345_",
+ "name": "Service account user",
+ "email": "service_account_group_345_@noreply.gitlab.example.com"
+ },
+ {
+ "id": 58,
+ "username": "service_account_group_346_",
+ "name": "Service account user",
+ "email": "service_account_group_346_@noreply.gitlab.example.com",
+ "unconfirmed_email": "custom_email@example.com"
+ }
+]
+```
+
+### Create a group service account
+
+{{< history >}}
+
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/407775) in GitLab 16.1.
+- `username` and `name` attributes [added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144841) in GitLab 16.10.
+- `email` attribute [added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/181456) in GitLab 17.9 [with a flag](../administration/feature_flags/_index.md) named `group_service_account_custom_email`.
+- `email` attribute [generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/186476) in GitLab 17.11. Feature flag `group_service_account_custom_email` removed.
+
+{{< /history >}}
+
+Creates a service account in a specified top-level group.
+
+{{< alert type="note" >}}
+
+This endpoint only works on top-level groups.
+
+{{< /alert >}}
+
+```plaintext
+POST /groups/:id/service_accounts
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+| ---------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | ID or [URL-encoded path](rest/_index.md#namespaced-paths) of a top-level group. |
+| `name` | string | no | User account name. If not specified, uses `Service account user`. |
+| `username` | string | no | User account username. If not specified, generates a name prepended with `service_account_group_`. |
+| `email` | string | no | Email of the user account. If not specified, generates an email prepended with `service_account_group_`. Custom email addresses require confirmation, unless the group has a matching [verified domain](../user/enterprise_user/_index.md#verified-domains-for-groups) or email confirmation settings are [turned off](../administration/settings/sign_up_restrictions.md#confirm-user-email). |
+
+Example request:
+
+```shell
+curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/345/service_accounts" --data "email=custom_email@example.com"
+```
+
+Example response:
+
+```json
+{
+ "id": 57,
+ "username": "service_account_group_345_6018816a18e515214e0c34c2b33523fc",
+ "name": "Service account user",
+ "email": "custom_email@example.com"
+}
+```
+
+### Update a group service account
+
+{{< history >}}
+
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/182607/) in GitLab 17.10.
+- Add custom email address [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/196309) in GitLab 18.2.
+
+{{< /history >}}
+
+Updates a service account in a specified top-level group.
+
+{{< alert type="note" >}}
+
+This endpoint only works on top-level groups.
+
+{{< /alert >}}
+
+```plaintext
+PATCH /groups/:id/service_accounts/:user_id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| ---------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the target group](rest/_index.md#namespaced-paths). |
+| `user_id` | integer | yes | The ID of the service account. |
+| `name` | string | no | Name of the user. |
+| `username` | string | no | Username of the user. |
+| `email` | string | no | Email of the user account. Custom email addresses require confirmation, unless the group has a matching [verified domain](../user/enterprise_user/_index.md#verified-domains-for-groups) or email confirmation settings are [turned off](../administration/settings/sign_up_restrictions.md#confirm-user-email). |
+
+Example request:
+
+```shell
+curl --request PATCH --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/345/service_accounts/57" --data "name=Updated Service Account email=updated_email@example.com"
+```
+
+Example response:
+
+```json
+{
+ "id": 57,
+ "username": "service_account_group_345_6018816a18e515214e0c34c2b33523fc",
+ "name": "Updated Service Account",
+ "email": "service_account_group_345_@noreply.gitlab.example.com",
+ "unconfirmed_email": "custom_email@example.com"
+}
+```
+
+### Delete a group service account
+
+{{< history >}}
+
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/416729) in GitLab 17.1.
+
+{{< /history >}}
+
+Deletes a service account from a specified top-level group.
+
+{{< alert type="note" >}}
+
+This endpoint only works on top-level groups.
+
+{{< /alert >}}
+
+```plaintext
+DELETE /groups/:id/service_accounts/:user_id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| ------------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the target group](rest/_index.md#namespaced-paths). |
+| `user_id` | integer | yes | The ID of a service account. |
+| `hard_delete` | boolean | no | If true, contributions that would usually be [moved to a Ghost User](../user/profile/account/delete_account.md#associated-records) are instead deleted, as well as groups owned solely by this service account. |
+
+Example request:
+
+```shell
+curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/345/service_accounts/181"
+```
+
+### List all personal access tokens for a group service account
+
+{{< history >}}
+
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/526924) in GitLab 17.11.
+
+{{< /history >}}
+
+Lists all personal access tokens for a service account in a top-level group.
+
+```plaintext
+GET /groups/:id/service_accounts/:user_id/personal_access_tokens
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+| ------------------ | ------------------- | -------- | ----------- |
+| `id` | integer/string | yes | ID or [URL-encoded path](rest/_index.md#namespaced-paths) of a top-level group. |
+| `user_id` | integer | yes | ID of service account. |
+| `created_after` | datetime (ISO 8601) | no | If defined, returns tokens created after the specified time. |
+| `created_before` | datetime (ISO 8601) | no | If defined, returns tokens created before the specified time. |
+| `expires_after` | date (ISO 8601) | no | If defined, returns tokens that expire after the specified time. |
+| `expires_before` | date (ISO 8601) | no | If defined, returns tokens that expire before the specified time. |
+| `last_used_after` | datetime (ISO 8601) | no | If defined, returns tokens last used after the specified time. |
+| `last_used_before` | datetime (ISO 8601) | no | If defined, returns tokens last used before the specified time. |
+| `revoked` | boolean | no | If `true`, only returns revoked tokens. |
+| `search` | string | no | If defined, returns tokens that include the specified value in the name. |
+| `sort` | string | no | If defined, sorts the results by the specified value. Possible values: `created_asc`, `created_desc`, `expires_asc`, `expires_desc`, `last_used_asc`, `last_used_desc`, `name_asc`, `name_desc`. |
+| `state` | string | no | If defined, returns tokens with the specified state. Possible values: `active` and `inactive`. |
+
+Example request:
+
+```shell
+curl --request GET \
+ --header "PRIVATE-TOKEN: " \
+ --url "https://gitlab.example.com/api/v4/groups/187/service_accounts/195/personal_access_tokens?sort=id_desc&search=token2b&created_before=2025-03-27"
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 187,
+ "name": "service_accounts_token2b",
+ "revoked": false,
+ "created_at": "2025-03-26T14:42:51.084Z",
+ "description": null,
+ "scopes": [
+ "api"
+ ],
+ "user_id": 195,
+ "last_used_at": null,
+ "active": true,
+ "expires_at": null
+ }
+]
+```
+
+Example of unsuccessful responses:
+
+- `401: Unauthorized`
+- `404 Group Not Found`
+
+### Create a personal access token for a group service account
+
+{{< history >}}
+
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/406781) in GitLab 16.1.
+
+{{< /history >}}
+
+Creates a personal access token for an existing service account in a specified top-level group.
+
+```plaintext
+POST /groups/:id/service_accounts/:user_id/personal_access_tokens
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| ------------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | ID or [URL-encoded path](rest/_index.md#namespaced-paths) of a top-level group. |
+| `user_id` | integer | yes | ID of service account. |
+| `name` | string | yes | Name of personal access token. |
+| `description` | string | no | Description of personal access token. |
+| `scopes` | array | yes | Array of approved scopes. For a list of possible values, see [Personal access token scopes](../user/profile/personal_access_tokens.md#personal-access-token-scopes). |
+| `expires_at` | date | no | Expiration date of the access token in ISO format (`YYYY-MM-DD`). If not specified, the date is set to the [maximum allowable lifetime limit](../user/profile/personal_access_tokens.md#access-token-expiration). |
+
+Example request:
+
+```shell
+curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/35/service_accounts/71/personal_access_tokens" --data "scopes[]=api,read_user,read_repository" --data "name=service_accounts_token"
+```
+
+Example response:
+
+```json
+{
+ "id":6,
+ "name":"service_accounts_token",
+ "revoked":false,
+ "created_at":"2023-06-13T07:47:13.900Z",
+ "scopes":["api"],
+ "user_id":71,
+ "last_used_at":null,
+ "active":true,
+ "expires_at":"2024-06-12",
+ "token":""
+}
+```
+
+### Revoke a personal access token for a group service account
+
+{{< history >}}
+
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/184287) in GitLab 17.11
+
+{{< /history >}}
+
+Revokes a personal access token for an existing service account in a specified top-level group.
+
+{{< alert type="note" >}}
+
+This endpoint only works on top-level groups.
+
+{{< /alert >}}
+
+```plaintext
+DELETE /groups/:id/service_accounts/:user_id/personal_access_tokens/:token_id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| ---------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the target group](rest/_index.md#namespaced-paths). |
+| `user_id` | integer | yes | The ID of the service account. |
+| `token_id` | integer | yes | The ID of the token. |
+
+Example request:
+
+```shell
+curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/35/service_accounts/71/personal_access_tokens/6"
+```
+
+If successful, returns `204: No Content`.
+
+Other possible responses:
+
+- `400: Bad Request` if not revoked successfully.
+- `401: Unauthorized` if the request is not authorized.
+- `403: Forbidden` if the request is not allowed.
+- `404: Not Found` if the access token does not exist.
+
+### Rotate a personal access token for a group service account
+
+{{< history >}}
+
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/406781) in GitLab 16.1.
+
+{{< /history >}}
+
+Rotates a personal access token for an existing service account in a specified top-level group. This creates a new token valid for one week and revokes any existing tokens.
+
+{{< alert type="note" >}}
+
+This endpoint only works on top-level groups.
+
+{{< /alert >}}
+
+```plaintext
+POST /groups/:id/service_accounts/:user_id/personal_access_tokens/:token_id/rotate
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| ------------ | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the target group](rest/_index.md#namespaced-paths). |
+| `user_id` | integer | yes | The ID of the service account. |
+| `token_id` | integer | yes | The ID of the token. |
+| `expires_at` | date | no | Expiration date of the access token in ISO format (`YYYY-MM-DD`). [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/505671) in GitLab 17.9. If the token requires an expiration date, defaults to one week. If not required, defaults to the [maximum allowable lifetime limit](../user/profile/personal_access_tokens.md#access-token-expiration). |
+
+Example request:
+
+```shell
+curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/35/service_accounts/71/personal_access_tokens/6/rotate"
+```
+
+Example response:
+
+```json
+{
+ "id":7,
+ "name":"service_accounts_token",
+ "revoked":false,
+ "created_at":"2023-06-13T07:54:49.962Z",
+ "scopes":["api"],
+ "user_id":71,
+ "last_used_at":null,
+ "active":true,
+ "expires_at":"2023-06-20",
+ "token":""
+}
+```
diff --git a/doc/api/user_service_accounts.md b/doc/api/user_service_accounts.md
index fa2b67ed9f5..0a1d7929e39 100644
--- a/doc/api/user_service_accounts.md
+++ b/doc/api/user_service_accounts.md
@@ -1,163 +1,13 @@
---
-stage: Software Supply Chain Security
-group: Authentication
-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: Service account users API
+redirect_to: 'service_accounts.md'
+remove_date: '2025-10-16'
---
-{{< details >}}
+
-- Tier: Premium, Ultimate
-- Offering: GitLab Self-Managed, GitLab Dedicated
+This document was moved to [another location](service_accounts.md).
-{{< /details >}}
-
-Use this API to interact with instance service accounts. Instance service accounts are available to
-an entire GitLab instance, but must still be added to groups and projects like a human user.
-For more information, see [service accounts](../user/profile/service_accounts.md).
-
-You can also interact with service accounts through the [users API](users.md).
-
-## List all instance service accounts
-
-{{< history >}}
-
-- List all service accounts [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/416729) in GitLab 17.1.
-
-{{< /history >}}
-
-Lists all instance service accounts.
-
-Use the `page` and `per_page` [pagination parameters](rest/_index.md#offset-based-pagination) to filter the results.
-
-Prerequisites:
-
-- You must have administrator access to the instance.
-
-```plaintext
-GET /service_accounts
-```
-
-Supported attributes:
-
-| Attribute | Type | Required | Description |
-| ---------- | ------ | -------- | ----------- |
-| `order_by` | string | no | Attribute to order results by. Possible values: `id` or `username`. Default value: `id`. |
-| `sort` | string | no | Direction to sort results by. Possible values: `desc` or `asc`. Default value: `desc`. |
-
-Example request:
-
-```shell
-curl --request GET --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/service_accounts"
-```
-
-Example response:
-
-```json
-[
- {
- "id": 114,
- "username": "service_account_33",
- "name": "Service account user"
- },
- {
- "id": 137,
- "username": "service_account_34",
- "name": "john doe"
- }
-]
-```
-
-## Create an instance service account
-
-{{< history >}}
-
-- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/406782) in GitLab 16.1
-- `username` and `name` attributes [added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144841) in GitLab 16.10.
-- `email` attribute [added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/178689) in GitLab 17.9.
-
-{{< /history >}}
-
-Creates an instance service account.
-
-Prerequisites:
-
-- You must have administrator access to the instance.
-
-```plaintext
-POST /service_accounts
-POST /service_accounts?email=custom_email@gitlab.example.com
-```
-
-Supported attributes:
-
-| Attribute | Type | Required | Description |
-| ---------- | ------ | -------- | ----------- |
-| `name` | string | no | Name of the user. If not set, uses `Service account user`. |
-| `username` | string | no | Username of the user account. If undefined, generates a name prepended with `service_account_`. |
-| `email` | string | no | Email of the user account. If undefined, generates a no-reply email address. Custom email addresses require confirmation, unless the email confirmation settings are [turned off](../administration/settings/sign_up_restrictions.md#confirm-user-email). |
-
-Example request:
-
-```shell
-curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/service_accounts"
-```
-
-Example response:
-
-```json
-{
- "id": 57,
- "username": "service_account_6018816a18e515214e0c34c2b33523fc",
- "name": "Service account user",
- "email": "service_account_6018816a18e515214e0c34c2b33523fc@noreply.gitlab.example.com"
-}
-```
-
-If the email address defined by the `email` attribute is already in use by another user,
-returns a `400 Bad request` error.
-
-## Update an instance service account
-
-{{< history >}}
-
-- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/196309/) in GitLab 18.2.
-
-{{< /history >}}
-
-Updates a specified instance service account.
-
-Prerequisites:
-
-- You must have administrator access to the instance.
-
-```plaintext
-PATCH /service_accounts/:id
-```
-
-Parameters:
-
-| Attribute | Type | Required | Description |
-|:-----------|:---------------|:---------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `id` | integer | yes | ID of the service account. |
-| `name` | string | no | Name of the user. |
-| `username` | string | no | Username of the user account. |
-| `email` | string | no | Email of the user account. Custom email addresses require confirmation, unless the email confirmation settings are [turned off](../administration/settings/sign_up_restrictions.md#confirm-user-email). |
-
-Example request:
-
-```shell
-curl --request PATCH --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/service_accounts/57" --data "name=Updated Service Account email=updated_email@example.com"
-```
-
-Example response:
-
-```json
-{
- "id": 57,
- "username": "service_account_6018816a18e515214e0c34c2b33523fc",
- "name": "Updated Service Account",
- "email": "service_account_@noreply.gitlab.example.com",
- "unconfirmed_email": "custom_email@example.com"
-}
-```
+
+
+
+
diff --git a/doc/editor_extensions/visual_studio_code/ssl.md b/doc/editor_extensions/visual_studio_code/ssl.md
index eec3683b103..8d820156c23 100644
--- a/doc/editor_extensions/visual_studio_code/ssl.md
+++ b/doc/editor_extensions/visual_studio_code/ssl.md
@@ -22,8 +22,12 @@ Prerequisites:
the system certificate store, and changes all node `http` requests to trust the certificates:
```mermaid
- graph LR;
- A[Self-signed CA] -- signed --> B[Your GitLab instance certificate]
+ %%{init: { "fontFamily": "GitLab Sans" }}%%
+ graph LR
+ accTitle: Self-signed certificate chain
+ accDescr: Shows a self-signed CA that signs the GitLab instance certificate.
+
+ A[Self-signed CA] -- signed --> B[Your GitLab instance certificate]
```
For more information, see [Self-signed certificate error when installing Python support in WSL](https://github.com/microsoft/vscode/issues/131836#issuecomment-909983815) in the Visual Studio Code issue tracker.
diff --git a/doc/integration/jira/connect-app.md b/doc/integration/jira/connect-app.md
index 0f74e699ef0..51dbe201955 100644
--- a/doc/integration/jira/connect-app.md
+++ b/doc/integration/jira/connect-app.md
@@ -208,11 +208,11 @@ This token authenticates the service account token used to manage GitLab deploym
To create the service account token:
-1. [Create a service account user](../../api/user_service_accounts.md#create-an-instance-service-account).
+1. [Create a service account user](../../api/service_accounts.md#create-an-instance-service-account).
1. [Add the service account to a group or project](../../api/members.md#add-a-member-to-a-group-or-project)
by using your personal access token.
1. [Add the service account to protected environments](../../ci/environments/protected_environments.md#protecting-environments).
-1. [Generate a service account token](../../api/group_service_accounts.md#create-a-personal-access-token-for-a-group-service-account)
+1. [Generate a service account token](../../api/service_accounts.md#create-a-personal-access-token-for-a-group-service-account)
by using your personal access token.
1. Copy the service account token value.
diff --git a/doc/solutions/integrations/aws_googlecloud_ollama.md b/doc/solutions/integrations/aws_googlecloud_ollama.md
index 6ceac03bca6..4f3aae0bf74 100644
--- a/doc/solutions/integrations/aws_googlecloud_ollama.md
+++ b/doc/solutions/integrations/aws_googlecloud_ollama.md
@@ -57,7 +57,11 @@ We will install GitLab, GitLab AI Gateway and Ollama each in their own separate
For more information about the component and its purpose, see [AI Gateway](../../user/gitlab_duo/gateway.md).
```mermaid
+%%{init: { "fontFamily": "GitLab Sans" }}%%
flowchart LR
+ accTitle: GitLab Duo Self-Hosted architecture
+ accDescr: Shows the flow from GitLab Ultimate to the AI gateway, which connects to Ollama running Mistral.
+
A[GitLab Ultimate] --> C
C[GitLab AI Gateway] --> B[Ollama Mistral]
```
diff --git a/doc/topics/git/undo.md b/doc/topics/git/undo.md
index 5df9e03d6c8..c500871afd2 100644
--- a/doc/topics/git/undo.md
+++ b/doc/topics/git/undo.md
@@ -271,6 +271,9 @@ want to undo. This process preserves the history and provides a clear timeline a
```mermaid
%%{init: { "fontFamily": "GitLab Sans" }}%%
flowchart LR
+ accTitle: Git revert operation workflow diagram
+ accDescr: Shows commits A, B, C in sequence, then commit -B that reverses B's changes, followed by D. Commit B remains in history.
+
REMOTE["REMOTE"] --> A(A)
A --> B(B)
B --> C(C)
diff --git a/doc/topics/runner_fleet_design_guides/gitlab_runner_manager_performance.md b/doc/topics/runner_fleet_design_guides/gitlab_runner_manager_performance.md
index 3f828735f7a..762af58a7cf 100644
--- a/doc/topics/runner_fleet_design_guides/gitlab_runner_manager_performance.md
+++ b/doc/topics/runner_fleet_design_guides/gitlab_runner_manager_performance.md
@@ -42,7 +42,11 @@ It handles:
- **Pod lifecycle management**: Manages worker pod provisioning and cleanup
```mermaid
+%%{init: { "fontFamily": "GitLab Sans" }}%%
flowchart LR
+ accTitle: GitLab Runner manager pod architecture
+ accDescr: The manager pod polls GitLab for jobs, creates job pods through the Kubernetes API, manages the S3 cache, and forwards logs from job pods to GitLab.
+
subgraph "External Services"
GL[GitLab Instance]
S3[S3 Cache Storage]
@@ -105,13 +109,17 @@ To configure monitoring for the Operator, see [Monitor GitLab Runner Operator](h
Effective monitoring is crucial for maintaining optimal manager pod performance.
```mermaid
+%%{init: { "fontFamily": "GitLab Sans" }}%%
flowchart TD
+ accTitle: Metrics collection and monitoring flow
+ accDescr: The manager pod exposes metrics, Prometheus scrapes the metrics using PodMonitor configuration, Grafana visualizes the data, and Alertmanager notifies operators.
+
subgraph "Metrics Collection Flow"
MP[Manager Pod :9252/metrics]
PM[PodMonitor]
P[Prometheus]
G[Grafana]
- A[AlertManager]
+ A[Alertmanager]
MP -->|Expose Metrics| PM
PM -->|Scrape| P
@@ -281,8 +289,11 @@ to stress test the manager pod's log processing capabilities.
| 100 | 657m | 369 MB |
```mermaid
+%%{init: { "fontFamily": "GitLab Sans" }}%%
xychart-beta
- title "Manager Pod Resource Usage vs Concurrent Jobs"
+ accTitle: Manager pod resource usage compared to concurrent jobs
+ accDescr: Chart showing CPU usage (10-610 millicores) and memory usage (50-300 MB) that scale with concurrent jobs (0-100).
+
x-axis [0, 25, 50, 75, 100]
y-axis "Resource Usage" 0 --> 700
line "CPU (millicores)" [10, 160, 310, 460, 610]
@@ -486,7 +497,11 @@ performance and prevent resource contention. This isolation prevents job pods
from disrupting critical manager pod operations.
```mermaid
+%%{init: { "fontFamily": "GitLab Sans" }}%%
graph TB
+ accTitle: Kubernetes node segregation architecture
+ accDescr: Node segregation with manager pods on dedicated manager nodes and job pods on worker nodes, separated by taints.
+
subgraph "Kubernetes Cluster"
subgraph "Manager Nodes"
MN1[Manager Node 1 Taint: runner.gitlab.com/manager]
diff --git a/doc/update/deprecations.md b/doc/update/deprecations.md
index 733c617306e..a2e8f5873a9 100644
--- a/doc/update/deprecations.md
+++ b/doc/update/deprecations.md
@@ -990,6 +990,25 @@ and will be moved to the JiHu GitLab codebase.
+### `bin_path` and `use_bundled_binaries` configuration options in Gitaly
+
+
+
+- Announced in GitLab 18.2
+- Removal in GitLab 19.0 ([breaking change](https://docs.gitlab.com/update/terminology/#breaking-change))
+- To discuss this change or learn more, see the [deprecation issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/9181).
+
+
+
+Support for using `bin_path` and `use_bundled_binaries` configuration options in Gitaly is deprecated and will be
+removed in GitLab 19.0.
+
+The Git binaries provided by Gitaly will be the only supported way to execute Git.
+
+
+
+
+
### `ciJobTokenScopeAddProject` GraphQL mutation is deprecated
diff --git a/doc/user/compliance/compliance_center/compliance_violations_report.md b/doc/user/compliance/compliance_center/compliance_violations_report.md
index 58a7866c926..88b8a83e517 100644
--- a/doc/user/compliance/compliance_center/compliance_violations_report.md
+++ b/doc/user/compliance/compliance_center/compliance_violations_report.md
@@ -16,12 +16,97 @@ title: Compliance violations report
- [Renamed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/112111) to compliance violations report in GitLab 15.9.
- Ability to create and edit compliance frameworks [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/394950) in GitLab 16.0.
+- New dynamic compliance violations report [introduced](https://gitlab.com/groups/gitlab-org/-/epics/12774) in GitLab 18.2 [with a flag](../../../administration/feature_flags/_index.md) named `compliance_violations_report`. Disabled by default.
{{< /history >}}
-With the compliance violations report, you can see a high-level view of merge request activity for all projects in the group.
+{{< alert type="flag" >}}
-When you select a row in the compliance violations report, a drawer appears that provides:
+The availability of this feature is controlled by a feature flag.
+For more information, see the history.
+This feature is available for testing, but not ready for production use. For production use, continue to use the
+[static compliance violations report](#static-compliance-violations-report).
+
+{{< /alert >}}
+
+Use the compliance violations report to see a comprehensive view of compliance violations across all projects in
+your group. The report provides detailed information about violated controls, associated audit events, and allows you
+to manage violation statuses.
+
+## View the compliance violations report
+
+Prerequisites:
+
+- You must be an administrator or have the Owner role for the project or group.
+
+To view the compliance violations report:
+
+1. On the left sidebar, select **Search or go to** and find your project or group.
+1. Select **Secure > Compliance center**.
+
+The compliance violations report displays:
+
+- **Status**: The current status of the violation. For example, Needs Review, Resolved, or Dismissed.
+- **Violated control and framework**: The specific compliance control that was violated and its associated framework.
+- **Audit Event**: Details about the event that triggered the violation.
+- **Project**: The project where the violation occurred.
+- **Date detected**: When the violation was identified.
+- **Action**: Link to view detailed information about the violation.
+
+In the report, you can:
+
+- Sort the report by selecting column headers.
+- Change the status of violations using the status dropdown list.
+- Navigate through multiple pages of violations by using pagination.
+- View detailed information about each violation.
+
+## Violation details
+
+When you select **Details** for a specific violation, you can view:
+
+- The violation ID and status.
+- Location (project) where the violation occurred.
+- Comprehensive audit event information including:
+ - Event author.
+ - Event target.
+ - Event details.
+ - IP address.
+ - Target type.
+- Violated control information including:
+ - Control name and description.
+ - Associated compliance framework.
+ - Requirements.
+- Fix suggestions with links to resolve the violation.
+
+## Manage violation statuses
+
+You can update the status of compliance violations to track their remediation progress. Available statuses include:
+
+- **Needs Review**: Default status for new violations
+- **In Progress**: Violation is being addressed
+- **Resolved**: Violation has been remediated
+- **Dismissed**: Violation has been reviewed and dismissed
+
+To change a violation status:
+
+1. In the compliance violations report, locate the violation you want to update.
+1. Select the current status dropdown list in the **Status** column.
+1. Choose the new status from the dropdown list menu.
+
+The status updates immediately and is reflected in the report.
+
+## Static compliance violations report
+
+{{< alert type="warning" >}}
+
+This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/551236) in GitLab 18.2
+and is planned for removal in 18.8.
+
+{{< /alert >}}
+
+The static compliance violations report provides a high-level view of merge request activity for all projects in the group.
+
+When you select a row in the static compliance violations report, a drawer appears that provides:
- The project name and [compliance framework label](../../project/working_with_projects.md#add-a-compliance-framework-to-a-project),
if the project has one assigned.
@@ -32,7 +117,7 @@ When you select a row in the compliance violations report, a drawer appears that
- A list of users that approved the merge request.
- The user that merged the merge request.
-## View the compliance violations report
+### View the static compliance violations report
{{< history >}}
@@ -44,7 +129,7 @@ Prerequisites:
- You must be an administrator or have the Owner role for the project or group.
-To view the compliance violations report:
+To view the static compliance violations report:
1. On the left sidebar, select **Search or go to** and find your project or group.
1. Select **Secure > Compliance center**.
@@ -98,7 +183,7 @@ separation of duties is:
- [A merge request committer is **not** allowed to approve a merge request they have added commits to](../../project/merge_requests/approvals/settings.md#prevent-approvals-by-users-who-add-commits).
- [The minimum number of approvals required to merge a merge request is **at least** two](../../project/merge_requests/approvals/rules.md).
-## Export a report of merge request compliance violations on projects in a group
+### Export a report of merge request compliance violations on projects in a group
{{< history >}}
diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md
index 70d43c190c5..4a2d5b47cf5 100644
--- a/doc/user/profile/personal_access_tokens.md
+++ b/doc/user/profile/personal_access_tokens.md
@@ -353,7 +353,7 @@ You can subscribe to an iCalendar endpoint which contains events at the expiry d
### Create a service account personal access token with no expiry date
-You can [create a personal access token for a service account](../../api/group_service_accounts.md#create-a-personal-access-token-for-a-group-service-account) with no expiry date. These personal access tokens never expire, unlike non-service account personal access tokens.
+You can [create a personal access token for a service account](../../api/service_accounts.md#create-a-personal-access-token-for-a-group-service-account) with no expiry date. These personal access tokens never expire, unlike non-service account personal access tokens.
{{< alert type="note" >}}
diff --git a/doc/user/profile/service_accounts.md b/doc/user/profile/service_accounts.md
index 4304e67894b..913bd3261aa 100644
--- a/doc/user/profile/service_accounts.md
+++ b/doc/user/profile/service_accounts.md
@@ -36,15 +36,15 @@ Service accounts:
- Do not use a seat.
- Cannot sign in to GitLab through the UI.
- Are identified in the group and project membership as service accounts.
-- Do not receive notification emails without [adding a custom email address](../../api/user_service_accounts.md#create-an-instance-service-account).
+- Do not receive notification emails without [adding a custom email address](../../api/service_accounts.md#create-an-instance-service-account).
- Are not [billable users](../../subscriptions/self_managed/_index.md#billable-users) or [internal users](../../administration/internal_users.md).
- Cannot be used with [trial versions](https://gitlab.com/-/trial_registrations/new?glm_source=docs.gitlab.com&glm_content=free-user-limit-faq/ee/user/free_user_limit.html) of GitLab.com.
- Can be used with trial versions of GitLab Self-Managed and GitLab Dedicated.
You can also manage service accounts through the API.
-- For instance service accounts, use the [service account users API](../../api/user_service_accounts.md).
-- For group service accounts, use the [group service accounts API](../../api/group_service_accounts.md).
+- For instance service accounts, use the [service account users API](../../api/service_accounts.md).
+- For group service accounts, use the [group service accounts API](../../api/service_accounts.md).
## Prerequisites
@@ -172,7 +172,7 @@ contributions can include activity such as merge requests, issues, groups, and p
You can also delete service accounts through the API.
- For instance service accounts, use the [users API](../../api/users.md#delete-a-user).
-- For group service accounts, use the [group service accounts API](../../api/group_service_accounts.md#delete-a-group-service-account).
+- For group service accounts, use the [group service accounts API](../../api/service_accounts.md#delete-a-group-service-account).
## View and manage personal access tokens for a service account
@@ -185,7 +185,7 @@ The personal access tokens page displays information about the personal access t
You can also manage personal access tokens for service accounts through the API.
- For instance service accounts, use the [personal access tokens API](../../api/personal_access_tokens.md).
-- For group service accounts, use the [group service accounts API](../../api/group_service_accounts.md).
+- For group service accounts, use the [group service accounts API](../../api/service_accounts.md).
To view the personal access tokens page for a service account:
diff --git a/doc/user/project/deploy_keys/_index.md b/doc/user/project/deploy_keys/_index.md
index 6d7d27e2301..48fd457e62f 100644
--- a/doc/user/project/deploy_keys/_index.md
+++ b/doc/user/project/deploy_keys/_index.md
@@ -219,8 +219,8 @@ This issue occurs because all deploy keys are associated to an account. Because
To resolve this issue, you can use the deploy keys API to create deploy keys for project service account users, instead of for your own users:
-1. [Create a service account user](../../../api/group_service_accounts.md#create-a-group-service-account).
-1. [Create a personal access token](../../../api/group_service_accounts.md#create-a-personal-access-token-for-a-group-service-account) for that service account user. This token must have at least the `api` scope.
+1. [Create a service account user](../../../api/service_accounts.md#create-a-group-service-account).
+1. [Create a personal access token](../../../api/service_accounts.md#create-a-personal-access-token-for-a-group-service-account) for that service account user. This token must have at least the `api` scope.
1. [Invite the service account user to the project](../../profile/service_accounts.md#service-account-access-to-groups-and-projects).
1. Use the deploy key API to [create a deploy key for the service account user](../../../api/deploy_keys.md#add-deploy-key):
diff --git a/doc/user/project/merge_requests/homepage.md b/doc/user/project/merge_requests/homepage.md
index 3012281ad9b..3db84b3ed55 100644
--- a/doc/user/project/merge_requests/homepage.md
+++ b/doc/user/project/merge_requests/homepage.md
@@ -19,7 +19,11 @@ shows you which merge requests need your attention first, regardless of whether
the work of someone else. The workflow view groups merge requests by their stage in this review process:
```mermaid
+%%{init: { "fontFamily": "GitLab Sans" }}%%
flowchart LR
+ accTitle: Merge request review workflow
+ accDescr: Flow from merge request creation through review, approval, and merge stages with decision points for reviewers and approvals.
+
A[Your merge request] --> B{Reviewers added?}
B-->|Yes| D[Review requested]
B -.->|No| C[Assigned to you]
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 583e846c414..7bf064d48e2 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -567,8 +567,8 @@ module API
render_api_error!(message || '405 Method Not Allowed', :method_not_allowed)
end
- def not_acceptable!
- render_api_error!('406 Not Acceptable', 406)
+ def not_acceptable!(message = nil)
+ render_api_error!(message || '406 Not Acceptable', 406)
end
def service_unavailable!(message = nil)
@@ -583,8 +583,8 @@ module API
render_api_error!(message || '422 Unprocessable Entity', :unprocessable_entity)
end
- def file_too_large!
- render_api_error!('413 Request Entity Too Large', 413)
+ def file_too_large!(message = nil)
+ render_api_error!(message || '413 Request Entity Too Large', 413)
end
def too_many_requests!(message = nil, retry_after: 1.minute)
@@ -593,20 +593,20 @@ module API
render_api_error!(message || '429 Too Many Requests', 429)
end
- def not_modified!
- render_api_error!('304 Not Modified', 304)
+ def not_modified!(message = nil)
+ render_api_error!(message || '304 Not Modified', 304)
end
- def no_content!
- render_api_error!('204 No Content', 204)
+ def no_content!(message = nil)
+ render_api_error!(message || '204 No Content', 204)
end
- def created!
- render_api_error!('201 Created', 201)
+ def created!(message = nil)
+ render_api_error!(message || '201 Created', 201)
end
- def accepted!(message = '202 Accepted')
- render_api_error!(message, 202)
+ def accepted!(message = nil)
+ render_api_error!(message || '202 Accepted', 202)
end
def render_validation_error!(models, status = 400)
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index c9a885242a7..57a8d6b3e65 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -13264,9 +13264,6 @@ msgstr ""
msgid "CiVariables|Learn how to %{linkStart}restrict CI/CD variables to specific environments%{linkEnd} for better security."
msgstr ""
-msgid "CiVariables|Manual job empty state image"
-msgstr ""
-
msgid "CiVariables|Masked"
msgstr ""
diff --git a/spec/frontend/ci/job_details/components/empty_state_spec.js b/spec/frontend/ci/job_details/components/empty_state_spec.js
index 8b34b7954b4..19cfb0197b7 100644
--- a/spec/frontend/ci/job_details/components/empty_state_spec.js
+++ b/spec/frontend/ci/job_details/components/empty_state_spec.js
@@ -1,3 +1,4 @@
+import { GlEmptyState } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import EmptyState from '~/ci/job_details/components/empty_state.vue';
import ManualJobForm from '~/ci/job_details/components/manual_job_form.vue';
@@ -8,7 +9,6 @@ describe('Empty State', () => {
const defaultProps = {
illustrationPath: 'illustrations/empty-state/empty-job-pending-md.svg',
- illustrationSizeClass: '',
jobId: mockId,
jobName: 'My job',
title: 'This job has not started yet',
@@ -27,8 +27,9 @@ describe('Empty State', () => {
const content = 'This job is in pending state and is waiting to be picked by a runner';
- const findEmptyStateImage = () => wrapper.find('img');
- const findTitle = () => wrapper.findByTestId('job-empty-state-title');
+ const findEmptyState = () => wrapper.findComponent(GlEmptyState);
+ const findEmptyStateImage = () => findEmptyState().props('svgPath');
+ const findTitle = () => findEmptyState().props('title');
const findContent = () => wrapper.findByTestId('job-empty-state-content');
const findAction = () => wrapper.findByTestId('job-empty-state-action');
const findManualVarsForm = () => wrapper.findComponent(ManualJobForm);
@@ -39,15 +40,11 @@ describe('Empty State', () => {
});
it('renders empty state image', () => {
- expect(findEmptyStateImage().exists()).toBe(true);
- });
-
- it('renders alt text', () => {
- expect(findEmptyStateImage().attributes('alt')).toBe('Manual job empty state image');
+ expect(findEmptyStateImage()).toBe(defaultProps.illustrationPath);
});
it('renders provided title', () => {
- expect(findTitle().text().trim()).toBe(defaultProps.title);
+ expect(findTitle()).toBe(defaultProps.title);
});
});
diff --git a/spec/lib/api/helpers_spec.rb b/spec/lib/api/helpers_spec.rb
index 5d9de7505ee..2afa2f4bd4b 100644
--- a/spec/lib/api/helpers_spec.rb
+++ b/spec/lib/api/helpers_spec.rb
@@ -1653,45 +1653,57 @@ RSpec.describe API::Helpers, feature_category: :shared do
end
end
- describe '#unauthorized!' do
- it 'renders 401' do
- expect(helper).to receive(:render_api_error_with_reason!).with(401, '401 Unauthorized', nil)
-
- helper.unauthorized!
+ describe 'error helper methods with reason' do
+ where(:method_name, :expected_code, :expected_message) do
+ [
+ [:forbidden!, 403, '403 Forbidden'],
+ [:bad_request!, 400, '400 Bad request'],
+ [:unauthorized!, 401, '401 Unauthorized']
+ ]
end
- it 'renders 401 with a reason' do
- expect(helper).to receive(:render_api_error_with_reason!).with(401, '401 Unauthorized', 'custom reason')
+ with_them do
+ it "renders #{params[:expected_code]}" do
+ expect(helper).to receive(:render_api_error_with_reason!).with(expected_code, expected_message, nil)
- helper.unauthorized!('custom reason')
+ helper.send(method_name)
+ end
+
+ it "renders #{params[:expected_code]} with a reason" do
+ expect(helper).to receive(:render_api_error_with_reason!).with(expected_code, expected_message, 'custom reason')
+
+ helper.send(method_name, 'custom reason')
+ end
end
end
- describe '#forbidden!' do
- it 'renders 401' do
- expect(helper).to receive(:render_api_error_with_reason!).with(403, '403 Forbidden', nil)
-
- helper.forbidden!
+ describe 'error helper methods with message' do
+ where(:method_name, :expected_code, :expected_message) do
+ [
+ [:not_allowed!, :method_not_allowed, '405 Method Not Allowed'],
+ [:not_acceptable!, 406, '406 Not Acceptable'],
+ [:service_unavailable!, 503, '503 Service Unavailable'],
+ [:conflict!, 409, '409 Conflict'],
+ [:unprocessable_entity!, :unprocessable_entity, '422 Unprocessable Entity'],
+ [:file_too_large!, 413, '413 Request Entity Too Large'],
+ [:not_modified!, 304, '304 Not Modified'],
+ [:no_content!, 204, '204 No Content'],
+ [:created!, 201, '201 Created']
+ ]
end
- it 'renders 401 with a reason' do
- expect(helper).to receive(:render_api_error_with_reason!).with(403, '403 Forbidden', 'custom reason')
+ with_them do
+ it "renders #{params[:expected_code]}" do
+ expect(helper).to receive(:render_api_error!).with(expected_message, expected_code)
- helper.forbidden!('custom reason')
- end
- end
+ helper.send(method_name)
+ end
- describe '#bad_request!' do
- it 'renders 400' do
- expect(helper).to receive(:render_api_error_with_reason!).with(400, '400 Bad request', nil)
+ it "renders #{params[:expected_code]} with a custom message" do
+ expect(helper).to receive(:render_api_error!).with('custom message', expected_code)
- helper.bad_request!
- end
-
- it 'renders 401 with a reason' do
- expect(helper).to receive(:render_api_error_with_reason!).with(400, '400 Bad request', 'custom reason')
-
- helper.bad_request!('custom reason')
+ helper.send(method_name, 'custom message')
+ end
end
end