Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-06-05 09:08:29 +00:00
parent dfebbcd6b1
commit dea5229941
24 changed files with 1384 additions and 57 deletions

View File

@ -288,8 +288,11 @@ rspec:coverage:
- rspec migration pg13
- rspec background_migration pg13
- rspec unit pg13
- rspec unit pg13 single-redis
- rspec integration pg13
- rspec integration pg13 single-redis
- rspec system pg13
- rspec system pg13 single-redis
# as-if-foss jobs
- rspec migration pg13-as-if-foss
- rspec background_migration pg13-as-if-foss
@ -300,8 +303,11 @@ rspec:coverage:
- rspec-ee migration pg13
- rspec-ee background_migration pg13
- rspec-ee unit pg13
- rspec-ee unit pg13 single-redis
- rspec-ee integration pg13
- rspec-ee integration pg13 single-redis
- rspec-ee system pg13
- rspec-ee system pg13 single-redis
# Memory jobs
- memory-on-boot
script:

View File

@ -74,13 +74,6 @@ gemnasium-dependency_scanning:
gemnasium-python-dependency_scanning:
rules: !reference [".reports:rules:gemnasium-python-dependency_scanning", rules]
yarn-audit-dependency_scanning:
extends: .ds-analyzer
image: "${REGISTRY_HOST}/${REGISTRY_GROUP}/security-products/analyzers/npm-audit:1"
variables:
TOOL: yarn
rules: !reference [".reports:rules:yarn-audit-dependency_scanning", rules]
# Analyze dependencies for malicious behavior
# See https://gitlab.com/gitlab-com/gl-security/security-research/package-hunter
.package_hunter-base:

View File

@ -2313,17 +2313,6 @@
- <<: *if-default-refs
changes: *python-patterns
.reports:rules:yarn-audit-dependency_scanning:
rules:
- <<: *if-merge-request-labels-pipeline-expedite
when: never
- if: '$DEPENDENCY_SCANNING_DISABLED || $GITLAB_FEATURES !~ /\bdependency_scanning\b/'
when: never
# Run Dependency Scanning on master until https://gitlab.com/gitlab-org/gitlab/-/issues/361657 is resolved
- <<: *if-default-branch-refs
- <<: *if-default-refs
changes: *nodejs-patterns
.reports:rules:test-dast:
rules:
- <<: *if-merge-request-labels-pipeline-expedite

View File

@ -117,11 +117,11 @@ ports:
vscode:
extensions:
- GitLab.gitlab-workflow
- rebornix.ruby@0.28.1
- wingrunr21.vscode-ruby@0.28.0
- karunamurti.haml@1.4.1
- octref.vetur@0.36.0
- dbaeumer.vscode-eslint@2.2.6
- GitLab.gitlab-workflow@3.56.0
- DavidAnson.vscode-markdownlint@0.47.0
- octref.vetur@0.37.3
- dbaeumer.vscode-eslint@2.4.0
- DavidAnson.vscode-markdownlint@0.49.0
- esbenp.prettier-vscode

View File

@ -1 +1 @@
v16.1.1
v16.1.2

View File

@ -1 +1 @@
8317dab17a135879a493ca23e4963c0c58391000
862528b4c59ddb9b266552f53e133cfba38c9765

View File

@ -100,6 +100,40 @@ class AuditEvent < ApplicationRecord
super || details[:target_details]
end
def self.by_group(group)
group_id = group.id
# Bring entity_type and entity_id from projects and group into one query
scope1 = Group.find(group_id).all_projects.select("'Project' as entity_type", 'id AS entity_id')
scope2 = Project.from("(VALUES ('Group', #{group_id})) as projects(entity_type, entity_id)").select('entity_type',
'entity_id')
array_scope = Project.from_union([scope1, scope2], remove_duplicates: false).select(:entity_type, :entity_id)
# order by created_at (id is the tie breaker)
scope = AuditEvent.order(:created_at, :id)
array_mapping_scope = ->(entity_type_expression, entity_id_expression) do
AuditEvent.where(AuditEvent.arel_table[:entity_id].eq(entity_id_expression))
.where(AuditEvent.arel_table[:entity_type].eq(entity_type_expression))
end
finder_query = ->(created_at_expression, id_expression) do
# we need to add created_at filter as well because that's the partitioning key
AuditEvent.where(
AuditEvent.arel_table[:id].eq(id_expression)
).where(
AuditEvent.arel_table[:created_at].eq(created_at_expression)
)
end
Gitlab::Pagination::Keyset::InOperatorOptimization::QueryBuilder.new(
scope: scope,
array_scope: array_scope,
array_mapping_scope: array_mapping_scope,
finder_query: finder_query
).execute
end
private
def sanitize_message

View File

@ -0,0 +1,6 @@
---
migration_job_name: BackfillRootStorageStatisticsForkStorageSizes
description: Backfill the public_forks_storage_size, internal_forks_storage_size, and private_forks_storage_size columns on the namespace_root_storage_statistics table
feature_category: consumables_cost_management
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120916
milestone: 16.1

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
class QueueBackfillRootStorageStatisticsForkStorageSizes < Gitlab::Database::Migration[2.1]
MIGRATION = "BackfillRootStorageStatisticsForkStorageSizes"
DELAY_INTERVAL = 2.minutes
BATCH_SIZE = 1000
SUB_BATCH_SIZE = 100
restrict_gitlab_migration gitlab_schema: :gitlab_main
def up
queue_batched_background_migration(
MIGRATION,
:namespace_root_storage_statistics,
:namespace_id,
job_interval: DELAY_INTERVAL,
batch_size: BATCH_SIZE,
sub_batch_size: SUB_BATCH_SIZE
)
end
def down
delete_batched_background_migration(MIGRATION, :namespace_root_storage_statistics, :namespace_id, [])
end
end

View File

@ -0,0 +1 @@
bdda58a5015942f8fe98dedbbab66ff9e39505229da2e6d1726eb73105a89ae1

View File

