Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-03-27 15:10:52 +00:00
parent cc310f2111
commit ef111ed730
46 changed files with 356 additions and 293 deletions

View File

@ -36,6 +36,7 @@ workflow:
GITLAB_ADMIN_USERNAME: root
GITLAB_ADMIN_PASSWORD: 5iveL!fe
GITLAB_QA_ADMIN_ACCESS_TOKEN: $QA_ADMIN_ACCESS_TOKEN
KNAPSACK_TEST_FILE_PATTERN: ""
QA_DOCKER_NETWORK: host
QA_GENERATE_ALLURE_REPORT: "true"
QA_CAN_TEST_PRAEFECT: "false"
@ -50,7 +51,7 @@ workflow:
- deploy "${GITLAB_DOMAIN}"
- cd qa && bundle install
script:
- export QA_COMMAND="bundle exec bin/qa ${QA_SCENARIO:=Test::Instance::All} $QA_GITLAB_URL -- $QA_TESTS --force-color --order random --format documentation --format RspecJunitFormatter --out tmp/rspec-${CI_JOB_ID}.xml"
- export QA_COMMAND="bundle exec bin/qa ${QA_SCENARIO:=Test::Instance::All} $QA_GITLAB_URL -- --force-color --order random --format documentation --format RspecJunitFormatter --out tmp/rspec-${CI_JOB_ID}.xml"
- echo "Running - '$QA_COMMAND'"
- eval "$QA_COMMAND"
after_script:

View File

@ -1,6 +1 @@
import '../main';
import { runModules } from '~/run_modules';
const modules = import.meta.glob('../pages/**/index.js');
runModules(modules, 'CE');

View File

@ -1,5 +0,0 @@
import { runModules } from '~/run_modules';
const modules = import.meta.glob('../../../../ee/app/assets/javascripts/pages/**/index.js');
runModules(modules, 'EE');

View File

@ -1,5 +0,0 @@
import { runModules } from '~/run_modules';
const modules = import.meta.glob('../../../../jh/app/assets/javascripts/pages/**/index.js');
runModules(modules, 'JH');

View File

