Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-02-26 21:09:55 +00:00
parent 17dc78581f
commit 53b01d4a2c
86 changed files with 1627 additions and 1161 deletions

View File

@ -24,7 +24,7 @@ gem 'bundler-checksum', '~> 0.1.0', path: 'vendor/gems/bundler-checksum', requir
# https://gitlab.com/gitlab-org/gitlab/-/issues/375713
#
# See https://docs.gitlab.com/ee/development/gemfile.html#upgrade-rails for guidelines when upgrading Rails
gem 'rails', '~> 7.0.8' # rubocop:todo Gemfile/MissingFeatureCategory
gem 'rails', '~> 7.0.8.1' # rubocop:todo Gemfile/MissingFeatureCategory
gem 'activerecord-gitlab', path: 'gems/activerecord-gitlab' # rubocop:todo Gemfile/MissingFeatureCategory

View File

@ -2,18 +2,18 @@
{"name":"CFPropertyList","version":"3.0.5","platform":"ruby","checksum":"a78551cd4768d78ebca98488c27e33652ef818be64697a54676d34e6434674a4"},
{"name":"RedCloth","version":"4.3.3","platform":"ruby","checksum":"d941b8ac96e2730d2d9326d97dda9fcf64cb73532b3f902d91c18970c5f4632d"},
{"name":"acme-client","version":"2.0.11","platform":"ruby","checksum":"edf6da9f3c5dbe3ab0c6738eb3b97978b7a60e3500445480d2a72fcc610089de"},
{"name":"actioncable","version":"7.0.8","platform":"ruby","checksum":"1f504ddb4ab6a34f7c52e9df924441a403e9f358bace330c36dcca6358ecfb84"},
{"name":"actionmailbox","version":"7.0.8","platform":"ruby","checksum":"9420037b801e44aa4e36cf113f4bd6eb25c17eb1b84d9c8865e8abf8846c14e5"},
{"name":"actionmailer","version":"7.0.8","platform":"ruby","checksum":"22574f270ed80bcd158f16b99068fad7772173e21c4332504238dae58fdccf70"},
{"name":"actionpack","version":"7.0.8","platform":"ruby","checksum":"2b998c6f6540ec07ad2e16b39f9acae22c8c4fda6b377417c2cfddf8c04d61d0"},
{"name":"actiontext","version":"7.0.8","platform":"ruby","checksum":"f7966296cec0a48e8644b59de2bfc8b7847d43a7809dfe040015a32aecc88744"},
{"name":"actionview","version":"7.0.8","platform":"ruby","checksum":"a22d692b9a6422f36882425301a4043fbe078a66e94a909a60a6a216246fd776"},
{"name":"activejob","version":"7.0.8","platform":"ruby","checksum":"cb63d6a9f9af3379b7927bcb09a453d63db66ba9ec681018a8b21c5a0f8bc1b2"},
{"name":"activemodel","version":"7.0.8","platform":"ruby","checksum":"95beb8a2f6d1e0c7b4e3c0f17771b3a3024a25ad8c6e9d2d357e3cf1d5479c00"},
{"name":"activerecord","version":"7.0.8","platform":"ruby","checksum":"f236255235ab8c15f7a7bea3b77a35377801827e24d6e536dc776080f4dd8a13"},
{"name":"actioncable","version":"7.0.8.1","platform":"ruby","checksum":"bc5eddc8c6412d067b9fecec6a53dd14f3bd83baca96762eb864f01fb4c40649"},
{"name":"actionmailbox","version":"7.0.8.1","platform":"ruby","checksum":"89d721547b178b397b86e1af11adb221098134d083f481ebf90b37431982c8b8"},
{"name":"actionmailer","version":"7.0.8.1","platform":"ruby","checksum":"4c1f470e5577a82bdfbf5fd1eca6590990371e80c48eb04ae79883a7e521f21c"},
{"name":"actionpack","version":"7.0.8.1","platform":"ruby","checksum":"5dcd2b39cb69abe899edc9faf878fb667a64a9fe306a2e56d09e3ed3701e084a"},
{"name":"actiontext","version":"7.0.8.1","platform":"ruby","checksum":"42e4cd0e7e8f98a8ed96d04b1d6ab83bb69afc4ceb0a46f5c18ef60fff889810"},
{"name":"actionview","version":"7.0.8.1","platform":"ruby","checksum":"4a01b36c605dc89a5e1dd3866e6db05132387827411fb7fb62cdb9e1ca79f7f9"},
{"name":"activejob","version":"7.0.8.1","platform":"ruby","checksum":"8f4ee9288480b9fddc5aece947bcd846546d14d96c38faedc3ab87c6c84e147b"},
{"name":"activemodel","version":"7.0.8.1","platform":"ruby","checksum":"4115aef7f780abd168629c5d77031b014eecd84a52760ab149920148dfbe2d3f"},
{"name":"activerecord","version":"7.0.8.1","platform":"ruby","checksum":"8e5dfbad90638944fc99b64337dffa729b1aaf2cd38ea624a08dcd9259f09366"},
{"name":"activerecord-explain-analyze","version":"0.1.0","platform":"ruby","checksum":"5debb11fe23f35b91953a80677d80ba9284ee737fd9d148c1d7603ce45217f7b"},
{"name":"activestorage","version":"7.0.8","platform":"ruby","checksum":"8c2cae8de321ec899c7e7c4655331714fdd57f0966215286330f5c4d95a9db34"},
{"name":"activesupport","version":"7.0.8","platform":"ruby","checksum":"458316bb5098211ba9436d3c64d883177f09c49d1e29aa00f970d160275f13a1"},
{"name":"activestorage","version":"7.0.8.1","platform":"ruby","checksum":"1fd641a93c93a133d016e11998953221db28736a667fe5da2331969850198f38"},
{"name":"activesupport","version":"7.0.8.1","platform":"ruby","checksum":"b0aff5023a6f84e2fefadee80c0e1c0156ee3eea318c402bfcd40140f0e9c339"},
{"name":"acts-as-taggable-on","version":"10.0.0","platform":"ruby","checksum":"d360e96f1622010a2f8fe5c6f480f8cf95ba0bc2072e0b9974574e5f336edb83"},
{"name":"addressable","version":"2.8.1","platform":"ruby","checksum":"bc724a176ef02118c8a3ed6b5c04c39cf59209607ffcce77b91d0261dbadedfa"},
{"name":"aes_key_wrap","version":"1.1.0","platform":"ruby","checksum":"b935f4756b37375895db45669e79dfcdc0f7901e12d4e08974d5540c8e0776a5"},
@ -500,12 +500,12 @@
{"name":"rack-session","version":"1.0.2","platform":"ruby","checksum":"a02115e5420b4de036839b9811e3f7967d73446a554b42aa45106af335851d76"},
{"name":"rack-test","version":"2.1.0","platform":"ruby","checksum":"0c61fc61904049d691922ea4bb99e28004ed3f43aa5cfd495024cc345f125dfb"},
{"name":"rack-timeout","version":"0.6.3","platform":"ruby","checksum":"1754892eacc124d405e7f1145731ec9b7421ebd1bee5d51ddc18b72c204d0ab3"},
{"name":"rails","version":"7.0.8","platform":"ruby","checksum":"8e43af921acf766fb429126f020ec90c3b25809631f8fbdff95c3553828d5867"},
{"name":"rails","version":"7.0.8.1","platform":"ruby","checksum":"7deb37884ac5e9afeaeb6ad503c56e819f68e53746d621b2187322f874ba2ded"},
{"name":"rails-controller-testing","version":"1.0.5","platform":"ruby","checksum":"741448db59366073e86fc965ba403f881c636b79a2c39a48d0486f2607182e94"},
{"name":"rails-dom-testing","version":"2.0.3","platform":"ruby","checksum":"b140c4f39f6e609c8113137b9a60dfc2ecb89864e496f87f23a68b3b8f12d8d1"},
{"name":"rails-html-sanitizer","version":"1.6.0","platform":"ruby","checksum":"86e9f19d2e6748890dcc2633c8945ca45baa08a1df9d8c215ce17b3b0afaa4de"},
{"name":"rails-i18n","version":"7.0.3","platform":"ruby","checksum":"e3158e98c5332d129fd5131f171ac575eb30dbb8919b21595382b08850cf2bd3"},
{"name":"railties","version":"7.0.8","platform":"ruby","checksum":"12325c3933efd33f8ead640197dec3b8c27c8d45607dd68b7b925896bf09cc69"},
{"name":"railties","version":"7.0.8.1","platform":"ruby","checksum":"c2e4e3617defafad5c1c2c5761d697873197422ec49f58a96d6728f3a729ea21"},
{"name":"rainbow","version":"3.1.1","platform":"ruby","checksum":"039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a"},
{"name":"rake","version":"13.0.6","platform":"ruby","checksum":"5ce4bf5037b4196c24ac62834d8db1ce175470391026bd9e557d669beeb19097"},
{"name":"rb-fsevent","version":"0.11.2","platform":"ruby","checksum":"43900b972e7301d6570f64b850a5aa67833ee7d87b458ee92805d56b7318aefe"},

View File