@ -138,8 +138,16 @@ Example response:
## Group Audit Events
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34078) in GitLab 12.5.
> - Support for keyset pagination [added](https://gitlab.com/gitlab-org/gitlab/-/issues/333968) in GitLab 15.2.
> - Also returning project audit events for projects within the given group was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/feat/337757) in GitLab 16.1 behind feature flag `audit_event_group_rollup`. Disabled by default.
FLAG:
On self-managed GitLab, by default returning project audit events for projects within the given group is not available. To make it available, ask an administrator
to [enable the feature flag](../administration/feature_flags.md) named `audit_event_group_rollup`. On GitLab.com, this feature is not available. The feature is not ready for
production use.
The Group Audit Events API allows you to retrieve [group audit events](../administration/audit_events.md#group-events).
This API cannot retrieve project audit events.
A user with:

View File

@ -961,10 +961,13 @@ job:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/223273) in GitLab 13.8 [with a flag](../../user/feature_flags.md) named `non_public_artifacts`, disabled by default.
> - [Updated](https://gitlab.com/gitlab-org/gitlab/-/issues/322454) in GitLab 15.10. Artifacts created with `artifacts:public` before 15.10 are not guaranteed to remain private after this update.
FLAG:
WARNING:
On self-managed GitLab, by default this feature is not available. To make it available,
ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `non_public_artifacts`. On
GitLab.com, this feature is not available.
GitLab.com, this feature is not available. Due to [issue 413822](https://gitlab.com/gitlab-org/gitlab/-/issues/413822),
the keyword can be used when the feature flag is disabled, but the feature does not work.
Do not attempt to use this feature when the feature flag is disabled, and always test
with non-production data first.
Use `artifacts:public` to determine whether the job artifacts should be
publicly available.

View File

@ -0,0 +1,676 @@
---
stage: Secure
group: Composition Analysis
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Tutorial: Set up dependency scanning **(ULTIMATE SAAS)**
Dependency Scanning can automatically find security vulnerabilities in your software dependencies
while you're developing and testing your applications. For example, dependency scanning lets you
know if your application uses an external (open source) library that is known to be vulnerable. You
can then take action to protect your application.
This tutorial shows you how to create a sample vulnerable application, then:
- How to detect, triage, and resolve vulnerabilities in the application's dependencies.
- How to detect vulnerabilities in a merge request.
To set up dependency scanning:
- [Create example application files](#create-example-application-files).
- [Triage the vulnerabilities](#triage-the-vulnerabilities).
- [Resolve the high severity vulnerability](#resolve-the-high-severity-vulnerability).
- [Test vulnerability detection in a merge request](#test-vulnerability-detection-in-a-merge-request).
## Prerequisites
Before you begin, make sure you have GitPod enabled. GitPod is an on-demand cloud development
environment. For details, see [GitPod](../integration/gitpod.md). Alternatively you can use your
own development setup. In this case you need to have Yarn and Node.js installed.
## Create example application files
First, in a new project, create files to configure your pipeline, and add dependencies that can be
scanned for vulnerabilities.
1. Create a blank project, using the default values.
1. Create the following files in the `main` branch.
Filename: `.gitlab-ci.yml`
```yaml
stages:
- build
- test
include:
- template: Security/Dependency-Scanning.gitlab-ci.yml
# override the dependency scanning job
gemnasium-dependency_scanning:
tags: [ saas-linux-large-amd64 ]
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_MERGE_REQUEST_IID
```
Filename: `index.js`
```javascript
// Require the framework and instantiate it
const fastify = require('fastify')({ logger: true })
const path = require('path')
//const fetch = require('node-fetch')
fastify.register(require('fastify-static'), {
root: path.join(__dirname, 'public'),
prefix: '/'
})
fastify.register(require('./routes'), {
message: "hello"
})
// fastify.register(require('fastify-redis'), { url: constants.redisUrl, /* other redis options */ })
// Run the server!
const start = async () => {
try {
await fastify.listen(8080, "0.0.0.0")
fastify.log.info(`server listening on ${fastify.server.address().port}`)
} catch (error) {
fastify.log.error(error)
//process.exit(1)
}
}
start()
```
Filename `package.json`
```json
{
"dependencies": {
"fastify": "2.14.1",
"fastify-static": "2.0.0"
}
}
```
Filename `yarn.lock`
Use the content shown in the [Yarn lockfile](#yarn-lock-file-content) section.
1. Go to **CI/CD > Pipelines** and confirm that the latest pipeline completed successfully.
In the pipeline, dependency scanning runs and the vulnerabilities are detected automatically.
## Triage the vulnerabilities
The vulnerability report provides vital information on vulnerabilities. You would usually triage
vulnerabilities according to your organization's policies. For this tutorial, you'll dismiss the
medium severity vulnerabilities and confirm only the high severity vulnerability.
To triage the vulnerabilities:
1. Go to **Security and Compliance > Vulnerability report**.
1. Select each of the medium severity vulnerabilities by selecting the checkbox in each row.
1. From the **Set status** dropdown list select **Dismiss**. From the **Dismissal reason** dropdown
list select **Used in tests**, add the comment "Used in tests", then select **Change status**.
The medium severity vulnerabilities are filtered out of the view, leaving only the high
severity vulnerability remaining.
1. Select the **High** vulnerability's description.
The recommended solution is to upgrade the `fastify` package. You would usually investigate
this further, but for this tutorial, you can consider this vulnerability confirmed.
1. From the **Status** dropdown list select **Confirm**, then select **Change status**.
## Resolve the high severity vulnerability
Only the high severity vulnerability remains to be resolved. From the triage step you know that you
need to upgrade the `fastify` package.
To fix the vulnerability:
1. Go to **Repository > Files**.
1. From the **WebIDE** dropdown list select **GitPod**, then right-click on **GitPod** to open
GitPod in a new tab.
1. If you are prompted to, select **Continue with GitLab**, then select **Authorize**.
1. On the **New Workspace** page, select **Continue**.
1. In the **Terminal** pane, enter the following command to create a new branch.
```plaintext
git checkout -b update_packages main
```
1. In the **Terminal** pane, run the command `yarn upgrade --latest`. This updates the project's
dependencies and the `yarn.lock` file.
1. In the **Terminal** pane, run the following commands to commit your changes. This triggers a CI/CD
pipeline.
```plaintext
git add package.json yarn.lock
git commit -m "Update package versions"
git push --set-upstream origin update_packages
```
1. Switch to the GitLab browser tab.
1. Go to **Merge requests**, then select **Create merge request**.
1. On the **New merge request** page, scroll to the bottom and select **Create merge request**.
Wait for the merge request pipeline to complete.
1. Refresh the page, then select **Merge**.
1. Wait for the pipeline to complete successfully.
1. Go to **Security and Compliance > Vulnerability report**.
1. Select the **High** vulnerability's description.
A banner confirms that the vulnerability has been resolved in the `main` branch. You would
usually confirm that manually by verifying the version of the `fastify` package specified in the
`yarn.lock` file. For this tutorial, you can skip the verification step.
1. In the **Status** dropdown list, select **Resolve**, then select **Change status**.
1. Go to **Security and Compliance > Vulnerability report**.
You should now see _no_ vulnerabilities listed in the vulnerability report.
## Test vulnerability detection in a merge request
You now know how to triage and resolve vulnerabilities. Now, to see how to detect new potential
vulnerabilities in a merge request, add a dependency known to have vulnerabilities.
To add a new vulnerability:
1. Switch to the GitPod tab. If it's timed out, select **Open Workspace**.
1. In the **Terminal** pane run the following command to update the local `main` branch:
```plaintext
git checkout main
git fetch origin
git rebase origin/main
```
1. In the **Terminal** pane run the following command to create a new branch:
```plaintext
git checkout -b add_dependency main
```
1. In the file explorer sidebar, select the `package.json` file.
1. Add the following line to the `dependencies` section of the `package.json` file.
```json
"axios": "0.21.0",
```
1. In the **Terminal** pane, run the following command to install the dependency added to the
`package.json` file.
```plaintext
yarn install
```
1. In the **Terminal** pane, run the following commands to commit your changes. This triggers a
CI/CD pipeline on GitLab.
```plaintext
git add package.json yarn.lock
git commit -m "Add dependency"
git push --set-upstream origin add_dependency
```
1. Switch to the GitLab browser tab.
1. Go to **Merge requests**, then select **Create merge request**.
1. On the **New merge request** page, scroll to the bottom and select **Create merge request**.
Wait for the merge request pipeline to complete, then refresh the page. The merge
request security widget warns of new potential vulnerabilities. These vulnerabilities exist
only in the `add_dependency` branch, not the `main` branch.
You now know how to:
- Detect vulnerabilities in an application's dependencies.
- Triage and resolve vulnerabilities.
- Detect new vulnerabilities in a merge request.
### Yarn lock file content
```yaml
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
abstract-logging@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839"
integrity sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==
ajv@^6.10.2, ajv@^6.11.0, ajv@^6.12.0:
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
dependencies:
fast-deep-equal "^3.1.1"
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
archy@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40"
integrity sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==
atomic-sleep@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b"
integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==
avvio@^6.3.1:
version "6.5.0"
resolved "https://registry.yarnpkg.com/avvio/-/avvio-6.5.0.tgz#d2cf119967fe90d2156afc29de350ced800cdaab"
integrity sha512-BmzcZ7gFpyFJsW8G+tfQw8vJNUboA9SDkkHLZ9RAALhvw/rplfWwni8Ee1rA11zj/J7/E5EvZmweusVvTHjWCA==
dependencies:
archy "^1.0.0"
debug "^4.0.0"
fastq "^1.6.0"
cookie@^0.4.0:
version "0.4.2"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432"
integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==
debug@2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
dependencies:
ms "2.0.0"
debug@^4.0.0:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"
deepmerge@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==
depd@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==
destroy@~1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
integrity sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
encodeurl@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
escape-html@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
etag@~1.8.1:
version "1.8.1"
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
fast-decode-uri-component@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz#46f8b6c22b30ff7a81357d4f59abfae938202543"
integrity sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==
fast-deep-equal@^3.1.1:
version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
fast-json-stable-stringify@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
fast-json-stringify@^1.18.0:
version "1.21.0"
resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-1.21.0.tgz#51bc8c6d77d8c7b2cc7e5fa754f7f909f9e1262f"
integrity sha512-xY6gyjmHN3AK1Y15BCbMpeO9+dea5ePVsp3BouHCdukcx0hOHbXwFhRodhcI0NpZIgDChSeAKkHW9YjKvhwKBA==
dependencies:
ajv "^6.11.0"
deepmerge "^4.2.2"
string-similarity "^4.0.1"
fast-redact@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-2.1.0.tgz#dfe3c1ca69367fb226f110aa4ec10ec85462ffdf"
integrity sha512-0LkHpTLyadJavq9sRzzyqIoMZemWli77K2/MGOkafrR64B9ItrvZ9aT+jluvNDsv0YEHjSNhlMBtbokuoqii4A==
fast-safe-stringify@^2.0.7:
version "2.1.1"
resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884"
integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==
fastify-plugin@^1.2.0:
version "1.6.1"
resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-1.6.1.tgz#122f5a5eeb630d55c301713145a9d188e6d5dd5b"
integrity sha512-APBcb27s+MjaBIerFirYmBLatoPCgmHZM6XP0K+nDL9k0yX8NJPWDY1RAC3bh6z+AB5ULS2j31BUfLMT3uaZ4A==
dependencies:
semver "^6.3.0"
fastify-static@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/fastify-static/-/fastify-static-2.0.0.tgz#674f3f3180e8b055e5e1ee1bcee68114cfb09a8f"
integrity sha512-8YQ4QWcSR3YJTFLpExXIej2GzCHThowyLUUxt1uZN8rBEEI2T2ZcaRXPmkaNcaUiKzLXceGjdbJm5yByp5dlkA==
dependencies:
fastify-plugin "^1.2.0"
readable-stream "^3.0.2"
send "^0.16.0"
fastify@2.14.1:
version "2.14.1"
resolved "https://registry.yarnpkg.com/fastify/-/fastify-2.14.1.tgz#2946e8e9adebcd1b4f634178c8fb7162fb816cf4"
integrity sha512-nSL8AgIdFCpZmFwjqB5Zzv+3/1KpwwVtB/h88Q4Og8njYbkddKGpuQlQ2tHUULXPTJrLZ7wop6olzx6HEbHdpw==
dependencies:
abstract-logging "^2.0.0"
ajv "^6.12.0"
avvio "^6.3.1"
fast-json-stringify "^1.18.0"
find-my-way "^2.2.2"
flatstr "^1.0.12"
light-my-request "^3.7.3"
middie "^4.1.0"
pino "^5.17.0"
proxy-addr "^2.0.6"
readable-stream "^3.6.0"
rfdc "^1.1.2"
secure-json-parse "^2.1.0"
tiny-lru "^7.0.2"
fastq@^1.6.0:
version "1.13.0"
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c"
integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==
dependencies:
reusify "^1.0.4"
find-my-way@^2.2.2:
version "2.2.5"
resolved "https://registry.yarnpkg.com/find-my-way/-/find-my-way-2.2.5.tgz#86ce825266fa28cd962e538a45ec2aaa84c3d514"
integrity sha512-GjRZZlGcGmTh9t+6Xrj5K0YprpoAFCAiCPgmAH9Kb09O4oX6hYuckDfnDipYj+Q7B1GtYWSzDI5HEecNYscLQg==
dependencies:
fast-decode-uri-component "^1.0.0"
safe-regex2 "^2.0.0"
semver-store "^0.3.0"
flatstr@^1.0.12:
version "1.0.12"
resolved "https://registry.yarnpkg.com/flatstr/-/flatstr-1.0.12.tgz#c2ba6a08173edbb6c9640e3055b95e287ceb5931"
integrity sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==
forwarded@0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
fresh@0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==
http-errors@~1.6.2:
version "1.6.3"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d"
integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==
dependencies:
depd "~1.1.2"
inherits "2.0.3"
setprototypeof "1.1.0"
statuses ">= 1.4.0 < 2"
inherits@2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==
inherits@^2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
ipaddr.js@1.9.1:
version "1.9.1"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
json-schema-traverse@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
light-my-request@^3.7.3:
version "3.8.0"
resolved "https://registry.yarnpkg.com/light-my-request/-/light-my-request-3.8.0.tgz#7da96786e4d479371b25cfd524ee05d5d583dae8"
integrity sha512-cIOWmNsgoStysmkzcv2EwvLwMb2hEm6oqKMerG/b5ey9F0we2Qony8cAZgBktmGPYUvPyKsDCzMcYU6fXbpWew==
dependencies:
ajv "^6.10.2"
cookie "^0.4.0"
readable-stream "^3.4.0"
set-cookie-parser "^2.4.1"
middie@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/middie/-/middie-4.1.0.tgz#0fe986c83d5081489514ca1a2daba5ca36263436"
integrity sha512-eylPpZA+K3xO9kpDjagoPkEUkNcWV3EAo5OEz0MqsekUpT7KbnQkk8HNZkh4phx2vvOAmNNZuLRWF9lDDHPpVQ==
dependencies:
path-to-regexp "^4.0.0"
reusify "^1.0.2"
mime@1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
on-finished@~2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==
dependencies:
ee-first "1.1.1"
path-to-regexp@^4.0.0:
version "4.0.5"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-4.0.5.tgz#2d4fd140af9a369bf7b68f77a7fdc340490f4239"
integrity sha512-l+fTaGG2N9ZRpCEUj5fG1VKdDLaiqwCIvPngpnxzREhcdobhZC4ou4w984HBu72DqAJ5CfcdV6tjqNOunfpdsQ==
pino-std-serializers@^2.4.2:
version "2.5.0"
resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-2.5.0.tgz#40ead781c65a0ce7ecd9c1c33f409d31fe712315"
integrity sha512-wXqbqSrIhE58TdrxxlfLwU9eDhrzppQDvGhBEr1gYbzzM4KKo3Y63gSjiDXRKLVS2UOXdPNR2v+KnQgNrs+xUg==
pino@^5.17.0:
version "5.17.0"
resolved "https://registry.yarnpkg.com/pino/-/pino-5.17.0.tgz#b9def314e82402154f89a25d76a31f20ca84b4c8"
integrity sha512-LqrqmRcJz8etUjyV0ddqB6OTUutCgQULPFg2b4dtijRHUsucaAdBgSUW58vY6RFSX+NT8963F+q0tM6lNwGShA==
dependencies:
fast-redact "^2.0.0"
fast-safe-stringify "^2.0.7"
flatstr "^1.0.12"
pino-std-serializers "^2.4.2"
quick-format-unescaped "^3.0.3"
sonic-boom "^0.7.5"
proxy-addr@^2.0.6:
version "2.0.7"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==
dependencies:
forwarded "0.2.0"
ipaddr.js "1.9.1"
punycode@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
quick-format-unescaped@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-3.0.3.tgz#fb3e468ac64c01d22305806c39f121ddac0d1fb9"
integrity sha512-dy1yjycmn9blucmJLXOfZDx1ikZJUi6E8bBZLnhPG5gBrVhHXx2xVyqqgKBubVNEXmx51dBACMHpoMQK/N/AXQ==
range-parser@~1.2.0:
version "1.2.1"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
readable-stream@^3.0.2, readable-stream@^3.4.0, readable-stream@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
dependencies:
inherits "^2.0.3"
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
ret@~0.2.0:
version "0.2.2"
resolved "https://registry.yarnpkg.com/ret/-/ret-0.2.2.tgz#b6861782a1f4762dce43402a71eb7a283f44573c"
integrity sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==
reusify@^1.0.2, reusify@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
rfdc@^1.1.2:
version "1.3.0"
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b"
integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==
safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
safe-regex2@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/safe-regex2/-/safe-regex2-2.0.0.tgz#b287524c397c7a2994470367e0185e1916b1f5b9"
integrity sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==
dependencies:
ret "~0.2.0"
secure-json-parse@^2.1.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.5.0.tgz#f929829df2adc7ccfb53703569894d051493a6ac"
integrity sha512-ZQruFgZnIWH+WyO9t5rWt4ZEGqCKPwhiw+YbzTwpmT9elgLrLcfuyUiSnwwjUiVy9r4VM3urtbNF1xmEh9IL2w==
semver-store@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/semver-store/-/semver-store-0.3.0.tgz#ce602ff07df37080ec9f4fb40b29576547befbe9"
integrity sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg==
semver@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
send@^0.16.0:
version "0.16.2"
resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==
dependencies:
debug "2.6.9"
depd "~1.1.2"
destroy "~1.0.4"
encodeurl "~1.0.2"
escape-html "~1.0.3"
etag "~1.8.1"
fresh "0.5.2"
http-errors "~1.6.2"
mime "1.4.1"
ms "2.0.0"
on-finished "~2.3.0"
range-parser "~1.2.0"
statuses "~1.4.0"
set-cookie-parser@^2.4.1:
version "2.5.1"
resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.5.1.tgz#ddd3e9a566b0e8e0862aca974a6ac0e01349430b"
integrity sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==
setprototypeof@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==
sonic-boom@^0.7.5:
version "0.7.7"
resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-0.7.7.tgz#d921de887428208bfa07b0ae32c278de043f350a"
integrity sha512-Ei5YOo5J64GKClHIL/5evJPgASXFVpfVYbJV9PILZQytTK6/LCwHvsZJW2Ig4p9FMC2OrBrMnXKgRN/OEoAWfg==
dependencies:
atomic-sleep "^1.0.0"
flatstr "^1.0.12"
"statuses@>= 1.4.0 < 2":
version "1.5.0"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==
statuses@~1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==
string-similarity@^4.0.1:
version "4.0.4"
resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b"
integrity sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==
string_decoder@^1.1.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
dependencies:
safe-buffer "~5.2.0"
tiny-lru@^7.0.2:
version "7.0.6"
resolved "https://registry.yarnpkg.com/tiny-lru/-/tiny-lru-7.0.6.tgz#b0c3cdede1e5882aa2d1ae21cb2ceccf2a331f24"
integrity sha512-zNYO0Kvgn5rXzWpL0y3RS09sMK67eGaQj9805jlK9G6pSadfriTczzLHFXa/xcW4mIRfmlB9HyQ/+SgL0V1uow==
uri-js@^4.2.2:
version "4.4.1"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
dependencies:
punycode "^2.1.0"
util-deprecate@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
```

View File

@ -32,7 +32,7 @@ The ability to create project access tokens without expiry was [deprecated](http
You can use project access tokens:
- On GitLab SaaS: If you have the Premium or Ultimate license tier. Project access tokens are not available with a [trial license](https://about.gitlab.com/free-trial/).
- On GitLab SaaS: If you have the Premium or Ultimate license tier. Only one project access token is available with a [trial license](https://about.gitlab.com/free-trial/).
- On self-managed instances of GitLab: With any license tier. If you have the Free tier:
- Review your security and compliance policies around
[user self-enrollment](../../admin_area/settings/sign_up_restrictions.md#disable-new-sign-ups).
@ -139,4 +139,4 @@ See also [Bot users for groups](../../group/settings/group_access_tokens.md#bot-
## Token availability
Project access tokens are only available in paid subscriptions, and not available in trial subscriptions. For more information, see the ["What is included" section of the GitLab Trial FAQ](https://about.gitlab.com/free-trial/#what-is-included-in-my-free-trial-what-is-excluded).
More than one project access token is only available in paid subscriptions, and only one is available in trial subscriptions. For more information, see the ["What is included" section of the GitLab Trial FAQ](https://about.gitlab.com/free-trial/#what-is-included-in-my-free-trial-what-is-excluded).

View File

@ -0,0 +1,99 @@
# frozen_string_literal: true
module Gitlab
module BackgroundMigration
# Backfill the following columns on the namespace_root_storage_statistics table:
# - public_forks_storage_size
# - internal_forks_storage_size
# - private_forks_storage_size
class BackfillRootStorageStatisticsForkStorageSizes < BatchedMigrationJob
operation_name :backfill_root_storage_statistics_fork_sizes
feature_category :consumables_cost_management
VISIBILITY_LEVELS_TO_STORAGE_SIZE_COLUMNS = {
0 => :private_forks_storage_size,
10 => :internal_forks_storage_size,
20 => :public_forks_storage_size
}.freeze
def perform
each_sub_batch do |sub_batch|
sub_batch.each do |root_storage_statistics|
next if has_fork_data?(root_storage_statistics)
namespace_id = root_storage_statistics.namespace_id
namespace_type = execute("SELECT type FROM namespaces WHERE id = #{namespace_id}").first&.fetch('type')
next if namespace_type.nil?
sql = if user_namespace?(namespace_type)
user_namespace_sql(namespace_id)
else
group_namespace_sql(namespace_id)
end
stats = execute(sql)
.map { |h| { h['projects_visibility_level'] => h['sum_project_statistics_storage_size'] } }
.reduce({}) { |memo, h| memo.merge(h) }
.transform_keys { |k| VISIBILITY_LEVELS_TO_STORAGE_SIZE_COLUMNS[k] }
root_storage_statistics.update!(stats)
end
end
end
def has_fork_data?(root_storage_statistics)
root_storage_statistics.public_forks_storage_size != 0 ||
root_storage_statistics.internal_forks_storage_size != 0 ||
root_storage_statistics.private_forks_storage_size != 0
end
def user_namespace?(type)
type.nil? || type == 'User' || !(type == 'Group' || type == 'Project')
end
def execute(sql)
::ApplicationRecord.connection.execute(sql)
end
def user_namespace_sql(namespace_id)
<<~SQL
SELECT
SUM("project_statistics"."storage_size") AS sum_project_statistics_storage_size,
"projects"."visibility_level" AS projects_visibility_level
FROM
"projects"
INNER JOIN "project_statistics" ON "project_statistics"."project_id" = "projects"."id"
INNER JOIN "fork_network_members" ON "fork_network_members"."project_id" = "projects"."id"
INNER JOIN "fork_networks" ON "fork_networks"."id" = "fork_network_members"."fork_network_id"
WHERE
"projects"."namespace_id" = #{namespace_id}
AND (fork_networks.root_project_id != projects.id)
GROUP BY "projects"."visibility_level"
SQL
end
def group_namespace_sql(namespace_id)
<<~SQL
SELECT
SUM("project_statistics"."storage_size") AS sum_project_statistics_storage_size,
"projects"."visibility_level" AS projects_visibility_level
FROM
"projects"
INNER JOIN "project_statistics" ON "project_statistics"."project_id" = "projects"."id"
INNER JOIN "fork_network_members" ON "fork_network_members"."project_id" = "projects"."id"
INNER JOIN "fork_networks" ON "fork_networks"."id" = "fork_network_members"."fork_network_id"
WHERE
"projects"."namespace_id" IN (
SELECT namespaces.traversal_ids[array_length(namespaces.traversal_ids, 1)] AS id
FROM "namespaces"
WHERE "namespaces"."type" = 'Group' AND (traversal_ids @> ('{#{namespace_id}}'))
)
AND (fork_networks.root_project_id != projects.id)
GROUP BY "projects"."visibility_level"
SQL
end
end
end
end

View File

@ -0,0 +1,37 @@
# frozen_string_literal: true
module Gitlab
module Database
class ConvertFeatureCategoryToGroupLabel
STAGES_URL = 'https://gitlab.com/gitlab-com/www-gitlab-com/-/raw/master/data/stages.yml'
def initialize(feature_category)
@feature_category = feature_category
end
def execute
feature_categories_map[feature_category]
end
private
attr_reader :feature_category
def stages
response = Gitlab::HTTP.get(STAGES_URL)
YAML.safe_load(response) if response.success?
end
def feature_categories_map
stages['stages'].each_with_object({}) do |(_, stage), result|
stage['groups'].each do |group_name, group|
group['categories'].each do |category|
result[category] = "group::#{group_name.sub('_', ' ')}"
end
end
end
end
end
end
end

View File

@ -41,7 +41,7 @@ module Gitlab
title: issue_title,
description: description,
issue_type: 'issue',
labels: %w[database database-inconsistency-report]
labels: default_labels + group_labels
}
end
@ -84,6 +84,24 @@ module Gitlab
MSG
end
def group_labels
dictionary = YAML.safe_load(File.read(table_file_path))
dictionary['feature_categories'].to_a.filter_map do |feature_category|
Gitlab::Database::ConvertFeatureCategoryToGroupLabel.new(feature_category).execute
end
rescue Errno::ENOENT
[]
end
def default_labels
%w[database database-inconsistency-report type::maintenance severity::4]
end
def table_file_path
Rails.root.join(Gitlab::Database::GitlabSchema.dictionary_paths.first, "#{inconsistency.table_name}.yml")
end
def schema_inconsistency_model
Gitlab::Database::SchemaValidation::SchemaInconsistency
end

View File

@ -59,7 +59,14 @@ module QA
project.visit!
end
it 'lists branches correctly after CRUD operations', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347740' do
it(
'lists branches correctly after CRUD operations',
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347740',
quarantine: {
issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/414026',
type: :stale
}
) do
Page::Project::Menu.perform(&:go_to_repository_branches)
expect(page).to have_content(master_branch)

10
spec/fixtures/achievements.yml vendored Normal file
View File

@ -0,0 +1,10 @@
---
table_name: achievements
classes:
- Achievements::Achievement
feature_categories:
- feature_category_example
description: Achievements which can be created by namespaces to award them to users
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105871
milestone: '15.7'
gitlab_schema: gitlab_main

View File

@ -1,5 +1,4 @@
import MockAdapter from 'axios-mock-adapter';
import { shallowMount, mount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import { GlBadge, GlModal, GlToast } from '@gitlab/ui';
import JobItem from '~/pipelines/components/graph/job_item.vue';
@ -7,7 +6,7 @@ import axios from '~/lib/utils/axios_utils';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import ActionComponent from '~/pipelines/components/jobs_shared/action_component.vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
import {
delayedJob,
mockJob,
@ -44,23 +43,21 @@ describe('pipeline graph job item', () => {
job: mockJob,
};
const createWrapper = ({ props, data, mountFn = mount, mocks = {} } = {}) => {
wrapper = extendedWrapper(
mountFn(JobItem, {
data() {
return {
...data,
};
},
propsData: {
...defaultProps,
...props,
},
mocks: {
...mocks,
},
}),
);
const createWrapper = ({ props, data, mountFn = mountExtended, mocks = {} } = {}) => {
wrapper = mountFn(JobItem, {
data() {
return {
...data,
};
},
propsData: {
...defaultProps,
...props,
},
mocks: {
...mocks,
},
});
};
const triggerActiveClass = 'gl-shadow-x0-y0-b3-s1-blue-500';
@ -219,7 +216,7 @@ describe('pipeline graph job item', () => {
});
expect(findJobWithLink().attributes('title')).toBe(
`delayed job - delayed manual action (${wrapper.vm.remainingTime})`,
`delayed job - delayed manual action (00:00:00)`,
);
});
});
@ -249,10 +246,7 @@ describe('pipeline graph job item', () => {
beforeEach(async () => {
createWrapper({
mountFn: shallowMount,
data: {
currentSkipModalValue: true,
},
mountFn: shallowMountExtended,
props: {
skipRetryModal: true,
job: triggerJobWithRetryAction,
@ -264,8 +258,6 @@ describe('pipeline graph job item', () => {
},
});
jest.spyOn(wrapper.vm.$toast, 'show');
await findActionVueComponent().vm.$emit('pipelineActionRequestComplete');
await nextTick();
});

View File

@ -0,0 +1,302 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::BackfillRootStorageStatisticsForkStorageSizes, schema: 20230517163300, feature_category: :consumables_cost_management do # rubocop:disable Layout/LineLength
describe '#perform' do
let(:namespaces_table) { table(:namespaces) }
let(:root_storage_statistics_table) { table(:namespace_root_storage_statistics) }
let(:projects_table) { table(:projects) }
let(:project_statistics_table) { table(:project_statistics) }
let(:fork_networks_table) { table(:fork_networks) }
let(:fork_network_members_table) { table(:fork_network_members) }
it 'updates the public_forks_storage_size' do
namespace, root_storage_statistics = create_namespace!
project = create_project!(namespace: namespace, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
create_fork!(project, storage_size: 100)
migrate
expect(root_storage_statistics.reload.public_forks_storage_size).to eq(100)
end
it 'totals the size of public forks in the namespace' do
namespace, root_storage_statistics = create_namespace!
project = create_project!(namespace: namespace, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
create_fork!(project, name: 'my fork', storage_size: 100)
create_fork!(project, name: 'my other fork', storage_size: 100)
migrate
expect(root_storage_statistics.reload.public_forks_storage_size).to eq(200)
end
it 'updates the internal_forks_storage_size' do
namespace, root_storage_statistics = create_namespace!
project = create_project!(namespace: namespace, visibility_level: Gitlab::VisibilityLevel::INTERNAL)
create_fork!(project, storage_size: 250)
migrate
expect(root_storage_statistics.reload.internal_forks_storage_size).to eq(250)
end
it 'totals the size of internal forks in the namespace' do
namespace, root_storage_statistics = create_namespace!
project = create_project!(namespace: namespace, visibility_level: Gitlab::VisibilityLevel::INTERNAL)
create_fork!(project, name: 'my fork', storage_size: 300)
create_fork!(project, name: 'my other fork', storage_size: 300)
migrate
expect(root_storage_statistics.reload.internal_forks_storage_size).to eq(600)
end
it 'updates the private_forks_storage_size' do
namespace, root_storage_statistics = create_namespace!
project = create_project!(namespace: namespace, visibility_level: Gitlab::VisibilityLevel::PRIVATE)
create_fork!(project, storage_size: 50)
migrate
expect(root_storage_statistics.reload.private_forks_storage_size).to eq(50)
end
it 'totals the size of private forks in the namespace' do
namespace, root_storage_statistics = create_namespace!
project = create_project!(namespace: namespace, visibility_level: Gitlab::VisibilityLevel::PRIVATE)
create_fork!(project, name: 'my fork', storage_size: 350)
create_fork!(project, name: 'my other fork', storage_size: 400)
migrate
expect(root_storage_statistics.reload.private_forks_storage_size).to eq(750)
end
it 'counts only the size of forks' do
namespace, root_storage_statistics = create_namespace!
project = create_project!(namespace: namespace, storage_size: 100,
visibility_level: Gitlab::VisibilityLevel::PUBLIC)
create_fork!(project, name: 'my public fork', storage_size: 150,
visibility_level: Gitlab::VisibilityLevel::PUBLIC)
create_fork!(project, name: 'my internal fork', storage_size: 250,
visibility_level: Gitlab::VisibilityLevel::INTERNAL)
create_fork!(project, name: 'my private fork', storage_size: 350,
visibility_level: Gitlab::VisibilityLevel::PRIVATE)
migrate
root_storage_statistics.reload
expect(root_storage_statistics.public_forks_storage_size).to eq(150)
expect(root_storage_statistics.internal_forks_storage_size).to eq(250)
expect(root_storage_statistics.private_forks_storage_size).to eq(350)
end
it 'sums forks for multiple namespaces' do
namespace_a, root_storage_statistics_a = create_namespace!
namespace_b, root_storage_statistics_b = create_namespace!
project = create_project!(namespace: namespace_a)
create_fork!(project, namespace: namespace_a, storage_size: 100)
create_fork!(project, namespace: namespace_b, storage_size: 200)
migrate
expect(root_storage_statistics_a.reload.private_forks_storage_size).to eq(100)
expect(root_storage_statistics_b.reload.private_forks_storage_size).to eq(200)
end
it 'counts the size of forks in subgroups' do
group, root_storage_statistics = create_group!
subgroup = create_group!(parent: group)
project = create_project!(namespace: group, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
create_fork!(project, namespace: subgroup, name: 'my fork A',
storage_size: 123, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
create_fork!(project, namespace: subgroup, name: 'my fork B',
storage_size: 456, visibility_level: Gitlab::VisibilityLevel::INTERNAL)
create_fork!(project, namespace: subgroup, name: 'my fork C',
storage_size: 789, visibility_level: Gitlab::VisibilityLevel::PRIVATE)
migrate
root_storage_statistics.reload
expect(root_storage_statistics.public_forks_storage_size).to eq(123)
expect(root_storage_statistics.internal_forks_storage_size).to eq(456)
expect(root_storage_statistics.private_forks_storage_size).to eq(789)
end
it 'counts the size of forks in more nested subgroups' do
root, root_storage_statistics = create_group!
child = create_group!(parent: root)
grand_child = create_group!(parent: child)
great_grand_child = create_group!(parent: grand_child)
project = create_project!(namespace: root, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
create_fork!(project, namespace: grand_child, name: 'my fork A',
storage_size: 200, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
create_fork!(project, namespace: great_grand_child, name: 'my fork B',
storage_size: 300, visibility_level: Gitlab::VisibilityLevel::INTERNAL)
create_fork!(project, namespace: great_grand_child, name: 'my fork C',
storage_size: 400, visibility_level: Gitlab::VisibilityLevel::PRIVATE)
migrate
root_storage_statistics.reload
expect(root_storage_statistics.public_forks_storage_size).to eq(200)
expect(root_storage_statistics.internal_forks_storage_size).to eq(300)
expect(root_storage_statistics.private_forks_storage_size).to eq(400)
end
it 'counts forks of forks' do
group, root_storage_statistics = create_group!
other_group, other_root_storage_statistics = create_group!
project = create_project!(namespace: group)
fork_a = create_fork!(project, namespace: group, storage_size: 100)
fork_b = create_fork!(fork_a, name: 'my other fork', namespace: group, storage_size: 50)
create_fork!(fork_b, namespace: other_group, storage_size: 27)
migrate
expect(root_storage_statistics.reload.private_forks_storage_size).to eq(150)
expect(other_root_storage_statistics.reload.private_forks_storage_size).to eq(27)
end
it 'counts multiple forks of the same project' do
group, root_storage_statistics = create_group!
project = create_project!(namespace: group)
create_fork!(project, storage_size: 200)
create_fork!(project, name: 'my other fork', storage_size: 88)
migrate
expect(root_storage_statistics.reload.private_forks_storage_size).to eq(288)
end
it 'updates a namespace with no forks' do
namespace, root_storage_statistics = create_namespace!
create_project!(namespace: namespace)
migrate
root_storage_statistics.reload
expect(root_storage_statistics.public_forks_storage_size).to eq(0)
expect(root_storage_statistics.internal_forks_storage_size).to eq(0)
expect(root_storage_statistics.private_forks_storage_size).to eq(0)
end
it 'skips the update if the public_forks_storage_size has already been set' do
namespace, root_storage_statistics = create_namespace!
project = create_project!(namespace: namespace, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
create_fork!(project, storage_size: 200)
root_storage_statistics.update!(public_forks_storage_size: 100)
migrate
root_storage_statistics.reload
expect(root_storage_statistics.public_forks_storage_size).to eq(100)
end
it 'skips the update if the internal_forks_storage_size has already been set' do
namespace, root_storage_statistics = create_namespace!
project = create_project!(namespace: namespace, visibility_level: Gitlab::VisibilityLevel::INTERNAL)
create_fork!(project, storage_size: 200)
root_storage_statistics.update!(internal_forks_storage_size: 100)
migrate
root_storage_statistics.reload
expect(root_storage_statistics.internal_forks_storage_size).to eq(100)
end
it 'skips the update if the private_forks_storage_size has already been set' do
namespace, root_storage_statistics = create_namespace!
project = create_project!(namespace: namespace, visibility_level: Gitlab::VisibilityLevel::PRIVATE)
create_fork!(project, storage_size: 200)
root_storage_statistics.update!(private_forks_storage_size: 100)
migrate
root_storage_statistics.reload
expect(root_storage_statistics.private_forks_storage_size).to eq(100)
end
it 'skips the update if the namespace is not found' do
namespace, root_storage_statistics = create_namespace!
project = create_project!(namespace: namespace)
create_fork!(project, storage_size: 100)
allow(::ApplicationRecord.connection).to receive(:execute)
.with("SELECT type FROM namespaces WHERE id = #{namespace.id}")
.and_return([])
migrate
root_storage_statistics.reload
expect(root_storage_statistics.public_forks_storage_size).to eq(0)
expect(root_storage_statistics.internal_forks_storage_size).to eq(0)
expect(root_storage_statistics.private_forks_storage_size).to eq(0)
end
end
def create_namespace!(name: 'abc', path: 'abc')
namespace = namespaces_table.create!(name: name, path: path)
namespace.update!(traversal_ids: [namespace.id])
root_storage_statistics = root_storage_statistics_table.create!(namespace_id: namespace.id)
[namespace, root_storage_statistics]
end
def create_group!(name: 'abc', path: 'abc', parent: nil)
parent_id = parent.try(:id)
group = namespaces_table.create!(name: name, path: path, type: 'Group', parent_id: parent_id)
if parent_id
parent_traversal_ids = namespaces_table.find(parent_id).traversal_ids
group.update!(traversal_ids: parent_traversal_ids + [group.id])
group
else
group.update!(traversal_ids: [group.id])
root_storage_statistics = root_storage_statistics_table.create!(namespace_id: group.id)
[group, root_storage_statistics]
end
end
def create_project!(
namespace:, storage_size: 100, name: 'my project',
visibility_level: Gitlab::VisibilityLevel::PRIVATE)
project_namespace = namespaces_table.create!(name: name, path: name)
project = projects_table.create!(name: name, namespace_id: namespace.id, project_namespace_id: project_namespace.id,
visibility_level: visibility_level)
project_statistics_table.create!(project_id: project.id, namespace_id: project.namespace_id,
storage_size: storage_size)
project
end
def create_fork!(project, storage_size:, name: 'my fork', visibility_level: nil, namespace: nil)
fork_namespace = namespace || namespaces_table.find(project.namespace_id)
fork_visibility_level = visibility_level || project.visibility_level
project_fork = create_project!(name: name, namespace: fork_namespace,
visibility_level: fork_visibility_level, storage_size: storage_size)
fork_network_id = if membership = fork_network_members_table.find_by(project_id: project.id)
membership.fork_network_id
else
fork_network = fork_networks_table.create!(root_project_id: project.id)
fork_network_members_table.create!(fork_network_id: fork_network.id, project_id: project.id)
fork_network.id
end
fork_network_members_table.create!(fork_network_id: fork_network_id, project_id: project_fork.id,
forked_from_project_id: project.id)
project_fork
end
def migrate
described_class.new(start_id: 1, end_id: root_storage_statistics_table.last.id,
batch_table: 'namespace_root_storage_statistics',
batch_column: 'namespace_id',
sub_batch_size: 100, pause_ms: 0,
connection: ApplicationRecord.connection).perform
end
end

View File

@ -0,0 +1,34 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Database::ConvertFeatureCategoryToGroupLabel, feature_category: :database do
describe '#execute' do
subject(:group_label) { described_class.new(feature_category).execute }
let_it_be(:stages_fixture) do
{ stages: { manage: { groups: { database: { categories: ['database'] } } } } }
end
before do
stub_request(:get, 'https://gitlab.com/gitlab-com/www-gitlab-com/-/raw/master/data/stages.yml')
.to_return(status: 200, body: stages_fixture.to_json, headers: {})
end
context 'when the group label exists' do
let(:feature_category) { 'database' }
it 'returns a group label' do
expect(group_label).to eql 'group::database'
end
end
context 'when the group label does not exist' do
let(:feature_category) { 'non_existing_feature_category_test' }
it 'returns nil' do
expect(group_label).to be nil
end
end
end
end

View File

@ -39,7 +39,12 @@ RSpec.describe Gitlab::Database::SchemaValidation::TrackInconsistency, feature_c
context 'when the issue creation fails' do
let(:issue_creation) { instance_double(Mutations::Issues::Create, resolve: { errors: 'error' }) }
let(:convert_object) do
instance_double('Gitlab::Database::ConvertFeatureCategoryToGroupLabel', execute: 'group_label')
end
before do
allow(Gitlab::Database::ConvertFeatureCategoryToGroupLabel).to receive(:new).and_return(convert_object)
allow(Mutations::Issues::Create).to receive(:new).and_return(issue_creation)
end
@ -51,7 +56,12 @@ RSpec.describe Gitlab::Database::SchemaValidation::TrackInconsistency, feature_c
end
context 'when a new inconsistency is found' do
let(:convert_object) do
instance_double('Gitlab::Database::ConvertFeatureCategoryToGroupLabel', execute: 'group_label')
end
before do
allow(Gitlab::Database::ConvertFeatureCategoryToGroupLabel).to receive(:new).and_return(convert_object)
project.add_developer(user)
end
@ -116,6 +126,15 @@ RSpec.describe Gitlab::Database::SchemaValidation::TrackInconsistency, feature_c
end
context 'when the GitLab is not open' do
let(:convert_object) do
instance_double('Gitlab::Database::ConvertFeatureCategoryToGroupLabel', execute: 'group_label')
end
before do
allow(Gitlab::Database::ConvertFeatureCategoryToGroupLabel).to receive(:new).and_return(convert_object)
project.add_developer(user)
end
it 'creates a new schema inconsistency record' do
allow(Gitlab).to receive(:com?).and_return(true)
schema_inconsistency.issue.update!(state_id: Issue.available_states[:closed])
@ -124,5 +143,47 @@ RSpec.describe Gitlab::Database::SchemaValidation::TrackInconsistency, feature_c
end
end
end
context 'when the dictionary file is not present' do
before do
allow(Gitlab::Database::GitlabSchema).to receive(:dictionary_paths).and_return(['dictionary_not_found_path/'])
project.add_developer(user)
end
it 'add the default labels' do
allow(Gitlab).to receive(:com?).and_return(true)
inconsistency = execute
labels = inconsistency.issue.labels.map(&:name)
expect(labels).to eq %w[database database-inconsistency-report type::maintenance severity::4]
end
end
context 'when dictionary feature_categories are available' do
let(:convert_object) do
instance_double('Gitlab::Database::ConvertFeatureCategoryToGroupLabel', execute: 'group_label')
end
before do
allow(Gitlab::Database::ConvertFeatureCategoryToGroupLabel).to receive(:new).and_return(convert_object)
allow(Gitlab::Database::GitlabSchema).to receive(:dictionary_paths).and_return(['spec/fixtures/'])
project.add_developer(user)
end
it 'add the default labels + group labels' do
allow(Gitlab).to receive(:com?).and_return(true)
inconsistency = execute
labels = inconsistency.issue.labels.map(&:name)
expect(labels).to eq %w[database database-inconsistency-report type::maintenance severity::4 group_label]
end
end
end
end

View File

@ -0,0 +1,26 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe QueueBackfillRootStorageStatisticsForkStorageSizes, feature_category: :consumables_cost_management do
let!(:batched_migration) { described_class::MIGRATION }
it 'schedules a new batched migration' do
reversible_migration do |migration|
migration.before -> {
expect(batched_migration).not_to have_scheduled_batched_migration
}
migration.after -> {
expect(batched_migration).to have_scheduled_batched_migration(
table_name: :namespace_root_storage_statistics,
column_name: :namespace_id,
interval: described_class::DELAY_INTERVAL,
batch_size: described_class::BATCH_SIZE,
sub_batch_size: described_class::SUB_BATCH_SIZE
)
}
end
end
end