Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-05-31 12:20:40 +00:00
parent 4191a43882
commit a7da5c1f5a
148 changed files with 1462 additions and 596 deletions

View File

@ -10,6 +10,7 @@ stages:
- review
- qa
- post-qa
- pre-merge
- pages
- notify
- release-environments

View File

@ -0,0 +1,14 @@
pre-merge-checks:
extends:
- .pre-merge:rules:pre-merge-checks
- .fast-no-clone-job
variables:
# We use > instead of | because we want the files to be space-separated.
FILES_TO_DOWNLOAD: >
scripts/utils.sh
scripts/pipeline/merge-train-checks.rb
image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}ruby:${RUBY_VERSION}-alpine3.16
stage: pre-merge
script:
- install_gitlab_gem
- chmod u+x scripts/pipeline/merge-train-checks.rb && scripts/pipeline/merge-train-checks.rb

View File

@ -144,7 +144,7 @@ xray_scan:
- .reports:rules:x-ray
stage: lint
needs: []
image: registry.gitlab.com/gitlab-org/code-creation/repository-x-ray:rc
image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/code-creation/repository-x-ray:rc
variables:
OUTPUT_DIR: reports
allow_failure: true

View File

@ -152,6 +152,9 @@
.if-dot-com-gitlab-org-merge-request: &if-dot-com-gitlab-org-merge-request
if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" && ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached")'
.if-dot-com-gitlab-org-and-subgroups-merge-train: &if-dot-com-gitlab-org-and-subgroups-merge-train
if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org/ && $CI_MERGE_REQUEST_EVENT_TYPE == "merge_train"'
.if-dot-com-gitlab-org-ee-tag: &if-dot-com-gitlab-org-ee-tag
if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_PATH == "gitlab-org/gitlab" && $CI_COMMIT_TAG =~ /^v?[\d]+\.[\d]+\.[\d]+[\d\w-]*-ee$/'
@ -943,7 +946,7 @@
rules:
- if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_PATH == "gitlab-org/gitlab" && $CI_COMMIT_TAG =~ /^v\d+\.\d+\.0-ee$/ && $CI_PIPELINE_SOURCE == "push"'
# In case gdk base tag is updated via backport mr, make sure we retag it with stable prefix as well
- if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_PATH == "gitlab-org/gitlab" && $CI_MERGE_REQUEST_IID && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^[\d-]+-stable-ee$/'
- if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_PATH == "gitlab-org/gitlab" && ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^[\d-]+-stable-ee$/'
changes:
- qa/gdk/Dockerfile.gdk
@ -3321,3 +3324,10 @@
changes: *ci-patterns
when: manual
allow_failure: true
##########################
# Pre-merge checks rules #
##########################
.pre-merge:rules:pre-merge-checks:
rules:
- <<: *if-dot-com-gitlab-org-and-subgroups-merge-train

View File

@ -73,7 +73,6 @@ set-pipeline-name:
- apk add --no-cache --update curl # Not present in ruby-alpine, so we add it manually
- !reference [".fast-no-clone-job", before_script]
script:
- source scripts/utils.sh
- install_gitlab_gem
- chmod u+x scripts/pipeline/set_pipeline_name.rb && scripts/pipeline/set_pipeline_name.rb
allow_failure:

View File

@ -18,7 +18,7 @@ workflow:
fi
.cng-base:
image: registry.gitlab.com/gitlab-org/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}:bundler-${BUNDLER_VERSION}-git-2.36-lfs-2.9-chrome-${CHROME_VERSION}-docker-${DOCKER_VERSION}-kubectl-1.23-helm-3.14-kind-0.20
image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}:bundler-${BUNDLER_VERSION}-git-2.36-lfs-2.9-chrome-${CHROME_VERSION}-docker-${DOCKER_VERSION}-kubectl-1.23-helm-3.14-kind-0.20
stage: test
extends: .qa-cache
needs: [build-cng]

View File

@ -13,7 +13,6 @@ Layout/SpaceInsideParens:
- 'spec/helpers/gitlab_script_tag_helper_spec.rb'
- 'spec/helpers/tab_helper_spec.rb'
- 'spec/initializers/carrierwave_s3_encryption_headers_patch_spec.rb'
- 'spec/initializers/rdoc_segfault_patch_spec.rb'
- 'spec/lib/api/entities/snippet_spec.rb'
- 'spec/lib/banzai/filter/references/alert_reference_filter_spec.rb'
- 'spec/lib/banzai/filter/references/feature_flag_reference_filter_spec.rb'

View File

@ -731,6 +731,7 @@ RSpec/BeforeAllRoleAssignment:
- 'spec/controllers/groups/group_members_controller_spec.rb'
- 'spec/controllers/groups/imports_controller_spec.rb'
- 'spec/controllers/groups/labels_controller_spec.rb'
- 'spec/controllers/groups/milestones_controller_spec.rb'
- 'spec/controllers/groups/settings/applications_controller_spec.rb'
- 'spec/controllers/groups/settings/ci_cd_controller_spec.rb'
- 'spec/controllers/groups/settings/integrations_controller_spec.rb'

View File

@ -2456,7 +2456,6 @@ RSpec/FeatureCategory:
- 'spec/initializers/rack_multipart_patch_spec.rb'
- 'spec/initializers/rails_asset_host_spec.rb'
- 'spec/initializers/rails_yaml_safe_load_spec.rb'
- 'spec/initializers/rdoc_segfault_patch_spec.rb'
- 'spec/initializers/remove_active_job_execute_callback_spec.rb'
- 'spec/initializers/rest-client-hostname_override_spec.rb'
- 'spec/initializers/sawyer_patch_spec.rb'

View File

@ -333,7 +333,6 @@ Style/ClassAndModuleChildren:
- 'config/initializers/omniauth.rb'
- 'config/initializers/postgres_cte_as_materialized.rb'
- 'config/initializers/postgresql_cte.rb'
- 'config/initializers/rdoc_segfault_patch.rb'
- 'config/initializers/zz_metrics.rb'
- 'ee/app/controllers/admin/audit_log_reports_controller.rb'
- 'ee/app/controllers/admin/audit_logs_controller.rb'

View File

@ -349,7 +349,7 @@
{"name":"kubeclient","version":"4.11.0","platform":"ruby","checksum":"4985fcd749fb8c364a668a8350a49821647f03aa52d9ee6cbc582beb8e883fcc"},
{"name":"language_server-protocol","version":"3.17.0.3","platform":"ruby","checksum":"3d5c58c02f44a20d972957a9febe386d7e7468ab3900ce6bd2b563dd910c6b3f"},
{"name":"launchy","version":"2.5.0","platform":"ruby","checksum":"954243c4255920982ce682f89a42e76372dba94770bf09c23a523e204bdebef5"},
{"name":"lefthook","version":"1.6.8","platform":"ruby","checksum":"248181e8374ce9ef306a45fdbd3f64c076aaa4845cad6c126be4414b9c71c623"},
{"name":"lefthook","version":"1.6.14","platform":"ruby","checksum":"78b51e17e9729c4ae0d9f9dfa0c67c7d9fa3f6651deb71419b4b4116f2367ce5"},
{"name":"letter_opener","version":"1.7.0","platform":"ruby","checksum":"095bc0d58e006e5b43ea7d219e64ecf2de8d1f7d9dafc432040a845cf59b4725"},
{"name":"letter_opener_web","version":"2.0.0","platform":"ruby","checksum":"33860ad41e1785d75456500e8ca8bba8ed71ee6eaf08a98d06bbab67c5577b6f"},
{"name":"libyajl2","version":"2.1.0","platform":"ruby","checksum":"aa5df6c725776fc050c8418450de0f7c129cb7200b811907c4c0b3b5c0aea0ef"},

View File

@ -1023,7 +1023,7 @@ GEM
language_server-protocol (3.17.0.3)
launchy (2.5.0)
addressable (~> 2.7)
lefthook (1.6.8)
lefthook (1.6.14)
letter_opener (1.7.0)
launchy (~> 2.2)
letter_opener_web (2.0.0)

View File