@ -203,70 +203,70 @@ GEM
acme-client (2.0.11)
faraday (>= 1.0, < 3.0.0)
faraday-retry (~> 1.0)
actioncable (7.0.8)
actionpack (= 7.0.8)
activesupport (= 7.0.8)
actioncable (7.0.8.1)
actionpack (= 7.0.8.1)
activesupport (= 7.0.8.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (7.0.8)
actionpack (= 7.0.8)
activejob (= 7.0.8)
activerecord (= 7.0.8)
activestorage (= 7.0.8)
activesupport (= 7.0.8)
actionmailbox (7.0.8.1)
actionpack (= 7.0.8.1)
activejob (= 7.0.8.1)
activerecord (= 7.0.8.1)
activestorage (= 7.0.8.1)
activesupport (= 7.0.8.1)
mail (>= 2.7.1)
net-imap
net-pop
net-smtp
actionmailer (7.0.8)
actionpack (= 7.0.8)
actionview (= 7.0.8)
activejob (= 7.0.8)
activesupport (= 7.0.8)
actionmailer (7.0.8.1)
actionpack (= 7.0.8.1)
actionview (= 7.0.8.1)
activejob (= 7.0.8.1)
activesupport (= 7.0.8.1)
mail (~> 2.5, >= 2.5.4)
net-imap
net-pop
net-smtp
rails-dom-testing (~> 2.0)
actionpack (7.0.8)
actionview (= 7.0.8)
activesupport (= 7.0.8)
actionpack (7.0.8.1)
actionview (= 7.0.8.1)
activesupport (= 7.0.8.1)
rack (~> 2.0, >= 2.2.4)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (7.0.8)
actionpack (= 7.0.8)
activerecord (= 7.0.8)
activestorage (= 7.0.8)
activesupport (= 7.0.8)
actiontext (7.0.8.1)
actionpack (= 7.0.8.1)
activerecord (= 7.0.8.1)
activestorage (= 7.0.8.1)
activesupport (= 7.0.8.1)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (7.0.8)
activesupport (= 7.0.8)
actionview (7.0.8.1)
activesupport (= 7.0.8.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activejob (7.0.8)
activesupport (= 7.0.8)
activejob (7.0.8.1)
activesupport (= 7.0.8.1)
globalid (>= 0.3.6)
activemodel (7.0.8)
activesupport (= 7.0.8)
activerecord (7.0.8)
activemodel (= 7.0.8)
activesupport (= 7.0.8)
activemodel (7.0.8.1)
activesupport (= 7.0.8.1)
activerecord (7.0.8.1)
activemodel (= 7.0.8.1)
activesupport (= 7.0.8.1)
activerecord-explain-analyze (0.1.0)
activerecord (>= 4)
pg
activestorage (7.0.8)
actionpack (= 7.0.8)
activejob (= 7.0.8)
activerecord (= 7.0.8)
activesupport (= 7.0.8)
activestorage (7.0.8.1)
actionpack (= 7.0.8.1)
activejob (= 7.0.8.1)
activerecord (= 7.0.8.1)
activesupport (= 7.0.8.1)
marcel (~> 1.0)
mini_mime (>= 1.1.0)
activesupport (7.0.8)
activesupport (7.0.8.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
@ -1334,20 +1334,20 @@ GEM
rack-test (2.1.0)
rack (>= 1.3)
rack-timeout (0.6.3)
rails (7.0.8)
actioncable (= 7.0.8)
actionmailbox (= 7.0.8)
actionmailer (= 7.0.8)
actionpack (= 7.0.8)
actiontext (= 7.0.8)
actionview (= 7.0.8)
activejob (= 7.0.8)
activemodel (= 7.0.8)
activerecord (= 7.0.8)
activestorage (= 7.0.8)
activesupport (= 7.0.8)
rails (7.0.8.1)
actioncable (= 7.0.8.1)
actionmailbox (= 7.0.8.1)
actionmailer (= 7.0.8.1)
actionpack (= 7.0.8.1)
actiontext (= 7.0.8.1)
actionview (= 7.0.8.1)
activejob (= 7.0.8.1)
activemodel (= 7.0.8.1)
activerecord (= 7.0.8.1)
activestorage (= 7.0.8.1)
activesupport (= 7.0.8.1)
bundler (>= 1.15.0)
railties (= 7.0.8)
railties (= 7.0.8.1)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1)
@ -1361,9 +1361,9 @@ GEM
rails-i18n (7.0.3)
i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 8)
railties (7.0.8)
actionpack (= 7.0.8)
activesupport (= 7.0.8)
railties (7.0.8.1)
actionpack (= 7.0.8.1)
activesupport (= 7.0.8.1)
method_source
rake (>= 12.2)
thor (~> 1.0)
@ -2062,7 +2062,7 @@ DEPENDENCIES
rack-oauth2 (~> 1.21.3)
rack-proxy (~> 0.7.7)
rack-timeout (~> 0.6.3)
rails (~> 7.0.8)
rails (~> 7.0.8.1)
rails-controller-testing
rails-i18n (~> 7.0)
rainbow (~> 3.0)

View File

@ -1,6 +1,6 @@
<script>
import {
GlLoadingIcon,
GlSkeletonLoader,
GlTable,
GlLink,
GlButtonGroup,
@ -12,6 +12,7 @@ import {
} from '@gitlab/ui';
import CiIcon from '~/vue_shared/components/ci_icon/ci_icon.vue';
import { createAlert } from '~/alert';
import { scrollToElement } from '~/lib/utils/common_utils';
import { getIdFromGraphQLId, convertToGraphQLId } from '~/graphql_shared/utils';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import { TYPENAME_PROJECT } from '~/graphql_shared/constants';
@ -57,7 +58,7 @@ const INITIAL_PAGINATION_STATE = {
export default {
name: 'JobArtifactsTable',
components: {
GlLoadingIcon,
GlSkeletonLoader,
GlTable,
GlLink,
GlButtonGroup,
@ -141,6 +142,7 @@ export default {
this.canBulkDestroyArtifacts && {
key: 'checkbox',
label: '',
thClass: 'gl-w-5p',
},
...this.$options.fields,
];
@ -208,6 +210,8 @@ export default {
currentPage: page,
};
}
scrollToElement(this.$el);
},
handleRowToggle(toggleDetails, hasArtifacts, id, detailsShowing) {
if (!hasArtifacts) return;
@ -389,8 +393,15 @@ export default {
details-td-class="gl-bg-gray-10! gl-p-0! gl-overflow-auto"
>
<template #table-busy>
<gl-loading-icon size="lg" />
<gl-skeleton-loader v-for="i in 20" :key="i" :width="1000" :height="75">
<rect width="90" height="20" x="40" y="5" rx="4" />
<rect width="300" height="40" x="180" y="5" rx="4" />
<rect width="80" height="20" x="610" y="5" rx="4" />
<rect width="80" height="20" x="710" y="5" rx="4" />
<rect width="100" height="30" x="900" y="5" rx="4" />
</gl-skeleton-loader>
</template>
<template v-if="canBulkDestroyArtifacts" #head(checkbox)>
<gl-form-checkbox
v-gl-tooltip.right

View File

@ -13,6 +13,10 @@ const parseJsonArray = (triggers) => {
export default (containerId = 'js-ci-pipeline-triggers-list') => {
const containerEl = document.getElementById(containerId);
if (!containerEl) {
return null;
}
const triggers = parseJsonArray(containerEl.dataset.triggers);
return new Vue({

View File

@ -5,6 +5,10 @@ import createStore from './store';
export default () => {
const el = document.getElementById('js-deploy-freeze-table');
if (!el) {
return null;
}
const { projectId, timezoneData } = el.dataset;
const store = createStore({

View File

@ -22,7 +22,9 @@ initInheritedGroupCiVariables();
// hide extra auto devops settings based checkbox state
const autoDevOpsExtraSettings = document.querySelector('.js-extra-settings');
const instanceDefaultBadge = document.querySelector('.js-instance-default-badge');
document.querySelector('.js-toggle-extra-settings').addEventListener('click', (event) => {
const extraSettingsToggle = document.querySelector('.js-toggle-extra-settings');
extraSettingsToggle?.addEventListener('click', (event) => {
const { target } = event;
if (instanceDefaultBadge) instanceDefaultBadge.style.display = 'none';
autoDevOpsExtraSettings.classList.toggle('hidden', !target.checked);

View File

@ -1,16 +1,3 @@
import { __ } from '~/locale';
import NamespaceStorageApp from './storage/components/namespace_storage_app.vue';
import { parseProvideData as parseStorageTabProvideData } from './storage/utils';
import { STORAGE_TAB_METADATA_EL_SELECTOR } from './constants';
import { getStorageTabMetadata } from './storage/tab_metadata';
export const usageQuotasViewProvideData = {
...parseStorageTabProvideData(document.querySelector(STORAGE_TAB_METADATA_EL_SELECTOR)),
};
export const storageTabMetadata = {
title: __('Storage'),
component: NamespaceStorageApp,
shouldRender: () => document.querySelector(STORAGE_TAB_METADATA_EL_SELECTOR),
};
export const usageQuotasTabsMetadata = [storageTabMetadata];
export const usageQuotasTabsMetadata = [getStorageTabMetadata()];

View File

@ -1,10 +1,7 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import {
usageQuotasTabsMetadata,
usageQuotasViewProvideData,
} from 'ee_else_ce/usage_quotas/group_view_metadata';
import { usageQuotasTabsMetadata } from 'ee_else_ce/usage_quotas/group_view_metadata';
import UsageQuotasApp from './components/usage_quotas_app.vue';
Vue.use(VueApollo);
@ -29,7 +26,6 @@ export default () => {
provide: {
namespaceName,
tabs: usageQuotasTabsMetadata.filter(Boolean),
...usageQuotasViewProvideData,
},
render(createElement) {
return createElement(UsageQuotasApp);

View File

@ -0,0 +1,42 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { __ } from '~/locale';
import createDefaultClient from '~/lib/graphql';
import { parseProvideData } from 'ee_else_ce/usage_quotas/storage/utils';
import { STORAGE_TAB_METADATA_EL_SELECTOR } from '../constants';
import NamespaceStorageApp from './components/namespace_storage_app.vue';
export const getStorageTabMetadata = ({ includeEl = false, customApolloProvider = false } = {}) => {
let apolloProvider;
const el = document.querySelector(STORAGE_TAB_METADATA_EL_SELECTOR);
if (!el) return false;
Vue.use(VueApollo);
if (customApolloProvider) {
apolloProvider = customApolloProvider;
} else {
apolloProvider = new VueApollo({
defaultClient: createDefaultClient(),
});
}
const storageTabMetadata = {
title: __('Storage'),
component: {
name: 'NamespaceStorageTab',
provide: parseProvideData(el),
apolloProvider,
render(createElement) {
return createElement(NamespaceStorageApp);
},
},
};
if (includeEl) {
storageTabMetadata.component.el = el;
}
return storageTabMetadata;
};

View File

@ -115,6 +115,7 @@ export default {
:get-active-token-value="getActiveUser"
:default-suggestions="defaultUsers"
:preloaded-suggestions="preloadedUsers"
value-identifier="username"
v-bind="$attrs"
@fetch-suggestions="fetchUsers"
v-on="$listeners"

View File

@ -0,0 +1,14 @@
@import 'mixins_and_variables_and_functions';
.commit-description,
.commit-row-description {
padding: $gl-padding-8 0 $gl-padding-8 $gl-padding-8;
margin-top: $gl-padding-8;
border: 0;
border-radius: unset;
background: none;
word-break: normal;
overflow-x: auto;
border-left: 3px solid var(--border-color, $gray-100);
color: var(--gray-700, $gl-text-color-secondary);
}

View File

@ -2,7 +2,7 @@
.commits-row {
+ .commits-row {
border-top: 1px solid $gray-50;
border-top: 1px solid var(--gray-50, $gray-50);
}
+ .commits-empty {
@ -23,7 +23,7 @@
}
.title-hint-text {
color: $gl-text-color-secondary;
color: var(--gray-700, $gl-text-color-secondary);
}
.gl-filtered-search-suggestion-list.dropdown-menu {

View File

@ -1,4 +1,6 @@
@import 'mixins_and_variables_and_functions';
@import 'page_bundles/commits';
@import 'page_bundles/commit_description';
$tabs-holder-z-index: 250;
$comparison-empty-state-height: 62px;

View File

@ -1,16 +1,3 @@
.commit-description,
.commit-row-description {
padding: $gl-padding-8 0 $gl-padding-8 $gl-padding-8;
margin-top: $gl-padding-8;
border: 0;
border-radius: unset;
background: none;
word-break: normal;
overflow-x: auto;
border-left: 3px solid $gray-100;
color: $gl-text-color-secondary;
}
.commit-box {
border-top: 1px solid $border-color;
padding: $gl-padding 0;

View File

@ -8,7 +8,8 @@ module Projects
NUMBER_OF_RUNNERS_PER_PAGE = 20
layout 'project_settings'
before_action :authorize_admin_pipeline!
before_action :authorize_admin_pipeline!, except: :show
before_action :authorize_admin_cicd_variables!, only: :show
before_action :check_builds_available!
before_action :define_variables

View File

@ -1,7 +1,8 @@
# frozen_string_literal: true
class Projects::VariablesController < Projects::ApplicationController
before_action :authorize_admin_build!
before_action :authorize_admin_build!, except: :update
before_action :authorize_admin_cicd_variables!, only: :update
feature_category :secrets_management

View File

@ -382,13 +382,13 @@ module Types
field :ci_variables, Types::Ci::ProjectVariableType.connection_type,
null: true,
description: "List of the project's CI/CD variables.",
authorize: :admin_build,
authorize: :admin_cicd_variables,
resolver: Resolvers::Ci::VariablesResolver
field :inherited_ci_variables, Types::Ci::InheritedCiVariableType.connection_type,
null: true,
description: "List of CI/CD variables the project inherited from its parent group and ancestors.",
authorize: :admin_build,
authorize: :admin_cicd_variables,
resolver: Resolvers::Ci::InheritedVariablesResolver
field :ci_cd_settings, Types::Ci::CiCdSettingType,

View File

@ -9,6 +9,14 @@ module Ci
include Limitable
include EachBatch
include BatchNullifyDependentAssociations
include Gitlab::Utils::StrongMemoize
VALID_REF_REGEX = %r{\A(#{Gitlab::Git::TAG_REF_PREFIX}|#{Gitlab::Git::BRANCH_REF_PREFIX}).+}
# The only way that ref can be unexpanded after #expand_short_ref runs is if the ref
# is ambiguous because both a branch and a tag with the name exist, or it is
# ambiguous because neither exists.
INVALID_REF_MESSAGE = 'is ambiguous'
self.limit_name = 'ci_pipeline_schedules'
self.limit_scope = :project
@ -21,7 +29,13 @@ module Ci
validates :cron, unless: :importing?, cron: true, presence: { unless: :importing? }
validates :cron_timezone, cron_timezone: true, presence: { unless: :importing? }
validates :ref, presence: { unless: :importing? }
validates :ref, presence: { unless: :importing? },
format: { with: VALID_REF_REGEX,
allow_nil: true,
message: INVALID_REF_MESSAGE,
unless: ->(schedule) do
schedule.importing || Feature.disabled?(:enforce_full_refs_for_pipeline_schedules, schedule.project)
end }
validates :description, presence: true
validates :variables, nested_attributes_duplicates: true
@ -33,6 +47,8 @@ module Ci
scope :owned_by, ->(user) { where(owner: user) }
scope :for_project, ->(project_id) { where(project_id: project_id) }
before_validation :expand_short_ref
accepts_nested_attributes_for :variables, allow_destroy: true
alias_attribute :real_next_run, :next_run_at
@ -91,6 +107,22 @@ module Ci
super
end
private
def expand_short_ref
return if Feature.disabled?(:enforce_full_refs_for_pipeline_schedules, project)
return if ref.blank? || VALID_REF_REGEX.match?(ref) || ambiguous_ref?
# In case the ref doesn't exist default to the initial value
self.ref = project.repository.expand_ref(ref) || ref
end
def ambiguous_ref?
strong_memoize_with(:ambiguous_ref, ref) do
project.repository.ambiguous_ref?(ref)
end
end
end
end

View File

@ -24,25 +24,16 @@ class CommitCollection
commits.each(&block)
end
def committers(with_merge_commits: false, lazy: false)
return committers_lazy(with_merge_commits: with_merge_commits).flatten if lazy
def committers(with_merge_commits: false)
emails = if with_merge_commits
commits.filter_map(&:committer_email).uniq
else
without_merge_commits.filter_map(&:committer_email).uniq
end
User.by_any_email(committers_emails(with_merge_commits: with_merge_commits))
User.by_any_email(emails)
end
def committers_lazy(with_merge_commits: false)
emails = committers_emails(with_merge_commits: with_merge_commits)
emails.map do |email|
BatchLoader.for(email.downcase).batch(default_value: []) do |committer_emails, loader|
User.by_any_email(committer_emails).each do |user|
loader.call(user.email) { |memo| memo << user }
end
end
end
end
alias_method :add_committers_to_batch_loader, :committers_lazy
def committer_user_ids
committers.pluck(:id)
end
@ -152,12 +143,4 @@ class CommitCollection
self
end
private
def committers_emails(with_merge_commits: false)
return commits.filter_map(&:committer_email).uniq if with_merge_commits
without_merge_commits.filter_map(&:committer_email).uniq
end
end

View File

@ -668,8 +668,8 @@ class MergeRequest < ApplicationRecord
[:assignees, :reviewers] + super
end
def committers(with_merge_commits: false, lazy: false)
@committers ||= commits.committers(with_merge_commits: with_merge_commits, lazy: lazy)
def committers(with_merge_commits: false)
@committers ||= commits.committers(with_merge_commits: with_merge_commits)
end
# Verifies if title has changed not taking into account Draft prefix

View File

@ -33,16 +33,7 @@ class MergeRequestDiff < ApplicationRecord
-> { order(:merge_request_diff_id, :relative_order) },
inverse_of: :merge_request_diff
has_many :merge_request_diff_commits, -> { order(:merge_request_diff_id, :relative_order) }, inverse_of: :merge_request_diff do
def with_users
ActiveRecord::Associations::Preloader.new(
records: self,
associations: [:commit_author, :committer]
).call
self
end
end
has_many :merge_request_diff_commits, -> { order(:merge_request_diff_id, :relative_order) }, inverse_of: :merge_request_diff
sha_attribute :patch_id_sha
@ -810,9 +801,7 @@ class MergeRequestDiff < ApplicationRecord
end
def load_commits(limit: nil, load_from_gitaly: false, page: nil)
diff_commits = merge_request_diff_commits
diff_commits = diff_commits.page(page).per(limit) if page.present?
diff_commits = diff_commits.limit(limit) if limit.present?
diff_commits = page.present? ? merge_request_diff_commits.page(page).per(limit) : merge_request_diff_commits.limit(limit)
if load_from_gitaly
commits = Gitlab::Git::Commit.batch_by_oid(repository, diff_commits.map(&:sha))

View File

@ -32,6 +32,8 @@ class MergeRequestDiffCommit < ApplicationRecord
attribute :trailers, :ind_jsonb
validates :trailers, json_schema: { filename: 'git_trailers' }
scope :with_users, -> { preload(:commit_author, :committer) }
# A list of keys of which their values need to be trimmed before they can be
# inserted into the merge_request_diff_commit_users table.
TRIM_USER_KEYS =

View File

@ -596,6 +596,7 @@ class ProjectPolicy < BasePolicy
enable :admin_incident_management_timeline_event_tag
enable :stop_environment
enable :read_import_error
enable :admin_cicd_variables
end
rule { can?(:admin_build) }.enable :manage_trigger

View File

@ -4,7 +4,7 @@
-# This is a temporary place for the page specific style migrations to be included on all pages like page_specific_files
- if Feature.disabled?(:page_specific_styles, current_user)
- add_page_specific_style('page_bundles/commits')
- add_page_specific_style('page_bundles/commit_description')
%head{ omit_og ? { } : { prefix: "og: http://ogp.me/ns#" } }
%meta{ charset: "utf-8" }

View File

@ -6,6 +6,7 @@
- add_page_startup_api_call logs_file_project_ref_path(@project, ref, @path, format: "json", offset: 0, ref_type: @ref_type)
- if readme_path = @project.repository.readme_path
- add_page_startup_api_call project_blob_path(@project, tree_join(@ref, readme_path), viewer: "rich", format: "json")
- add_page_specific_style 'page_bundles/commit_description'
#tree-holder.tree-holder.clearfix.js-per-page.gl-mt-5{ data: { blame_per_page: Gitlab::Git::BlamePagination::PAGINATION_PER_PAGE } }
- if Feature.enabled?(:project_overview_reorg)

View File

@ -1,3 +1,5 @@
- add_page_specific_style 'page_bundles/commit_description'
.page-content-header
.header-main-content
= render partial: 'signature', object: @commit.signature

View File

@ -21,6 +21,7 @@
- link = commit_path(project, commit, merge_request: merge_request)
- show_project_name = local_assigns.fetch(:show_project_name, false)
- toggle_commit_message = _("Toggle commit description")
- add_page_specific_style 'page_bundles/commit_description'
%li{ class: ["commit flex-row", ("js-toggle-container" if collapsible)], id: "commit-#{commit.short_id}" }
.avatar-cell.d-none.d-sm-block

View File

@ -1,4 +1,3 @@
- add_page_specific_style 'page_bundles/merge_request'
- add_page_specific_style 'page_bundles/commits'
= render 'page'

View File

@ -5,118 +5,121 @@
- expanded = expanded_by_default?
- general_expanded = @project.errors.empty? ? expanded : true
%section.settings#js-general-pipeline-settings.no-animate{ class: ('expanded' if general_expanded) }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= _("General pipelines")
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded ? _('Collapse') : _('Expand')
%p.gl-text-secondary
= _("Customize your pipeline configuration.")
.settings-content
= render 'form'
%section.settings#autodevops-settings.no-animate{ class: ('expanded' if expanded), data: { testid: 'autodevops-settings-content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= s_('CICD|Auto DevOps')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded ? _('Collapse') : _('Expand')
%p.gl-text-secondary
- auto_devops_url = help_page_path('topics/autodevops/index')
- quickstart_url = help_page_path('topics/autodevops/cloud_deployments/auto_devops_with_gke')
- auto_devops_link = link_to('', auto_devops_url, target: '_blank', rel: 'noopener noreferrer')
- quickstart_link = link_to('', quickstart_url, target: '_blank', rel: 'noopener noreferrer')
= safe_format(s_('AutoDevOps|%{auto_devops_start}Automate building, testing, and deploying%{auto_devops_end} your applications based on your continuous integration and delivery configuration. %{quickstart_start}How do I get started?%{quickstart_end}'), tag_pair(auto_devops_link, :auto_devops_start, :auto_devops_end), tag_pair(quickstart_link, :quickstart_start, :quickstart_end))
.settings-content
= render 'autodevops_form', auto_devops_enabled: @project.auto_devops_enabled?
= render_if_exists 'projects/settings/ci_cd/protected_environments', expanded: expanded
- expand_runners = expanded || params[:expand_runners]
%section.settings.no-animate#js-runners-settings{ class: ('expanded' if expand_runners), data: { testid: 'runners-settings-content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= _("Runners")
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expand_runners ? _('Collapse') : _('Expand')
%p.gl-text-secondary
= _("Runners are processes that pick up and execute CI/CD jobs for GitLab.")
= link_to s_('What is GitLab Runner?'), 'https://docs.gitlab.com/runner/', target: '_blank', rel: 'noopener noreferrer'
.settings-content
= render 'projects/runners/settings'
- if Gitlab::CurrentSettings.current_application_settings.keep_latest_artifact?
%section.settings.no-animate#js-artifacts-settings{ class: ('expanded' if expanded) }
- if can?(current_user, :admin_pipeline, @project)
%section.settings#js-general-pipeline-settings.no-animate{ class: ('expanded' if general_expanded) }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= _("Artifacts")
= _("General pipelines")
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded ? _('Collapse') : _('Expand')
%p.gl-text-secondary
= _("A job artifact is an archive of files and directories saved by a job when it finishes.")
= _("Customize your pipeline configuration.")
.settings-content
#js-artifacts-settings-app{ data: { full_path: @project.full_path, help_page_path: help_page_path('ci/jobs/job_artifacts', anchor: 'keep-artifacts-from-most-recent-successful-jobs') } }
= render 'form'
%section.settings.no-animate#js-cicd-variables-settings{ class: ('expanded' if expanded), data: { testid: 'variables-settings-content' } }
.settings-header
= render 'ci/variables/header', expanded: expanded
.settings-content
= render 'ci/variables/index', save_endpoint: project_variables_path(@project)
%section.settings.no-animate#js-pipeline-triggers{ class: ('expanded' if expanded) }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= _("Pipeline trigger tokens")
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded ? _('Collapse') : _('Expand')
%p.gl-text-secondary
= _("Trigger a pipeline for a branch or tag by generating a trigger token and using it with an API call. The token impersonates a user's project access and permissions.")
= link_to _('Learn more.'), help_page_path('ci/triggers/index'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
= render 'projects/triggers/index'
= render_if_exists 'projects/settings/ci_cd/auto_rollback', expanded: expanded
- if can?(current_user, :create_freeze_period, @project)
%section.settings.no-animate#js-deploy-freeze-settings{ class: ('expanded' if expanded) }
%section.settings#autodevops-settings.no-animate{ class: ('expanded' if expanded), data: { testid: 'autodevops-settings-content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= _("Deploy freezes")
= s_('CICD|Auto DevOps')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded ? _('Collapse') : _('Expand')
%p.gl-text-secondary
- freeze_period_docs = help_page_path('user/project/releases/index', anchor: 'prevent-unintentional-releases-by-setting-a-deploy-freeze')
- freeze_period_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: freeze_period_docs }
= html_escape(s_('DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}')) % { freeze_period_link_start: freeze_period_link_start, freeze_period_link_end: '</a>'.html_safe, filename: tag.code('.gitlab-ci.yml') }
- cron_syntax_url = 'https://crontab.guru/'
- cron_syntax_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: cron_syntax_url }
= s_('DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}.').html_safe % { cron_syntax_link_start: cron_syntax_link_start, cron_syntax_link_end: "</a>".html_safe }
- auto_devops_url = help_page_path('topics/autodevops/index')
- quickstart_url = help_page_path('topics/autodevops/cloud_deployments/auto_devops_with_gke')
- auto_devops_link = link_to('', auto_devops_url, target: '_blank', rel: 'noopener noreferrer')
- quickstart_link = link_to('', quickstart_url, target: '_blank', rel: 'noopener noreferrer')
= safe_format(s_('AutoDevOps|%{auto_devops_start}Automate building, testing, and deploying%{auto_devops_end} your applications based on your continuous integration and delivery configuration. %{quickstart_start}How do I get started?%{quickstart_end}'), tag_pair(auto_devops_link, :auto_devops_start, :auto_devops_end), tag_pair(quickstart_link, :quickstart_start, :quickstart_end))
.settings-content
= render 'ci/deploy_freeze/index'
= render 'autodevops_form', auto_devops_enabled: @project.auto_devops_enabled?
%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")
= 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.")
.settings-content
= render 'ci/token_access/index'
= render_if_exists 'projects/settings/ci_cd/protected_environments', expanded: expanded
- if show_secure_files_setting(@project, current_user)
%section.settings.no-animate#js-secure-files{ class: ('expanded' if expanded) }
- expand_runners = expanded || params[:expand_runners]
%section.settings.no-animate#js-runners-settings{ class: ('expanded' if expand_runners), data: { testid: 'runners-settings-content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= _("Secure Files")
= _("Runners")
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expand_runners ? _('Collapse') : _('Expand')
%p.gl-text-secondary
= _("Runners are processes that pick up and execute CI/CD jobs for GitLab.")
= link_to s_('What is GitLab Runner?'), 'https://docs.gitlab.com/runner/', target: '_blank', rel: 'noopener noreferrer'
.settings-content
= render 'projects/runners/settings'
- if Gitlab::CurrentSettings.current_application_settings.keep_latest_artifact?
%section.settings.no-animate#js-artifacts-settings{ class: ('expanded' if expanded) }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= _("Artifacts")
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded ? _('Collapse') : _('Expand')
%p.gl-text-secondary
= _("A job artifact is an archive of files and directories saved by a job when it finishes.")
.settings-content
#js-artifacts-settings-app{ data: { full_path: @project.full_path, help_page_path: help_page_path('ci/jobs/job_artifacts', anchor: 'keep-artifacts-from-most-recent-successful-jobs') } }
- if can?(current_user, :admin_cicd_variables, @project)
%section.settings.no-animate#js-cicd-variables-settings{ class: ('expanded' if expanded), data: { testid: 'variables-settings-content' } }
.settings-header
= render 'ci/variables/header', expanded: expanded
.settings-content
= render 'ci/variables/index', save_endpoint: project_variables_path(@project)
- if can?(current_user, :admin_pipeline, @project)
%section.settings.no-animate#js-pipeline-triggers{ class: ('expanded' if expanded) }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= _("Pipeline trigger tokens")
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded ? _('Collapse') : _('Expand')
%p.gl-text-secondary
= _("Use Secure Files to store files used by your pipelines such as Android keystores, or Apple provisioning profiles and signing certificates.")
= link_to _('Learn more'), help_page_path('ci/secure_files/index'), target: '_blank', rel: 'noopener noreferrer'
= _("Trigger a pipeline for a branch or tag by generating a trigger token and using it with an API call. The token impersonates a user's project access and permissions.")
= link_to _('Learn more.'), help_page_path('ci/triggers/index'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
#js-ci-secure-files{ data: { project_id: @project.id, admin: can?(current_user, :admin_secure_files, @project).to_s, file_size_limit: Ci::SecureFile::FILE_SIZE_LIMIT.to_mb } }
= render 'projects/triggers/index'
= render_if_exists 'projects/settings/ci_cd/auto_rollback', expanded: expanded
- if can?(current_user, :create_freeze_period, @project)
%section.settings.no-animate#js-deploy-freeze-settings{ class: ('expanded' if expanded) }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= _("Deploy freezes")
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded ? _('Collapse') : _('Expand')
%p.gl-text-secondary
- freeze_period_docs = help_page_path('user/project/releases/index', anchor: 'prevent-unintentional-releases-by-setting-a-deploy-freeze')
- freeze_period_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: freeze_period_docs }
= html_escape(s_('DeployFreeze|Add a freeze period to prevent unintended releases during a period of time for a given environment. You must update the deployment jobs in %{filename} according to the deploy freezes added here. %{freeze_period_link_start}Learn more.%{freeze_period_link_end}')) % { freeze_period_link_start: freeze_period_link_start, freeze_period_link_end: '</a>'.html_safe, filename: tag.code('.gitlab-ci.yml') }
- cron_syntax_url = 'https://crontab.guru/'
- cron_syntax_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: cron_syntax_url }
= s_('DeployFreeze|Specify deploy freezes using %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}.').html_safe % { cron_syntax_link_start: cron_syntax_link_start, cron_syntax_link_end: "</a>".html_safe }
.settings-content
= render 'ci/deploy_freeze/index'
%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")
= 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.")
.settings-content
= render 'ci/token_access/index'
- if show_secure_files_setting(@project, current_user)
%section.settings.no-animate#js-secure-files{ class: ('expanded' if expanded) }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= _("Secure Files")
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded ? _('Collapse') : _('Expand')
%p.gl-text-secondary
= _("Use Secure Files to store files used by your pipelines such as Android keystores, or Apple provisioning profiles and signing certificates.")
= link_to _('Learn more'), help_page_path('ci/secure_files/index'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
#js-ci-secure-files{ data: { project_id: @project.id, admin: can?(current_user, :admin_secure_files, @project).to_s, file_size_limit: Ci::SecureFile::FILE_SIZE_LIMIT.to_mb } }

View File

@ -1,6 +1,7 @@
- wiki_page_title @page, _('Changes')
- add_page_specific_style 'page_bundles/wiki'
- commit = @diffs.diffable
- add_page_specific_style 'page_bundles/commit_description'
.wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row
= wiki_sidebar_toggle_button

View File

@ -305,6 +305,7 @@ module Gitlab
config.assets.precompile << "page_bundles/cluster_agents.css"
config.assets.precompile << "page_bundles/clusters.css"
config.assets.precompile << "page_bundles/commits.css"
config.assets.precompile << "page_bundles/commit_description.css"
config.assets.precompile << "page_bundles/cycle_analytics.css"
config.assets.precompile << "page_bundles/dashboard.css"
config.assets.precompile << "page_bundles/dashboard_projects.css"

View File

@ -0,0 +1,9 @@
---
name: enforce_full_refs_for_pipeline_schedules
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/435357
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144953
rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/17604
milestone: '16.10'
group: group::pipeline execution
type: development
default_enabled: false

View File

@ -6,5 +6,3 @@ Rails.backtrace_cleaner.remove_silencers!
if Rails.env.development? || Rails.env.test?
Rails.backtrace_cleaner.add_silencer { |line| %r{^lib/gitlab/database/load_balancing}.match?(line) }
end
Rails.backtrace_cleaner.add_silencer { |line| !Gitlab::APP_DIRS_PATTERN.match?(line) }

View File

@ -17,8 +17,7 @@ Settings = GitlabSettings.load(file, Rails.env) do
[
gitlab.host,
custom_port,
gitlab.relative_url_root,
'/'
gitlab.relative_url_root
].join('')
end

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
class UnscheduleOpenAiClearConversationsWorker < Gitlab::Database::Migration[2.2]
milestone '16.10'
disable_ddl_transaction!
def up
# This is to clean up the cron schedule for OpenAi::ClearConversationsWorker
# which was removed in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/139626
removed_job = Sidekiq::Cron::Job.find('open_ai_clear_conversations_worker')
removed_job.destroy if removed_job
sidekiq_remove_jobs(job_klasses: %w[OpenAi::ClearConversationsWorker])
end
def down
# No-op
end
end

View File

@ -0,0 +1 @@
f5e8162f1d63cc4ba8331f9fd29f6e2fa389871448193d3ded4157fac1318456

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
{
"id": 13,
"description": "Test schedule pipeline",
"ref": "main",
"ref": "refs/heads/main",
"cron": "* * * * *",
"cron_timezone": "Asia/Tokyo",
"next_run_at": "2017-05-19T13:41:00.000Z",
@ -74,7 +74,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
{
"id": 13,
"description": "Test schedule pipeline",
"ref": "main",
"ref": "refs/heads/main",
"cron": "* * * * *",
"cron_timezone": "Asia/Tokyo",
"next_run_at": "2017-05-19T13:41:00.000Z",
@ -84,7 +84,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
"last_pipeline": {
"id": 332,
"sha": "0e788619d0b5ec17388dffb973ecd505946156db",
"ref": "main",
"ref": "refs/heads/main",
"status": "pending"
},
"owner": {
@ -168,14 +168,14 @@ Create a new pipeline schedule of a project.
POST /projects/:id/pipeline_schedules
```
| Attribute | Type | Required | Description |
|-----------------|----------------|----------|-------------|
| `cron` | string | Yes | The [cron](https://en.wikipedia.org/wiki/Cron) schedule, for example: `0 1 * * *`. |
| `description` | string | Yes | The description of the pipeline schedule. |
| `id` | integer/string | Yes | The ID or [URL-encoded path of the project](rest/index.md#namespaced-path-encoding). |
| `ref` | string | Yes | The branch or tag name that is triggered. |
| `active` | boolean | No | The activation of pipeline schedule. If false is set, the pipeline schedule is initially deactivated (default: `true`). |
| `cron_timezone` | string | No | The time zone supported by `ActiveSupport::TimeZone`, for example: `Pacific Time (US & Canada)` (default: `UTC`). |
| Attribute | Type | Required | Description |
|-----------------|----------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `cron` | string | Yes | The [cron](https://en.wikipedia.org/wiki/Cron) schedule, for example: `0 1 * * *`. |
| `description` | string | Yes | The description of the pipeline schedule. |
| `id` | integer/string | Yes | The ID or [URL-encoded path of the project](rest/index.md#namespaced-path-encoding). |
| `ref` | string | Yes | The branch or tag name that is triggered. Both the short (e.g. `main`) and full (e.g. `refs/heads/main` or `refs/tags/main`) ref versions are accepted. If a short version is provided, it is automatically expanded to the full ref version but, if the ref is [ambiguous](../ci/pipelines/schedules.md#ambiguous-refs), it will be rejected |
| `active` | boolean | No | The activation of pipeline schedule. If false is set, the pipeline schedule is initially deactivated (default: `true`). |
| `cron_timezone` | string | No | The time zone supported by `ActiveSupport::TimeZone`, for example: `Pacific Time (US & Canada)` (default: `UTC`). |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
@ -187,7 +187,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
{
"id": 14,
"description": "Build packages",
"ref": "main",
"ref": "refs/heads/main",
"cron": "0 1 * * 5",
"cron_timezone": "UTC",
"next_run_at": "2017-05-26T01:00:00.000Z",
@ -214,15 +214,15 @@ Updates the pipeline schedule of a project. After the update is done, it is resc
PUT /projects/:id/pipeline_schedules/:pipeline_schedule_id
```
| Attribute | Type | Required | Description |
|------------------------|----------------|----------|-------------|
| `id` | integer/string | Yes | The ID or [URL-encoded path of the project](rest/index.md#namespaced-path-encoding). |
| `pipeline_schedule_id` | integer | Yes | The pipeline schedule ID. |
| `active` | boolean | No | The activation of pipeline schedule. If false is set, the pipeline schedule is initially deactivated. |
| `cron_timezone` | string | No | The time zone supported by `ActiveSupport::TimeZone` (for example `Pacific Time (US & Canada)`), or `TZInfo::Timezone` (for example `America/Los_Angeles`). |
| `cron` | string | No | The [cron](https://en.wikipedia.org/wiki/Cron) schedule, for example: `0 1 * * *`. |
| `description` | string | No | The description of the pipeline schedule. |
| `ref` | string | No | The branch or tag name that is triggered. |
| Attribute | Type | Required | Description |
|------------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `id` | integer/string | Yes | The ID or [URL-encoded path of the project](rest/index.md#namespaced-path-encoding). |
| `pipeline_schedule_id` | integer | Yes | The pipeline schedule ID. |
| `active` | boolean | No | The activation of pipeline schedule. If false is set, the pipeline schedule is initially deactivated. |
| `cron_timezone` | string | No | The time zone supported by `ActiveSupport::TimeZone` (for example `Pacific Time (US & Canada)`), or `TZInfo::Timezone` (for example `America/Los_Angeles`). |
| `cron` | string | No | The [cron](https://en.wikipedia.org/wiki/Cron) schedule, for example: `0 1 * * *`. |
| `description` | string | No | The description of the pipeline schedule. |
| `ref` | string | No | The branch or tag name that is triggered. Both the short (e.g. `main`) and full (e.g. `refs/heads/main` or `refs/tags/main`) ref versions are accepted. If a short version is provided, it is automatically expanded to the full ref version but, if the ref is [ambiguous](../ci/pipelines/schedules.md#ambiguous-refs), it will be rejected |
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
@ -233,7 +233,7 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
{
"id": 13,
"description": "Test schedule pipeline",
"ref": "main",
"ref": "refs/heads/main",
"cron": "0 2 * * *",
"cron_timezone": "Asia/Tokyo",
"next_run_at": "2017-05-19T17:00:00.000Z",
@ -243,7 +243,7 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \
"last_pipeline": {
"id": 332,
"sha": "0e788619d0b5ec17388dffb973ecd505946156db",
"ref": "main",
"ref": "refs/heads/main",
"status": "pending"
},
"owner": {
@ -278,7 +278,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitla
{
"id": 13,
"description": "Test schedule pipeline",
"ref": "main",
"ref": "refs/heads/main",
"cron": "0 2 * * *",
"cron_timezone": "Asia/Tokyo",
"next_run_at": "2017-05-19T17:00:00.000Z",
@ -288,7 +288,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitla
"last_pipeline": {
"id": 332,
"sha": "0e788619d0b5ec17388dffb973ecd505946156db",
"ref": "main",
"ref": "refs/heads/main",
"status": "pending"
},
"owner": {
@ -323,7 +323,7 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
{
"id": 13,
"description": "Test schedule pipeline",
"ref": "main",
"ref": "refs/heads/main",
"cron": "0 2 * * *",
"cron_timezone": "Asia/Tokyo",
"next_run_at": "2017-05-19T17:00:00.000Z",
@ -333,7 +333,7 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
"last_pipeline": {
"id": 332,
"sha": "0e788619d0b5ec17388dffb973ecd505946156db",
"ref": "main",
"ref": "refs/heads/main",
"status": "pending"
},
"owner": {

View File

@ -105,3 +105,19 @@ questions that you know someone might ask.
Each scenario can be a third-level heading, for example `### Getting error message X`.
If you have none to add when creating a doc, leave this section in place
but commented out to help encourage others to add to it in the future. -->
## Troubleshooting
### Short refs are expanded to Full refs
This behavior is normal and it introduced in order to enforce explicit resources.
The API still accepts both `short` (e.g. `main`) and `full` (e.g. `refs/heads/main` or `refs/tags/main`) refs and expands any `short`
ref provided, to a `full` ref.
### Ambiguous Refs
When a ref is being expanded, there can be cases where the full ref can't be automatically inferred.
Such cases can be:
- A `short` ref is provided (e.g. `main`) but **both** a branch and a tag exist with the provided `short` ref name
- A `short` ref is provided, but **neither** a branch or tag with the provided `short` ref name exist

View File

@ -5387,6 +5387,10 @@ In this example, the script:
The following keywords are deprecated.
NOTE:
These keywords are still usable to ensure backwards compatibility,
but could be scheduled for removal in a future major milestone.
### Globally-defined `image`, `services`, `cache`, `before_script`, `after_script`
Defining `image`, `services`, `cache`, `before_script`, and `after_script` globally is deprecated.

View File

@ -6,21 +6,83 @@ info: Any user with at least the Maintainer role can merge updates to this conte
# GitLab Workhorse
GitLab Workhorse is a smart reverse proxy for GitLab. It handles
"large" HTTP requests such as file downloads, file uploads, Git
push/pull and Git archive downloads.
GitLab Workhorse is a smart reverse proxy for GitLab intended to handle resource-intensive and long-running requests.
It sits in front of Puma and intercepts every HTTP request destined for and emitted from GitLab Rails.
Rails delegates requests to Workhorse and it takes responsibility for resource intensive HTTP requests
such as file downloads and uploads, `git` over HTTP push/pull and `git` over HTTP archive downloads,
which optimizes resource utilization and improves request handling efficiency.
Workhorse itself is not a feature, but there are
[several features in GitLab](gitlab_features.md) that would not work efficiently without Workhorse.
## Role in the GitLab stack
The canonical source for Workhorse is
Workhorse can have other reverse proxy servers in front of it but only NGINX is supported.
It is also possible (although unsupported) to use other reverse proxies such as Apache when installing
GitLab from source.
On many instances of GitLab, such as `gitlab.com`, a CDN like CloudFlare sits in front of NGINX.
Every Rails controller and other code that handles HTTP requests and returning HTTP responses is
proxied through GitLab Workhorse.
Workhorse is unlike other reverse proxies as it is very tightly
coupled to GitLab Rails where as most reverse proxies are quite generic.
When required, Workhorse makes modifications to HTTP headers which GitLab Rails depends on to offload work efficiently.
## Functionality and operations
### Request processing
- Workhorse primarily acts as a pass-through entity for incoming requests, forwarding them to Rails for processing.
In essence, it performs minimal intervention on most requests, thereby maintaining a streamlined
request handling pipeline.
- For specific types of requests, especially those that are resource-intensive or require specialized handling
(for example, large file uploads), Workhorse takes a more active role.
Upon receiving directives from Rails, Workhorse executes specialized tasks such as directly
interacting with [Gitaly](../../administration/gitaly/index.md) or offloading processing file uploads from Rails.
### Specialized task handling
- Workhorse is capable of intercepting certain requests based on Rails' responses and executing
predefined operations.
This includes interacting with [Gitaly](../../administration/gitaly/index.md), managing large data
blobs, and altering request handling logic as required.
- A notable functionality is its ability to manage file uploads efficiently.
Workhorse can hijack the file upload process, perform necessary actions as dictated by Rails
(such as storing files temporarily or uploading them to object storage), and update Rails when the
process has completed.
### Integration with the Rails API
Workhorse serves as a proxy to the Rails API, especially in contexts requiring interaction with container
registry services.
This setup exemplifies Workhorse's ability to handle high-load services by acting as a reverse proxy,
thereby minimizing the direct load on Rails.
## Architectural considerations
### Expanding functionality
- **Maintaining Simplicity:** While expanding Workhorse's functionalities to include direct handling
of specific services (for example, container registry), it's crucial to maintain its simplicity and efficiency.
Workhorse should not encompass complex control logic but rather focus on executing tasks as directed
by Rails.
- **Service Implementation and Data Migration:** Implementing new functionalities in Workhorse
requires careful consideration of data migration strategies and service continuity.
### Data management and operational integrity
- Workhorse's architecture facilitates efficient data management strategies, including garbage
collection and data migration.
Workhorse's role is to support high-performance operations without directly involving complex data
manipulation or control logic, which remains the purview of Rails.
- For operations requiring background processing or long-running tasks, it is suggested to use
separate services or Sidekiq job queues, with Workhorse and Rails coordinating to manage task execution and data integrity.
Workhorse is contained in a subfolder of the Rails monorepo at
[`gitlab-org/gitlab/workhorse`](https://gitlab.com/gitlab-org/gitlab/tree/master/workhorse).
## Learning Resources
## Learning resources
- Workhorse documentation (this page)
- [GitLab Workhorse Deep Dive: Dependency Proxy](https://www.youtube.com/watch?v=9cRd-k0TRqI) _video_
- [How Dependency Proxy via Workhorse works](https://gitlab.com/gitlab-org/gitlab/-/issues/370235)
- Video: [GitLab Workhorse Deep Dive: Dependency Proxy](https://www.youtube.com/watch?v=9cRd-k0TRqI)
- [How Dependency Proxy with Workhorse works](https://gitlab.com/gitlab-org/gitlab/-/issues/370235)
- [Workhorse overview for the Dependency Proxy](https://www.youtube.com/watch?v=WmBibT9oQms)
- [Workhorse architecture discussion](https://www.youtube.com/watch?v=QlHdh-yudtw)
@ -53,9 +115,8 @@ Workhorse uses [ExifTool](https://exiftool.org/) for
removing EXIF data (which may contain sensitive information) from uploaded
images. If you installed GitLab:
- Using the Omnibus package, you're all set.
*NOTE* that if you are using CentOS Minimal, you may need to install `perl`
package: `yum install perl`
- Using the Linux package, you're all set.
If you are using CentOS Minimal, you may need to install `perl` package: `yum install perl`.
- From source, make sure `exiftool` is installed:
```shell

View File

@ -79,7 +79,7 @@ As a single-tenant SaaS solution, GitLab Dedicated provides infrastructure-level
#### Access controls
GitLab Dedicated adheres to the [principle of least privilege](https://handbook.gitlab.com/handbook/security/access-management-policy/#principle-of-least-privilege) to control access to customer tenant environments. Tenant AWS accounts live under a top-level GitLab Dedicated AWS parent organization. Access to the AWS Organization is restricted to select GitLab team members. All user accounts within the AWS Organization follow the overall [GitLab Access Management Policy](https://handbook.gitlab.com/handbook/security/access-management-policy/). Direct access to customer tenant environments is restricted to a single Hub account. The GitLab Dedicated Control Plane uses the Hub account to perform automated actions over tenant accounts when managing environments. Similarly, GitLab Dedicated engineers do not have direct access to customer tenant environments. In break glass situations, where access to resources in the tenant environment is required to address a high-severity issue, GitLab engineers must go through the Hub account to manage those resources. This is done via an approval process, and after permission is granted, the engineer will assume an IAM role on a temporary basis to access tenant resources through the Hub account. All actions within the hub account and tenant account are logged to CloudTrail.
GitLab Dedicated adheres to the [principle of least privilege](https://handbook.gitlab.com/handbook/security/access-management-policy/#principle-of-least-privilege) to control access to customer tenant environments. Tenant AWS accounts live under a top-level GitLab Dedicated AWS parent organization. Access to the AWS Organization is restricted to select GitLab team members. All user accounts within the AWS Organization follow the overall [GitLab Access Management Policy](https://handbook.gitlab.com/handbook/security/access-management-policy/). Direct access to customer tenant environments is restricted to a single Hub account. The GitLab Dedicated Control Plane uses the Hub account to perform automated actions over tenant accounts when managing environments. Similarly, GitLab Dedicated engineers do not have direct access to customer tenant environments. In [break glass](https://gitlab.com/gitlab-com/gl-infra/gitlab-dedicated/team/-/blob/main/engineering/breaking_glass.md) situations, where access to resources in the tenant environment is required to address a high-severity issue, GitLab engineers must go through the Hub account to manage those resources. This is done via an approval process, and after permission is granted, the engineer will assume an IAM role on a temporary basis to access tenant resources through the Hub account. All actions within the hub account and tenant account are logged to CloudTrail.
Inside tenant accounts, GitLab leverages Intrusion Detection and Malware Scanning capabilities from AWS GuardDuty. Infrastructure logs are monitored by the GitLab Security Incident Response Team to detect anomalous events.

View File

@ -49,14 +49,6 @@ Prerequisites:
synchronize subscription (**{retry}**).
1. To the right of the user, turn on the toggle to assign GitLab Duo Pro.
### Assign seats in bulk
To assign seats in bulk, you can use [this GraphQL API endpoint](../api/graphql/reference/index.md#mutationuseraddonassignmentcreate).
This endpoint works for both self-managed and SaaS.
Administrators of self-managed instances can also assign users by using a [Rake task](../raketasks/user_management.md#bulk-assign-users-to-gitlab-duo-pro).
#### Configure network and proxy settings
For self-managed instances, you must also ensure that your firewalls and HTTP proxy servers
@ -65,6 +57,14 @@ allow outbound connections to `cloud.gitlab.com`.
To use an HTTP proxy, ensure that both `gitLab _workhorse` and `gitLab_rails` set the necessary
[web proxy environment variables](https://docs.gitlab.com/omnibus/settings/environment-variables.html).
### Assign seats in bulk
To assign seats in bulk, you can use [this GraphQL API endpoint](../api/graphql/reference/index.md#mutationuseraddonassignmentcreate).
This endpoint works for both self-managed and SaaS.
Administrators of self-managed instances can also assign users by using a [Rake task](../raketasks/user_management.md#bulk-assign-users-to-gitlab-duo-pro).
## Purchase additional GitLab Duo Pro seats
DETAILS:

View File

@ -132,7 +132,7 @@ The summary is displayed only for you.
Provide feedback on this experimental feature in [issue 407779](https://gitlab.com/gitlab-org/gitlab/-/issues/407779).
**Data usage**: When you use this feature, the text of public comments on the issue are sent to the large
**Data usage**: When you use this feature, the text of all comments on the issue are sent to the large
language model referenced above.
### Forecast deployment frequency with Value stream forecasting
@ -217,7 +217,7 @@ language model referenced above.
| Feature | Large Language Model |
|---|---|
| [Git suggestions](https://gitlab.com/gitlab-org/gitlab/-/issues/409636) | Vertex AI Codey [`codechat-bison`](https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/code-chat) |
| [Discussion summary](#summarize-issue-discussions-with-discussion-summary) | Vertex AI Codey [`text-bison`](https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/text) |
| [Discussion summary](#summarize-issue-discussions-with-discussion-summary) |Anthropic [`Claude-2`](https://docs.anthropic.com/claude/reference/selecting-a-model) |
| [Issue description generation](#summarize-an-issue-with-issue-description-generation) | Anthropic [`Claude-2`](https://docs.anthropic.com/claude/reference/selecting-a-model) |
| [Code Suggestions](project/repository/code_suggestions/index.md) | For Code Completion: Vertex AI Codey [`code-gecko`](https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/code-completion) For Code Generation: Anthropic [`Claude-2`](https://docs.anthropic.com/claude/reference/selecting-a-model) |
| [Test generation](gitlab_duo_chat.md#write-tests-in-the-ide) | Anthropic [`Claude-2`](https://docs.anthropic.com/claude/reference/selecting-a-model) |

View File

@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Beyond Identity
DETAILS:
**Tier:** Free, Premium, Ultimate
**Tier:** Premium, Ultimate
**Offering:** SaaS, self-managed
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/431433) in GitLab 16.9.

View File

@ -29,9 +29,15 @@ module Gitlab
def self.clean_backtrace(backtrace)
return unless backtrace
Array(Rails.backtrace_cleaner.clean(backtrace)).reject do |line|
Array(backtrace_cleaner.clean(backtrace)).reject do |line|
IGNORED_BACKTRACES_REGEXP.match?(line)
end
end
def self.backtrace_cleaner
@backtrace_cleaner ||= Rails.backtrace_cleaner.dup.tap do |cleaner|
cleaner.add_silencer { |line| !Gitlab::APP_DIRS_PATTERN.match?(line) }
end
end
end
end

View File

@ -10,14 +10,15 @@ module Gitlab
LATEST_VERSION_KEYWORD = '~latest'
def self.match?(address)
address.include?('@') && address.start_with?(Settings.gitlab_ci['component_fqdn'])
address.include?('@') && address.start_with?(fqdn_prefix)
end
attr_reader :host
def self.fqdn_prefix
"#{Settings.gitlab_ci['component_fqdn']}/"
end
def initialize(address:)
@full_path, @version = address.to_s.split('@', 2)
@host = Settings.gitlab_ci['component_fqdn']
end
def fetch_content!(current_user:)
@ -74,7 +75,7 @@ module Gitlab
end
def instance_path
@full_path.delete_prefix(host)
@full_path.delete_prefix(self.class.fqdn_prefix)
end
def extract_component_name(project_path)

View File

@ -44,34 +44,17 @@ module Gitlab
def handle_not_found(exception)
detail = Gitlab::GitalyClient.decode_detailed_error(exception)
handle_find_commits_error(detail, exception) if detail.is_a?(Gitaly::FindCommitsError)
case detail.class.name
when Gitaly::ReferenceNotFoundError.name
raise Gitlab::Git::ReferenceNotFoundError.new(
exception, detail.reference_name
)
when Gitaly::FindCommitsError.name
raise Gitlab::Git::Repository::CommitNotFound, exception
else
raise Gitlab::Git::Repository::NoRepository, exception
end
end
def handle_find_commits_error(detail, exception)
if detail.ambiguous_ref
raise Gitlab::Git::Repository::CommitNotFound, "ambiguous reference:#{detail.ambiguous_ref.reference}"
end
if detail.bad_object
raise Gitlab::Git::Repository::CommitNotFound,
"bad object:#{detail.bad_object.to_h[:bad_oid]}"
end
if detail.invalid_range
raise Gitlab::Git::Repository::CommitNotFound, "invalid range:#{detail.invalid_range.range}"
end
raise Gitlab::Git::Repository::CommitNotFound, exception
end
end
end
end

View File

@ -60,7 +60,7 @@ module Gitlab
case context
when :block
['NOTE:', *parts].join("\n")
['DETAILS:', *parts].join("\n")
when :inline
parts.join(' ')
end
@ -128,8 +128,8 @@ module Gitlab
" #{changed_in_milestone}: #{reason_text}"
end
# Returns 'Deprecated in <milestone>' for proper deprecations.
# Retruns 'Introduced in <milestone>' for :alpha deprecations.
# Returns 'Deprecated in GitLab <milestone>' for proper deprecations.
# Returns 'Introduced in GitLab <milestone>' for :alpha deprecations.
# Formatted to markdown or plain format.
def changed_in_milestone(format: :plain)
verb = if alpha?
@ -140,9 +140,9 @@ module Gitlab
case format
when :plain
"#{verb} in #{milestone}"
"#{verb} in GitLab #{milestone}"
when :markdown
"**#{verb}** in #{milestone}"
"**#{verb}** in GitLab #{milestone}"
end
end
end

View File

@ -1918,9 +1918,6 @@ msgstr ""
msgid "AIAgents|AI Agents"
msgstr ""
msgid "AIAgents|Agent name"
msgstr ""
msgid "AIAgents|An error has occurred when saving the agent."
msgstr ""
@ -1936,9 +1933,18 @@ msgstr ""
msgid "AIAgent|Agent"
msgstr ""
msgid "AIAgent|Agent name"
msgstr ""
msgid "AIAgent|Ask your agent"
msgstr ""
msgid "AIAgent|Create agent"
msgstr ""
msgid "AIAgent|Prompt (optional)"
msgstr ""
msgid "AIAgent|Try out your agent"
msgstr ""
@ -40048,9 +40054,6 @@ msgstr ""
msgid "Promotions|You can restrict access to protected branches by choosing a role (Maintainers, Developers) as well as certain users."
msgstr ""
msgid "Prompt"
msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
@ -58654,15 +58657,9 @@ msgstr ""
msgid "ciReport|Coverage fuzzing"
msgstr ""
msgid "ciReport|Create Jira issue"
msgstr ""
msgid "ciReport|Create a merge request to implement this solution, or download and apply the patch manually."
msgstr ""
msgid "ciReport|Create issue"
msgstr ""
msgid "ciReport|DAST"
msgstr ""
@ -58717,9 +58714,6 @@ msgstr ""
msgid "ciReport|Generic Report"
msgstr ""
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
msgid "ciReport|License Compliance"
msgstr ""
@ -60467,18 +60461,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
msgid "vulnerability|Add comment and dismiss"
msgstr ""
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
msgid "vulnerability|Save comment"
msgstr ""
msgid "vulnerability|Undo dismiss"
msgstr ""
msgid "vulnerability|dismissed"
msgstr ""

View File

@ -66,8 +66,8 @@
"@gitlab/visual-review-tools": "1.7.3",
"@gitlab/web-ide": "^0.0.1-dev-20240214084918",
"@mattiasbuelens/web-streams-adapter": "^0.1.0",
"@rails/actioncable": "7.0.8",
"@rails/ujs": "7.0.8",
"@rails/actioncable": "7.0.8-1",
"@rails/ujs": "7.0.8-1",
"@snowplow/browser-plugin-client-hints": "^3.9.0",
"@snowplow/browser-plugin-form-tracking": "^3.9.0",
"@snowplow/browser-plugin-ga-cookies": "^3.9.0",

View File

@ -5,7 +5,7 @@ source 'https://rubygems.org'
gem 'gitlab-qa', '~> 14', '>= 14.2.1', require: 'gitlab/qa'
gem 'gitlab_quality-test_tooling', '~> 1.11.0', require: false
gem 'gitlab-utils', path: '../gems/gitlab-utils'
gem 'activesupport', '~> 7.0.8' # This should stay in sync with the root's Gemfile
gem 'activesupport', '~> 7.0.8.1' # This should stay in sync with the root's Gemfile
gem 'allure-rspec', '~> 2.24.0'
gem 'capybara', '~> 3.39.2'
gem 'capybara-screenshot', '~> 1.0.26'

View File

@ -10,13 +10,13 @@ PATH
GEM
remote: https://rubygems.org/
specs:
actionview (7.0.8)
activesupport (= 7.0.8)
actionview (7.0.8.1)
activesupport (= 7.0.8.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activesupport (7.0.8)
activesupport (7.0.8.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
@ -207,7 +207,7 @@ GEM
mime-types-data (3.2023.0218.1)
mini_mime (1.1.5)
mini_portile2 (2.8.5)
minitest (5.21.1)
minitest (5.22.2)
mize (0.4.1)
protocol (~> 2.0)
multi_json (1.15.0)
@ -344,7 +344,7 @@ PLATFORMS
ruby
DEPENDENCIES
activesupport (~> 7.0.8)
activesupport (~> 7.0.8.1)
airborne (~> 0.3.7)
allure-rspec (~> 2.24.0)
capybara (~> 3.39.2)

View File

@ -2,22 +2,25 @@
module QA
RSpec.describe 'Verify', :requires_admin, :reliable, product_group: :pipeline_execution do
describe 'When user is blocked' do
describe 'When user is blocked', feature_flag: { name: 'enforce_full_refs_for_pipeline_schedules,
scope: :project' } do
let!(:admin_api_client) { Runtime::API::Client.as_admin }
let!(:user_api_client) { Runtime::API::Client.new(:gitlab, user: user) }
let(:user) { create(:user, api_client: admin_api_client) }
let(:project) { create(:project, name: 'project-for-canceled-schedule') }
let(:ref) { 'master' }
before do
project.add_member(user, Resource::Members::AccessLevel::MAINTAINER)
project.create_repository_branch(ref)
# Retry is needed due to delays with project authorization updates
# Long term solution to accessing the status of a project authorization update
# has been proposed in https://gitlab.com/gitlab-org/gitlab/-/issues/393369
Support::Retrier.retry_on_exception(max_attempts: 60, sleep_interval: 1) do
create(:pipeline_schedule, api_client: user_api_client, project: project)
create(:pipeline_schedule, ref: ref, api_client: user_api_client, project: project)
end
Support::Waiter.wait_until { !pipeline_schedule[:id].nil? && pipeline_schedule[:active] == true }

View File

@ -21,6 +21,10 @@ module RuboCop
}
end
end
def checksum
@checksum ||= Digest::SHA256.hexdigest(dictionary_data.to_s)
end
end
def initialize(queued_migration_version)

View File

@ -51,6 +51,10 @@ module RuboCop
add_offense(node, message: format(MSG[error_code], msg_params))
end
def external_dependency_checksum
RuboCop::BatchedBackgroundMigrationsDictionary.checksum
end
private
def valid_url?(url)

View File

@ -50,11 +50,11 @@ RSpec.describe Settings, feature_category: :system_access do
subject(:fqdn) { described_class.build_ci_component_fqdn }
where(:host, :port, :relative_url, :result) do
'acme.com' | 9090 | '/gitlab' | 'acme.com:9090/gitlab/'
'acme.com' | 443 | '/gitlab' | 'acme.com/gitlab/'
'acme.com' | 443 | '' | 'acme.com/'
'acme.com' | 9090 | '' | 'acme.com:9090/'
'test' | 9090 | '' | 'test:9090/'
'acme.com' | 9090 | '/gitlab' | 'acme.com:9090/gitlab'
'acme.com' | 443 | '/gitlab' | 'acme.com/gitlab'
'acme.com' | 443 | '' | 'acme.com'
'acme.com' | 9090 | '' | 'acme.com:9090'
'test' | 9090 | '' | 'test:9090'
end
with_them do

View File

@ -255,7 +255,7 @@ RSpec.describe Projects::PipelineSchedulesController, feature_category: :continu
context 'when a pipeline schedule has no variables' do
let(:basic_param) do
{ description: 'updated_desc', cron: '0 1 * * *', cron_timezone: 'UTC', ref: 'patch-x', active: true }
{ description: 'updated_desc', cron: '0 1 * * *', cron_timezone: 'UTC', ref: 'master', active: true }
end
context 'when params include one variable' do
@ -309,7 +309,7 @@ RSpec.describe Projects::PipelineSchedulesController, feature_category: :continu
context 'when a pipeline schedule has one variable' do
let(:basic_param) do
{ description: 'updated_desc', cron: '0 1 * * *', cron_timezone: 'UTC', ref: 'patch-x', active: true }
{ description: 'updated_desc', cron: '0 1 * * *', cron_timezone: 'UTC', ref: 'master', active: true }
end
let!(:pipeline_schedule_variable) do

View File

@ -4,7 +4,7 @@ FactoryBot.define do
factory :ci_pipeline_schedule, class: 'Ci::PipelineSchedule' do
cron { '0 1 * * *' }
cron_timezone { Gitlab::Ci::CronParser::VALID_SYNTAX_SAMPLE_TIME_ZONE }
ref { 'master' }
ref { "#{Gitlab::Git::BRANCH_REF_PREFIX}master" }
active { true }
description { "pipeline schedule" }
project

View File

@ -1,4 +1,11 @@
import { GlLoadingIcon, GlTable, GlLink, GlPagination, GlModal, GlFormCheckbox } from '@gitlab/ui';
import {
GlSkeletonLoader,
GlTable,
GlLink,
GlPagination,
GlModal,
GlFormCheckbox,
} from '@gitlab/ui';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import getJobArtifactsResponse from 'test_fixtures/graphql/ci/artifacts/graphql/queries/get_job_artifacts.query.graphql.json';
@ -38,7 +45,7 @@ describe('JobArtifactsTable component', () => {
const mockToastShow = jest.fn();
const findLoadingState = () => wrapper.findComponent(GlLoadingIcon);
const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
const findTable = () => wrapper.findComponent(GlTable);
const findDetailsRows = () => wrapper.findAllComponents(ArtifactsTableRowDetails);
const findDetailsInRow = (i) =>
@ -165,10 +172,11 @@ describe('JobArtifactsTable component', () => {
});
};
it('when loading, shows a loading state', () => {
it('when loading, shows a skeleton loader', () => {
createComponent();
expect(findLoadingState().exists()).toBe(true);
expect(findTable().attributes('aria-busy')).toBe('true');
expect(findSkeletonLoader().exists()).toBe(true);
});
it('on error, shows an alert', async () => {
@ -188,7 +196,8 @@ describe('JobArtifactsTable component', () => {
await waitForPromises();
expect(findTable().exists()).toBe(true);
expect(findTable().attributes('aria-busy')).toBe('false');
expect(findSkeletonLoader().exists()).toBe(false);
});
describe('job details', () => {

View File

@ -208,9 +208,9 @@ describe('UserToken', () => {
const baseTokenEl = findBaseToken();
expect(baseTokenEl.exists()).toBe(true);
expect(baseTokenEl.props()).toMatchObject({
suggestions: mockUsers,
valueIdentifier: 'username',
getActiveTokenValue: baseTokenEl.props('getActiveTokenValue'),
});
});

View File

@ -4,14 +4,6 @@ require 'spec_helper'
RSpec.describe Gitlab::BacktraceCleaner do
describe '.clean_backtrace' do
it 'uses the Rails backtrace cleaner' do
backtrace = []
expect(Rails.backtrace_cleaner).to receive(:clean).with(backtrace)
described_class.clean_backtrace(backtrace)
end
it 'removes lines from IGNORE_BACKTRACES' do
backtrace = [
"lib/gitlab/gitaly_client.rb:294:in `block (2 levels) in migrate'",

View File

@ -6,8 +6,9 @@ RSpec.describe Gitlab::Ci::Components::InstancePath, feature_category: :pipeline
let_it_be(:user) { create(:user) }
let(:path) { described_class.new(address: address) }
let(:settings) { GitlabSettings::Options.build({ 'component_fqdn' => current_host }) }
let(:current_host) { 'acme.com/' }
let(:settings) { GitlabSettings::Options.build({ 'component_fqdn' => component_fqdn }) }
let(:component_fqdn) { 'acme.com' }
let(:fqdn_prefix) { "#{component_fqdn}/" }
before do
allow(::Settings).to receive(:gitlab_ci).and_return(settings)
@ -55,7 +56,6 @@ RSpec.describe Gitlab::Ci::Components::InstancePath, feature_category: :pipeline
result = path.fetch_content!(current_user: user)
expect(result.content).to eq(file_content)
expect(result.path).to eq(file_path)
expect(path.host).to eq(current_host)
expect(path.project).to eq(project)
expect(path.sha).to eq(project.commit('master').id)
end
@ -138,7 +138,6 @@ RSpec.describe Gitlab::Ci::Components::InstancePath, feature_category: :pipeline
result = path.fetch_content!(current_user: user)
expect(result.content).to eq('image: alpine_2')
expect(result.path).to eq('templates/secret-detection.yml')
expect(path.host).to eq(current_host)
expect(path.project).to eq(project)
expect(path.sha).to eq(latest_sha)
end
@ -156,7 +155,6 @@ RSpec.describe Gitlab::Ci::Components::InstancePath, feature_category: :pipeline
result = path.fetch_content!(current_user: user)
expect(result.content).to eq('image: alpine_2')
expect(result.path).to eq('templates/secret-detection.yml')
expect(path.host).to eq(current_host)
expect(path.project).to eq(project)
expect(path.sha).to eq(latest_sha)
end
@ -168,7 +166,6 @@ RSpec.describe Gitlab::Ci::Components::InstancePath, feature_category: :pipeline
it 'returns nil', :aggregate_failures do
expect(path.fetch_content!(current_user: user)).to be_nil
expect(path.host).to eq(current_host)
expect(path.project).to eq(project)
expect(path.sha).to be_nil
end
@ -176,13 +173,12 @@ RSpec.describe Gitlab::Ci::Components::InstancePath, feature_category: :pipeline
context 'when current GitLab instance is installed on a relative URL' do
let(:address) { "acme.com/gitlab/#{project_path}/secret-detection@#{version}" }
let(:current_host) { 'acme.com/gitlab/' }
let(:component_fqdn) { 'acme.com/gitlab' }
it 'fetches the component content', :aggregate_failures do
result = path.fetch_content!(current_user: user)
expect(result.content).to eq('image: alpine_1')
expect(result.path).to eq('templates/secret-detection.yml')
expect(path.host).to eq(current_host)
expect(path.project).to eq(project)
expect(path.sha).to eq(project.commit('master').id)
end
@ -216,7 +212,6 @@ RSpec.describe Gitlab::Ci::Components::InstancePath, feature_category: :pipeline
expect(result.content).to eq('image: alpine_1')
expect(result.path).to eq('templates/secret-detection.yml')
expect(path.host).to eq(current_host)
expect(path.project).to eq(project)
end
end
@ -236,7 +231,6 @@ RSpec.describe Gitlab::Ci::Components::InstancePath, feature_category: :pipeline
expect(result.content).to eq('image: alpine_1')
expect(result.path).to eq('templates/secret-detection.yml')
expect(path.host).to eq(current_host)
expect(path.project).to eq(project)
end
end
@ -250,11 +244,32 @@ RSpec.describe Gitlab::Ci::Components::InstancePath, feature_category: :pipeline
expect(result.content).to eq('image: alpine_1')
expect(result.path).to eq('templates/secret-detection.yml')
expect(path.host).to eq(current_host)
expect(path.project).to eq(project)
end
end
end
end
end
describe '.match?' do
subject(:match) { described_class.match?(address) }
context 'when address is a valid path' do
let(:address) { "#{fqdn_prefix}group/project@master" }
it { is_expected.to be_truthy }
end
context 'when address is an invalid path' do
let(:address) { 'group/project@master' }
it { is_expected.to be_falsey }
end
end
describe '.fqdn_prefix' do
subject(:fqdn_prefix) { described_class.fqdn_prefix }
it { is_expected.to eq("#{component_fqdn}/") }
end
end

View File

@ -18,7 +18,7 @@ RSpec.describe Gitlab::ExceptionLogFormatter do
expect(payload['exception.class']).to eq('RuntimeError')
expect(payload['exception.message']).to eq('bad request')
expect(payload['exception.backtrace']).to eq(Gitlab::BacktraceCleaner.clean_backtrace(backtrace))
expect(payload['exception.backtrace']).to eq(Rails.backtrace_cleaner.clean(backtrace))
expect(payload['exception.sql']).to be_nil
end

View File

@ -79,48 +79,23 @@ RSpec.describe Gitlab::Git::WrapsGitalyErrors, feature_category: :gitaly do
end
end
shared_examples 'commit not found' do |message|
it 'wraps the commit not found error' do
expect { wrapped_gitaly_errors }.to raise_error do |wrapped_error|
expect(wrapped_error).to be_a(Gitlab::Git::Repository::CommitNotFound)
expect(wrapped_error.message).to eql(message)
end
end
end
context 'when receiving GRPC::Core::StatusCodes::NOT_FOUND' do
subject(:wrapped_gitaly_errors) { wrapper.wrapped_gitaly_errors { raise original_error } }
let(:original_error) do
new_detailed_error(
GRPC::Core::StatusCodes::NOT_FOUND,
'commits not found',
Gitaly::FindCommitsError.new(commit_error)
)
end
context 'with Gitaly::FindCommitsError contains Gitaly::AmbiguousReferenceError detail' do
let(:commit_error) do
{ ambiguous_ref: Gitaly::AmbiguousReferenceError.new(reference: 'non-existing-ref') }
context 'with Gitaly::FindCommitsError' do
let(:original_error) do
new_detailed_error(
GRPC::Core::StatusCodes::NOT_FOUND,
'commits not found',
Gitaly::FindCommitsError.new
)
end
it_behaves_like 'commit not found', 'ambiguous reference:non-existing-ref'
end
context 'with Gitaly::FindCommitsError contains Gitaly::BadObjectError detail' do
let(:commit_error) do
{ bad_object: Gitaly::BadObjectError.new(bad_oid: '0b4bc9a49b562e85de7cc9e834518ea6828729b9') }
it 'wraps the commit not found error' do
expect { wrapped_gitaly_errors }.to raise_error do |wrapped_error|
expect(wrapped_error).to be_a(Gitlab::Git::Repository::CommitNotFound)
end
end
it_behaves_like 'commit not found', 'bad object:0b4bc9a49b562e85de7cc9e834518ea6828729b9'
end
context 'with Gitaly::FindCommitsError contains Gitaly::InvalidRevisionRange detail' do
let(:commit_error) do
{ invalid_range: Gitaly::InvalidRevisionRange.new(range: '0b4bc9a49b562e85de7cc9e834518ea6828729b9') }
end
it_behaves_like 'commit not found', 'invalid range:0b4bc9a49b562e85de7cc9e834518ea6828729b9'
end
context 'with non Gitaly::FindCommitsError' do

View File

@ -128,7 +128,7 @@ RSpec.describe ::Gitlab::Graphql::Deprecations::Deprecation, feature_category: :
let(:options) { { reason: :renamed, milestone: '10.10', replacement: 'X.y' } }
it 'renders as reason-replacement-milestone' do
expect(deprecation.deprecation_reason).to eq('This was renamed. Please use `X.y`. Deprecated in 10.10.')
expect(deprecation.deprecation_reason).to eq('This was renamed. Please use `X.y`. Deprecated in GitLab 10.10.')
end
end
@ -136,7 +136,7 @@ RSpec.describe ::Gitlab::Graphql::Deprecations::Deprecation, feature_category: :
let(:options) { { reason: :renamed, milestone: '10.10' } }
it 'renders as reason-milestone' do
expect(deprecation.deprecation_reason).to eq('This was renamed. Deprecated in 10.10.')
expect(deprecation.deprecation_reason).to eq('This was renamed. Deprecated in GitLab 10.10.')
end
end
@ -167,7 +167,7 @@ RSpec.describe ::Gitlab::Graphql::Deprecations::Deprecation, feature_category: :
it 'appends milestone:reason with a leading space if there is a description' do
desc = deprecation.edit_description('Some description.')
expect(desc).to eq('Some description. Deprecated in 10.10: This was renamed.')
expect(desc).to eq('Some description. Deprecated in GitLab 10.10: This was renamed.')
end
it 'returns nil if there is no description' do
@ -179,7 +179,7 @@ RSpec.describe ::Gitlab::Graphql::Deprecations::Deprecation, feature_category: :
it 'strips any leading or trailing spaces' do
desc = deprecation.edit_description(" Some description. \n")
expect(desc).to eq('Some description. Deprecated in 10.10: This was renamed.')
expect(desc).to eq('Some description. Deprecated in GitLab 10.10: This was renamed.')
end
it 'strips any leading or trailing spaces in heredoc string literals' do
@ -190,7 +190,7 @@ RSpec.describe ::Gitlab::Graphql::Deprecations::Deprecation, feature_category: :
desc = deprecation.edit_description(description)
expect(desc).to eq("Lorem ipsum\ndolor sit amet. Deprecated in 10.10: This was renamed.")
expect(desc).to eq("Lorem ipsum\ndolor sit amet. Deprecated in GitLab 10.10: This was renamed.")
end
end
@ -208,7 +208,7 @@ RSpec.describe ::Gitlab::Graphql::Deprecations::Deprecation, feature_category: :
context 'when the context is :inline' do
it 'renders on one line' do
expectation = '**Deprecated** in 10.10. This was renamed. Use: [`X.y`](#xy).'
expectation = '**Deprecated** in GitLab 10.10. This was renamed. Use: [`X.y`](#xy).'
expect(deprecation.markdown).to eq(expectation)
expect(deprecation.markdown(context: :inline)).to eq(expectation)
@ -218,8 +218,8 @@ RSpec.describe ::Gitlab::Graphql::Deprecations::Deprecation, feature_category: :
context 'when the context is :block' do
it 'renders a warning note' do
expectation = <<~MD.chomp
NOTE:
**Deprecated** in 10.10.
DETAILS:
**Deprecated** in GitLab 10.10.
This was renamed.
Use: [`X.y`](#xy).
MD
@ -234,7 +234,7 @@ RSpec.describe ::Gitlab::Graphql::Deprecations::Deprecation, feature_category: :
context 'when the context is :inline' do
it 'renders on one line' do
expectation = '**Deprecated** in 10.10. Removed.'
expectation = '**Deprecated** in GitLab 10.10. Removed.'
expect(deprecation.markdown).to eq(expectation)
expect(deprecation.markdown(context: :inline)).to eq(expectation)
@ -244,8 +244,8 @@ RSpec.describe ::Gitlab::Graphql::Deprecations::Deprecation, feature_category: :
context 'when the context is :block' do
it 'renders a warning note' do
expectation = <<~MD.chomp
NOTE:
**Deprecated** in 10.10.
DETAILS:
**Deprecated** in GitLab 10.10.
Removed.
MD

View File

@ -447,7 +447,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer, feature_category: :i
aggregate_failures do
expect(pipeline_schedule.description).to eq('Schedule Description')
expect(pipeline_schedule.ref).to eq('master')
expect(pipeline_schedule.ref).to eq('refs/heads/master')
expect(pipeline_schedule.cron).to eq('0 4 * * 0')
expect(pipeline_schedule.cron_timezone).to eq('UTC')
expect(pipeline_schedule.active).to eq(false)

View File

@ -118,7 +118,7 @@ RSpec.describe Gitlab::Profiler do
it 'logs the backtrace, ignoring lines as appropriate' do
# Skip Rails's backtrace cleaning.
allow(Rails.backtrace_cleaner).to receive(:clean, &:itself)
allow(Gitlab::BacktraceCleaner.backtrace_cleaner).to receive(:clean, &:itself)
expect(custom_logger).to receive(:add)
.with(Logger::DEBUG,

View File

@ -3,9 +3,14 @@
require 'spec_helper'
RSpec.describe Ci::PipelineSchedule, feature_category: :continuous_integration do
let_it_be_with_reload(:project) { create_default(:project) }
let_it_be_with_reload(:project) { create_default(:project, :repository) }
let_it_be(:repository) { project.repository }
subject { build(:ci_pipeline_schedule) }
subject { build(:ci_pipeline_schedule, project: project) }
before do
stub_feature_flags(enforce_full_refs_for_pipeline_schedules: false)
end
it { is_expected.to belong_to(:project) }
it { is_expected.to belong_to(:owner) }
@ -25,31 +30,200 @@ RSpec.describe Ci::PipelineSchedule, feature_category: :continuous_integration d
it_behaves_like 'cleanup by a loose foreign key' do
let!(:parent) { create(:user) }
let!(:model) { create(:ci_pipeline_schedule, owner: parent) }
let!(:model) { create(:ci_pipeline_schedule, owner: parent, project: project) }
end
describe 'validations' do
it 'does not allow invalid cron patterns' do
pipeline_schedule = build(:ci_pipeline_schedule, cron: '0 0 0 * *')
pipeline_schedule = build(:ci_pipeline_schedule, cron: '0 0 0 * *', project: project)
expect(pipeline_schedule).not_to be_valid
end
it 'does not allow invalid cron patterns' do
pipeline_schedule = build(:ci_pipeline_schedule, cron_timezone: 'invalid')
pipeline_schedule = build(:ci_pipeline_schedule, cron_timezone: 'invalid', project: project)
expect(pipeline_schedule).not_to be_valid
end
it 'does not allow empty variable key' do
pipeline_schedule = build(:ci_pipeline_schedule, variables_attributes: [{ secret_value: 'test_value' }])
pipeline_schedule = build(:ci_pipeline_schedule,
variables_attributes: [{ secret_value: 'test_value' }],
project: project)
expect(pipeline_schedule).not_to be_valid
end
context 'when an short ref record is being updated' do
let(:new_description) { 'some description' }
let(:ref) { 'other' }
let(:pipeline_schedule) do
build(:ci_pipeline_schedule, cron: ' 0 0 * * * ', ref: ref, project: project)
end
before do
repository.add_branch(project.creator, ref, 'master')
pipeline_schedule.save!(validate: false)
end
it 'does not update the ref' do
pipeline_schedule.update!(description: new_description)
expect(pipeline_schedule.reload.ref).to eq(ref)
expect(pipeline_schedule.description).to eq(new_description)
end
end
context 'ref is branch and tag' do
let(:ref) { 'ambiguous' }
let(:pipeline_schedule) { build(:ci_pipeline_schedule, ref: ref, project: project) }
it 'allows ambiguous ref' do
pipeline_schedule.valid?
expect(pipeline_schedule.errors.full_messages)
.not_to include("Ref is ambiguous")
end
end
context 'ref is not a branch or tag' do
let(:ref) { 'unknown' }
let(:pipeline_schedule) { build(:ci_pipeline_schedule, ref: ref, project: project) }
it 'allows any ref' do
pipeline_schedule.valid?
expect(pipeline_schedule.errors.full_messages)
.not_to include("Ref is ambiguous")
end
end
context 'enforce_full_refs_for_pipeline_schedules is enabled' do
before do
stub_feature_flags(enforce_full_refs_for_pipeline_schedules: true)
end
context 'ref is invalid' do
let_it_be(:ref) { 'ambiguous' }
before_all do
repository.add_tag(project.creator, ref, 'master')
repository.add_branch(project.creator, ref, 'master')
end
context 'when an short ref record is being updated' do
let(:new_description) { 'some description' }
let(:ref) { 'other' }
let(:pipeline_schedule) do
build(:ci_pipeline_schedule, cron: ' 0 0 * * * ', ref: ref, project: project)
end
before do
repository.add_branch(project.creator, ref, 'master')
pipeline_schedule.save!(validate: false)
end
it 'updates the ref' do
pipeline_schedule.update!(description: new_description)
expect(pipeline_schedule.reload.ref).to eq("#{Gitlab::Git::BRANCH_REF_PREFIX}#{ref}")
expect(pipeline_schedule.description).to eq(new_description)
end
context 'when an existing record has no ref' do
let(:pipeline_schedule) do
build(:ci_pipeline_schedule,
cron: ' 0 0 * * * ',
ref: nil,
project: project,
importing: true)
end
it 'updates the record' do
pipeline_schedule.update!(description: new_description)
expect(pipeline_schedule.reload.description).to eq(new_description)
end
end
end
context 'ref is branch and tag' do
let(:pipeline_schedule) { build(:ci_pipeline_schedule, ref: ref, project: project) }
it 'does not allow ambiguous ref' do
pipeline_schedule.valid?
expect(pipeline_schedule.errors.full_messages)
.to include("Ref is ambiguous")
end
context 'importing is enabled' do
let(:pipeline_schedule) do
build(:ci_pipeline_schedule, ref: ref, project: project, importing: true)
end
it 'does not validate the ref' do
expect(pipeline_schedule)
.to be_valid
end
end
end
context 'ref is not a branch or tag' do
let(:ref) { 'unknown' }
let(:pipeline_schedule) { build(:ci_pipeline_schedule, ref: ref, project: project) }
it 'does not allow wrong ref' do
pipeline_schedule.valid?
expect(pipeline_schedule.errors.full_messages)
.to include("Ref is ambiguous")
end
context 'importing is enabled' do
let(:pipeline_schedule) do
build(:ci_pipeline_schedule, ref: ref, project: project, importing: true)
end
it 'does not validate the ref' do
expect(pipeline_schedule)
.to be_valid
end
end
end
end
context 'when an existing record has a valid ref' do
let(:new_description) { 'some description' }
let(:pipeline_schedule) do
build(:ci_pipeline_schedule, cron: ' 0 0 * * * ', project: project)
end
it 'updates the record' do
pipeline_schedule.update!(description: new_description)
expect(pipeline_schedule.reload.description).to eq(new_description)
end
end
context 'when a record is being created' do
let(:ref) { 'master' }
let(:pipeline_schedule) do
build(:ci_pipeline_schedule, cron: ' 0 0 * * * ', project: project, ref: ref)
end
before do
repository.add_branch(project.creator, ref, ref)
end
it 'expands the ref' do
pipeline_schedule.save!
expect(pipeline_schedule.ref).to eq("#{Gitlab::Git::BRANCH_REF_PREFIX}#{ref}")
end
end
end
context 'when active is false' do
it 'does not allow nullified ref' do
pipeline_schedule = build(:ci_pipeline_schedule, :inactive, ref: nil)
pipeline_schedule = build(:ci_pipeline_schedule, :inactive, ref: nil, project: project)
expect(pipeline_schedule).not_to be_valid
end
@ -57,7 +231,7 @@ RSpec.describe Ci::PipelineSchedule, feature_category: :continuous_integration d
context 'when cron contains trailing whitespaces' do
it 'strips the attribute' do
pipeline_schedule = build(:ci_pipeline_schedule, cron: ' 0 0 * * * ')
pipeline_schedule = build(:ci_pipeline_schedule, cron: ' 0 0 * * * ', project: project)
expect(pipeline_schedule).to be_valid
expect(pipeline_schedule.cron).to eq('0 0 * * *')
@ -70,7 +244,7 @@ RSpec.describe Ci::PipelineSchedule, feature_category: :continuous_integration d
let!(:pipeline_schedule) do
travel_to(1.day.ago) do
create(:ci_pipeline_schedule, :hourly)
create(:ci_pipeline_schedule, :hourly, project: project)
end
end
@ -91,7 +265,7 @@ RSpec.describe Ci::PipelineSchedule, feature_category: :continuous_integration d
subject { described_class.preloaded }
before do
create_list(:ci_pipeline_schedule, 3)
create_list(:ci_pipeline_schedule, 3, project: project)
end
it 'preloads the associations' do
@ -105,8 +279,8 @@ RSpec.describe Ci::PipelineSchedule, feature_category: :continuous_integration d
describe '.owned_by' do
let(:user) { create(:user) }
let!(:owned_pipeline_schedule) { create(:ci_pipeline_schedule, owner: user) }
let!(:other_pipeline_schedule) { create(:ci_pipeline_schedule) }
let!(:owned_pipeline_schedule) { create(:ci_pipeline_schedule, owner: user, project: project) }
let!(:other_pipeline_schedule) { create(:ci_pipeline_schedule, project: project) }
subject { described_class.owned_by(user) }
@ -116,7 +290,6 @@ RSpec.describe Ci::PipelineSchedule, feature_category: :continuous_integration d
end
describe '.for_project' do
let(:project) { create(:project) }
let!(:project_pipeline_schedule) { create(:ci_pipeline_schedule, project: project) }
let!(:other_pipeline_schedule) { create(:ci_pipeline_schedule) }
@ -129,7 +302,7 @@ RSpec.describe Ci::PipelineSchedule, feature_category: :continuous_integration d
describe '#set_next_run_at' do
let(:now) { Time.zone.local(2021, 3, 2, 1, 0) }
let(:pipeline_schedule) { create(:ci_pipeline_schedule, cron: "0 1 * * *") }
let(:pipeline_schedule) { create(:ci_pipeline_schedule, cron: "0 1 * * *", project: project) }
it 'calls fallback method next_run_at if there is no plan limit' do
allow(Settings).to receive(:cron_jobs).and_return({ 'pipeline_schedule_worker' => { 'cron' => "0 1 2 3 *" } })
@ -144,8 +317,13 @@ RSpec.describe Ci::PipelineSchedule, feature_category: :continuous_integration d
end
context 'when there are two different pipeline schedules in different time zones' do
let(:pipeline_schedule_1) { create(:ci_pipeline_schedule, :weekly, cron_timezone: 'Eastern Time (US & Canada)') }
let(:pipeline_schedule_2) { create(:ci_pipeline_schedule, :weekly, cron_timezone: 'UTC') }
let(:pipeline_schedule_1) do
create(:ci_pipeline_schedule, :weekly, cron_timezone: 'Eastern Time (US & Canada)', project: project)
end
let(:pipeline_schedule_2) do
create(:ci_pipeline_schedule, :weekly, cron_timezone: 'UTC', project: project)
end
it 'sets different next_run_at' do
expect(pipeline_schedule_1.next_run_at).not_to eq(pipeline_schedule_2.next_run_at)
@ -154,7 +332,7 @@ RSpec.describe Ci::PipelineSchedule, feature_category: :continuous_integration d
end
describe '#schedule_next_run!' do
let!(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly) }
let!(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly, project: project) }
before do
pipeline_schedule.update_column(:next_run_at, nil)
@ -179,7 +357,7 @@ RSpec.describe Ci::PipelineSchedule, feature_category: :continuous_integration d
end
describe '#job_variables' do
let!(:pipeline_schedule) { create(:ci_pipeline_schedule) }
let!(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project) }
let!(:pipeline_schedule_variables) do
create_list(:ci_pipeline_schedule_variable, 2, pipeline_schedule: pipeline_schedule)
@ -289,13 +467,13 @@ RSpec.describe Ci::PipelineSchedule, feature_category: :continuous_integration d
context 'loose foreign key on ci_pipeline_schedules.project_id' do
it_behaves_like 'cleanup by a loose foreign key' do
let!(:parent) { create(:project) }
let_it_be(:parent) { create(:project, :repository) }
let!(:model) { create(:ci_pipeline_schedule, project: parent) }
end
end
describe 'before_destroy' do
let_it_be_with_reload(:pipeline_schedule) { create(:ci_pipeline_schedule, cron: ' 0 0 * * * ') }
let_it_be_with_reload(:pipeline_schedule) { create(:ci_pipeline_schedule, cron: ' 0 0 * * * ', project: project) }
let_it_be_with_reload(:pipeline) { create(:ci_pipeline, pipeline_schedule: pipeline_schedule) }
it 'nullifys associated pipelines' do

View File

@ -28,9 +28,8 @@ RSpec.describe CommitCollection, feature_category: :source_code_management do
end
context 'when is with_merge_commits false' do
let(:commit) { project.commit("60ecb67744cb56576c30214ff52294f8ce2def98") }
it 'excludes authors of merge commits' do
commit = project.commit("60ecb67744cb56576c30214ff52294f8ce2def98")
create(:user, email: commit.committer_email.upcase)
expect(collection.committers).to be_empty

View File

@ -2053,10 +2053,10 @@ RSpec.describe MergeRequest, factory_default: :keep, feature_category: :code_rev
let(:commits) { double }
let(:committers) { double }
context 'when not given with_merge_commits and lazy' do
context 'when not given with_merge_commits' do
it 'calls committers on the commits object with the expected param' do
expect(subject).to receive(:commits).and_return(commits)
expect(commits).to receive(:committers).with(with_merge_commits: false, lazy: false).and_return(committers)
expect(commits).to receive(:committers).with(with_merge_commits: false).and_return(committers)
expect(subject.committers).to eq(committers)
end
@ -2065,20 +2065,11 @@ RSpec.describe MergeRequest, factory_default: :keep, feature_category: :code_rev
context 'when given with_merge_commits true' do
it 'calls committers on the commits object with the expected param' do
expect(subject).to receive(:commits).and_return(commits)
expect(commits).to receive(:committers).with(with_merge_commits: true, lazy: false).and_return(committers)
expect(commits).to receive(:committers).with(with_merge_commits: true).and_return(committers)
expect(subject.committers(with_merge_commits: true)).to eq(committers)
end
end
context 'when given lazy true' do
it 'calls committers on the commits object with the expected param' do
expect(subject).to receive(:commits).and_return(commits)
expect(commits).to receive(:committers).with(with_merge_commits: false, lazy: true).and_return(committers)
expect(subject.committers(lazy: true)).to eq(committers)
end
end
end
describe '#diverged_commits_count' do

View File

@ -45,7 +45,7 @@ RSpec.describe 'PipelineSchedulecreate', feature_category: :continuous_integrati
description: 'created_desc',
cron: '0 1 * * *',
cronTimezone: 'UTC',
ref: 'patch-x',
ref: 'master',
active: true,
variables: [
{ key: 'AAA', value: "AAA123", variableType: 'ENV_VAR' }
@ -107,7 +107,11 @@ RSpec.describe 'PipelineSchedulecreate', feature_category: :continuous_integrati
expect(mutation_response['errors'])
.to match_array(
["Cron is invalid syntax", "Cron timezone is invalid syntax"]
[
"Cron is invalid syntax",
"Cron timezone is invalid syntax",
"Ref is ambiguous"
]
)
end
end

View File

@ -17,6 +17,7 @@ RSpec.describe 'PipelineScheduleUpdate', feature_category: :continuous_integrati
create(:ci_pipeline_schedule_variable, key: 'bar', value: 'barvalue', pipeline_schedule: pipeline_schedule)
end
let(:repository) { project.repository }
let(:mutation) do
variables = {
id: pipeline_schedule.to_global_id.to_s,
@ -50,6 +51,10 @@ RSpec.describe 'PipelineScheduleUpdate', feature_category: :continuous_integrati
let(:pipeline_schedule_parameters) { {} }
let(:mutation_response) { graphql_mutation_response(:pipeline_schedule_update) }
before do
stub_feature_flags(enforce_full_refs_for_pipeline_schedules: false)
end
context 'when unauthorized' do
it_behaves_like 'a mutation on an unauthorized resource'
end
@ -73,6 +78,10 @@ RSpec.describe 'PipelineScheduleUpdate', feature_category: :continuous_integrati
}
end
before do
repository.add_branch(project.creator, 'patch-x', 'master')
end
it do
post_graphql_mutation(mutation, current_user: current_user)
@ -135,7 +144,30 @@ RSpec.describe 'PipelineScheduleUpdate', feature_category: :continuous_integrati
}
end
it do
context 'when enforce_full_refs_for_pipeline_schedules is enabled' do
before do
stub_feature_flags(enforce_full_refs_for_pipeline_schedules: true)
end
it 'returns the errors' do
post_graphql_mutation(mutation, current_user: current_user)
expect(response).to have_gitlab_http_status(:success)
expect(mutation_response['errors'])
.to match_array(
[
"Cron is invalid syntax",
"Cron timezone is invalid syntax",
"Ref can't be blank",
"Description can't be blank",
"Ref is ambiguous"
]
)
end
end
it 'returns the errors' do
post_graphql_mutation(mutation, current_user: current_user)
expect(response).to have_gitlab_http_status(:success)

View File

@ -64,4 +64,14 @@ RSpec.describe RuboCop::BatchedBackgroundMigrationsDictionary, feature_category:
expect(described_class.new('random').finalize_after).to be_nil
end
end
describe '.checksum' do
let(:dictionary_data) { { c: "d", a: "b" } }
it 'returns a checksum of the dictionary_data' do
allow(described_class).to receive(:dictionary_data).and_return(dictionary_data)
expect(described_class.checksum).to eq(Digest::SHA256.hexdigest(dictionary_data.to_s))
end
end
end

View File

@ -227,4 +227,12 @@ RSpec.describe RuboCop::Cop::BackgroundMigration::DictionaryFile, feature_catego
end
end
end
describe '#external_dependency_checksum' do
it 'uses the RuboCop::BatchedBackgroundMigrationsDictionary.checksum' do
allow(RuboCop::BatchedBackgroundMigrationsDictionary).to receive(:checksum).and_return('aaaaa')
expect(cop.external_dependency_checksum).to eq('aaaaa')
end
end
end

View File

@ -6,6 +6,7 @@ RSpec.describe Ci::PipelineSchedules::CreateService, feature_category: :continuo
let_it_be(:reporter) { create(:user) }
let_it_be_with_reload(:user) { create(:user) }
let_it_be_with_reload(:project) { create(:project, :public, :repository) }
let_it_be_with_reload(:repository) { project.repository }
subject(:service) { described_class.new(project, user, params) }
@ -14,7 +15,15 @@ RSpec.describe Ci::PipelineSchedules::CreateService, feature_category: :continuo
project.add_reporter(reporter)
end
before do
stub_feature_flags(enforce_full_refs_for_pipeline_schedules: false)
end
describe "execute" do
before_all do
repository.add_branch(project.creator, 'patch-x', 'master')
end
context 'when user does not have permission' do
subject(:service) { described_class.new(project, reporter, {}) }
@ -43,12 +52,30 @@ RSpec.describe Ci::PipelineSchedules::CreateService, feature_category: :continuo
subject(:service) { described_class.new(project, user, params) }
context 'when enforce_full_refs_for_pipeline_schedules is enabled' do
before do
stub_feature_flags(enforce_full_refs_for_pipeline_schedules: true)
end
it 'saves values with passed params' do
result = service.execute
expect(result.payload).to have_attributes(
description: 'desc',
ref: "#{Gitlab::Git::BRANCH_REF_PREFIX}patch-x",
active: false,
cron: '*/1 * * * *',
cron_timezone: 'UTC'
)
end
end
it 'saves values with passed params' do
result = service.execute
expect(result.payload).to have_attributes(
description: 'desc',
ref: 'patch-x',
ref: "patch-x",
active: false,
cron: '*/1 * * * *',
cron_timezone: 'UTC'

View File

@ -14,14 +14,21 @@ RSpec.describe Ci::PipelineSchedules::UpdateService, feature_category: :continuo
key: 'foo', value: 'foovalue', pipeline_schedule: pipeline_schedule)
end
let_it_be_with_reload(:repository) { project.repository }
before_all do
project.add_maintainer(user)
project.add_owner(project_owner)
project.add_reporter(reporter)
repository.add_branch(project.creator, 'patch-x', 'master')
pipeline_schedule.reload
end
before do
stub_feature_flags(enforce_full_refs_for_pipeline_schedules: false)
end
describe "execute" do
context 'when user does not have permission' do
subject(:service) { described_class.new(pipeline_schedule, reporter, {}) }
@ -53,16 +60,55 @@ RSpec.describe Ci::PipelineSchedules::UpdateService, feature_category: :continuo
subject(:service) { described_class.new(pipeline_schedule, user, params) }
context 'when enforce_full_refs_for_pipeline_schedules is enabled' do
before do
stub_feature_flags(enforce_full_refs_for_pipeline_schedules: true)
end
it 'updates database values with passed params' do
expect do
service.execute
pipeline_schedule.reload
end.to change { pipeline_schedule.description }
.from('pipeline schedule').to('updated_desc')
.and change { pipeline_schedule.ref }
.from("#{Gitlab::Git::BRANCH_REF_PREFIX}master")
.to("#{Gitlab::Git::BRANCH_REF_PREFIX}patch-x")
.and change {
pipeline_schedule.active
}.from(true).to(false)
.and change {
pipeline_schedule.cron
}.from('0 1 * * *').to('*/1 * * * *')
.and change {
pipeline_schedule.variables.last.key
}.from('foo').to('bar')
.and change {
pipeline_schedule.variables.last.value
}.from('foovalue').to('barvalue')
end
end
it 'updates database values with passed params' do
expect do
service.execute
pipeline_schedule.reload
end.to change { pipeline_schedule.description }.from('pipeline schedule').to('updated_desc')
.and change { pipeline_schedule.ref }.from('master').to('patch-x')
.and change { pipeline_schedule.active }.from(true).to(false)
.and change { pipeline_schedule.cron }.from('0 1 * * *').to('*/1 * * * *')
.and change { pipeline_schedule.variables.last.key }.from('foo').to('bar')
.and change { pipeline_schedule.variables.last.value }.from('foovalue').to('barvalue')
end.to change { pipeline_schedule.description }
.from('pipeline schedule').to('updated_desc')
.and change { pipeline_schedule.ref }
.from("#{Gitlab::Git::BRANCH_REF_PREFIX}master").to("patch-x")
.and change {
pipeline_schedule.active
}.from(true).to(false)
.and change {
pipeline_schedule.cron
}.from('0 1 * * *').to('*/1 * * * *')
.and change {
pipeline_schedule.variables.last.key
}.from('foo').to('bar')
.and change {
pipeline_schedule.variables.last.value
}.from('foovalue').to('barvalue')
end
context 'when the new branch is protected', :request_store do

View File

@ -13,13 +13,32 @@ RSpec.shared_examples 'pipeline schedules checking variables permission' do
end
shared_examples 'success response' do
context 'when enforce_full_refs_for_pipeline_schedules is enabled' do
before do
stub_feature_flags(enforce_full_refs_for_pipeline_schedules: true)
end
it 'saves values with passed params' do
result = service.execute
expect(result.status).to eq(:success)
expect(result.payload).to have_attributes(
description: 'desc',
ref: "#{Gitlab::Git::BRANCH_REF_PREFIX}patch-x",
active: false,
cron: '*/1 * * * *',
cron_timezone: 'UTC'
)
end
end
it 'saves values with passed params' do
result = service.execute
expect(result.status).to eq(:success)
expect(result.payload).to have_attributes(
description: 'desc',
ref: 'patch-x',
ref: "patch-x",
active: false,
cron: '*/1 * * * *',
cron_timezone: 'UTC'

View File

@ -31,7 +31,7 @@ RSpec.shared_examples 'Gitlab-style deprecations' do
it 'adds a formatted `deprecated_reason` to the subject' do
deprecable = subject(deprecated: { milestone: '1.10', reason: 'Deprecation reason' })
expect(deprecable.deprecation_reason).to eq('Deprecation reason. Deprecated in 1.10.')
expect(deprecable.deprecation_reason).to eq('Deprecation reason. Deprecated in GitLab 1.10.')
end
it 'appends to the description if given' do
@ -40,7 +40,7 @@ RSpec.shared_examples 'Gitlab-style deprecations' do
description: 'Deprecable description.'
)
expect(deprecable.description).to eq('Deprecable description. Deprecated in 1.10: Deprecation reason.')
expect(deprecable.description).to eq('Deprecable description. Deprecated in GitLab 1.10: Deprecation reason.')
end
it 'does not append to the description if it is absent' do
@ -58,14 +58,14 @@ RSpec.shared_examples 'Gitlab-style deprecations' do
it 'supports named reasons: renamed' do
deprecable = subject(deprecated: { milestone: '1.10', reason: :renamed })
expect(deprecable.deprecation_reason).to eq('This was renamed. Deprecated in 1.10.')
expect(deprecable.deprecation_reason).to eq('This was renamed. Deprecated in GitLab 1.10.')
end
it 'supports :alpha' do
deprecable = subject(alpha: { milestone: '1.10' })
expect(deprecable.deprecation_reason).to eq(
'**Status**: Experiment. Introduced in 1.10.'
'**Status**: Experiment. Introduced in GitLab 1.10.'
)
end

View File

@ -1,5 +1,6 @@
# frozen_string_literal: true
require 'spec_helper'
require_relative '../../../../tooling/graphql/docs/renderer'
RSpec.describe Tooling::Graphql::Docs::Renderer do
@ -243,7 +244,7 @@ RSpec.describe Tooling::Graphql::Docs::Renderer do
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="deprecatedtestfoofooarg"></a>`fooArg` **{warning-solid}** | [`String`](#string) | **Deprecated** in 101.2. Bad argument. |
| <a id="deprecatedtestfoofooarg"></a>`fooArg` **{warning-solid}** | [`String`](#string) | **Deprecated** in GitLab 101.2. Bad argument. |
DOC
end
@ -290,8 +291,8 @@ RSpec.describe Tooling::Graphql::Docs::Renderer do
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="deprecatedtestbar"></a>`bar` **{warning-solid}** | [`String!`](#string) | **Deprecated** in 1.10. This was renamed. Use: [`Query.boom`](#queryboom). |
| <a id="deprecatedtestfoo"></a>`foo` **{warning-solid}** | [`String!`](#string) | **Deprecated** in 1.10. This is deprecated. |
| <a id="deprecatedtestbar"></a>`bar` **{warning-solid}** | [`String!`](#string) | **Deprecated** in GitLab 1.10. This was renamed. Use: [`Query.boom`](#queryboom). |
| <a id="deprecatedtestfoo"></a>`foo` **{warning-solid}** | [`String!`](#string) | **Deprecated** in GitLab 1.10. This is deprecated. |
#### Fields with arguments
@ -299,8 +300,8 @@ RSpec.describe Tooling::Graphql::Docs::Renderer do
A description.
NOTE:
**Deprecated** in 1.10.
DETAILS:
**Deprecated** in GitLab 1.10.
Do not use.
Use: [`X.y`](#xy).
@ -335,8 +336,8 @@ RSpec.describe Tooling::Graphql::Docs::Renderer do
A bar.
NOTE:
**Deprecated** in 10.11.
DETAILS:
**Deprecated** in GitLab 10.11.
This was renamed.
Use: [`Query.foo`](#queryfoo).
@ -377,7 +378,7 @@ RSpec.describe Tooling::Graphql::Docs::Renderer do
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="alphatestfoofooarg"></a>`fooArg` **{warning-solid}** | [`String`](#string) | **Introduced** in 101.2. **Status**: Experiment. Argument description. |
| <a id="alphatestfoofooarg"></a>`fooArg` **{warning-solid}** | [`String`](#string) | **Introduced** in GitLab 101.2. **Status**: Experiment. Argument description. |
DOC
end
@ -415,7 +416,7 @@ RSpec.describe Tooling::Graphql::Docs::Renderer do
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="alphatestfoo"></a>`foo` **{warning-solid}** | [`String!`](#string) | **Introduced** in 1.10. **Status**: Experiment. A description. |
| <a id="alphatestfoo"></a>`foo` **{warning-solid}** | [`String!`](#string) | **Introduced** in GitLab 1.10. **Status**: Experiment. A description. |
#### Fields with arguments
@ -423,8 +424,8 @@ RSpec.describe Tooling::Graphql::Docs::Renderer do
A description.
NOTE:
**Introduced** in 1.10.
DETAILS:
**Introduced** in GitLab 1.10.
**Status**: Experiment.
Returns [`String!`](#string).
@ -458,8 +459,8 @@ RSpec.describe Tooling::Graphql::Docs::Renderer do
A bar.
NOTE:
**Introduced** in 10.11.
DETAILS:
**Introduced** in GitLab 10.11.
**Status**: Experiment.
Returns [`Int`](#int).
@ -500,9 +501,9 @@ RSpec.describe Tooling::Graphql::Docs::Renderer do
| Value | Description |
| ----- | ----------- |
| <a id="myenumbar"></a>`BAR` **{warning-solid}** | **Deprecated** in 1.10. This is deprecated. |
| <a id="myenumbar"></a>`BAR` **{warning-solid}** | **Deprecated** in GitLab 1.10. This is deprecated. |
| <a id="myenumbaz"></a>`BAZ` | A description of BAZ. |
| <a id="myenumboop"></a>`BOOP` **{warning-solid}** | **Deprecated** in 1.10. This was renamed. Use: [`MyEnum.BAR`](#myenumbar). |
| <a id="myenumboop"></a>`BOOP` **{warning-solid}** | **Deprecated** in GitLab 1.10. This was renamed. Use: [`MyEnum.BAR`](#myenumbar). |
DOC
end
@ -611,7 +612,7 @@ RSpec.describe Tooling::Graphql::Docs::Renderer do
| ---- | ---- | ----------- |
| <a id="mutationmakeitprettyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationmakeitprettyprettinessfactor"></a>`prettinessFactor` | [`Float!`](#float) | How much prettier?. |
| <a id="mutationmakeitprettypulchritude"></a>`pulchritude` **{warning-solid}** | [`Float`](#float) | **Deprecated:** This was renamed. Please use `prettinessFactor`. Deprecated in 72.34. |
| <a id="mutationmakeitprettypulchritude"></a>`pulchritude` **{warning-solid}** | [`Float`](#float) | **Deprecated:** This was renamed. Please use `prettinessFactor`. Deprecated in GitLab 72.34. |
#### Fields
@ -620,7 +621,7 @@ RSpec.describe Tooling::Graphql::Docs::Renderer do
| <a id="mutationmakeitprettyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationmakeitprettyerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationmakeitprettyeverything"></a>`everything` | [`String`](#string) | What we made prettier. |
| <a id="mutationmakeitprettyomnis"></a>`omnis` **{warning-solid}** | [`String`](#string) | **Deprecated:** This was renamed. Please use `everything`. Deprecated in 72.34. |
| <a id="mutationmakeitprettyomnis"></a>`omnis` **{warning-solid}** | [`String`](#string) | **Deprecated:** This was renamed. Please use `everything`. Deprecated in GitLab 72.34. |
DOC
end
end

View File

@ -9,7 +9,7 @@ RSpec.describe RunPipelineScheduleWorker, feature_category: :continuous_integrat
describe '#perform' do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, namespace: group) }
let_it_be(:project) { create(:project, :repository, namespace: group) }
let_it_be(:user) { create(:user) }
let_it_be(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly, project: project ) }

View File

@ -7,25 +7,25 @@ PATH
GEM
remote: https://rubygems.org/
specs:
actionpack (7.0.8)
actionview (= 7.0.8)
activesupport (= 7.0.8)
actionpack (7.0.8.1)
actionview (= 7.0.8.1)
activesupport (= 7.0.8.1)
rack (~> 2.0, >= 2.2.4)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actionview (7.0.8)
activesupport (= 7.0.8)
actionview (7.0.8.1)
activesupport (= 7.0.8.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activemodel (7.0.8)
activesupport (= 7.0.8)
activerecord (7.0.8)
activemodel (= 7.0.8)
activesupport (= 7.0.8)
activesupport (7.0.8)
activemodel (7.0.8.1)
activesupport (= 7.0.8.1)
activerecord (7.0.8.1)
activemodel (= 7.0.8.1)
activesupport (= 7.0.8.1)
activesupport (7.0.8.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
@ -35,7 +35,7 @@ GEM
builder (3.2.4)
codeclimate-test-reporter (0.6.0)
simplecov (>= 0.7.1, < 1.0.0)
concurrent-ruby (1.2.2)
concurrent-ruby (1.2.3)
crass (1.0.6)
data_objects (0.10.17)
addressable (~> 2.1)
@ -54,7 +54,7 @@ GEM
erubi (1.12.0)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
loofah (2.21.3)
loofah (2.22.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mini_portile2 (2.8.0)
@ -63,8 +63,8 @@ GEM
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
public_suffix (5.0.0)
racc (1.7.1)
rack (2.2.8)
racc (1.7.3)
rack (2.2.8.1)
rack-test (2.1.0)
rack (>= 1.3)
rails-dom-testing (2.2.0)
@ -93,8 +93,8 @@ PLATFORMS
ruby
DEPENDENCIES
actionpack (~> 7.0.8)
activerecord (~> 7.0.8)
actionpack (~> 7.0.8.1)
activerecord (~> 7.0.8.1)
attr_encrypted!
codeclimate-test-reporter (<= 0.6.0)
dm-sqlite-adapter

View File

@ -29,7 +29,7 @@ Forked from https://github.com/attr-encrypted/attr_encrypted."
s.add_dependency('encryptor', ['~> 3.0.0'])
activerecord_version = "~> 7.0.8"
activerecord_version = "~> 7.0.8.1"
s.add_development_dependency('activerecord', activerecord_version)
s.add_development_dependency('actionpack', activerecord_version)
s.add_development_dependency('rake')

View File

@ -1905,15 +1905,15 @@
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.5.tgz#db5a11bf66bdab39569719555b0f76e138d7bd64"
integrity sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==
"@rails/actioncable@7.0.8":
version "7.0.8"
resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-7.0.8.tgz#f44e7517f2d1570f1eabeea457dbeb17ed3a2d12"
integrity sha512-GjYQv89ZOOfbFw8VMNUOG33GXzyAA/TCVoD+742Ob4svm1XXUkd+w+ewqUXd+7VHQtV35y1/O78AGIPeJDTy/g==
"@rails/actioncable@7.0.8-1":
version "7.0.8-1"
resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-7.0.8-1.tgz#aa45d584ca316474411e44df2fb3c1fb268d0e48"
integrity sha512-d9dl+IWhYg0fozbsE0imewWEx6EpnRP3SDfdF4vwLdWJKLXZKOKJ6AiCKEvsratabS/COyxVHajuW3n5f1JlFA==
"@rails/ujs@7.0.8":
version "7.0.8"
resolved "https://registry.yarnpkg.com/@rails/ujs/-/ujs-7.0.8.tgz#59853367d0827b3955d2c4bedfd5eba4a79d3422"
integrity sha512-tOQQBVH8LsUpGXqDnk+kaOGVsgZ8maHAhEiw3Git3p88q+c0Slgu47HuDnL6sVxeCfz24zbq7dOjsVYDiTpDIA==
"@rails/ujs@7.0.8-1":
version "7.0.8-1"
resolved "https://registry.yarnpkg.com/@rails/ujs/-/ujs-7.0.8-1.tgz#4156942025aa6b016d3d9a7df3e542ac962359e2"
integrity sha512-uZRCeEl6zY/9JvjTpQilbJyBqFr4onNJTkQTJgfsXDZPJyqCAvyGGraO0LaiHvWKNqD1fTRamdSYg/l+U7daVA==
"@remirror/core-constants@^2.0.0":
version "2.0.0"