Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot
2023-11-17 03:13:50 +00:00
parent e7ddd83a44
commit eac5de0317
20 changed files with 333 additions and 162 deletions

View File

@ -29,8 +29,10 @@ import {
EVENT_ACTION,
EXPANDED_VARIABLES_NOTE,
FLAG_LINK_TITLE,
MASKED_VALUE_MIN_LENGTH,
VARIABLE_ACTIONS,
variableOptions,
WHITESPACE_REG_EX,
} from '../constants';
import CiEnvironmentsDropdown from './ci_environments_dropdown.vue';
import { awsTokenList } from './ci_variable_autocomplete_tokens';
@ -54,21 +56,30 @@ export const i18n = {
maskedDescription: s__(
'CiVariables|Variable will be masked in job logs. Requires values to meet regular expression requirements.',
),
maskedValueMinLengthValidationText: s__(
'CiVariables|The value must have at least %{charsAmount} characters.',
),
modalDeleteMessage: s__('CiVariables|Do you want to delete the variable %{key}?'),
protectedField: s__('CiVariables|Protect variable'),
protectedDescription: s__(
'CiVariables|Export variable to pipelines running on protected branches and tags only.',
),
unsupportedCharsValidationText: s__(
'CiVariables|This value cannot be masked because it contains the following characters: %{unsupportedChars}.',
),
unsupportedAndWhitespaceCharsValidationText: s__(
'CiVariables|This value cannot be masked because it contains the following characters: %{unsupportedChars} and whitespace characters.',
),
valueFeedback: {
rawHelpText: s__('CiVariables|Variable value will be evaluated as raw string.'),
maskedReqsNotMet: s__(
'CiVariables|This variable value does not meet the masking requirements.',
),
},
variableReferenceTitle: s__('CiVariables|Value might contain a variable reference'),
variableReferenceDescription: s__(
'CiVariables|Unselect "Expand variable reference" if you want to use the variable value as a raw string.',
),
whitespaceCharsValidationText: s__(
'CiVariables|This value cannot be masked because it contains the following characters: whitespace characters.',
),
type: __('Type'),
value: __('Value'),
};
@ -169,11 +180,76 @@ export default {
isEditing() {
return this.mode === EDIT_VARIABLE_ACTION;
},
isMaskedValueContainsWhitespaceChars() {
return this.isValueMaskable && WHITESPACE_REG_EX.test(this.variable.value);
},
maskedRegexToUse() {
return this.variable.raw ? this.maskableRawRegex : this.maskableRegex;
},
maskedReqsNotMetText() {
return !this.isMaskedReqsMet ? this.$options.i18n.valueFeedback.maskedReqsNotMet : '';
maskedSupportedCharsRegEx() {
const supportedChars = this.maskedRegexToUse.replace('^', '').replace(/{(\d,)}\$/, '');
return new RegExp(supportedChars, 'g');
},
maskedValueMinLengthValidationText() {
return sprintf(this.$options.i18n.maskedValueMinLengthValidationText, {
charsAmount: MASKED_VALUE_MIN_LENGTH,
});
},
unsupportedCharsList() {
if (this.isMaskedReqsMet) {
return [];
}
return [
...new Set(
this.variable.value
.replace(WHITESPACE_REG_EX, '')
.replace(this.maskedSupportedCharsRegEx, '')
.split(''),
),
];
},
unsupportedChars() {
return this.unsupportedCharsList.join(', ');
},
unsupportedCharsValidationText() {
return sprintf(
this.$options.i18n.unsupportedCharsValidationText,
{
unsupportedChars: this.unsupportedChars,
},
false,
);
},
unsupportedAndWhitespaceCharsValidationText() {
return sprintf(
this.$options.i18n.unsupportedAndWhitespaceCharsValidationText,
{
unsupportedChars: this.unsupportedChars,
},
false,
);
},
maskedValidationIssuesText() {
if (this.isMaskedReqsMet) {
return '';
}
let validationIssuesText = '';
if (this.unsupportedCharsList.length && !this.isMaskedValueContainsWhitespaceChars) {
validationIssuesText = this.unsupportedCharsValidationText;
} else if (this.unsupportedCharsList.length && this.isMaskedValueContainsWhitespaceChars) {
validationIssuesText = this.unsupportedAndWhitespaceCharsValidationText;
} else if (!this.unsupportedCharsList.length && this.isMaskedValueContainsWhitespaceChars) {
validationIssuesText = this.$options.i18n.whitespaceCharsValidationText;
}
if (this.variable.value.length < MASKED_VALUE_MIN_LENGTH) {
validationIssuesText += ` ${this.maskedValueMinLengthValidationText}`;
}
return validationIssuesText.trim();
},
modalActionText() {
return this.isEditing ? this.$options.i18n.editVariable : this.$options.i18n.addVariable;
@ -218,9 +294,7 @@ export default {
let property;
if (this.isValueMaskable) {
const supportedChars = this.maskedRegexToUse.replace('^', '').replace(/{(\d,)}\$/, '');
const regex = new RegExp(supportedChars, 'g');
property = this.variable.value.replace(regex, '');
property = this.variable.value.replace(this.maskedSupportedCharsRegEx, '');
} else if (this.hasVariableReference) {
property = '$';
}
@ -382,7 +456,7 @@ export default {
label-for="ci-variable-value"
class="gl-border-none gl-mb-n2"
data-testid="ci-variable-value-label"
:invalid-feedback="maskedReqsNotMetText"
:invalid-feedback="maskedValidationIssuesText"
:state="isValueValid"
>
<gl-form-textarea

View File

@ -2,6 +2,10 @@ import { __, s__, sprintf } from '~/locale';
export const ENVIRONMENT_QUERY_LIMIT = 30;
export const MASKED_VALUE_MIN_LENGTH = 8;
export const WHITESPACE_REG_EX = /\s/;
export const SORT_DIRECTIONS = {
ASC: 'KEY_ASC',
DESC: 'KEY_DESC',

View File

@ -25,7 +25,7 @@
input_name: 'project[namespace_id]',
root_url: root_url,
track_label: track_label,
user_namespace_id: current_user.namespace.id } }
user_namespace_id: current_user.namespace_id } }
- else
.input-group-prepend.static-namespace.flex-shrink-0.has-tooltip{ title: user_url(current_user.username) + '/' }
.input-group-text.border-0

View File

@ -1,8 +1,8 @@
---
name: import_fallback_to_db_empty_cache
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133914
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/428700
milestone: '16.6'
name: use_500_page_size_for_contribution_analytics
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/136724
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/431595
milestone: '16.7'
type: development
group: group::import and integrate
group: group::optimize
default_enabled: false

View File

@ -204,11 +204,118 @@ If you have to clean up a nullable column for a [high-traffic table](../migratio
it needs an additional [batched background migration cleaning up](batched_background_migrations.md#cleaning-up-a-batched-background-migration)
in the release after adding the data migration.
In that rare case you need 3 releases end-to-end:
In this case the number of releases depends on the amount of time needed to migrate existing records. The cleanup is
scheduled after the background migration has completed, which could be several releases after the constraint was added.
1. Release `N.M` - Add the `NOT NULL` constraint and the background-migration to fix the existing records.
1. Release `N.M+1` - Cleanup the background migration.
1. Release `N.M+2` - Validate the `NOT NULL` constraint.
1. Release `N.M`:
- Add the `NOT NULL` constraint without validating it:
```ruby
# db/post_migrate/
class AddMergeRequestDiffsProjectIdNotNullConstraint < Gitlab::Database::Migration[2.2]
disable_ddl_transaction!
milestone '16.7'
def up
add_not_null_constraint :merge_request_diffs, :project_id, validate: false
end
def down
remove_not_null_constraint :merge_request_diffs, :project_id
end
end
```
- Add the background-migration to fix the existing records:
```ruby
# db/post_migrate/
class QueueBackfillMergeRequestDiffsProjectId < Gitlab::Database::Migration[2.2]
milestone '16.7'
restrict_gitlab_migration gitlab_schema: :gitlab_main
MIGRATION = 'BackfillMergeRequestDiffsProjectId'
DELAY_INTERVAL = 2.minutes
def up
queue_batched_background_migration(
MIGRATION,
:merge_request_diffs,
:id,
job_interval: DELAY_INTERVAL,
queued_migration_version: '20231114043522'
)
end
def down
delete_batched_background_migration(MIGRATION, :merge_request_diffs, :id, [])
end
end
```
1. Release `N.M+X`, where `X` is the number of releases the migration was running:
- Cleanup the background migration:
```ruby
# db/post_migrate/
class FinalizeMergeRequestDiffsProjectIdBackfill < Gitlab::Database::Migration[2.2]
disable_ddl_transaction!
milestone '16.10'
restrict_gitlab_migration gitlab_schema: :gitlab_main
MIGRATION = 'BackfillMergeRequestDiffsProjectId'
def up
ensure_batched_background_migration_is_finished(
job_class_name: MIGRATION,
table_name: :merge_request_diffs,
column_name: :id,
job_arguments: [],
finalize: true
)
end
def down
# no-op
end
end
```
- **Optional.** For very large tables, schedule asynchronous validation of the `NOT NULL` constraint:
```ruby
# db/post_migrate/
class PrepareMergeRequestDiffsProjectIdNotNullValidation < Gitlab::Database::Migration[2.2]
milestone '16.10'
CONSTRAINT_NAME = 'check_11c5f029ad'
def up
prepare_async_check_constraint_validation :merge_request_diffs, name: CONSTRAINT_NAME
end
def down
unprepare_async_check_constraint_validation :merge_request_diffs, name: CONSTRAINT_NAME
end
end
```
1. Validate the `NOT NULL` constraint (if the constraint was validated asynchronously, wait for this validation to finish):
```ruby
# db/post_migrate/
class ValidateMergeRequestDiffsProjectIdNullConstraint < Gitlab::Database::Migration[2.2]
milestone '16.10'
def up
validate_not_null_constraint :merge_request_diffs, :project_id
end
def down
# no-op
end
end
```
For these cases, consult the database team early in the update cycle. The `NOT NULL`
constraint may not be required or other options could exist that do not affect really large

View File

@ -258,6 +258,11 @@ expect(wrapper.text()).toBe('There was an error: Please refresh and hope for the
For more details you can see how we [keep translations dynamic](#keep-translations-dynamic).
## Making changes to translated strings
If you change the source strings in GitLab, you must [update the `pot` file](#updating-the-po-files-with-the-new-content) before pushing your changes.
If the `pot` file is out of date, pre-push checks and a pipeline job for `gettext` fail.
## Working with special content
### Interpolation

View File

@ -29,6 +29,10 @@ strings.
See [Externalization for GitLab](externalization.md).
### Editing externalized strings
If you edit externalized strings in GitLab, you must [update the `pot` file](externalization.md#updating-the-po-files-with-the-new-content) before pushing your changes.
## Translate strings
The translation process is managed at [https://crowdin.com/project/gitlab-ee](https://crowdin.com/project/gitlab-ee)

View File

@ -270,7 +270,9 @@ In the Free tier, the reports above aren't parsed by GitLab. As a result, the wi
A merge request contains a security widget which displays a summary of the _new_ results. New results are determined by comparing the findings of the merge request against the findings of the most recent completed pipeline (`success`, `failed`, `canceled` or `skipped`) for the commit when the feature branch was created from the target branch.
GitLab checks the last 10 pipelines for the commit when the feature was created from the target branch to find one with security reports to use in comparison logic. If security scans have not run for the last 10 completed pipelines in the target branch when the feature branch was created, there is no base for comparison. The vulnerabilities from the merge request findings are listed as new in the merge request security widget. We recommend you run a scan of the `default` (target) branch before enabling feature branch scans for your developers.
GitLab checks the last 10 pipelines for the commit when the feature branch was created from the target branch to find one with security reports to use in comparison logic. If security scans have not run for the last 10 completed pipelines in the target branch when the feature branch was created, there is no base for comparison. The vulnerabilities from the merge request findings are listed as _new_ in the merge request security widget. We recommend you run a scan of the `default` (target) branch before enabling feature branch scans for your developers.
The MR security widget considers all supported pipeline sources (based on the [`CI_PIPELINE_SOURCE` variable](../../ci/variables/predefined_variables.md)) when comparing results from both the source and target branches when determining if a merge request requires approval. Pipeline sources `webide` and `parent_pipeline` are not supported.
The merge request security widget displays only a subset of the vulnerabilities in the generated JSON artifact because it contains both new and existing findings.

View File

@ -224,10 +224,9 @@ Note the following:
policy project's repository must have access to the scanner and site profiles. Otherwise, the scan
is not scheduled successfully.
- For a secret detection scan, only rules with the default ruleset are supported. [Custom rulesets](../secret_detection/index.md#custom-rulesets)
are not supported.
- A secret detection scan runs in `default` mode when executed as part of a pipeline, and in
[`historic`](../secret_detection/index.md#full-history-secret-detection)
mode when executed as part of a scheduled scan.
are not supported. Alternatively, you may configure a [remote configuration file](../secret_detection/index.md#specify-a-remote-configuration-file) and set the `SECRET_DETECTION_RULESET_GIT_REFERENCE` variable.
- By default, for `scheduled` scan execution policies, secret detection scans configured without any CI variables defined run first in `historic` mode (`SECRET_DETECTION_HISTORIC_SCAN` = `true`). All subsequent scheduled scans run in default mode with `SECRET_DETECTION_LOG_OPTIONS` set to the commit range between last run and current SHA. CI variables provided in the scan execution policy can override this behavior. Learn more about [historic mode](../secret_detection/index.md#full-history-secret-detection).
- For `triggered` scan execution policies, secret detection works just like regular scan [configured manually in the `.gitlab-ci.yml`](../secret_detection/index.md#edit-the-gitlab-ciyml-file-manually).
- A container scanning scan that is configured for the `pipeline` rule type ignores the agent defined in the `agents` object. The `agents` object is only considered for `schedule` rule types.
An agent with a name provided in the `agents` object must be created and configured for the project.
- Variables defined in a Scan Execution Policy follow the standard [CI/CD variable precedence](../../../ci/variables/index.md#cicd-variable-precedence).

View File

@ -26,8 +26,6 @@ module Gitlab
def database_id
val = Gitlab::Cache::Import::Caching.read_integer(cache_key, timeout: timeout)
return val if Feature.disabled?(:import_fallback_to_db_empty_cache, project)
return if val == CACHE_OBJECT_NOT_FOUND
return val if val.present?

View File

@ -19,8 +19,6 @@ module Gitlab
cache_key = cache_key_for(name)
val = Gitlab::Cache::Import::Caching.read_integer(cache_key)
return val if Feature.disabled?(:import_fallback_to_db_empty_cache, project)
return if val == CACHE_OBJECT_NOT_FOUND
return val if val.present?

View File

@ -24,8 +24,6 @@ module Gitlab
val = Gitlab::Cache::Import::Caching.read_integer(cache_key)
return val if Feature.disabled?(:import_fallback_to_db_empty_cache, project)
return if val == CACHE_OBJECT_NOT_FOUND
return val if val.present?

View File

@ -10561,13 +10561,22 @@ msgstr ""
msgid "CiVariables|State"
msgstr ""
msgid "CiVariables|The value must have at least %{charsAmount} characters."
msgstr ""
msgid "CiVariables|There was an error fetching the inherited CI variables."
msgstr ""
msgid "CiVariables|This %{entity} has %{currentVariableCount} defined CI/CD variables. The maximum number of variables per %{entity} is %{maxVariableLimit}. To add new variables, you must reduce the number of defined variables."
msgstr ""
msgid "CiVariables|This variable value does not meet the masking requirements."
msgid "CiVariables|This value cannot be masked because it contains the following characters: %{unsupportedChars} and whitespace characters."
msgstr ""
msgid "CiVariables|This value cannot be masked because it contains the following characters: %{unsupportedChars}."
msgstr ""
msgid "CiVariables|This value cannot be masked because it contains the following characters: whitespace characters."
msgstr ""
msgid "CiVariables|Type"

View File

@ -61,7 +61,7 @@
"@gitlab/svgs": "3.71.0",
"@gitlab/ui": "^68.5.0",
"@gitlab/visual-review-tools": "1.7.3",
"@gitlab/web-ide": "0.0.1-dev-20231004090414",
"@gitlab/web-ide": "^0.0.1-dev-20231116214726",
"@mattiasbuelens/web-streams-adapter": "^0.1.0",
"@rails/actioncable": "7.0.8",
"@rails/ujs": "7.0.8",

View File

@ -20,6 +20,8 @@ describe('CI Variable Drawer', () => {
let wrapper;
let trackingSpy;
const itif = (condition) => (condition ? it : it.skip);
const mockProjectVariable = mockVariablesWithScopes(projectString)[0];
const mockProjectVariableFileType = mockVariablesWithScopes(projectString)[1];
const mockEnvScope = 'staging';
@ -284,52 +286,106 @@ describe('CI Variable Drawer', () => {
expect(findConfirmBtn().attributes('disabled')).toBeUndefined();
});
const invalidValues = {
short: 'short',
multiLine: 'multiline\nvalue',
unsupportedChar: 'unsupported|char',
twoUnsupportedChars: 'unsupported|chars!',
threeUnsupportedChars: '%unsupported|chars!',
shortAndMultiLine: 'sho\nrt',
shortAndUnsupportedChar: 'short!',
shortAndMultiLineAndUnsupportedChar: 'short\n!',
multiLineAndUnsupportedChar: 'multiline\nvalue!',
};
const maskedValidationIssuesText = {
short: 'The value must have at least 8 characters.',
multiLine:
'This value cannot be masked because it contains the following characters: whitespace characters.',
unsupportedChar:
'This value cannot be masked because it contains the following characters: |.',
unsupportedDollarChar:
'This value cannot be masked because it contains the following characters: $.',
twoUnsupportedChars:
'This value cannot be masked because it contains the following characters: |, !.',
threeUnsupportedChars:
'This value cannot be masked because it contains the following characters: %, |, !.',
shortAndMultiLine:
'This value cannot be masked because it contains the following characters: whitespace characters. The value must have at least 8 characters.',
shortAndUnsupportedChar:
'This value cannot be masked because it contains the following characters: !. The value must have at least 8 characters.',
shortAndMultiLineAndUnsupportedChar:
'This value cannot be masked because it contains the following characters: ! and whitespace characters. The value must have at least 8 characters.',
multiLineAndUnsupportedChar:
'This value cannot be masked because it contains the following characters: ! and whitespace characters.',
};
describe.each`
value | canSubmit | trackingErrorProperty
${'secretValue'} | ${true} | ${null}
${'~v@lid:symbols.'} | ${true} | ${null}
${'short'} | ${false} | ${null}
${'multiline\nvalue'} | ${false} | ${'\n'}
${'dollar$ign'} | ${false} | ${'$'}
${'unsupported|char'} | ${false} | ${'|'}
`('masking requirements', ({ value, canSubmit, trackingErrorProperty }) => {
beforeEach(async () => {
createComponent();
value | canSubmit | trackingErrorProperty | validationIssueKey
${'secretValue'} | ${true} | ${null} | ${''}
${'~v@lid:symbols.'} | ${true} | ${null} | ${''}
${invalidValues.short} | ${false} | ${null} | ${'short'}
${invalidValues.multiLine} | ${false} | ${'\n'} | ${'multiLine'}
${'dollar$ign'} | ${false} | ${'$'} | ${'unsupportedDollarChar'}
${invalidValues.unsupportedChar} | ${false} | ${'|'} | ${'unsupportedChar'}
${invalidValues.twoUnsupportedChars} | ${false} | ${'|!'} | ${'twoUnsupportedChars'}
${invalidValues.threeUnsupportedChars} | ${false} | ${'%|!'} | ${'threeUnsupportedChars'}
${invalidValues.shortAndMultiLine} | ${false} | ${'\n'} | ${'shortAndMultiLine'}
${invalidValues.shortAndUnsupportedChar} | ${false} | ${'!'} | ${'shortAndUnsupportedChar'}
${invalidValues.shortAndMultiLineAndUnsupportedChar} | ${false} | ${'\n!'} | ${'shortAndMultiLineAndUnsupportedChar'}
${invalidValues.multiLineAndUnsupportedChar} | ${false} | ${'\n!'} | ${'multiLineAndUnsupportedChar'}
`(
'masking requirements',
({ value, canSubmit, trackingErrorProperty, validationIssueKey }) => {
beforeEach(() => {
createComponent();
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
await findKeyField().vm.$emit('input', 'NEW_VARIABLE');
await findValueField().vm.$emit('input', value);
await findMaskedCheckbox().vm.$emit('input', true);
});
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
findKeyField().vm.$emit('input', 'NEW_VARIABLE');
findValueField().vm.$emit('input', value);
findMaskedCheckbox().vm.$emit('input', true);
});
it(`${
canSubmit ? 'can submit' : 'shows validation errors and disables submit button'
} when value is '${value}'`, () => {
if (canSubmit) {
itif(canSubmit)(`can submit when value is ${value}`, () => {
/* eslint-disable jest/no-standalone-expect */
expect(findValueLabel().attributes('invalid-feedback')).toBe('');
expect(findConfirmBtn().attributes('disabled')).toBeUndefined();
} else {
expect(findValueLabel().attributes('invalid-feedback')).toBe(
'This variable value does not meet the masking requirements.',
);
expect(findConfirmBtn().attributes('disabled')).toBeDefined();
}
});
/* eslint-enable jest/no-standalone-expect */
});
it(`${
trackingErrorProperty ? 'sends the correct' : 'does not send the'
} variable validation tracking event when value is '${value}'`, () => {
const trackingEventSent = trackingErrorProperty ? 1 : 0;
expect(trackingSpy).toHaveBeenCalledTimes(trackingEventSent);
itif(!canSubmit)(
`shows validation errors and disables submit button when value is ${value}`,
() => {
const validationIssueText = maskedValidationIssuesText[validationIssueKey] || '';
if (trackingErrorProperty) {
expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTION, {
label: DRAWER_EVENT_LABEL,
property: trackingErrorProperty,
});
}
});
});
/* eslint-disable jest/no-standalone-expect */
expect(findValueLabel().attributes('invalid-feedback')).toBe(validationIssueText);
expect(findConfirmBtn().attributes('disabled')).toBeDefined();
/* eslint-enable jest/no-standalone-expect */
},
);
itif(trackingErrorProperty)(
`sends the correct variable validation tracking event when value is ${value}`,
() => {
/* eslint-disable jest/no-standalone-expect */
expect(trackingSpy).toHaveBeenCalledTimes(1);
expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTION, {
label: DRAWER_EVENT_LABEL,
property: trackingErrorProperty,
});
/* eslint-enable jest/no-standalone-expect */
},
);
itif(!trackingErrorProperty)(
`does not send the the correct variable validation tracking event when value is ${value}`,
() => {
// eslint-disable-next-line jest/no-standalone-expect
expect(trackingSpy).toHaveBeenCalledTimes(0);
},
);
},
);
it('only sends the tracking event once', async () => {
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);

View File

@ -48,34 +48,6 @@ RSpec.describe Gitlab::GithubImport::IssuableFinder, :clean_gitlab_redis_cache,
expect { finder.database_id }.to raise_error(TypeError)
end
context 'with FF import_fallback_to_db_empty_cache disabled' do
before do
stub_feature_flags(import_fallback_to_db_empty_cache: false)
end
it 'returns nil if object does not exist' do
missing_issue = double(:issue, issuable_type: 'MergeRequest', issuable_id: 999)
expect(described_class.new(project, missing_issue).database_id).to be_nil
end
it 'does not fetch object id from database if not in cache' do
expect(finder.database_id).to eq(nil)
end
it 'fetches object id from cache if present' do
finder.cache_database_id(10)
expect(finder.database_id).to eq(10)
end
it 'returns -1 if cache is -1' do
finder.cache_database_id(-1)
expect(finder.database_id).to eq(-1)
end
end
context 'when group is present' do
context 'when settings single_endpoint_notes_import is enabled' do
let(:single_endpoint_optional_stage) { true }

View File

@ -49,34 +49,6 @@ RSpec.describe Gitlab::GithubImport::LabelFinder, :clean_gitlab_redis_cache, fea
expect(finder.id_for(feature.name)).to eq(feature.id)
end
end
context 'with FF import_fallback_to_db_empty_cache disabled' do
before do
stub_feature_flags(import_fallback_to_db_empty_cache: false)
end
it 'returns nil for a non existing label name' do
expect(finder.id_for('kittens')).to be_nil
end
it 'does not fetch object id from database if not in cache' do
expect(finder.id_for(feature.name)).to be_nil
end
it 'fetches object id from cache if present' do
finder.build_cache
expect(finder.id_for(feature.name)).to eq(feature.id)
end
it 'returns -1 if cache is -1' do
key = finder.cache_key_for(bug.name)
Gitlab::Cache::Import::Caching.write(key, -1)
expect(finder.id_for(bug.name)).to eq(-1)
end
end
end
describe '#build_cache' do

View File

@ -57,36 +57,6 @@ RSpec.describe Gitlab::GithubImport::MilestoneFinder, :clean_gitlab_redis_cache,
expect(finder.id_for(issuable)).to eq(milestone.id)
end
end
context 'with FF import_fallback_to_db_empty_cache disabled' do
before do
stub_feature_flags(import_fallback_to_db_empty_cache: false)
end
it 'returns nil if object does not exist' do
missing_issuable = double(:issuable, milestone_number: 999)
expect(finder.id_for(missing_issuable)).to be_nil
end
it 'does not fetch object id from database if not in cache' do
expect(finder.id_for(issuable)).to be_nil
end
it 'fetches object id from cache if present' do
finder.build_cache
expect(finder.id_for(issuable)).to eq(milestone.id)
end
it 'returns -1 if cache is -1' do
key = finder.cache_key_for(milestone.iid)
Gitlab::Cache::Import::Caching.write(key, -1)
expect(finder.id_for(issuable)).to eq(-1)
end
end
end
describe '#build_cache' do

View File

@ -140,7 +140,10 @@ RSpec.shared_examples 'variable list drawer' do
toggle_masked
fill_variable('EMPTY_MASK_KEY', '???')
expect(page).to have_content('This variable value does not meet the masking requirements.')
# rubocop:disable Layout/LineLength -- error message is too long
expect(page).to have_content('This value cannot be masked because it contains the following characters: ?. The value must have at least 8 characters.')
# rubocop:enable Layout/LineLength
page.within('[data-testid="ci-variable-drawer"]') do
expect(find_button('Add variable', disabled: true)).to be_present
end

View File

@ -1292,10 +1292,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/visual-review-tools/-/visual-review-tools-1.7.3.tgz#9ea641146436da388ffbad25d7f2abe0df52c235"
integrity sha512-NMV++7Ew1FSBDN1xiZaauU9tfeSfgDHcOLpn+8bGpP+O5orUPm2Eu66R5eC5gkjBPaXosNAxNWtriee+aFk4+g==
"@gitlab/web-ide@0.0.1-dev-20231004090414":
version "0.0.1-dev-20231004090414"
resolved "https://registry.yarnpkg.com/@gitlab/web-ide/-/web-ide-0.0.1-dev-20231004090414.tgz#925c9e942917acbbb17c4ea77b0841649ae186ad"
integrity sha512-NfkRzvz5Z3uDceQC5QN8W5u1ETlHbbEXjrnKxiYM4TD1d+bOV567GYglRKjyOhQMTYRGpqbisLSAPgvShAQB6g==
"@gitlab/web-ide@^0.0.1-dev-20231116214726":
version "0.0.1-dev-20231116214726"
resolved "https://registry.yarnpkg.com/@gitlab/web-ide/-/web-ide-0.0.1-dev-20231116214726.tgz#3b80e3de4dce8d07e6acd913d287de0c772b4bb3"
integrity sha512-sc/LVSKqcSyKQ5rQlgMfvAMxiJvOkhAI5ZJqA8pHqnKK/sAx7C66lBtYfkWGvj+Dw31ElkZgV/7tS2wQXLnwjA==
"@graphql-eslint/eslint-plugin@3.20.1":
version "3.20.1"