@ -71,13 +71,7 @@ export default {
return !this.isDisabled;
},
cardStyle() {
return this.isColorful && this.item.color ? { borderColor: this.item.color } : '';
},
isColorful() {
return gon?.features?.epicColorHighlight;
},
colorClass() {
return this.isColorful ? 'gl-pl-4 gl-border-l-solid gl-border-4' : '';
return this.item.color ? { borderColor: this.item.color } : '';
},
formattedItem() {
return {
@ -147,7 +141,7 @@ export default {
'is-active gl-bg-blue-50': isActive,
'gl-cursor-not-allowed gl-bg-gray-10': item.isLoading,
},
colorClass,
'gl-pl-4 gl-border-l-solid gl-border-4',
]"
:index="index"
:data-item-id="item.id"

View File

@ -412,7 +412,6 @@ export default {
boardId: this.boardId,
itemToMove,
}),
withColor: this.isEpicBoard && this.glFeatures.epicColorHighlight,
},
update: (cache, { data: { issuableMoveList } }) =>
this.updateCacheAfterMovingItem({
@ -505,7 +504,6 @@ export default {
itemToMove: item,
}),
positionInList,
withColor: this.isEpicBoard && this.glFeatures.epicColorHighlight,
},
optimisticResponse: {
issuableMoveList: {
@ -558,7 +556,6 @@ export default {
mutation: listIssuablesQueries[this.issuableType].createMutation,
variables: {
input: this.isEpicBoard ? input : { ...input, moveAfterId: this.boardListItems[0]?.id },
withColor: this.isEpicBoard && this.glFeatures.epicColorHighlight,
},
update: (cache, { data: { createIssuable } }) => {
issuable = createIssuable.issuable;

View File

@ -7,7 +7,14 @@ import { helpPagePath } from '~/helpers/help_page_helper';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { k8sResourceType } from '~/environments/graphql/resolvers/kubernetes/constants';
import { createK8sAccessConfiguration } from '~/environments/helpers/k8s_integration_helper';
import { CLUSTER_HEALTH_SUCCESS, CLUSTER_HEALTH_ERROR } from '~/environments/constants';
import fluxKustomizationQuery from '~/environments/graphql/queries/flux_kustomization.query.graphql';
import fluxHelmReleaseQueryStatus from '~/environments/graphql/queries/flux_helm_release_status.query.graphql';
import {
CLUSTER_HEALTH_SUCCESS,
CLUSTER_HEALTH_ERROR,
HELM_RELEASES_RESOURCE_TYPE,
KUSTOMIZATIONS_RESOURCE_TYPE,
} from '~/environments/constants';
import KubernetesStatusBar from './kubernetes_status_bar.vue';
import KubernetesAgentInfo from './kubernetes_agent_info.vue';
import KubernetesTabs from './kubernetes_tabs.vue';
@ -44,13 +51,49 @@ export default {
default: '',
},
},
apollo: {
fluxKustomization: {
query: fluxKustomizationQuery,
variables() {
return {
configuration: this.k8sAccessConfiguration,
fluxResourcePath: this.fluxResourcePath,
};
},
skip() {
return Boolean(
!this.fluxResourcePath || this.fluxResourcePath?.includes(HELM_RELEASES_RESOURCE_TYPE),
);
},
error(err) {
this.fluxApiError = err.message;
},
},
fluxHelmReleaseStatus: {
query: fluxHelmReleaseQueryStatus,
variables() {
return {
configuration: this.k8sAccessConfiguration,
fluxResourcePath: this.fluxResourcePath,
};
},
skip() {
return Boolean(
!this.fluxResourcePath || this.fluxResourcePath?.includes(KUSTOMIZATIONS_RESOURCE_TYPE),
);
},
error(err) {
this.fluxApiError = err.message;
},
},
},
data() {
return {
error: null,
failedState: {},
podsLoading: false,
activeTab: k8sResourceType.k8sPods,
fluxApiError: '',
};
},
computed: {
@ -72,6 +115,9 @@ export default {
hasFailedState() {
return Object.values(this.failedState).some((item) => item);
},
fluxResourceStatus() {
return this.fluxKustomization?.conditions || this.fluxHelmReleaseStatus?.conditions;
},
},
methods: {
handleError(message) {
@ -114,6 +160,8 @@ export default {
:environment-name="environmentName"
:flux-resource-path="fluxResourcePath"
:resource-type="activeTab"
:flux-resource-status="fluxResourceStatus"
:flux-api-error="fluxApiError"
@error="handleError"
/>
</div>
@ -126,6 +174,7 @@ export default {
v-model="activeTab"
:configuration="k8sAccessConfiguration"
:namespace="kubernetesNamespace"
:flux-kustomization="fluxKustomization"
class="gl-mb-5"
@cluster-error="handleError"
@loading="podsLoading = $event"

View File

@ -14,8 +14,6 @@ import {
HELM_RELEASES_RESOURCE_TYPE,
KUSTOMIZATIONS_RESOURCE_TYPE,
} from '~/environments/constants';
import fluxKustomizationStatusQuery from '~/environments/graphql/queries/flux_kustomization_status.query.graphql';
import fluxHelmReleaseStatusQuery from '~/environments/graphql/queries/flux_helm_release_status.query.graphql';
import KubernetesConnectionStatus from '~/environments/environment_details/components/kubernetes/kubernetes_connection_status.vue';
import KubernetesConnectionStatusBadge from '~/environments/environment_details/components/kubernetes/kubernetes_connection_status_badge.vue';
import {
@ -64,46 +62,19 @@ export default {
type: String,
required: true,
},
},
apollo: {
fluxKustomizationStatus: {
query: fluxKustomizationStatusQuery,
variables() {
return {
configuration: this.configuration,
fluxResourcePath: this.fluxResourcePath,
};
},
skip() {
return Boolean(
!this.fluxResourcePath || this.fluxResourcePath?.includes(HELM_RELEASES_RESOURCE_TYPE),
);
},
error(err) {
this.fluxApiError = err.message;
},
fluxResourceStatus: {
type: Array,
required: false,
default: () => [],
},
fluxHelmReleaseStatus: {
query: fluxHelmReleaseStatusQuery,
variables() {
return {
configuration: this.configuration,
fluxResourcePath: this.fluxResourcePath,
};
},
skip() {
return Boolean(
!this.fluxResourcePath || this.fluxResourcePath?.includes(KUSTOMIZATIONS_RESOURCE_TYPE),
);
},
error(err) {
this.fluxApiError = err.message;
},
fluxApiError: {
type: String,
required: false,
default: '',
},
},
data() {
return {
fluxApiError: '',
clusterResourceTypeParams: {
[k8sResourceType.k8sServices]: {
resourceType: k8sResourceType.k8sServices,
@ -157,35 +128,16 @@ export default {
healthBadge() {
return HEALTH_BADGES[this.clusterHealthStatus];
},
hasKustomizations() {
return this.fluxKustomizationStatus?.length;
},
hasHelmReleases() {
return this.fluxHelmReleaseStatus?.length;
},
isLoading() {
return (
this.$apollo.queries.fluxKustomizationStatus.loading ||
this.$apollo.queries.fluxHelmReleaseStatus.loading
);
},
fluxBadgeId() {
return `${this.environmentName}-flux-sync-badge`;
},
fluxCRD() {
if (!this.hasKustomizations && !this.hasHelmReleases) {
return [];
}
return this.hasKustomizations ? this.fluxKustomizationStatus : this.fluxHelmReleaseStatus;
},
fluxAnyStalled() {
return this.fluxCRD.find((condition) => {
return this.fluxResourceStatus.find((condition) => {
return condition.status === STATUS_TRUE && condition.type === 'Stalled';
});
},
fluxAnyReconcilingWithBadConfig() {
return this.fluxCRD.find((condition) => {
return this.fluxResourceStatus.find((condition) => {
return (
condition.status === STATUS_UNKNOWN &&
condition.type === 'Ready' &&
@ -194,25 +146,25 @@ export default {
});
},
fluxAnyReconciling() {
return this.fluxCRD.find((condition) => {
return this.fluxResourceStatus.find((condition) => {
return condition.status === STATUS_TRUE && condition.type === 'Reconciling';
});
},
fluxAnyReconciled() {
return this.fluxCRD.find((condition) => {
return this.fluxResourceStatus.find((condition) => {
return condition.status === STATUS_TRUE && condition.type === 'Ready';
});
},
fluxAnyFailed() {
return this.fluxCRD.find((condition) => {
return this.fluxResourceStatus.find((condition) => {
return condition.status === STATUS_FALSE && condition.type === 'Ready';
});
},
syncStatusBadge() {
if (!this.fluxCRD.length && this.fluxApiError) {
if (!this.fluxResourceStatus.length && this.fluxApiError) {
return { ...SYNC_STATUS_BADGES.unavailable, popoverText: this.fluxApiError };
}
if (!this.fluxCRD.length) {
if (!this.fluxResourceStatus.length) {
return SYNC_STATUS_BADGES.unavailable;
}
if (this.fluxAnyFailed) {

View File

@ -1,4 +1,5 @@
<script>
import { isEmpty } from 'lodash';
import { GlTab } from '@gitlab/ui';
import { s__ } from '~/locale';
@ -10,10 +11,25 @@ export default {
summaryTitle: s__('Environment|Summary'),
treeView: s__('Environment|Tree view'),
},
props: {
fluxKustomization: {
required: true,
type: Object,
},
},
computed: {
hasFluxKustomization() {
return !isEmpty(this.fluxKustomization);
},
},
};
</script>
<template>
<gl-tab :title="$options.i18n.summaryTitle">
<p class="gl-mt-3 gl-text-secondary">{{ $options.i18n.treeView }}</p>
</gl-tab>
<p v-if="hasFluxKustomization">
{{ fluxKustomization.kind }}: {{ fluxKustomization.metadata.name }}
</p></gl-tab
>
</template>

View File

@ -34,6 +34,11 @@ export default {
required: true,
type: String,
},
fluxKustomization: {
required: false,
type: Object,
default: () => ({}),
},
},
data() {
return {
@ -70,7 +75,7 @@ export default {
<template>
<div>
<gl-tabs v-model="activeTabIndex">
<kubernetes-summary v-if="renderTreeView" />
<kubernetes-summary v-if="renderTreeView" :flux-kustomization="fluxKustomization" />
<kubernetes-pods
:namespace="namespace"

View File

@ -9,7 +9,7 @@ import k8sPodsQuery from './queries/k8s_pods.query.graphql';
import k8sConnectionStatusQuery from './queries/k8s_connection_status.query.graphql';
import k8sServicesQuery from './queries/k8s_services.query.graphql';
import k8sNamespacesQuery from './queries/k8s_namespaces.query.graphql';
import fluxKustomizationStatusQuery from './queries/flux_kustomization_status.query.graphql';
import fluxKustomizationQuery from './queries/flux_kustomization.query.graphql';
import fluxHelmReleaseStatusQuery from './queries/flux_helm_release_status.query.graphql';
import { resolvers } from './resolvers';
import typeDefs from './typedefs.graphql';
@ -128,21 +128,29 @@ export const apolloProvider = (endpoint) => {
},
});
cache.writeQuery({
query: fluxKustomizationStatusQuery,
query: fluxKustomizationQuery,
data: {
message: '',
reason: '',
status: '',
type: '',
kind: '',
metadata: {
name: '',
},
conditions: {
message: '',
reason: '',
status: '',
type: '',
},
},
});
cache.writeQuery({
query: fluxHelmReleaseStatusQuery,
data: {
message: '',
reason: '',
status: '',
type: '',
conditions: {
message: '',
reason: '',
status: '',
type: '',
},
},
});

View File

@ -1,9 +1,11 @@
query getFluxHelmReleaseStatusQuery($configuration: LocalConfiguration, $fluxResourcePath: String) {
fluxHelmReleaseStatus(configuration: $configuration, fluxResourcePath: $fluxResourcePath)
@client {
message
reason
status
type
conditions {
message
reason
status
type
}
}
}

View File

@ -0,0 +1,14 @@
query getFluxKustomizationQuery($configuration: LocalConfiguration, $fluxResourcePath: String) {
fluxKustomization(configuration: $configuration, fluxResourcePath: $fluxResourcePath) @client {
kind
metadata {
name
}
conditions {
message
reason
status
type
}
}
}

View File

@ -1,12 +0,0 @@
query getFluxHelmKustomizationStatusQuery(
$configuration: LocalConfiguration
$fluxResourcePath: String
) {
fluxKustomizationStatus(configuration: $configuration, fluxResourcePath: $fluxResourcePath)
@client {
message
reason
status
type
}
}

View File

@ -6,14 +6,14 @@ import {
} from '~/environments/constants';
import { updateConnectionStatus } from '~/environments/graphql/resolvers/kubernetes/k8s_connection_status';
import { connectionStatus } from '~/environments/graphql/resolvers/kubernetes/constants';
import fluxKustomizationStatusQuery from '../queries/flux_kustomization_status.query.graphql';
import fluxKustomizationQuery from '../queries/flux_kustomization.query.graphql';
import fluxHelmReleaseStatusQuery from '../queries/flux_helm_release_status.query.graphql';
const helmReleasesApiVersion = 'helm.toolkit.fluxcd.io/v2beta1';
const kustomizationsApiVersion = 'kustomize.toolkit.fluxcd.io/v1';
const helmReleaseField = 'fluxHelmReleaseStatus';
const kustomizationField = 'fluxKustomizationStatus';
const kustomizationField = 'fluxKustomization';
const handleClusterError = (err) => {
const error = err?.response?.data?.message ? new Error(err.response.data.message) : err;
@ -28,6 +28,21 @@ export const buildFluxResourceWatchPath = ({ namespace, apiVersion, resourceType
return `/apis/${apiVersion}/namespaces/${namespace}/${resourceType}`;
};
const mapFluxItems = (fluxItem, resourceType) => {
if (resourceType === KUSTOMIZATIONS_RESOURCE_TYPE) {
return {
kind: fluxItem?.kind || '',
metadata: {
name: fluxItem?.metadata?.name || '',
},
conditions: fluxItem?.status?.conditions || [],
};
}
return {
conditions: fluxItem?.status?.conditions || [],
};
};
const watchFluxResource = ({
watchPath,
resourceName,
@ -55,7 +70,7 @@ const watchFluxResource = ({
let result = [];
watcher.on(EVENT_DATA, (data) => {
result = data[0]?.status?.conditions;
result = mapFluxItems(data[0], resourceType);
client.writeQuery({
query,
@ -85,7 +100,7 @@ const watchFluxResource = ({
});
};
const getFluxResourceStatus = ({ query, variables, field, resourceType, client }) => {
const getFluxResource = ({ query, variables, field, resourceType, client }) => {
const { headers } = variables.configuration;
const withCredentials = true;
const url = `${variables.configuration.basePath}/apis/${variables.fluxResourcePath}`;
@ -113,7 +128,7 @@ const getFluxResourceStatus = ({ query, variables, field, resourceType, client }
});
}
return fluxData?.status?.conditions || [];
return mapFluxItems(fluxData, resourceType);
})
.catch((err) => {
handleClusterError(err);
@ -121,12 +136,12 @@ const getFluxResourceStatus = ({ query, variables, field, resourceType, client }
};
export const watchFluxKustomization = ({ configuration, client, fluxResourcePath }) => {
const query = fluxKustomizationStatusQuery;
const query = fluxKustomizationQuery;
const variables = { configuration, fluxResourcePath };
const field = kustomizationField;
const resourceType = KUSTOMIZATIONS_RESOURCE_TYPE;
getFluxResourceStatus({ query, variables, field, resourceType, client });
getFluxResource({ query, variables, field, resourceType, client });
};
export const watchFluxHelmRelease = ({ configuration, client, fluxResourcePath }) => {
@ -135,7 +150,7 @@ export const watchFluxHelmRelease = ({ configuration, client, fluxResourcePath }
const field = helmReleaseField;
const resourceType = HELM_RELEASES_RESOURCE_TYPE;
getFluxResourceStatus({ query, variables, field, resourceType, client });
getFluxResource({ query, variables, field, resourceType, client });
};
const getFluxResources = (configuration, url) => {
@ -164,9 +179,9 @@ const getFluxResources = (configuration, url) => {
};
export default {
fluxKustomizationStatus(_, { configuration, fluxResourcePath }, { client }) {
return getFluxResourceStatus({
query: fluxKustomizationStatusQuery,
fluxKustomization(_, { configuration, fluxResourcePath }, { client }) {
return getFluxResource({
query: fluxKustomizationQuery,
variables: { configuration, fluxResourcePath },
field: kustomizationField,
resourceType: KUSTOMIZATIONS_RESOURCE_TYPE,
@ -174,7 +189,7 @@ export default {
});
},
fluxHelmReleaseStatus(_, { configuration, fluxResourcePath }, { client }) {
return getFluxResourceStatus({
return getFluxResource({
query: fluxHelmReleaseStatusQuery,
variables: { configuration, fluxResourcePath },
field: helmReleaseField,

View File

@ -70,11 +70,26 @@ type LocalK8sNamespaces {
metadata: k8sNamespaceMetadata
}
type LocalFluxResourceStatus {
type LocalFluxResourceMetadata {
name: String
}
type LocalFluxResourceConditions {
message: String
reason: String
status: String
type: String
}
type LocalFluxKustomization {
kind: String
metadata: LocalFluxResourceMetadata
conditions: [LocalFluxResourceConditions]
}
type LocalFluxHelmReleaseStatus {
conditions: [LocalFluxResourceConditions]
}
type K8sResources {
k8sPods: K8sResource
k8sServices: K8sResource
@ -95,14 +110,14 @@ extend type Query {
k8sPods(configuration: LocalConfiguration, namespace: String): [LocalWorkloadItem]
k8sServices(configuration: LocalConfiguration, namespace: String): [LocalWorkloadItem]
k8sConnection(configuration: LocalConfiguration): K8sResources
fluxKustomizationStatus(
fluxKustomization(
configuration: LocalConfiguration
fluxResourcePath: String
): LocalFluxResourceStatus
): LocalFluxKustomization
fluxHelmReleaseStatus(
configuration: LocalConfiguration
fluxResourcePath: String
): LocalFluxResourceStatus
): LocalFluxHelmReleaseStatus
}
input ResourceTypeParam {

View File

@ -321,7 +321,7 @@ class GfmAutoComplete {
displayTpl({ name }) {
const reviewState = REVIEW_STATES[name];
return `<li><span class="name gl-font-weight-bold">${reviewState.header}</span><small class="description"><em>${reviewState.description}</em></small></li>`;
return `<li><span class="name gl-font-bold">${reviewState.header}</span><small class="description"><em>${reviewState.description}</em></small></li>`;
},
});
}

View File

@ -341,7 +341,7 @@ export default {
<div :class="{ 'gl-font-weight-bold': item.memberRoleId }">{{ item.text }}</div>
<div
v-if="item.description"
class="gl-text-gray-700 gl-font-sm gl-pt-1 gl-line-clamp-2"
class="gl-text-gray-700 gl-font-sm gl-pt-1 gl-line-clamp-2 gl-whitespace-normal"
>
{{ item.description }}
</div>

View File

@ -134,7 +134,10 @@ export default {
<div data-testid="access-level-link" :class="{ 'gl-font-weight-bold': item.memberRoleId }">
{{ item.text }}
</div>
<div v-if="item.description" class="gl-text-gray-700 gl-font-sm gl-pt-1 gl-line-clamp-2">
<div
v-if="item.description"
class="gl-text-gray-700 gl-font-sm gl-pt-1 gl-line-clamp-2 gl-whitespace-normal"
>
{{ item.description }}
</div>
</template>

View File

@ -94,7 +94,7 @@ export default {
v-safe-html:[$options.safeHtmlConfig]="commit.titleHtml"
:href="commit.webPath"
:class="{ 'gl-italic': !commit.message }"
class="commit-row-message item-title gl-line-clamp-1 !gl-break-all"
class="commit-row-message item-title gl-line-clamp-1 gl-whitespace-normal !gl-break-all"
/>
<gl-button
v-if="commit.descriptionHtml"

View File

@ -24,11 +24,14 @@ import TokenAccessTable from './token_access_table.vue';
export default {
i18n: {
toggleLabelTitle: s__('CICD|Limit access %{italicStart}to%{italicEnd} this project'),
toggleLabelTitle: s__('CICD|Allow CI/CD job token access'),
toggleDescription: s__(
`CICD|Allow access to this project from authorized groups or projects by adding them to the allowlist. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API. %{linkStart}Learn more%{linkEnd}.`,
`CICD|When enabled, groups and projects listed in the allowlist are authorized to use a CI/CD job token to authenticate requests to this project. %{linkStart}Learn more%{linkEnd}.`,
),
cardHeaderTitle: s__('CICD|Authorized groups and projects'),
cardHeaderDescription: s__(
`CICD|Ensure only groups and projects with members authorized to access sensitive project data are added to the allowlist.`,
),
cardHeaderTitle: s__('CICD|Groups and projects with access'),
settingDisabledMessage: s__(
'CICD|No access is currently allowed to this project. Enable feature to authorize access from groups or projects in the allowlist below.',
),
@ -258,22 +261,25 @@ export default {
<div>
<gl-card
class="gl-new-card"
header-class="gl-new-card-header gl-border-bottom-0"
header-class="gl-new-card-header gl-border-bottom-0 gl-flex-wrap gl-md-flex-nowrap"
body-class="gl-new-card-body gl-px-0"
>
<template #header>
<div class="gl-new-card-title-wrapper">
<h5 class="gl-new-card-title">{{ $options.i18n.cardHeaderTitle }}</h5>
<span class="gl-new-card-count">
<gl-icon name="group" class="gl-mr-2" />
{{ groups.length }}
</span>
<span class="gl-new-card-count">
<gl-icon name="project" class="gl-mr-2" />
{{ projects.length }}
</span>
<div class="gl-new-card-title-wrapper gl-flex-direction-column gl-flex-wrap">
<div class="gl-new-card-title">
<h5>{{ $options.i18n.cardHeaderTitle }}</h5>
<span class="gl-new-card-count">
<gl-icon name="group" class="gl-mr-2" />
{{ groups.length }}
</span>
<span class="gl-new-card-count">
<gl-icon name="project" class="gl-mr-2" />
{{ projects.length }}
</span>
</div>
<p class="gl-text-secondary">{{ $options.i18n.cardHeaderDescription }}</p>
</div>
<div class="gl-new-card-actions">
<div class="gl-new-card-actions gl-w-full gl-md-w-auto gl-text-right">
<gl-button
v-if="!isAddFormVisible"
size="small"

View File

@ -20,7 +20,7 @@ import getCIJobTokenScopeQuery from '../graphql/queries/get_ci_job_token_scope.q
import getProjectsWithCIJobTokenScopeQuery from '../graphql/queries/get_projects_with_ci_job_token_scope.query.graphql';
import TokenAccessTable from './token_access_table.vue';
// Note: This component will be removed in 17.0, as the outbound access token is getting deprecated
// Note: This component will be removed in 18.0, as the outbound access token is getting deprecated
export default {
i18n: {
toggleLabelTitle: s__(
@ -39,7 +39,7 @@ export default {
projectsFetchError: __('There was a problem fetching the projects'),
scopeFetchError: __('There was a problem fetching the job token scope value'),
outboundTokenAlertDeprecationMessage: s__(
`CICD|The %{boldStart}Limit access %{boldEnd}%{italicAndBoldStart}from%{italicAndBoldEnd}%{boldStart} this project%{boldEnd} setting is deprecated and will be removed in the 18.0 milestone. Use the %{boldStart}Limit access %{boldEnd}%{italicAndBoldStart}to%{italicAndBoldEnd}%{boldStart} this project%{boldEnd} setting and allowlist instead. %{linkStart}How do I do this?%{linkEnd}`,
`CICD|The %{boldStart}Limit access %{boldEnd}%{italicAndBoldStart}from%{italicAndBoldEnd}%{boldStart} this project%{boldEnd} setting is deprecated and will be removed in the 18.0 milestone. Use the %{boldStart}Allow CI/CD job token access%{boldEnd} setting and allowlist instead. %{linkStart}How do I do this?%{linkEnd}`,
),
disableToggleWarning: s__('CICD|Disabling this feature is a permanent change.'),
},

View File

@ -101,7 +101,7 @@ export default {
variant="confirm"
data-testid="diff-stats-dropdown"
class="gl-align-baseline"
toggle-class="gl-px-0! gl-font-weight-bold!"
toggle-class="gl-px-0! !gl-font-bold"
fluid-width
@shown="focusInput"
>

View File

@ -277,7 +277,7 @@ export default {
data-testid="preview-toggle"
:value="previewMarkdown ? 'preview' : 'edit'"
:label="$options.i18n.previewTabTitle"
class="js-md-preview-button gl-flex-direction-row-reverse gl-align-items-center gl-font-weight-normal!"
class="js-md-preview-button gl-flex-direction-row-reverse gl-align-items-center !gl-font-normal"
size="small"
category="tertiary"
@click="switchPreview"

View File

@ -252,7 +252,7 @@ export default {
class="gl-m-0"
:label="$options.i18n.startDate"
:label-for="$options.startDateInputId"
label-class="gl-font-weight-normal! gl-pb-2!"
label-class="!gl-font-normal gl-pb-2!"
>
<gl-datepicker
ref="startDatePicker"
@ -272,7 +272,7 @@ export default {
class="gl-m-0 gl-pl-3 gl-pr-2"
:label="$options.i18n.dueDate"
:label-for="$options.dueDateInputId"
label-class="gl-font-weight-normal! gl-pb-2!"
label-class="!gl-font-normal gl-pb-2!"
>
<gl-datepicker
v-model="dirtyDueDate"

View File

@ -559,6 +559,6 @@
}
.projects-list .description p {
@include gl-line-clamp-2;
@apply gl-line-clamp-2 gl-whitespace-normal;
margin-bottom: 0;
}

View File

@ -2,9 +2,9 @@
.gl-display-flex.gl-align-items-center.gl-text-gray-700.gl-mb-2
- if title_icon?
= sprite_icon(@title_icon, css_class: 'gl-mr-2')
%span.gl-font-base.gl-font-weight-normal{ data: { testid: 'title-text' } }
%span.gl-font-base.gl-font-normal{ data: { testid: 'title-text' } }
= title || @title
.gl-single-stat-content.gl-display-flex.gl-align-items-baseline.gl-font-weight-bold.gl-text-gray-900
.gl-single-stat-content.gl-display-flex.gl-align-items-baseline.gl-font-bold.gl-text-gray-900
%span.gl-single-stat-number.gl-leading-1{ class: unit_class, data: { testid: 'displayValue' } }
%span{ data: { testid: @stat_value_testid } }
= stat_value || @stat_value

View File

@ -32,7 +32,7 @@
= f.label :screenshot do
%span
= s_('ReportAbuse|Screenshot')
.gl-font-weight-normal
.gl-font-normal
= s_('ReportAbuse|Screenshot of abuse')
%div
= render 'shared/file_picker_button', f: f, field: :screenshot, help_text: _("Screenshot must be less than 1 MB."), mime_types: valid_image_mimetypes

View File

@ -9,10 +9,10 @@
_('Enable unauthenticated Git HTTP request rate limit'),
help_text: _('Helps reduce unauthenticated Git HTTP request volume for git paths.')
.form-group
= f.label :throttle_unauthenticated_git_http_requests_per_period, _('Maximum unauthenticated Git HTTP requests per period per IP'), class: 'gl-font-weight-bold'
= f.label :throttle_unauthenticated_git_http_requests_per_period, _('Maximum unauthenticated Git HTTP requests per period per IP'), class: 'gl-font-bold'
= f.number_field :throttle_unauthenticated_git_http_requests_per_period, class: 'form-control gl-form-input'
.form-group
= f.label :throttle_unauthenticated_git_http_period_in_seconds, _('Unauthenticated Git HTTP rate limit period in seconds'), class: 'gl-font-weight-bold'
= f.label :throttle_unauthenticated_git_http_period_in_seconds, _('Unauthenticated Git HTTP rate limit period in seconds'), class: 'gl-font-bold'
= f.number_field :throttle_unauthenticated_git_http_period_in_seconds, class: 'form-control gl-form-input'
= f.submit _('Save changes'), pajamas_button: true

View File

@ -9,10 +9,10 @@
_('Enable authenticated Git LFS request rate limit'),
help_text: _('Helps reduce request volume (for example, from crawlers or abusive bots)')
.form-group
= f.label :throttle_authenticated_git_lfs_requests_per_period, _('Max authenticated Git LFS requests per period per user'), class: 'gl-font-weight-bold'
= f.label :throttle_authenticated_git_lfs_requests_per_period, _('Max authenticated Git LFS requests per period per user'), class: 'gl-font-bold'
= f.number_field :throttle_authenticated_git_lfs_requests_per_period, class: 'form-control gl-form-input'
.form-group
= f.label :throttle_authenticated_git_lfs_period_in_seconds, _('Authenticated Git LFS rate limit period in seconds'), class: 'gl-font-weight-bold'
= f.label :throttle_authenticated_git_lfs_period_in_seconds, _('Authenticated Git LFS rate limit period in seconds'), class: 'gl-font-bold'
= f.number_field :throttle_authenticated_git_lfs_period_in_seconds, class: 'form-control gl-form-input'
= f.submit _('Save changes'), pajamas_button: true

View File

@ -14,7 +14,7 @@
%span.form-text.text-muted#support_help_block= _('Alternate support URL for Help page and Help dropdown.')
.form-group
= f.label :help_page_documentation_base_url, _('Documentation pages URL'), class: 'gl-font-weight-bold'
= f.label :help_page_documentation_base_url, _('Documentation pages URL'), class: 'gl-font-bold'
= f.text_field :help_page_documentation_base_url, class: 'form-control gl-form-input', placeholder: 'https://docs.gitlab.com'
- docs_link_url = help_page_path('administration/settings/help_page', anchor: 'destination-requirements')
- docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: docs_link_url }

View File

@ -15,12 +15,12 @@
= f.label :project_export, s_('AdminSettings|Project export'), class: 'label-bold'
= f.gitlab_ui_checkbox_component :project_export_enabled, s_('AdminSettings|Enabled')
.form-group{ data: { testid: 'bulk-import' } }
= f.label :bulk_import, s_('AdminSettings|Allow migrating GitLab groups and projects by direct transfer'), class: 'gl-font-weight-bold'
= f.label :bulk_import, s_('AdminSettings|Allow migrating GitLab groups and projects by direct transfer'), class: 'gl-font-bold'
= f.gitlab_ui_checkbox_component :bulk_import_enabled, s_('AdminSettings|Enabled')
.form-group{ data: { testid: 'silent-admin-exports' } }
- tag_pair_silent_admin_exports = tag_pair(link_to('', help_page_path('administration/settings/import_and_export_settings', anchor: 'enable-silent-admin-exports'), target: '_blank', rel: 'noopener noreferrer'), :silent_admin_exports_link_start, :silent_admin_exports_link_end)
- silent_admin_exports_label_text = safe_format(s_('AdminSettings|Silent exports by admins %{silent_admin_exports_link_start}%{icon}%{silent_admin_exports_link_end}'), tag_pair_silent_admin_exports, icon: sprite_icon('question-o'))
= f.label :silent_admin_exports_enabled, silent_admin_exports_label_text, class: 'gl-font-weight-bold'
= f.label :silent_admin_exports_enabled, silent_admin_exports_label_text, class: 'gl-font-bold'
= f.gitlab_ui_checkbox_component :silent_admin_exports_enabled, s_('AdminSettings|Enabled')
.form-group
= f.label :max_export_size, _('Maximum export size (MiB)'), class: 'label-light'

View File

@ -12,7 +12,7 @@
help_text: Gitlab::Auth::Ldap::Config.enabled? ? _('Clear this checkbox to use a personal access token or LDAP password instead.') : _('Clear this checkbox to use a personal access token instead.')
- if omniauth_enabled? && button_based_providers.any?
%fieldset.form-group
%legend.gl-font-base.gl-mb-3.gl-border-none.gl-font-weight-bold= _('Enabled OAuth authentication sources')
%legend.gl-font-base.gl-mb-3.gl-border-none.gl-font-bold= _('Enabled OAuth authentication sources')
= hidden_field_tag 'application_setting[enabled_oauth_sign_in_sources][]'
- oauth_providers_checkboxes(f).each do |source|
= source

View File

@ -85,7 +85,7 @@
= f.label :spam_check_endpoint_url, _('URL of the external Spam Check endpoint'), class: 'label-bold'
= f.text_field :spam_check_endpoint_url, class: 'form-control gl-form-input'
.form-group
= f.label :spam_check_api_key, _('Spam Check API key'), class: 'gl-font-weight-bold'
= f.label :spam_check_api_key, _('Spam Check API key'), class: 'gl-font-bold'
= f.text_field :spam_check_api_key, class: 'form-control gl-form-input'
.form-text.text-muted= _('The API key used by GitLab for accessing the Spam Check service endpoint.')

View File

@ -16,7 +16,7 @@
= form.gitlab_ui_checkbox_component :email_header_and_footer_enabled,
_('Enable header and footer in emails'),
help_text: _('Add header and footer to emails. Please note that color settings will only be applied within the application interface'),
label_options: { class: 'gl-font-weight-bold!' }
label_options: { class: '!gl-font-bold' }
.form-group.js-toggle-colors-container
= render Pajamas::ButtonComponent.new(variant: :link, button_options: { class: 'js-toggle-colors-link' }) do

View File

@ -61,7 +61,7 @@
.gl-display-flex.gl-flex-wrap.gl-align-items-center.gl-gap-2
= link_to(s_('AdminArea|View latest users'), admin_users_path({ sort: 'created_desc' }))
%span.gl-text-secondary= "/"
= link_to(s_('AdminArea|Users statistics'), admin_dashboard_stats_path, class: "gl-font-base gl-font-weight-normal gl-text-capitalize")
= link_to(s_('AdminArea|Users statistics'), admin_dashboard_stats_path, class: "gl-font-base gl-font-normal gl-text-capitalize")
.col-md-4.gl-mb-6
= render Pajamas::CardComponent.new(**component_params) do |c|
- c.with_body do

View File

@ -5,7 +5,7 @@
= render 'admin/dashboard/stats_users_table', user_statistics: @users_statistics
%p.gl-font-weight-bold.gl-mt-8
%p.gl-font-bold.gl-mt-8
= s_('AdminArea|Totals')
%table.gl-table.gl-text-gray-500.gl-w-full

View File

@ -2,5 +2,5 @@
- help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe
- help_link_end = '</a>'.html_safe
%p.gl-font-weight-bold
%p.gl-font-bold
= s_('ClusterIntegration|Using AutoDevOps with multiple clusters? %{help_link_start}Read this first.%{help_link_end}').html_safe % { help_link_start: help_link_start % { url: autodevops_help_url }, help_link_end: help_link_end }

View File

@ -41,7 +41,7 @@
= s_('Import|Must only contain the base URL of the source GitLab instance.')
.form-group.gl-form-group.gl-display-flex.gl-flex-direction-column
= f.label :bulk_import_gitlab_access_token, s_('GroupsNew|Personal access token'), for: 'import_gitlab_token', class: 'col-form-label'
.gl-font-weight-normal
.gl-font-normal
- pat_link = link_to('', help_page_path('user/profile/personal_access_tokens'), target: '_blank')
- short_living_link = link_to('', help_page_path('security/token_overview', anchor: 'security-considerations'), target: '_blank')
= safe_format(s_('GroupsNew|Create a token with %{code_start}api%{code_end} and %{code_start}read_repository%{code_end} scopes in the %{pat_link_start}user settings%{pat_link_end} of the source GitLab instance. For %{short_living_link_start}security reasons%{short_living_link_end}, set a short expiration date for the token. Keep in mind that large migrations take more time.'), tag_pair('<code></code>'.html_safe, :code_start , :code_end), tag_pair(pat_link, :pat_link_start, :pat_link_end), tag_pair(short_living_link, :short_living_link_start, :short_living_link_end))

View File

@ -16,7 +16,7 @@
= render 'shared/groups/group_name_and_path_fields', f: f
.form-group
= f.label :file, s_('GroupsNew|Upload file')
.gl-font-weight-normal
.gl-font-normal
- import_export_link_start = '<a href="%{url}" target="_blank">'.html_safe % { url: help_page_path('user/project/settings/import_export', anchor: 'migrate-groups-by-uploading-an-export-file-deprecated') }
= s_('GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here.').html_safe % { link_start: import_export_link_start, link_end: '</a>'.html_safe }
.gl-mt-3

View File

@ -111,3 +111,7 @@
= render_if_exists "layouts/frontend_monitor"
%meta{ name: "description", content: page_description }
%meta{ name: 'theme-color', content: user_theme_primary_color }
- if Gitlab.config.gitlab.respond_to?(:custom_html_header_tags)
- unless Gitlab.config.gitlab.custom_html_header_tags.empty?
= Gitlab.config.gitlab.custom_html_header_tags.html_safe

View File

@ -21,7 +21,7 @@
- if current_user
.gl-display-flex.gl-gap-2.gl-align-items-center
.gl-text-right.gl-leading-normal
.gl-font-weight-bold= current_user.name
.gl-font-bold= current_user.name
.gl-text-gray-700 @#{current_user.username}
= render Pajamas::AvatarComponent.new(current_user, size: 32, avatar_options: { data: { testid: 'user-avatar-content' } })
- c.with_body do

View File

@ -24,7 +24,7 @@
= s_("Profiles|Increase your account's security by enabling two-factor authentication (2FA).")
%div
%p
%span.gl-font-weight-bold
%span.gl-font-bold
#{_('Status')}:
#{current_user.two_factor_enabled? ? _('Enabled') : _('Disabled')}
- if current_user.two_factor_enabled?

View File

@ -12,11 +12,11 @@
- link = link_to('', help_page_path('user/project/settings/import_export'), target: '_blank', rel: 'noopener noreferrer')
= safe_format(_('Export this project with all its related data in order to move it to a new GitLab instance. When the exported file is ready, you can download it from this page or from the download link in the email notification you will receive. You can then import it when creating a new project. %{link_start}Learn more.%{link_end}'), tag_pair(link, :link_start, :link_end))
.gl-mb-0
%p.gl-font-weight-bold= _('The following items will be exported:')
%p.gl-font-bold= _('The following items will be exported:')
%ul
- project_export_descriptions.each do |desc|
%li= desc
%p.gl-font-weight-bold= _('The following items will NOT be exported:')
%p.gl-font-bold= _('The following items will NOT be exported:')
%ul
%li= _('Job logs and artifacts')
%li= _('Container registry images')

View File

@ -5,7 +5,7 @@
.form-group.import-btn-container.clearfix
%h5.gl-display-flex
= _("Import project from")
= link_to _('History'), import_history_index_path, class: 'gl-link gl-ml-auto gl-font-weight-normal'
= link_to _('History'), import_history_index_path, class: 'gl-link gl-ml-auto gl-font-normal'
%div
= render Pajamas::AlertComponent.new(variant: :tip,
alert_options: { class: 'gl-my-3' },

View File

@ -1,4 +1,4 @@
%p.gl-font-weight-bold.gl-text-gray-900.gl-mt-0.-gl-mt-1.gl-mb-3{ data: { testid: 'invite-member-section',
%p.gl-font-bold.gl-text-gray-900.gl-mt-0.-gl-mt-1.gl-mb-3{ data: { testid: 'invite-member-section',
track_label: 'invite_members_empty_project',
track_action: 'render' } }
= s_('InviteMember|Invite your team')

View File

@ -6,7 +6,7 @@
%aside.project-page-sidebar{ data: { testid: 'project-page-sidebar' } }
.project-page-sidebar-block.home-panel-home-desc.gl-py-4.gl-border-b.gl-border-gray-50{ class: 'gl-pt-2!' }
%h2.gl-font-base.gl-font-weight-bold.gl-leading-reset.gl-text-gray-900.gl-m-0.gl-mb-1= s_('ProjectPage|Project information')
%h2.gl-font-base.gl-font-bold.gl-leading-reset.gl-text-gray-900.gl-m-0.gl-mb-1= s_('ProjectPage|Project information')
-# Project description
- if @project.description.present?
.home-panel-description.text-break
@ -63,5 +63,5 @@
-# Project created
.project-page-sidebar-block.gl-py-4
%p.gl-font-weight-bold.gl-text-gray-900.gl-m-0.gl-mb-1= s_('ProjectPage|Created on')
%p.gl-font-bold.gl-text-gray-900.gl-m-0.gl-mb-1= s_('ProjectPage|Created on')
%span= @project.created_at.to_date.to_fs(:long)

View File

@ -21,7 +21,7 @@
%p
= _("Don't have a group?")
= link_to _('Create one'), new_group_path, target: '_blank'
%p.gl-font-weight-bold= _('Things to be aware of before transferring:')
%p.gl-font-bold= _('Things to be aware of before transferring:')
%ul
%li= _("Be careful. Changing the project's namespace can have unintended side effects.")
%li= _('You can only transfer the project to namespaces you manage.')

View File

@ -103,11 +103,11 @@
%section.settings.no-animate#js-token-access{ class: ('expanded' if expanded) }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= _("Token Access")
= _("Job token permissions")
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded ? _('Collapse') : _('Expand')
%p.gl-text-secondary
= _("Control how the CI_JOB_TOKEN CI/CD variable is used for API access between projects.")
= _("Control whether CI/CD job tokens can be used to authenticate with this project.")
.settings-content
= render 'ci/token_access/index'

View File

@ -4,7 +4,7 @@
= gl_badge_tag issuable_state_text(issuable), variant: issuable_state_to_badge_class(issuable), size: :sm
= sprite_icon('eye-slash', css_class: 'gl-text-secondary gl-ml-2') if issuable.respond_to?(:confidential?) && issuable.confidential?
= link_to issuable_path(issuable), data: { track_action: 'click_text', track_label: "#{issuable.class.name.downcase}_title", track_property: 'search_result' }, class: 'gl-w-full' do
%span.term.str-truncated.gl-font-weight-bold.gl-ml-2= simple_search_highlight_and_truncate(issuable.title, @search_term)
%span.term.str-truncated.gl-font-bold.gl-ml-2= simple_search_highlight_and_truncate(issuable.title, @search_term)
.gl-text-secondary.gl-mb-3.gl-mt-2.gl-font-sm
= issuable_project_reference(issuable)
&middot;

View File

@ -5,15 +5,15 @@
= render Pajamas::AvatarComponent.new(user, size: 32, alt: '')
.gl-ml-3{ class: 'gl-text-left!' }
= link_to user_path(user), class: 'gl-text-body' do
.gl-display-inline-block.gl-font-weight-bold= simple_search_highlight_and_truncate(user.name, @search_term)
.gl-display-inline-block.gl-font-bold= simple_search_highlight_and_truncate(user.name, @search_term)
= user_status(user)
%div{ class: 'gl-text-left!' }= simple_search_highlight_and_truncate(user.to_reference, @search_term)
%td.gl-text-right{ data: { label: _('Activity') } }
%div
%span.gl-font-weight-bold= _('User created:')
%span.gl-font-bold= _('User created:')
= l(user.created_at.to_date, format: :long)
%div
%span.gl-font-weight-bold= _('Last activity:')
%span.gl-font-bold= _('Last activity:')
- if user.last_activity_on
= l(user.last_activity_on.to_date, format: :long)
- else

View File

@ -1,6 +1,6 @@
%div{ class: 'search-result-row gl-pb-3! gl-mt-5 gl-mb-0!' }
%span.gl-display-flex.gl-align-items-center
= link_to wiki_blob_link(wiki_blob), data: { track_action: 'click_text', track_label: "wiki_title", track_property: 'search_result' }, class: 'gl-w-full' do
%span.term.str-truncated.gl-font-weight-bold= ::Wiki.canonicalize_filename(wiki_blob.path)
%span.term.str-truncated.gl-font-bold= ::Wiki.canonicalize_filename(wiki_blob.path)
.description.term.col-sm-10.gl-px-0
= simple_search_highlight_and_truncate(wiki_blob.data, @search_term)

View File

@ -5,7 +5,7 @@
= f.gitlab_ui_radio_component :default_branch_protected?, level[:value], level[:label], help_text: level[:help_text], radio_options: { class: 'js-global-protection-levels' }
.js-global-protection-levels-protected.gl-ml-7
%legend.h6.gl-my-3.gl-border-none.gl-font-weight-normal= s_('ProtectedBranch|Allowed to push')
%legend.h6.gl-my-3.gl-border-none.gl-font-normal= s_('ProtectedBranch|Allowed to push')
- allowed_to_push_access_level = value['allowed_to_push'][0]['access_level']
- ProtectedBranch::PushAccessLevel.human_access_levels.each do |id, text|
= render Pajamas::RadioTagComponent.new(name: "#{field}[default_branch_protection_defaults][allowed_to_push][][access_level]",
@ -13,7 +13,7 @@
value: id,
checked: allowed_to_push_access_level == id)
%legend.h6.gl-my-3.gl-border-none.gl-font-weight-normal= s_('ProtectedBranch|Allowed to merge')
%legend.h6.gl-my-3.gl-border-none.gl-font-normal= s_('ProtectedBranch|Allowed to merge')
- allowed_to_merge_access_level = value['allowed_to_merge'][0]['access_level']
- ProtectedBranch::MergeAccessLevel.human_access_levels.each do |id, text|
= render Pajamas::RadioTagComponent.new(name: "#{field}[default_branch_protection_defaults][allowed_to_merge][][access_level]",

View File

@ -1,6 +1,6 @@
- full_path = label.subject_full_name
.gl-font-sm.gl-font-weight-semibold.gl-text-secondary
.gl-font-sm.gl-font-semibold.gl-text-secondary
- if label.project_label?
= sprite_icon('project', size: 12, css_class: 'gl-text-gray-600')
- else

View File

@ -34,7 +34,7 @@
= s_('Webhooks|Response headers data is empty')
- else
- hook_log.response_headers.each do |k, v|
<span class="gl-font-weight-bold">#{k}:</span> #{v}
<span class="gl-font-bold">#{k}:</span> #{v}
%br
%h3.gl-mt-6= _('Request')
@ -48,5 +48,5 @@
%h4= _('Headers')
%pre
- hook_log.request_headers.each do |k, v|
<span class="gl-font-weight-bold">#{k}:</span> #{v}
<span class="gl-font-bold">#{k}:</span> #{v}
%br

View File

@ -63,7 +63,7 @@
.js-sidebar-time-tracking-root.block
// Fallback while content is loading
.title.hide-collapsed.gl-display-flex.gl-justify-content-space-between.gl-align-items-center{ class: 'gl-mb-0!' }
%span.gl-font-weight-bold= _('Time tracking')
%span.gl-font-bold= _('Time tracking')
= gl_loading_icon(inline: true)
- if issuable_sidebar.dig(:features_available, :health_status)

View File

@ -5,7 +5,7 @@
max_assignees: dropdown_options[:data][:"max-select"],
directly_invite_members: can_admin_project_member?(@project) } }
.title.hide-collapsed.gl-display-flex.gl-justify-content-space-between.gl-align-items-center{ class: 'gl-mb-0!' }
%span.gl-font-weight-bold= s_('Label|Assignee')
%span.gl-font-bold= s_('Label|Assignee')
= gl_loading_icon(inline: true)
.js-sidebar-assignee-data.selectbox.hide-collapsed

View File

@ -2,7 +2,7 @@
.js-sidebar-reviewers-root{ data: { field: issuable_type, signed_in: signed_in } }
.title.hide-collapsed.gl-display-flex.gl-justify-content-space-between.gl-align-items-center{ class: 'gl-mb-0!' }
%span.gl-font-weight-bold= _('Reviewers')
%span.gl-font-bold= _('Reviewers')
= gl_loading_icon(inline: true)
.selectbox.hide-collapsed

View File

@ -5,7 +5,7 @@
- c.with_header do
.gl-flex-grow-2
= title
.gl-ml-3.gl-flex-shrink-0.gl-font-weight-bold.gl-whitespace-nowrap{ class: milestone_counter_class(primary) }
.gl-ml-3.gl-flex-shrink-0.gl-font-bold.gl-whitespace-nowrap{ class: milestone_counter_class(primary) }
- if show_counter
%span
= sprite_icon('issues', css_class: 'gl-vertical-align-text-bottom')

View File

@ -32,7 +32,7 @@
.note-header
.note-header-info
%a{ href: user_path(note.author) }
%span.note-header-author-name.gl-font-weight-bold
%span.note-header-author-name.gl-font-bold
= note.author.name
= user_status(note.author)
%span.note-headline-light{ data: { testid: 'note-author-content' } }

View File

@ -30,7 +30,7 @@
.gl-display-flex.gl-align-items-baseline.gl-flex-wrap
%h2.gl-font-base.gl-leading-20.gl-my-0.gl-overflow-wrap-anywhere
= link_to project_path(project), class: 'text-plain gl-mr-3 js-prefetch-document', title: project.name do
%span.namespace-name.gl-font-weight-normal
%span.namespace-name.gl-font-normal
- if project.namespace && !skip_namespace
= project.namespace.human_name
\/

View File

@ -28,7 +28,7 @@
.gl-display-flex.gl-align-items-center.gl-flex-wrap
%h2.gl-font-base.gl-leading-20.gl-my-0
= link_to project_path(project), class: 'text-plain gl-mr-3 js-prefetch-document', title: project.name do
%span.namespace-name.gl-font-weight-normal
%span.namespace-name.gl-font-normal
- if project.namespace && !skip_namespace
= project.namespace.human_name
\/

View File

@ -1,7 +1,7 @@
- max_project_topic_length = 15
- if project.topics.present?
.gl-w-full.gl-display-inline-flex.gl-flex-wrap.gl-font-base.gl-font-weight-normal.gl-align-items-center.-gl-mx-2.-gl-my-2{ 'data-testid': 'project_topic_list' }
.gl-w-full.gl-display-inline-flex.gl-flex-wrap.gl-font-base.gl-font-normal.gl-align-items-center.-gl-mx-2.-gl-my-2{ 'data-testid': 'project_topic_list' }
- project.topics_to_show.each do |topic|
- explore_project_topic_path = topic_explore_projects_cleaned_path(topic_name: topic[:name])
- if topic[:title].length > max_project_topic_length

View File

@ -8,7 +8,7 @@
.gl-sm-display-flex.gl-justify-content-space-between.gl-align-items-center.gl-flex-grow-1
%div
= link_to gitlab_snippet_path(snippet), class: "title gl-text-black-normal gl-font-weight-bold" do
= link_to gitlab_snippet_path(snippet), class: "title gl-text-black-normal gl-font-bold" do
= snippet.title
- if snippet.hidden_due_to_author_ban?
%span{ class: 'has-tooltip gl-bg-orange-50 gl-text-orange-600 border-radius-default gl-p-2', title: s_("Snippets|This snippet is hidden because its author has been banned") }

View File

@ -34,7 +34,7 @@
%div
%h1.gl-heading-1.gl-leading-1.gl-mr-2{ class: 'gl-my-0!', itemprop: 'name' }
= user_display_name(@user)
.gl-font-size-h2.gl-text-gray-500.gl-font-weight-normal.gl-my-0
.gl-font-size-h2.gl-text-gray-500.gl-font-normal.gl-my-0
= @user.to_reference
- if !@user.blocked? && @user.confirmed? && @user.status&.customized?
.gl-my-2.cover-status.gl-font-sm.gl-pt-2.gl-display-flex.gl-flex-direction-column

View File

@ -139,6 +139,15 @@ production: &base
## 11 - Dark Mode (alpha)
# default_theme: 1 # default: 1
## Custom html header tags
# In some cases some custom header tags are needed
# e.g., to add the EU cookie consent
# Tip: you must add the externals source to the content_security_policy as
# well, typically the script_src and style_src.
# custom_html_header_tags: |
# <script src="https://example.com/cookie-consent.js"></script>
# <link rel="stylesheet" href="https://example.com/cookie-consent.css"/>
## Automatic issue closing
# If a commit message matches this regular expression, all issues referenced from the matched text will be closed.
# This happens when the commit is pushed or merged into the default branch of a project.

View File

@ -187,6 +187,7 @@ Settings.gitlab['default_branch_protection_defaults'] ||= ::Gitlab::Access::Bran
# `default_can_create_group` is deprecated since GitLab 15.5 in favour of the `can_create_group` column on `ApplicationSetting`.
Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_can_create_group'].nil?
Settings.gitlab['default_theme'] = Gitlab::Themes::APPLICATION_DEFAULT if Settings.gitlab['default_theme'].nil?
Settings.gitlab['custom_html_header_tags'] ||= Settings.gitlab['custom_html_header_tags'] || ''
Settings.gitlab['host'] ||= ENV['GITLAB_HOST'] || 'localhost'
Settings.gitlab['cdn_host'] ||= ENV['GITLAB_CDN_HOST'].presence
Settings.gitlab['ssh_host'] ||= Settings.gitlab.host

View File

@ -1,21 +0,0 @@
# frozen_string_literal: true
# Monkey patch of RDoc to prevent Ruby segfault due to
# stack buffer overflow Ruby bug -
# https://bugs.ruby-lang.org/issues/16376
#
# Safe to remove once GitLab upgrades to Ruby 3.0
# or once the fix is backported to 2.7.x and
# GitLab upgrades.
# https://gitlab.com/gitlab-org/gitlab/-/issues/351179
class RDoc::Markup::ToHtml
def parseable?(_)
false
end
end
class RDoc::Markup::Verbatim
def ruby?
false
end
end

View File

@ -709,6 +709,8 @@
- 1
- - search_zoekt_namespace_indexer
- 1
- - search_zoekt_namespace_initial_indexing
- 1
- - search_zoekt_project_transfer
- 1
- - security_delete_orchestration_configuration

View File

@ -65,10 +65,6 @@ module.exports = {
*/
backgroundImage: false,
/*
Our lineClamp also sets white-space: normal, which tailwind doesn't do, maybe we are okay?
*/
lineClamp: false,
/*
outline-none in tailwind is 2px solid transparent, we have outline: none
I assume that tailwind has it's reasons, and we probably could enable it

View File

@ -20,6 +20,8 @@
To prepare for this change, users on GitLab.com or self-managed GitLab 15.9 or later can enable the **Allow access** setting now and add the other projects. It will not be possible to disable the setting in 18.0 or later.
In 16.3, the names of these settings were changed to clarify their meanings: the deprecated **Limit CI_JOB_TOKEN access** setting is now called **Limit access _from_ this project**, and the newer **Allow access to this project with a CI_JOB_TOKEN** setting is now called **Limit access _to_ this project**.
In 17.1, the name of the **Limit access _to_ this project** setting was further clarified: it is now called **Grant access to this project**.
#
# OPTIONAL END OF SUPPORT FIELDS
#

View File

@ -20,6 +20,8 @@
To prepare for this change, users on GitLab.com or self-managed GitLab 15.9 or later can enable the **Allow access** setting now and add the other projects. It will not be possible to disable the setting in 18.0 or later.
In 16.3, the names of these settings were changed to clarify their meanings: the deprecated **Limit CI_JOB_TOKEN access** setting is now called **Limit access _from_ this project**, and the newer **Allow access to this project with a CI_JOB_TOKEN** setting is now called **Limit access _to_ this project**.
In 17.1, the name of the **Limit access _to_ this project** setting was further clarified: it is now called **Grant access to this project**.
#
# OPTIONAL END OF SUPPORT FIELDS
#

View File

@ -0,0 +1,9 @@
---
migration_job_name: BackfillRemoteDevelopmentAgentConfigsProjectId
description: Backfills sharding key `remote_development_agent_configs.project_id` from `cluster_agents`.
feature_category: remote_development
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/154773
milestone: '17.1'
queued_migration_version: 20240530122159
finalize_after: '2024-06-22'
finalized_by: # version of the migration that finalized this BBM

View File

@ -23,3 +23,4 @@ desired_sharding_key:
table: cluster_agents
sharding_key: project_id
belongs_to: agent
desired_sharding_key_migration_job_name: BackfillRemoteDevelopmentAgentConfigsProjectId

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class AddProjectIdToRemoteDevelopmentAgentConfigs < Gitlab::Database::Migration[2.2]
milestone '17.1'
def change
add_column :remote_development_agent_configs, :project_id, :bigint
end
end

View File

@ -0,0 +1,26 @@
# frozen_string_literal: true
class DeleteInvalidReleasesRecords < Gitlab::Database::Migration[2.2]
disable_ddl_transaction!
restrict_gitlab_migration gitlab_schema: :gitlab_main
milestone '17.1'
BATCH_SIZE = 1000
def up
return if Gitlab.com?
relation = define_batchable_model('releases').where(project_id: nil)
loop do
batch = relation.limit(BATCH_SIZE)
delete_count = relation.where(id: batch.select(:id)).delete_all
break if delete_count == 0
end
end
def down
# no-op
end
end

View File

@ -0,0 +1,14 @@
# frozen_string_literal: true
class AddReleasesProjectIdNotNull < Gitlab::Database::Migration[2.2]
milestone '17.1'
disable_ddl_transaction!
def up
add_not_null_constraint :releases, :project_id
end
def down
remove_not_null_constraint :releases, :project_id
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class IndexRemoteDevelopmentAgentConfigsOnProjectId < Gitlab::Database::Migration[2.2]
milestone '17.1'
disable_ddl_transaction!
INDEX_NAME = 'index_remote_development_agent_configs_on_project_id'
def up
add_concurrent_index :remote_development_agent_configs, :project_id, name: INDEX_NAME
end
def down
remove_concurrent_index_by_name :remote_development_agent_configs, INDEX_NAME
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class AddRemoteDevelopmentAgentConfigsProjectIdFk < Gitlab::Database::Migration[2.2]
milestone '17.1'
disable_ddl_transaction!
def up
add_concurrent_foreign_key :remote_development_agent_configs, :projects, column: :project_id, on_delete: :cascade
end
def down
with_lock_retries do
remove_foreign_key :remote_development_agent_configs, column: :project_id
end
end
end

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
class AddRemoteDevelopmentAgentConfigsProjectIdTrigger < Gitlab::Database::Migration[2.2]
milestone '17.1'
def up
install_sharding_key_assignment_trigger(
table: :remote_development_agent_configs,
sharding_key: :project_id,
parent_table: :cluster_agents,
parent_sharding_key: :project_id,
foreign_key: :cluster_agent_id
)
end
def down
remove_sharding_key_assignment_trigger(
table: :remote_development_agent_configs,
sharding_key: :project_id,
parent_table: :cluster_agents,
parent_sharding_key: :project_id,
foreign_key: :cluster_agent_id
)
end
end

View File

@ -0,0 +1,40 @@
# frozen_string_literal: true
class QueueBackfillRemoteDevelopmentAgentConfigsProjectId < Gitlab::Database::Migration[2.2]
milestone '17.1'
restrict_gitlab_migration gitlab_schema: :gitlab_main_cell
MIGRATION = "BackfillRemoteDevelopmentAgentConfigsProjectId"
DELAY_INTERVAL = 2.minutes
BATCH_SIZE = 1000
SUB_BATCH_SIZE = 100
def up
queue_batched_background_migration(
MIGRATION,
:remote_development_agent_configs,
:id,
:project_id,
:cluster_agents,
:project_id,
:cluster_agent_id,
job_interval: DELAY_INTERVAL,
batch_size: BATCH_SIZE,
sub_batch_size: SUB_BATCH_SIZE
)
end
def down
delete_batched_background_migration(
MIGRATION,
:remote_development_agent_configs,
:id,
[
:project_id,
:cluster_agents,
:project_id,
:cluster_agent_id
]
)
end
end

View File

@ -0,0 +1 @@
2b906ce6ee156abf865898ef3375225b94fe6b0d6aa3f7b9ccb2ceb21003cb39

View File

@ -0,0 +1 @@
aa4487aa295371014271f91136a26f7c247d2d24a810a0e4d2267e573fd347d4

View File

@ -0,0 +1 @@
db6ea016be2674f7f37604dc4b7d6258dfd6c38cc27e0c73639f9b5facbcaf74

View File

@ -0,0 +1 @@
fe404a483937603c2ff7a7bd5d1e7642b5912f72c8430f2a2f9a6cf937e5a90d

View File

@ -0,0 +1 @@
382fa4b14b6ea173d02a3e53440136f28b51a3621bf23817d3f8a8308488faf5

View File

@ -0,0 +1 @@
2f1fc5a1ad818a85f4aa0a2ae663620b0a8d2bb5c748aae326632bf98616d6f1

View File

@ -0,0 +1 @@
c6dcaf0fd3cb9abe8d14dc1c63ecad29b3ae30618e18d3b0c3f27e26620fa455

View File

@ -799,6 +799,22 @@ BEGIN
END;
$$;
CREATE FUNCTION trigger_3691f9f6a69f() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
IF NEW."project_id" IS NULL THEN
SELECT "project_id"
INTO NEW."project_id"
FROM "cluster_agents"
WHERE "cluster_agents"."id" = NEW."cluster_agent_id";
END IF;
RETURN NEW;
END
$$;
CREATE FUNCTION trigger_3857ca5ea4af() RETURNS trigger
LANGUAGE plpgsql
AS $$
@ -15584,7 +15600,8 @@ CREATE TABLE releases (
name character varying,
sha character varying,
released_at timestamp with time zone NOT NULL,
release_published_at timestamp with time zone
release_published_at timestamp with time zone,
CONSTRAINT check_6bb9ce4925 CHECK ((project_id IS NOT NULL))
);
CREATE SEQUENCE releases_id_seq
@ -15610,6 +15627,7 @@ CREATE TABLE remote_development_agent_configs (
max_resources_per_workspace jsonb DEFAULT '{}'::jsonb NOT NULL,
workspaces_quota bigint DEFAULT '-1'::integer NOT NULL,
workspaces_per_user_quota bigint DEFAULT '-1'::integer NOT NULL,
project_id bigint,
CONSTRAINT check_72947a4495 CHECK ((char_length(gitlab_workspaces_proxy_namespace) <= 63)),
CONSTRAINT check_9f5cd54d1c CHECK ((char_length(dns_zone) <= 256))
);
@ -27596,6 +27614,8 @@ CREATE INDEX index_releases_on_released_at ON releases USING btree (released_at)
CREATE INDEX index_remote_development_agent_configs_on_cluster_agent_id ON remote_development_agent_configs USING btree (cluster_agent_id);
CREATE INDEX index_remote_development_agent_configs_on_project_id ON remote_development_agent_configs USING btree (project_id);
CREATE INDEX index_remote_mirrors_on_last_successful_update_at ON remote_mirrors USING btree (last_successful_update_at);
CREATE INDEX index_remote_mirrors_on_project_id ON remote_mirrors USING btree (project_id);
@ -30346,6 +30366,8 @@ CREATE TRIGGER trigger_25c44c30884f BEFORE INSERT OR UPDATE ON work_item_parent_
CREATE TRIGGER trigger_2ac3d66ed1d3 BEFORE INSERT OR UPDATE ON vulnerability_occurrence_pipelines FOR EACH ROW EXECUTE FUNCTION trigger_2ac3d66ed1d3();
CREATE TRIGGER trigger_3691f9f6a69f BEFORE INSERT OR UPDATE ON remote_development_agent_configs FOR EACH ROW EXECUTE FUNCTION trigger_3691f9f6a69f();
CREATE TRIGGER trigger_3857ca5ea4af BEFORE INSERT OR UPDATE ON merge_trains FOR EACH ROW EXECUTE FUNCTION trigger_3857ca5ea4af();
CREATE TRIGGER trigger_388e93f88fdd BEFORE INSERT OR UPDATE ON packages_build_infos FOR EACH ROW EXECUTE FUNCTION trigger_388e93f88fdd();
@ -30910,6 +30932,9 @@ ALTER TABLE ONLY cluster_agent_tokens
ALTER TABLE p_ci_builds
ADD CONSTRAINT fk_6661f4f0e8 FOREIGN KEY (resource_group_id) REFERENCES ci_resource_groups(id) ON DELETE SET NULL;
ALTER TABLE ONLY remote_development_agent_configs
ADD CONSTRAINT fk_6a09894a0f FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY merge_requests
ADD CONSTRAINT fk_6a5165a692 FOREIGN KEY (milestone_id) REFERENCES milestones(id) ON DELETE SET NULL;

View File

@ -47,3 +47,4 @@ Customize and configure your self-managed GitLab installation.
- [Issue closing pattern](../administration/issue_closing_pattern.md)
- [Snippets](../administration/snippets/index.md)
- [Host the product documentation](../administration/docs_self_host.md)
- [Custom HTML header tags](../administration/custom_html_header_tags.md)

View File

@ -0,0 +1,70 @@
---
stage: Govern
group: Compliance
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: Learn how to modify the HTML header tags of your GitLab instance.
---
# Custom HTML header tags
DETAILS:
**Tier:** Free, Premium, Ultimate
**Offering:** Self-managed
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/153877) in GitLab 17.1.
If you self-manage a GitLab instance in the EU, or any jurisdiction that
requires a cookie consent banner, additional HTML header tags are needed to
add scripts and stylesheets.
## Security implications
Before enabling this feature, you should understand the security implications this might have.
A previously legit external resource could end up being compromised and then used to extract
pretty much any data from any user in the GitLab instance. For that reason,
you should never add resources from untrusted external sources. If possible, you should always
use integrity checks like [Subresource Integrity](https://www.w3.org/TR/SRI/) with third-party
resources to confirm the authenticity of the resources that are loaded.
Limit the functionality you are adding by using HTML header tags to the minimum.
Otherwise, it could cause also stability or functionality issues if you, for example,
interact with other application code from GitLab.
## Add a custom HTML header tag
You must add the externals sources to the Content Security Policy which is
available in the `content_security_policy` option. For the following example, you
must extend the `script_src` and `style_src`.
To add a custom HTML header tag:
::Tabs
:::TabTitle Self-compiled
1. Edit `/home/git/gitlab/config/gitlab.yml`:
```yaml
production: &base
gitlab:
custom_html_header_tags: |
<script src="https://example.com/cookie-consent.js" integrity="sha384-Li9vy3DqF8tnTXuiaAJuML3ky+er10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://example.com/cookie-consent.css" integrity="sha384-+/M6kredJcxdsqkczBUjMLvqyHb1K/JThDXWsBVxMEeZHEaMKEOEct339VItX1zB" crossorigin="anonymous">
content_security_policy:
directives:
script_src: "'self' 'unsafe-eval' https://example.com http://localhost:* https://www.google.com/recaptcha/ https://www.recaptcha.net/ https://www.gstatic.com/recaptcha/ https://apis.google.com"
style_src: "'self' 'unsafe-inline' https://example.com"
```
1. Save the file and restart GitLab:
```shell
# For systems running systemd
sudo systemctl restart gitlab.target
# For systems running SysV init
sudo service gitlab restart
```
::EndTabs

View File

@ -81,6 +81,13 @@ and issue creation. Your instance becomes read-only and
an expiration message displays to all administrators. You have a 14-day grace period
before this occurs.
For example, if a license has a start date of January 1, 2024 and an end date of January 1, 2025:
- It expires at 11:59:59 PM UTC December 31, 2024.
- It is considered expired from 12:00:00 AM UTC January 1, 2025.
- The grace period of 14 days starts at 12:00:00 AM UTC January 1, 2025 and ends at 11:59:59 PM UTC January 14, 2025.
- Your instance becomes read-only at 12:00:00 AM UTC January 15, 2025.
To resume functionality, [renew your subscription](../subscriptions/self_managed/index.md#renew-subscription-manually).
If the license has been expired for more than 30 days, you must purchase a [new subscription](../subscriptions/self_managed/index.md) to resume functionality.

Some files were not shown because too many files have changed in this diff Show More