@ -324,7 +324,9 @@ export default {
</script>
<template>
<div class="detail-page-header-actions gl-display-flex gl-align-self-start gl-sm-gap-3">
<div
class="detail-page-header-actions gl-display-flex gl-align-self-start gl-sm-gap-3 gl-w-full gl-md-w-auto"
>
<div class="gl-md-display-none! gl-w-full">
<gl-disclosure-dropdown
v-if="hasMobileDropdown"
@ -335,7 +337,7 @@ export default {
:auto-close="false"
data-testid="mobile-dropdown"
:loading="isToggleStateButtonLoading"
placement="left"
placement="right"
>
<template v-if="showMovedSidebarOptions && !glFeatures.notificationsTodosButtons">
<sidebar-subscriptions-widget

View File

@ -1,48 +0,0 @@
const paths = [];
const allModules = {};
const prefixes = {
CE: '../pages/',
EE: '../../../../ee/app/assets/javascripts/pages/',
JH: '../../../../jh/app/assets/javascripts/pages/',
};
const editionExcludes = {
JH: [],
EE: [prefixes.JH],
CE: [prefixes.EE, prefixes.JH],
};
const runWithExcludes = (edition) => {
const prefix = prefixes[edition];
const excludes = editionExcludes[edition];
paths.forEach((path) => {
const hasDuplicateEntrypoint = excludes.some(
(editionPrefix) => `${editionPrefix}${path}` in allModules,
);
if (!hasDuplicateEntrypoint) allModules[`${prefix}${path}`]?.();
});
};
let pathsPopulated = false;
const populatePaths = () => {
if (pathsPopulated) return;
paths.push(
...document
.querySelector('meta[name="controller-path"]')
.content.split('/')
.map((part, index, arr) => `${[...arr.slice(0, index), part].join('/')}/index.js`),
);
pathsPopulated = true;
};
export const runModules = (modules, edition) => {
populatePaths();
Object.assign(allModules, modules);
// wait before all modules have been collected to exclude duplicates between CE and EE\JH
// <script> runs as a macrotask, can't schedule with promises here
requestAnimationFrame(() => {
runWithExcludes(edition);
});
};

View File

@ -1,6 +1,6 @@
import { mockGetProjectStorageStatisticsGraphQLResponse } from 'jest/usage_quotas/storage/mock_data';
import createMockApollo from 'helpers/mock_apollo_helper';
import getProjectStorageStatisticsQuery from 'ee_else_ce/usage_quotas/storage/queries/project_storage.query.graphql';
import getProjectStorageStatisticsQuery from 'ee_else_ce/usage_quotas/storage/project/queries/project_storage.query.graphql';
import ProjectStorageApp from './project_storage_app.vue';
const meta = {

View File

@ -5,8 +5,8 @@ import { updateRepositorySize } from '~/api/projects_api';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import SectionedPercentageBar from '~/usage_quotas/components/sectioned_percentage_bar.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import getCostFactoredProjectStorageStatistics from 'ee_else_ce/usage_quotas/storage/queries/cost_factored_project_storage.query.graphql';
import getProjectStorageStatistics from 'ee_else_ce/usage_quotas/storage/queries/project_storage.query.graphql';
import getProjectStorageStatistics from 'ee_else_ce/usage_quotas/storage/project/queries/project_storage.query.graphql';
import getCostFactoredProjectStorageStatistics from 'ee_else_ce/usage_quotas/storage/project/queries/cost_factored_project_storage.query.graphql';
import {
ERROR_MESSAGE,
LEARN_MORE_LABEL,

View File

@ -499,15 +499,6 @@ module ApplicationHelper
end
end
def controller_full_path
action = case controller.action_name
when 'create' then 'new'
when 'update' then 'edit'
else controller.action_name
end
"#{controller.controller_path}/#{action}"
end
private
def browser_id

View File

@ -15,4 +15,17 @@ module ViteHelper
def vite_hmr_http_url
ViteRuby.env['VITE_HMR_HTTP_URL']
end
def vite_page_entrypoint_paths
action = case controller.action_name
when 'create' then 'new'
when 'update' then 'edit'
else controller.action_name
end
parts = (controller.controller_path.split('/') << action)
parts.map
.with_index { |part, idx| "pages.#{(parts[0, idx] << part).join('.')}.js" }
end
end

View File

@ -55,14 +55,9 @@
= webpack_bundle_tag 'performance_bar' if performance_bar_enabled?
- if vite_enabled?
%meta{ name: 'controller-path', content: controller_full_path }
- if Rails.env.development?
= vite_client_tag
= vite_javascript_tag "main"
- if Gitlab.ee?
= vite_javascript_tag "main_ee"
- if Gitlab.jh?
= vite_javascript_tag "main_jh"
= vite_javascript_tag "main", *vite_page_entrypoint_paths
= yield :page_specific_javascripts

View File

@ -1,8 +0,0 @@
---
name: pause_clickhouse_workers_during_migration
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/138166
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/433389
milestone: '16.7'
type: development
group: group::runner
default_enabled: false

View File

@ -1,8 +0,0 @@
---
name: wait_for_clickhouse_workers_during_migration
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/138166
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/433389
milestone: '16.7'
type: development
group: group::runner
default_enabled: false

View File

@ -22,7 +22,6 @@ const BABEL_VERSION = require('@babel/core/package.json').version;
const BABEL_LOADER_VERSION = require('babel-loader/package.json').version;
const CompressionPlugin = require('compression-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const glob = require('glob');
// eslint-disable-next-line import/no-dynamic-require
const { VueLoaderPlugin } = require(VUE_LOADER_MODULE);
// eslint-disable-next-line import/no-dynamic-require
@ -45,6 +44,7 @@ const {
GITLAB_WEB_IDE_PUBLIC_PATH,
copyFilesPatterns,
} = require('./webpack.constants');
const { generateEntries } = require('./webpack.helpers');
const createIncrementalWebpackCompiler = require('./helpers/incremental_webpack_compiler');
const vendorDllHash = require('./helpers/vendor_dll_hash');
@ -90,10 +90,6 @@ if (WEBPACK_REPORT) {
const devtool = IS_PRODUCTION ? 'source-map' : 'cheap-module-eval-source-map';
let autoEntriesCount = 0;
let watchAutoEntries = [];
const defaultEntries = ['./main'];
const incrementalCompiler = createIncrementalWebpackCompiler(
INCREMENTAL_COMPILER_RECORD_HISTORY,
INCREMENTAL_COMPILER_ENABLED,
@ -101,82 +97,6 @@ const incrementalCompiler = createIncrementalWebpackCompiler(
INCREMENTAL_COMPILER_TTL,
);
function generateEntries() {
// generate automatic entry points
const autoEntries = {};
const autoEntriesMap = {};
const pageEntries = glob.sync('pages/**/index.js', {
cwd: path.join(ROOT_PATH, 'app/assets/javascripts'),
});
watchAutoEntries = [path.join(ROOT_PATH, 'app/assets/javascripts/pages/')];
function generateAutoEntries(entryPath, prefix = '.') {
const chunkPath = entryPath.replace(/\/index\.js$/, '');
const chunkName = chunkPath.replace(/\//g, '.');
autoEntriesMap[chunkName] = `${prefix}/${entryPath}`;
}
pageEntries.forEach((entryPath) => generateAutoEntries(entryPath));
if (IS_EE) {
const eePageEntries = glob.sync('pages/**/index.js', {
cwd: path.join(ROOT_PATH, 'ee/app/assets/javascripts'),
});
eePageEntries.forEach((entryPath) => generateAutoEntries(entryPath, 'ee'));
watchAutoEntries.push(path.join(ROOT_PATH, 'ee/app/assets/javascripts/pages/'));
}
if (IS_JH) {
const eePageEntries = glob.sync('pages/**/index.js', {
cwd: path.join(ROOT_PATH, 'jh/app/assets/javascripts'),
});
eePageEntries.forEach((entryPath) => generateAutoEntries(entryPath, 'jh'));
watchAutoEntries.push(path.join(ROOT_PATH, 'jh/app/assets/javascripts/pages/'));
}
const autoEntryKeys = Object.keys(autoEntriesMap);
autoEntriesCount = autoEntryKeys.length;
// import ancestor entrypoints within their children
autoEntryKeys.forEach((entry) => {
const entryPaths = [autoEntriesMap[entry]];
const segments = entry.split('.');
while (segments.pop()) {
const ancestor = segments.join('.');
if (autoEntryKeys.includes(ancestor)) {
entryPaths.unshift(autoEntriesMap[ancestor]);
}
}
autoEntries[entry] = defaultEntries.concat(entryPaths);
});
/*
If you create manual entries, ensure that these import `app/assets/javascripts/webpack.js` right at
the top of the entry in order to ensure that the public path is correctly determined for loading
assets async. See: https://webpack.js.org/configuration/output/#outputpublicpath
Note: WebPack 5 has an 'auto' option for the public path which could allow us to remove this option
Note 2: If you are using web-workers, you might need to reset the public path, see:
https://gitlab.com/gitlab-org/gitlab/-/issues/321656
*/
const manualEntries = {
default: defaultEntries,
legacy_sentry: './sentry/legacy_index.js',
sentry: './sentry/index.js',
performance_bar: './performance_bar/index.js',
jira_connect_app: './jira_connect/subscriptions/index.js',
sandboxed_mermaid: './lib/mermaid.js',
redirect_listbox: './entrypoints/behaviors/redirect_listbox.js',
sandboxed_swagger: './lib/swagger.js',
super_sidebar: './entrypoints/super_sidebar.js',
tracker: './entrypoints/tracker.js',
analytics: './entrypoints/analytics.js',
};
return Object.assign(manualEntries, incrementalCompiler.filterEntryPoints(autoEntries));
}
const alias = {
// Map Apollo client to apollo/client/core to prevent react related imports from being loaded
'@apollo/client$': '@apollo/client/core',
@ -318,12 +238,42 @@ if (USE_VUE3) {
vueLoaderOptions.compiler = require.resolve('./vue3migration/compiler');
}
const entriesState = {
autoEntriesCount: 0,
watchAutoEntries: [],
};
const defaultEntries = ['./main'];
module.exports = {
mode: IS_PRODUCTION ? 'production' : 'development',
context: path.join(ROOT_PATH, 'app/assets/javascripts'),
entry: generateEntries,
entry: () => {
/*
If you create manual entries, ensure that these import `app/assets/javascripts/webpack.js` right at
the top of the entry in order to ensure that the public path is correctly determined for loading
assets async. See: https://webpack.js.org/configuration/output/#outputpublicpath
Note: WebPack 5 has an 'auto' option for the public path which could allow us to remove this option
Note 2: If you are using web-workers, you might need to reset the public path, see:
https://gitlab.com/gitlab-org/gitlab/-/issues/321656
*/
return {
default: defaultEntries,
legacy_sentry: './sentry/legacy_index.js',
sentry: './sentry/index.js',
performance_bar: './performance_bar/index.js',
jira_connect_app: './jira_connect/subscriptions/index.js',
sandboxed_mermaid: './lib/mermaid.js',
redirect_listbox: './entrypoints/behaviors/redirect_listbox.js',
sandboxed_swagger: './lib/swagger.js',
super_sidebar: './entrypoints/super_sidebar.js',
tracker: './entrypoints/tracker.js',
analytics: './entrypoints/analytics.js',
...incrementalCompiler.filterEntryPoints(generateEntries({ defaultEntries, entriesState })),
};
},
output: {
path: WEBPACK_OUTPUT_PATH,
@ -522,7 +472,7 @@ module.exports = {
priority: 20,
name: 'main',
chunks: 'initial',
minChunks: autoEntriesCount * 0.9,
minChunks: entriesState.autoEntriesCount * 0.9,
}),
prosemirror: {
priority: 17,
@ -728,14 +678,16 @@ module.exports = {
if (hasMissingNodeModules) compilation.contextDependencies.add(nodeModulesPath);
// watch for changes to automatic entrypoints
watchAutoEntries.forEach((watchPath) => compilation.contextDependencies.add(watchPath));
entriesState.watchAutoEntries.forEach((watchPath) =>
compilation.contextDependencies.add(watchPath),
);
// report our auto-generated bundle count
if (incrementalCompiler.enabled) {
incrementalCompiler.logStatus(autoEntriesCount);
incrementalCompiler.logStatus(entriesState.autoEntriesCount);
} else {
console.log(
`${autoEntriesCount} entries from '/pages' automatically added to webpack output.`,
`${entriesState.autoEntriesCount} entries from '/pages' automatically added to webpack output.`,
);
}

69
config/webpack.helpers.js Normal file
View File

@ -0,0 +1,69 @@
const path = require('path');
const glob = require('glob');
const { IS_EE, IS_JH, ROOT_PATH } = require('./webpack.constants');
function generateEntries({ defaultEntries, entriesState } = { defaultEntries: [] }) {
// generate automatic entry points
const autoEntries = {};
const autoEntriesMap = {};
const pageEntries = glob.sync('pages/**/index.js', {
cwd: path.join(ROOT_PATH, 'app/assets/javascripts'),
});
if (entriesState) {
Object.assign(entriesState, {
watchAutoEntries: [path.join(ROOT_PATH, 'app/assets/javascripts/pages/')],
});
}
function generateAutoEntries(entryPath, prefix = '.') {
const chunkPath = entryPath.replace(/\/index\.js$/, '');
const chunkName = chunkPath.replace(/\//g, '.');
autoEntriesMap[chunkName] = `${prefix}/${entryPath}`;
}
pageEntries.forEach((entryPath) => generateAutoEntries(entryPath));
if (IS_EE) {
const eePageEntries = glob.sync('pages/**/index.js', {
cwd: path.join(ROOT_PATH, 'ee/app/assets/javascripts'),
});
eePageEntries.forEach((entryPath) => generateAutoEntries(entryPath, 'ee'));
if (entriesState) {
entriesState.watchAutoEntries.push(path.join(ROOT_PATH, 'ee/app/assets/javascripts/pages/'));
}
}
if (IS_JH) {
const eePageEntries = glob.sync('pages/**/index.js', {
cwd: path.join(ROOT_PATH, 'jh/app/assets/javascripts'),
});
eePageEntries.forEach((entryPath) => generateAutoEntries(entryPath, 'jh'));
if (entriesState) {
entriesState.watchAutoEntries.push(path.join(ROOT_PATH, 'jh/app/assets/javascripts/pages/'));
}
}
const autoEntryKeys = Object.keys(autoEntriesMap);
if (entriesState) {
Object.assign(entriesState, {
autoEntriesCount: autoEntryKeys.length,
});
}
// import ancestor entrypoints within their children
autoEntryKeys.forEach((entry) => {
const entryPaths = [autoEntriesMap[entry]];
const segments = entry.split('.');
while (segments.pop()) {
const ancestor = segments.join('.');
if (autoEntryKeys.includes(ancestor)) {
entryPaths.unshift(autoEntriesMap[ancestor]);
}
}
autoEntries[entry] = defaultEntries.concat(entryPaths);
});
return autoEntries;
}
module.exports = { generateEntries };

View File

@ -67,6 +67,7 @@ GET /groups
"emails_enabled": null,
"mentions_disabled": null,
"lfs_enabled": true,
"default_branch": null,
"default_branch_protection": 2,
"avatar_url": "http://localhost:3000/uploads/group/avatar/1/foo.jpg",
"web_url": "http://localhost:3000/groups/foo-bar",
@ -106,6 +107,7 @@ GET /groups?statistics=true
"emails_enabled": null,
"mentions_disabled": null,
"lfs_enabled": true,
"default_branch": null,
"default_branch_protection": 2,
"avatar_url": "http://localhost:3000/uploads/group/avatar/1/foo.jpg",
"web_url": "http://localhost:3000/groups/foo-bar",
@ -194,6 +196,7 @@ GET /groups/:id/subgroups
"emails_enabled": null,
"mentions_disabled": null,
"lfs_enabled": true,
"default_branch": null,
"default_branch_protection": 2,
"avatar_url": "http://gitlab.example.com/uploads/group/avatar/1/foo.jpg",
"web_url": "http://gitlab.example.com/groups/foo-bar",
@ -257,6 +260,7 @@ GET /groups/:id/descendant_groups
"emails_enabled": null,
"mentions_disabled": null,
"lfs_enabled": true,
"default_branch": null,
"default_branch_protection": 2,
"avatar_url": "http://gitlab.example.com/uploads/group/avatar/1/bar.jpg",
"web_url": "http://gitlab.example.com/groups/foo/bar",
@ -283,6 +287,7 @@ GET /groups/:id/descendant_groups
"emails_enabled": null,
"mentions_disabled": null,
"lfs_enabled": true,
"default_branch": null,
"default_branch_protection": 2,
"avatar_url": "http://gitlab.example.com/uploads/group/avatar/1/baz.jpg",
"web_url": "http://gitlab.example.com/groups/foo/bar/baz",
@ -845,6 +850,7 @@ Parameters:
| `path` | string | yes | The path of the group. |
| `auto_devops_enabled` | boolean | no | Default to Auto DevOps pipeline for all projects within this group. |
| `avatar` | mixed | no | Image file for avatar of the group. [Introduced in GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/issues/36681) |
| `default_branch` | string | no | The [default branch](../user/project/repository/branches/default.md) name for group's projects. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/442298) in GitLab 16.11. |
| `default_branch_protection` | integer | no | See [Options for `default_branch_protection`](#options-for-default_branch_protection). Default to the global level default branch protection setting. |
| `default_branch_protection_defaults` | hash | no | See [Options for `default_branch_protection_defaults`](#options-for-default_branch_protection_defaults). |
| `description` | string | no | The group's description. |
@ -1018,6 +1024,7 @@ PUT /groups/:id
| `path` | string | no | The path of the group. |
| `auto_devops_enabled` | boolean | no | Default to Auto DevOps pipeline for all projects within this group. |
| `avatar` | mixed | no | Image file for avatar of the group. [Introduced in GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/issues/36681) |
| `default_branch` | string | no | The [default branch](../user/project/repository/branches/default.md) name for group's projects. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/442298) in GitLab 16.11. |
| `default_branch_protection` | integer | no | See [Options for `default_branch_protection`](#options-for-default_branch_protection). |
| `default_branch_protection_defaults` | hash | no | See [Options for `default_branch_protection_defaults`](#options-for-default_branch_protection_defaults). |
| `description` | string | no | The description of the group. |

View File

@ -482,6 +482,58 @@ Example response:
]
```
## List indirect memberships for a billable member of a group
DETAILS:
**Status:** Experiment
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/386583) in GitLab 16.11.
Gets a list of indirect memberships for a billable member of a group.
Lists all projects and groups that a user is a member of, that have been invited to the requested root group.
For instance, if the requested group is `Root Group`, and the requested user is a direct member of `Other Group / Sub Group Two`, which was invited to `Root Group`, then only `Other Group / Sub Group Two` is returned.
The response lists only indirect memberships. Direct memberships are not included.
This API endpoint works on top-level groups only. It does not work on subgroups.
This API endpoint requires permission to administer memberships for the group.
This API endpoint takes [pagination](rest/index.md#pagination) parameters `page` and `per_page` to restrict the list of memberships.
```plaintext
GET /groups/:id/billable_members/:user_id/indirect
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](rest/index.md#namespaced-path-encoding) owned by the authenticated user |
| `user_id` | integer | yes | The user ID of the billable member |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/billable_members/:user_id/indirect"
```
Example response:
```json
[
{
"id": 168,
"source_id": 132,
"source_full_name": "Invited Group / Sub Group One",
"source_members_url": "https://gitlab.example.com/groups/invited-group/sub-group-one/-/group_members",
"created_at": "2021-03-31T17:28:44.812Z",
"expires_at": "2022-03-21",
"access_level": {
"string_value": "Developer",
"integer_value": 30
}
}
]
```
## Remove a billable member from a group
Removes a billable member from a group and its subgroups and projects.

View File

@ -18,10 +18,10 @@ your application on different environments.
These runners fully integrated with GitLab.com and are enabled by default for all projects, with no configuration required.
Your jobs can run on:
- [Hosted runners on Linux](saas/linux_saas_runner.md)
- [GPU-enabled hosted runners](saas/gpu_saas_runner.md)
- [Hosted runners on Windows](saas/windows_saas_runner.md) ([Beta](../../policy/experiment-beta-support.md#beta))
- [Hosted runners on macOS](saas/macos_saas_runner.md) ([Beta](../../policy/experiment-beta-support.md#beta))
- [Hosted runners on Linux](hosted_runners/linux.md)
- [GPU-enabled hosted runners](hosted_runners/gpu_enabled.md)
- [Hosted runners on Windows](hosted_runners/windows.md) ([Beta](../../policy/experiment-beta-support.md#beta))
- [Hosted runners on macOS](hosted_runners/macos.md) ([Beta](../../policy/experiment-beta-support.md#beta))
For more information about the cost factor applied to the machine type based on size, see [cost factor](../../ci/pipelines/cicd_minutes.md#gitlab-hosted-runner-costs).
The number of minutes you can use on these runners depends on the [maximum number of units of compute](../pipelines/cicd_minutes.md)
@ -37,7 +37,7 @@ The objective is to make 90% of CI/CD jobs start executing in 120 seconds or les
These runners are created on-demand for GitLab Dedicated customers and are fully integrated with your GitLab Dedicated instance.
Your jobs can run on:
- [Hosted runners on Linux](saas/linux_saas_runner.md) ([Beta](../../policy/experiment-beta-support.md#beta))
- [Hosted runners on Linux](hosted_runners/linux.md) ([Beta](../../policy/experiment-beta-support.md#beta))
## How hosted runners for GitLab.com work
@ -52,7 +52,7 @@ When you use hosted runners:
NOTE:
Jobs handled by hosted runners on GitLab.com **time out after 3 hours**, regardless of the timeout configured in a project.
## Release cycle for SaaS runner
## Release cycle for GitLab-hosted runners
We aim to update to the latest version of [GitLab Runner](https://docs.gitlab.com/runner/#gitlab-runner-versions) within a week of its release.
@ -65,13 +65,13 @@ The [Google Infrastructure Security Design Overview whitepaper](https://cloud.go
provides an overview of how Google designs security into its technical infrastructure.
The GitLab [Trust Center](https://about.gitlab.com/security/) and
[GitLab Security Compliance Controls](https://handbook.gitlab.com/handbook/security/security-assurance/security-compliance/sec-controls/)
pages provide an overview of the security and compliance controls that govern the GitLab SaaS runners.
pages provide an overview of the security and compliance controls that govern the GitLab-hosted runners.
The following section provides an overview of the additional built-in layers that harden the security of the GitLab Runner SaaS CI build environment.
The following section provides an overview of the additional built-in layers that harden the security of the GitLab Runner build environment.
### Security of CI job execution
A dedicated temporary runner VM hosts and runs each CI job. On GitLab SaaS, two CI jobs never run on the same VM.
A dedicated temporary runner VM hosts and runs each CI job. On hosted runners for GitLab.com, two CI jobs never run on the same VM.
In this example, there are three jobs in the project's pipeline. Therefore, there are three temporary VMs used to run that pipeline, or one VM per job.
@ -91,7 +91,7 @@ takes over the task of securely deleting the virtual machine and associated data
## Supported image lifecycle
SaaS runners on macOS and Windows can only run jobs on supported images. You cannot bring your own image. Supported images have the following lifecycle:
Hosted runners on macOS and Windows can only run jobs on supported images. You cannot bring your own image. Supported images have the following lifecycle:
- Beta
- Generally Available

View File

@ -63,6 +63,7 @@ If you want to upgrade multiple releases or do not meet these requirements [upgr
We recommend a "back to front" approach for the order of what components to upgrade with Zero Downtime.
Generally this would be stateful backends first, their dependents next and then the frontends accordingly.
While the order of deployment can be changed, it is best to deploy the components running GitLab application code (Rails, Sidekiq) together. If possible, upgrade the supporting infrastructure (PostgreSQL, PgBouncer, Consul, Gitaly, Praefect, Redis) separately since these components do not have dependencies on changes made in version updates within a major release.
As such, we generally recommend the following order:
1. Consul
@ -74,10 +75,6 @@ As such, we generally recommend the following order:
1. Rails
1. Sidekiq
NOTE:
While this order can be changed if desired, a hard requirement is that the Rails nodes are done after PostgreSQL
as they drive the upgrades of data on those stateful backends via migrations.
## Multi-node / HA deployment
In this section we'll go through the core process of upgrading a multi-node GitLab environment by

View File

@ -365,26 +365,26 @@ are also informational headers with this response detailed in
The following table describes the rate limits for GitLab.com:
| Rate limit | Setting |
|:---------------------------------------------------------------------------|:-------------------------------------|
| **Protected paths** (for a given **IP address**) | **10** requests per minute |
| **Raw endpoint** traffic (for a given **project, commit, and file path**) | **300** requests per minute |
| **Unauthenticated** traffic (from a given **IP address**) | **500** requests per minute |
| **Authenticated** API traffic (for a given **user**) | **2,000** requests per minute |
| **Authenticated** non-API HTTP traffic (for a given **user**) | **1,000** requests per minute |
| **All** traffic (from a given **IP address**) | **2,000** requests per minute |
| **Issue creation** | **200** requests per minute |
| **Note creation** (on issues and merge requests) | **60** requests per minute |
| **Advanced, project, and group search** API (for a given **IP address**) | **10** requests per minute |
| **GitLab Pages** requests (for a given **IP address**) | **1000** requests per **50 seconds** |
| **GitLab Pages** requests (for a given **GitLab Pages domain**) | **5000** requests per **10 seconds** |
| **GitLab Pages** TLS connections (for a given **IP address**) | **1000** requests per **50 seconds** |
| **GitLab Pages** TLS connections (for a given **GitLab Pages domain**) | **400** requests per **10 seconds** |
| **Pipeline creation** requests (for a given **project, user, and commit**) | **25** requests per minute |
| **Alert integration endpoint** requests (for a given **project**) | **3600** requests per hour |
| **[Pull mirroring](../project/repository/mirror/pull.md)** intervals | **5** minutes |
| **API Requests** (from a given **user**) to `/api/v4/users/:id` | **300** requests per **10 minutes** |
| GitLab package cloud requests for a given IP address ([introduced](https://gitlab.com/gitlab-com/gl-infra/production-engineering/-/issues/24083) in GitLab 16.11) | 3,000 requests per minute |
| Rate limit | Setting |
|:-----------------------------------------------------------------|:------------------------------|
| Protected paths for an IP address | 10 requests per minute |
| Raw endpoint traffic for a project, commit, or file path | 300 requests per minute |
| Unauthenticated traffic from an IP address | 500 requests per minute |
| Authenticated API traffic for a user | 2,000 requests per minute |
| Authenticated non-API HTTP traffic for a user | 1,000 requests per minute |
| All traffic from an IP address | 2,000 requests per minute |
| Issue creation | 200 requests per minute |
| Note creation on issues and merge requests | 60 requests per minute |
| Advanced, project, or group search API for an IP address | 10 requests per minute |
| GitLab Pages requests for an IP address | 1,000 requests per 50 seconds |
| GitLab Pages requests for a GitLab Pages domain | 5,000 requests per 10 seconds |
| GitLab Pages TLS connections for an IP address | 1,000 requests per 50 seconds |
| GitLab Pages TLS connections for a GitLab Pages domain | 400 requests per 10 seconds |
| Pipeline creation requests for a project, user, or commit | 25 requests per minute |
| Alert integration endpoint requests for a project | 3,600 requests per hour |
| [Pull mirroring](../project/repository/mirror/pull.md) intervals | 5 minutes |
| API requests from a user to `/api/v4/users/:id` | 300 requests per 10 minutes |
| GitLab package cloud requests for an IP address ([introduced](https://gitlab.com/gitlab-com/gl-infra/production-engineering/-/issues/24083) in GitLab 16.11) | 3,000 requests per minute |
More details are available on the rate limits for
[protected paths](#protected-paths-throttle) and

View File

@ -163,6 +163,11 @@ If a user is:
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 13.11 from a form to a modal window [with a flag](../../feature_flags.md). Disabled by default.
> - Modal window [enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 14.8.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/352526) in GitLab 14.9. [Feature flag `invite_members_group_modal`](https://gitlab.com/gitlab-org/gitlab/-/issues/352526) removed.
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/219230) to display invited group members on the Members tab of the Members page in GitLab 16.10 [with a flag](../../../administration/feature_flags.md) named `webui_members_inherited_users`. Disabled by default.
FLAG:
On self-managed GitLab, by default this feature is not available. To make it available per user, an administrator can [enable the feature flag](../../../administration/feature_flags.md) named `webui_members_inherited_users`.
On GitLab.com and GitLab Dedicated, this feature is not available.
When you add a group to a project, every group member (direct or inherited) gets access to the project.
Each member's access is based on the:
@ -192,7 +197,7 @@ To add a group to a project:
The invited group is displayed on the **Groups** tab.
Private groups are masked from unauthorized users.
Private groups are displayed in project settings for protected branches, protected tags, and protected environments.
The members of the invited group are not displayed on the **Members** tab.
The members of the invited group are not displayed on the **Members** tab, but are displayed if the `webui_members_inherited_users` feature flag is enabled.
The **Members** tab shows:
- Members who were directly added to the project.

View File

@ -17,8 +17,12 @@ You can share by invitation:
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/219230) to display invited group members on the Members tab of the Members page in GitLab 16.10 behind `webui_members_inherited_users` feature flag. Disabled by default.
[In GitLab 16.6 and later](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/134623),
the invited group's name and membership source are masked unless one of the following applies:
FLAG:
On self-managed GitLab, by default this feature is not available. To make it available per user, an administrator can [enable the feature flag](../../../administration/feature_flags.md) named `webui_members_inherited_users`.
On GitLab.com and GitLab Dedicated, this feature is not available.
[In GitLab 16.11 and later](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144638),
the invited group's name and membership source are masked on the **Members** and the **Groups** tabs, unless one of the following applies:
- The invited group is public.
- The current user is a member of the invited group.

View File

@ -16,6 +16,7 @@ module API
expose :lfs_enabled?, as: :lfs_enabled
expose :math_rendering_limits_enabled, documentation: { type: 'boolean' }
expose :lock_math_rendering_limits_enabled, documentation: { type: 'boolean' }
expose :default_branch_name, as: :default_branch
expose :default_branch_protection
expose :default_branch_protection_defaults
expose :avatar_url do |group, options|

View File

@ -23,6 +23,7 @@ module API
optional :mentions_disabled, type: Boolean, desc: 'Disable a group from getting mentioned'
optional :lfs_enabled, type: Boolean, desc: 'Enable/disable LFS for the projects in this group'
optional :request_access_enabled, type: Boolean, desc: 'Allow users to request member access'
optional :default_branch, type: String, desc: "The default branch of group's projects", documentation: { example: 'main' }, as: :default_branch_name
optional :default_branch_protection, type: Integer, values: ::Gitlab::Access.protection_values, desc: 'Determine if developers can push to default branch'
optional :default_branch_protection_defaults, type: Hash, desc: 'Determine if developers can push to default branch' do
optional :allowed_to_push, type: Array, desc: 'An array of access levels allowed to push' do

View File

@ -37,6 +37,8 @@ module Banzai
modified_footnotes = {}
doc.xpath(XPATH_FOOTNOTE).each do |link_node|
next unless link_node[:id]
ref_num = link_node[:id].delete_prefix(FOOTNOTE_LINK_ID_PREFIX)
ref_num.gsub!(/[[:punct:]]/, '\\\\\&')

View File

@ -57,8 +57,6 @@ module ClickHouse
workers_active = true
loop do
return if Feature.disabled?(:wait_for_clickhouse_workers_during_migration)
workers_active = active_sidekiq_workers?
break unless workers_active
break if Time.current >= worker_wait_ttl

View File

@ -1,5 +1,5 @@
variables:
DAST_AUTO_DEPLOY_IMAGE_VERSION: 'v2.87.0'
DAST_AUTO_DEPLOY_IMAGE_VERSION: 'v2.88.0'
.dast-auto-deploy:
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${DAST_AUTO_DEPLOY_IMAGE_VERSION}"

View File

@ -1,5 +1,5 @@
variables:
AUTO_DEPLOY_IMAGE_VERSION: 'v2.87.0'
AUTO_DEPLOY_IMAGE_VERSION: 'v2.88.0'
.auto-deploy:
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"

View File

@ -1,5 +1,5 @@
variables:
AUTO_DEPLOY_IMAGE_VERSION: 'v2.87.0'
AUTO_DEPLOY_IMAGE_VERSION: 'v2.88.0'
.auto-deploy:
image: "${CI_TEMPLATE_REGISTRY_HOST}/gitlab-org/cluster-integration/auto-deploy-image:${AUTO_DEPLOY_IMAGE_VERSION}"

View File

@ -7,8 +7,6 @@ module Gitlab
class ClickHouseMigration < Base
override :should_pause?
def should_pause?
return false unless Feature.enabled?(:pause_clickhouse_workers_during_migration)
::ClickHouse::MigrationSupport::ExclusiveLock.pause_workers?
end
end

View File

@ -45,7 +45,8 @@
"swagger:validate": "swagger-cli validate",
"webpack": "NODE_OPTIONS=\"${NODE_OPTIONS:=--max-old-space-size=5120}\" webpack --config config/webpack.config.js",
"webpack-vendor": "NODE_OPTIONS=\"${NODE_OPTIONS:=--max-old-space-size=5120}\" webpack --config config/webpack.vendor.config.js",
"webpack-prod": "NODE_OPTIONS=\"${NODE_OPTIONS:=--max-old-space-size=5120}\" NODE_ENV=production webpack --config config/webpack.config.js"
"webpack-prod": "NODE_OPTIONS=\"${NODE_OPTIONS:=--max-old-space-size=5120}\" NODE_ENV=production webpack --config config/webpack.config.js",
"vite-prod": "NODE_OPTIONS=\"${NODE_OPTIONS:=--max-old-space-size=8000}\" NODE_ENV=production vite build"
},
"dependencies": {
"@apollo/client": "^3.5.10",

View File

@ -109,8 +109,8 @@ RSpec.describe 'Projects (JavaScript fixtures)', type: :controller, feature_cate
)
end
base_input_path = 'usage_quotas/storage/queries/'
base_output_path = 'graphql/usage_quotas/storage/'
base_input_path = 'usage_quotas/storage/project/queries/'
base_output_path = 'graphql/usage_quotas/storage/project/'
query_name = 'project_storage.query.graphql'
it "#{base_output_path}#{query_name}.json" do

View File

@ -1,4 +1,4 @@
import mockGetProjectStorageStatisticsGraphQLResponse from 'test_fixtures/graphql/usage_quotas/storage/project_storage.query.graphql.json';
import mockGetProjectStorageStatisticsGraphQLResponse from 'test_fixtures/graphql/usage_quotas/storage/project/project_storage.query.graphql.json';
import mockGetNamespaceStorageGraphQLResponse from 'test_fixtures/graphql/usage_quotas/storage/namespace_storage.query.graphql.json';
import mockGetProjectListStorageGraphQLResponse from 'test_fixtures/graphql/usage_quotas/storage/project_list_storage.query.graphql.json';
import { storageTypeHelpPaths } from '~/usage_quotas/storage/constants';

View File

@ -17,8 +17,8 @@ import {
NAMESPACE_STORAGE_TYPES,
TOTAL_USAGE_DEFAULT_TEXT,
} from '~/usage_quotas/storage/constants';
import getCostFactoredProjectStorageStatistics from 'ee_else_ce/usage_quotas/storage/queries/cost_factored_project_storage.query.graphql';
import getProjectStorageStatistics from 'ee_else_ce/usage_quotas/storage/queries/project_storage.query.graphql';
import getCostFactoredProjectStorageStatistics from 'ee_else_ce/usage_quotas/storage/project/queries/cost_factored_project_storage.query.graphql';
import getProjectStorageStatistics from 'ee_else_ce/usage_quotas/storage/project/queries/project_storage.query.graphql';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import {
mockGetProjectStorageStatisticsGraphQLResponse,

View File

@ -979,38 +979,4 @@ RSpec.describe ApplicationHelper do
end
end
end
describe '#controller_full_path' do
let(:path) { 'some_path' }
let(:action) { 'show' }
before do
allow(helper.controller).to receive(:controller_path).and_return(path)
allow(helper.controller).to receive(:action_name).and_return(action)
end
context 'when is create action' do
let(:action) { 'create' }
it 'transforms to "new" path' do
expect(helper.controller_full_path).to eq("#{path}/new")
end
end
context 'when is update action' do
let(:action) { 'update' }
it 'transforms to "edit" path' do
expect(helper.controller_full_path).to eq("#{path}/edit")
end
end
context 'when is show action' do
let(:action) { 'show' }
it 'passes through' do
expect(helper.controller_full_path).to eq("#{path}/#{action}")
end
end
end
end

View File

@ -0,0 +1,26 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe ViteHelper, feature_category: :tooling do
describe '#vite_page_entrypoint_path' do
using RSpec::Parameterized::TableSyntax
where(:path, :action, :result) do
'some_path' | 'create' | %w[pages.some_path.js pages.some_path.new.js]
'some_path' | 'new' | %w[pages.some_path.js pages.some_path.new.js]
'some_path' | 'update' | %w[pages.some_path.js pages.some_path.edit.js]
'some_path' | 'show' | %w[pages.some_path.js pages.some_path.show.js]
'some/long' | 'path' | %w[pages.some.js pages.some.long.js pages.some.long.path.js]
end
with_them do
before do
allow(helper.controller).to receive(:controller_path).and_return(path)
allow(helper.controller).to receive(:action_name).and_return(action)
end
it { expect(helper.vite_page_entrypoint_paths).to eq(result) }
end
end
end

View File

@ -17,7 +17,7 @@ RSpec.describe API::Entities::Group, feature_category: :groups_and_projects do
:two_factor_grace_period, :project_creation_level, :auto_devops_enabled,
:subgroup_creation_level, :emails_disabled, :emails_enabled, :lfs_enabled, :default_branch_protection,
:default_branch_protection_defaults, :avatar_url, :request_access_enabled, :full_name, :full_path, :created_at,
:parent_id, :organization_id, :shared_runners_setting, :custom_attributes, :statistics
:parent_id, :organization_id, :shared_runners_setting, :custom_attributes, :statistics, :default_branch
)
)
end

View File

@ -15,6 +15,7 @@ RSpec.describe Banzai::Filter::FootnoteFilter, feature_category: :team_planning
let(:footnote) do
<<~EOF.strip_heredoc
<p>first<sup><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup> and second<sup><a href="#fn-second" id="fnref-second" data-footnote-ref>2</a></sup> and third<sup><a href="#fn-_%F0%9F%98%84_" id="fnref-_%F0%9F%98%84_" data-footnote-ref>3</a></sup></p>
<p>missing id<sup><a href="#fn-10" data-footnote-ref>1</a></sup></p>
<section data-footnotes>
<ol>
<li id="fn-1">
@ -32,6 +33,7 @@ RSpec.describe Banzai::Filter::FootnoteFilter, feature_category: :team_planning
let(:filtered_footnote) do
<<~EOF.strip_heredoc
<p>first<sup class="footnote-ref"><a href="#fn-1-#{identifier}" id="fnref-1-#{identifier}" data-footnote-ref>1</a></sup> and second<sup class="footnote-ref"><a href="#fn-second-#{identifier}" id="fnref-second-#{identifier}" data-footnote-ref>2</a></sup> and third<sup class="footnote-ref"><a href="#fn-_%F0%9F%98%84_-#{identifier}" id="fnref-_%F0%9F%98%84_-#{identifier}" data-footnote-ref>3</a></sup></p>
<p>missing id<sup><a href="#fn-10" data-footnote-ref>1</a></sup></p>
<section data-footnotes class=\"footnotes\">
<ol>
<li id="fn-1-#{identifier}">

View File

@ -96,17 +96,6 @@ RSpec.describe ClickHouse::MigrationSupport::ExclusiveLock, feature_category: :d
expect(Time.current - started_at).to eq(described_class::DEFAULT_CLICKHOUSE_WORKER_TTL)
end
context 'when wait_for_clickhouse_workers_during_migration FF is disabled' do
before do
stub_feature_flags(wait_for_clickhouse_workers_during_migration: false)
end
it 'runs migration without waiting for workers' do
expect { migration }.not_to raise_error
expect(Time.current - started_at).to eq(0.0)
end
end
it 'ignores expired workers' do
travel(described_class::DEFAULT_CLICKHOUSE_WORKER_TTL + 1.second)

View File

@ -55,14 +55,6 @@ RSpec.describe Gitlab::SidekiqMiddleware::PauseControl::Strategies::ClickHouseMi
expect(worker_class.jobs.count).to eq(0)
end
context 'when pause_clickhouse_workers_during_migration FF is disabled' do
before do
stub_feature_flags(pause_clickhouse_workers_during_migration: false)
end
it_behaves_like 'a worker being executed'
end
end
end
end

View File

@ -1041,6 +1041,36 @@ RSpec.describe API::Groups, feature_category: :groups_and_projects do
expect(json_response['message']['visibility_level']).to include('internal has been restricted by your GitLab administrator')
end
context 'updating the `default_branch` attribute' do
subject do
put api("/groups/#{group1.id}", user1), params: { default_branch: default_branch }
end
let(:default_branch) { 'new' }
it 'updates the attribute', :aggregate_failures do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['default_branch']).to eq(default_branch)
end
context 'when "default_branch" attribute is removed' do
before do
group1.namespace_settings.update!(default_branch_name: 'new')
end
let(:default_branch) { '' }
it 'removes the attribute', :aggregate_failures do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['default_branch']).to be_nil
end
end
end
context 'updating the `default_branch_protection` attribute' do
subject do
put api("/groups/#{group1.id}", user1), params: { default_branch_protection: ::Gitlab::Access::PROTECTION_NONE }
@ -2230,6 +2260,19 @@ RSpec.describe API::Groups, feature_category: :groups_and_projects do
end
end
context 'when creating a group with "default_branch" attribute' do
let(:params) { attributes_for_group_api default_branch: 'main' }
subject { post api("/groups", user3), params: params }
it 'creates group with the specified default branch', :aggregate_failures do
subject
expect(response).to have_gitlab_http_status(:created)
expect(json_response['default_branch']).to eq('main')
end
end
context 'when creating a group with `enabled_git_access_protocol' do
let(:params) { attributes_for_group_api enabled_git_access_protocol: 'all' }

View File

@ -10,6 +10,7 @@ import chokidar from 'chokidar';
import globby from 'globby';
import { viteCommonjs } from '@originjs/vite-plugin-commonjs';
import webpackConfig from './config/webpack.config';
import { generateEntries } from './config/webpack.helpers';
import {
IS_EE,
IS_JH,
@ -43,6 +44,15 @@ const emptyComponent = path.resolve(javascriptsPath, 'vue_shared/components/empt
const [rubyPlugin, ...rest] = RubyPlugin();
const comment = '/* this is a virtual module used by Vite, it exists only in dev mode */\n';
const virtualEntrypoints = Object.entries(generateEntries()).reduce((acc, [entryName, imports]) => {
const modulePath = imports[imports.length - 1];
const importPath = modulePath.startsWith('./') ? `~/${modulePath.substring(2)}` : modulePath;
acc[`${entryName}.js`] = `${comment}/* ${modulePath} */ import '${importPath}';\n`;
return acc;
}, {});
// We can't use regular 'resolve' which points to sourceCodeDir in vite.json
// Because we need for '~' alias to resolve to app/assets/javascripts
// We can't use javascripts folder in sourceCodeDir because we also need to resolve other assets
@ -163,6 +173,22 @@ function viteCopyPlugin({ patterns }) {
};
}
const entrypointsDir = '/javascripts/entrypoints/';
const pageEntrypointsPlugin = {
name: 'page-entrypoints',
load(id) {
if (!id.startsWith('pages.')) {
return undefined;
}
return virtualEntrypoints[id] ?? `/* doesn't exist */`;
},
resolveId(source) {
const fixedSource = source.replace(entrypointsDir, '');
if (fixedSource.startsWith('pages.')) return { id: fixedSource };
return undefined;
},
};
export default defineConfig({
cacheDir: path.resolve(__dirname, 'tmp/cache/vite'),
resolve: {
@ -181,6 +207,7 @@ export default defineConfig({
],
},
plugins: [
pageEntrypointsPlugin,
viteCSSCompilerPlugin({ shouldWatch: viteGDKConfig.hmr !== null }),
viteTailwindCompilerPlugin({ shouldWatch: viteGDKConfig.hmr !== null }),
viteCopyPlugin({
@ -238,4 +265,12 @@ export default defineConfig({
worker: {
format: 'es',
},
build: {
rollupOptions: {
input: Object.keys(virtualEntrypoints).reduce((acc, value) => {
acc[value] = value;
return acc;
}, {}),
},
},
});

View File

@ -22,7 +22,7 @@ require (
github.com/sirupsen/logrus v1.9.3
github.com/smartystreets/goconvey v1.8.1
github.com/stretchr/testify v1.9.0
gitlab.com/gitlab-org/gitaly/v16 v16.9.1
gitlab.com/gitlab-org/gitaly/v16 v16.9.2
gitlab.com/gitlab-org/labkit v1.21.0
gocloud.dev v0.37.0
golang.org/x/image v0.15.0

View File

@ -448,8 +448,8 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
gitlab.com/gitlab-org/gitaly/v16 v16.9.1 h1:XFoZyeV3HCGIB6pnQj6r5ZYsUYa34HoVOyod7XegIdI=
gitlab.com/gitlab-org/gitaly/v16 v16.9.1/go.mod h1:K2zAXwDEEwnm9NLxboCllREyS4Rx1yRBRxLBC0EcakA=
gitlab.com/gitlab-org/gitaly/v16 v16.9.2 h1:FkNYzuezmL9K+3ZzU26BL1m3/0VoWi7Mq0ahuWovTfs=
gitlab.com/gitlab-org/gitaly/v16 v16.9.2/go.mod h1:K2zAXwDEEwnm9NLxboCllREyS4Rx1yRBRxLBC0EcakA=
gitlab.com/gitlab-org/labkit v1.21.0 h1:hLmdBDtXjD1yOmZ+uJOac3a5Tlo83QaezwhES4IYik4=
gitlab.com/gitlab-org/labkit v1.21.0/go.mod h1:zeATDAaSBelPcPLbTTq8J3ZJEHyPTLVBM1q3nva+/W4=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=