Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-12-01 21:14:38 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-12-01 21:14:38 +0300
commit07cbb41fee42601767b3aea2979d6fa6d990ce5b (patch)
tree00ba0463347c4e2951660c7236652bb24750976d
parentc3ddbeb162e4261f4ce3df291909fadeba637995 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop_todo/style/redundant_return.yml1
-rw-r--r--app/assets/javascripts/content_editor/extensions/reference.js21
-rw-r--r--app/assets/javascripts/content_editor/services/asset_resolver.js9
-rw-r--r--app/controllers/concerns/import/github_oauth.rb6
-rw-r--r--app/models/ability.rb4
-rw-r--r--app/models/ci/build_dependencies.rb2
-rw-r--r--app/models/concerns/enums/sbom.rb27
-rw-r--r--app/models/repository.rb9
-rw-r--r--app/models/users/callout.rb3
-rw-r--r--app/services/ml/create_model_version_service.rb33
-rw-r--r--db/docs/batched_background_migrations/backfill_finding_id_in_vulnerabilities.yml2
-rw-r--r--doc/.vale/gitlab/SubstitutionWarning.yml2
-rw-r--r--doc/administration/settings/usage_statistics.md1
-rw-r--r--doc/api/commits.md10
-rw-r--r--doc/api/graphql/reference/index.md27
-rw-r--r--doc/architecture/blueprints/cells/index.md6
-rw-r--r--doc/architecture/blueprints/new_diffs/index.md2
-rw-r--r--doc/ci/ci_cd_for_external_repos/bitbucket_integration.md5
-rw-r--r--doc/ci/ci_cd_for_external_repos/github_integration.md8
-rw-r--r--doc/ci/ci_cd_for_external_repos/index.md4
-rw-r--r--doc/ci/cloud_deployment/ecs/deploy_to_aws_ecs.md20
-rw-r--r--doc/ci/cloud_deployment/ecs/img/rails-template.pngbin13497 -> 0 bytes
-rw-r--r--doc/ci/components/index.md6
-rw-r--r--doc/ci/examples/index.md2
-rw-r--r--doc/ci/pipeline_editor/index.md6
-rw-r--r--doc/ci/pipelines/downstream_pipelines.md4
-rw-r--r--doc/ci/testing/browser_performance_testing.md10
-rw-r--r--doc/ci/testing/code_quality.md16
-rw-r--r--doc/development/documentation/styleguide/word_list.md17
-rw-r--r--doc/gitlab-basics/start-using-git.md6
-rw-r--r--doc/user/group/saml_sso/scim_setup.md2
-rw-r--r--lib/gitlab/ci/reports/sbom/source.rb18
-rw-r--r--lib/gitlab/ci/reports/sbom/source_helper.rb43
-rw-r--r--lib/gitlab/ci/variables/downstream/generator.rb8
-rw-r--r--lib/gitlab/git.rb7
-rw-r--r--lib/gitlab/git/compare.rb10
-rw-r--r--lib/gitlab/git/repository.rb11
-rw-r--r--locale/gitlab.pot12
-rw-r--r--rubocop/cop/background_migration/dictionary_file.rb9
-rw-r--r--spec/factories/ci/reports/sbom/sources.rb53
-rw-r--r--spec/features/projects/settings/webhooks_settings_spec.rb2
-rw-r--r--spec/frontend/content_editor/extensions/reference_spec.js56
-rw-r--r--spec/frontend/content_editor/services/asset_resolver_spec.js55
-rw-r--r--spec/frontend/content_editor/test_constants.js15
-rw-r--r--spec/lib/gitlab/ci/reports/sbom/source_spec.rb102
-rw-r--r--spec/lib/gitlab/ci/variables/downstream/generator_spec.rb28
-rw-r--r--spec/lib/gitlab/git/compare_spec.rb108
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb65
-rw-r--r--spec/models/ability_spec.rb23
-rw-r--r--spec/models/concerns/enums/sbom_spec.rb62
-rw-r--r--spec/models/repository_spec.rb55
-rw-r--r--spec/rubocop/cop/background_migration/dictionary_file_spec.rb21
-rw-r--r--spec/services/ml/create_model_version_service_spec.rb37
53 files changed, 845 insertions, 226 deletions
diff --git a/.rubocop_todo/style/redundant_return.yml b/.rubocop_todo/style/redundant_return.yml
index 344dbbbc4cd..86f8bb37d67 100644
--- a/.rubocop_todo/style/redundant_return.yml
+++ b/.rubocop_todo/style/redundant_return.yml
@@ -73,7 +73,6 @@ Style/RedundantReturn:
- 'ee/app/serializers/vulnerabilities/merge_request_link_entity.rb'
- 'ee/app/services/audit_events/streaming/headers/base.rb'
- 'ee/app/services/ee/post_receive_service.rb'
- - 'ee/app/services/gitlab_subscriptions/user_add_on_assignments/create_service.rb'
- 'ee/app/services/security/orchestration/assign_service.rb'
- 'ee/app/services/vulnerabilities/manually_create_service.rb'
- 'ee/app/workers/ee/repository_check/batch_worker.rb'
diff --git a/app/assets/javascripts/content_editor/extensions/reference.js b/app/assets/javascripts/content_editor/extensions/reference.js
index fd248709b5a..0c385481ac5 100644
--- a/app/assets/javascripts/content_editor/extensions/reference.js
+++ b/app/assets/javascripts/content_editor/extensions/reference.js
@@ -72,11 +72,20 @@ export default Node.create({
addInputRules() {
const { editor } = this;
const { assetResolver } = this.options;
- const referenceInputRegex = /(?:^|\s)([\w/]*([!&#])\d+(\+?s?))(?:\s|\n)/m;
+ const referenceInputRegex = /(?:^|\s)([\w/]*([#!&%$@~]|\[vulnerability:)[\w.]+(\+?s?\]?))(?:\s|\n)/m;
const referenceTypes = {
'#': 'issue',
'!': 'merge_request',
'&': 'epic',
+ '%': 'milestone',
+ $: 'snippet',
+ '@': 'user',
+ '~': 'label',
+ '[vulnerability:': 'vulnerability',
+ };
+ const nodeTypes = {
+ label: editor.schema.nodes.referenceLabel,
+ default: editor.schema.nodes.reference,
};
return [
@@ -91,22 +100,26 @@ export default Node.create({
text,
expandedText,
fullyExpandedText,
+ backgroundColor,
} = await assetResolver.resolveReference(referenceId);
if (!text) return;
let referenceText = text;
- if (expansionType === '+') referenceText = expandedText;
- if (expansionType === '+s') referenceText = fullyExpandedText;
+ if (expansionType === '+') referenceText = expandedText || text;
+ if (expansionType === '+s') referenceText = fullyExpandedText || text;
const position = findReference(editor, referenceId);
if (!position) return;
+ const nodeType = nodeTypes[referenceType] || nodeTypes.default;
+
editor.view.dispatch(
editor.state.tr.replaceWith(position, position + referenceId.length, [
- this.type.create({
+ nodeType.create({
referenceType,
originalText: referenceId,
+ color: backgroundColor,
href,
text: referenceText,
}),
diff --git a/app/assets/javascripts/content_editor/services/asset_resolver.js b/app/assets/javascripts/content_editor/services/asset_resolver.js
index 0d4396fc176..07a69db7428 100644
--- a/app/assets/javascripts/content_editor/services/asset_resolver.js
+++ b/app/assets/javascripts/content_editor/services/asset_resolver.js
@@ -27,10 +27,11 @@ export default class AssetResolver {
if (!a.length) return {};
return {
- href: a[0].getAttribute('href'),
- text: a[0].textContent,
- expandedText: a[1].textContent,
- fullyExpandedText: a[2].textContent,
+ href: a[0]?.getAttribute('href'),
+ text: a[0]?.textContent,
+ expandedText: a[1]?.textContent,
+ fullyExpandedText: a[2]?.textContent,
+ backgroundColor: a[0]?.firstElementChild?.style.backgroundColor,
};
});
diff --git a/app/controllers/concerns/import/github_oauth.rb b/app/controllers/concerns/import/github_oauth.rb
index ae5a0401155..fa6162254dc 100644
--- a/app/controllers/concerns/import/github_oauth.rb
+++ b/app/controllers/concerns/import/github_oauth.rb
@@ -56,7 +56,11 @@ module Import
session[:auth_on_failure_path] = "#{new_project_path}#import_project"
oauth_client.auth_code.authorize_url(
redirect_uri: callback_import_url,
- scope: 'repo, user, user:email',
+ # read:org only required for collaborator import, which is optional,
+ # but at the time of this OAuth request we do not know which optional
+ # configuration the user will select because the options are only shown
+ # after authenticating
+ scope: 'repo, read:org',
state: state
)
end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 6ea48f2d668..f4654f52f7a 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -79,10 +79,10 @@ class Ability
policy = policy_for(user, subject, **opts.slice(:cache))
# https://gitlab.com/gitlab-org/gitlab/-/issues/421150#note_1638311666
- if ability == :read_namespace && Feature.enabled?(:log_read_namespace_usages, Feature.current_request)
+ if ability.to_sym == :read_namespace && Feature.enabled?(:log_read_namespace_usages, Feature.current_request)
Gitlab::AppLogger.info(
message: 'Ability is in use',
- ability: ability,
+ ability: ability.to_sym,
caller_locations: caller_locations(1, 5).map(&:to_s)
)
end
diff --git a/app/models/ci/build_dependencies.rb b/app/models/ci/build_dependencies.rb
index c4a04d42a1e..e1521e2f5fa 100644
--- a/app/models/ci/build_dependencies.rb
+++ b/app/models/ci/build_dependencies.rb
@@ -36,7 +36,7 @@ module Ci
next [] if no_local_dependencies_specified?
next [] unless processable.pipeline_id # we don't have any dependency when creating the pipeline
- deps = model_class.where(pipeline_id: processable.pipeline_id).latest
+ deps = model_class.where(pipeline_id: processable.pipeline_id, partition_id: processable.partition_id).latest
deps = find_dependencies(processable, deps)
from_dependencies(deps).to_a
diff --git a/app/models/concerns/enums/sbom.rb b/app/models/concerns/enums/sbom.rb
index 9c3bbc92e86..4e54e48e667 100644
--- a/app/models/concerns/enums/sbom.rb
+++ b/app/models/concerns/enums/sbom.rb
@@ -22,10 +22,37 @@ module Enums
wolfi: 13
}.with_indifferent_access.freeze
+ DEPENDENCY_SCANNING_PURL_TYPES = %w[
+ composer
+ conan
+ gem
+ golang
+ maven
+ npm
+ nuget
+ pypi
+ ].freeze
+
+ CONTAINER_SCANNING_PURL_TYPES = %w[
+ apk
+ rpm
+ deb
+ cbl-mariner
+ wolfi
+ ].freeze
+
def self.component_types
COMPONENT_TYPES
end
+ def self.dependency_scanning_purl_type?(purl_type)
+ DEPENDENCY_SCANNING_PURL_TYPES.include?(purl_type)
+ end
+
+ def self.container_scanning_purl_type?(purl_type)
+ CONTAINER_SCANNING_PURL_TYPES.include?(purl_type)
+ end
+
def self.purl_types
# return 0 by default if the purl_type is not found, to prevent
# consumers from producing invalid SQL caused by null entries
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 72a40ce5f01..5ab35ed1ef9 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -1278,15 +1278,6 @@ class Repository
.map(&:to_h)
end
- def filter_generated_files(revision, paths)
- # NOTE: We should still support linguist-generated override for GitHub compatibility,
- # but `gitlab-*` prefixed overrides would give us a better control moving forward.
- generated_files = get_file_attributes(revision, paths, %w[gitlab-generated linguist-generated])
- .pluck(:path)
-
- paths - generated_files
- end
-
def object_format
return unless exists?
diff --git a/app/models/users/callout.rb b/app/models/users/callout.rb
index a9880e56e8c..924e130aab5 100644
--- a/app/models/users/callout.rb
+++ b/app/models/users/callout.rb
@@ -77,7 +77,8 @@ module Users
vsd_feedback_banner: 75, # EE-only
security_policy_protected_branch_modification: 76, # EE-only
vulnerability_report_grouping: 77, # EE-only
- new_nav_for_everyone_callout: 78
+ new_nav_for_everyone_callout: 78,
+ duo_chat_callout: 79 # EE-only
}
validates :feature_name,
diff --git a/app/services/ml/create_model_version_service.rb b/app/services/ml/create_model_version_service.rb
index ff27e78221f..e7a59210107 100644
--- a/app/services/ml/create_model_version_service.rb
+++ b/app/services/ml/create_model_version_service.rb
@@ -7,19 +7,38 @@ module Ml
@version = params[:version]
@package = params[:package]
@description = params[:description]
+ @user = params[:user]
end
def execute
- @version ||= Ml::IncrementVersionService.new(@model.latest_version.try(:version)).execute
+ ApplicationRecord.transaction do
+ @version ||= Ml::IncrementVersionService.new(@model.latest_version.try(:version)).execute
- model_version = Ml::ModelVersion.find_or_create!(@model, @version, @package, @description)
+ package = @package || find_or_create_package(@model.name, @version)
- model_version.candidate = ::Ml::CreateCandidateService.new(
- @model.default_experiment,
- { model_version: model_version }
- ).execute
+ model_version = Ml::ModelVersion.create!(model: @model, project: @model.project, version: @version,
+ package: package, description: @description)
- model_version
+ model_version.candidate = ::Ml::CreateCandidateService.new(
+ @model.default_experiment,
+ { model_version: model_version }
+ ).execute
+
+ model_version
+ end
+ end
+
+ private
+
+ def find_or_create_package(model_name, model_version)
+ package_params = {
+ name: model_name,
+ version: model_version
+ }
+
+ ::Packages::MlModel::FindOrCreatePackageService
+ .new(@model.project, @user, package_params)
+ .execute
end
end
end
diff --git a/db/docs/batched_background_migrations/backfill_finding_id_in_vulnerabilities.yml b/db/docs/batched_background_migrations/backfill_finding_id_in_vulnerabilities.yml
index 84febc79e6f..8bc99c1ca2a 100644
--- a/db/docs/batched_background_migrations/backfill_finding_id_in_vulnerabilities.yml
+++ b/db/docs/batched_background_migrations/backfill_finding_id_in_vulnerabilities.yml
@@ -2,7 +2,7 @@
migration_job_name: BackfillFindingIdInVulnerabilities
description: Backfills finding_id column on vulnerabilities table for a proper 1:1 relation
feature_category: vulnerability_management
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/418971
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/130058
queued_migration_version: 20231116105945
milestone: 16.4
finalize_after: '2023-12-15'
diff --git a/doc/.vale/gitlab/SubstitutionWarning.yml b/doc/.vale/gitlab/SubstitutionWarning.yml
index 6860b308b46..d4bbe9fd83b 100644
--- a/doc/.vale/gitlab/SubstitutionWarning.yml
+++ b/doc/.vale/gitlab/SubstitutionWarning.yml
@@ -28,7 +28,7 @@ swap:
e-mail: "email"
emojis: "emoji"
ex: "for example"
- file name: "filename"
+ filename: "file name"
filesystem: "file system"
info: "information"
installation from source: self-compiled installation
diff --git a/doc/administration/settings/usage_statistics.md b/doc/administration/settings/usage_statistics.md
index 51a6fa153d1..e86493590ab 100644
--- a/doc/administration/settings/usage_statistics.md
+++ b/doc/administration/settings/usage_statistics.md
@@ -74,6 +74,7 @@ In the following table, you can see:
| [Сross-project pipelines with artifacts dependencies](../../ci/yaml/index.md#needsproject) | GitLab 16.7 and later |
| [Feature flag related issues](../../operations/feature_flags.md#feature-flag-related-issues) | GitLab 16.7 and later |
| [Merged results pipelines](../../ci/pipelines/merged_results_pipelines.md) | GitLab 16.7 and later |
+| [CI/CD for GitHub](../../ci/ci_cd_for_external_repos/github_integration.md) | GitLab 16.7 and later |
### Enable registration features
diff --git a/doc/api/commits.md b/doc/api/commits.md
index 94cdaaa191d..931893669fa 100644
--- a/doc/api/commits.md
+++ b/doc/api/commits.md
@@ -65,7 +65,9 @@ Example response:
"parent_ids": [
"6104942438c14ec7bd21c6cd5bd995272b3faff6"
],
- "web_url": "https://gitlab.example.com/janedoe/gitlab-foss/-/commit/ed899a2f4b50b4370feeea94676502b42383c746"
+ "web_url": "https://gitlab.example.com/janedoe/gitlab-foss/-/commit/ed899a2f4b50b4370feeea94676502b42383c746",
+ "trailers": {},
+ "extended_trailers": {}
},
{
"id": "6104942438c14ec7bd21c6cd5bd995272b3faff6",
@@ -76,11 +78,13 @@ Example response:
"committer_name": "ExampleName",
"committer_email": "user@example.com",
"created_at": "2021-09-20T09:06:12.201+00:00",
- "message": "Sanitize for network graph",
+ "message": "Sanitize for network graph\nCc: John Doe <johndoe@gitlab.com>\nCc: Jane Doe <janedoe@gitlab.com>",
"parent_ids": [
"ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba"
],
- "web_url": "https://gitlab.example.com/janedoe/gitlab-foss/-/commit/ed899a2f4b50b4370feeea94676502b42383c746"
+ "web_url": "https://gitlab.example.com/janedoe/gitlab-foss/-/commit/ed899a2f4b50b4370feeea94676502b42383c746",
+ "trailers": { "Cc": "Jane Doe <janedoe@gitlab.com>" },
+ "extended_trailers": { "Cc": ["John Doe <johndoe@gitlab.com>", "Jane Doe <janedoe@gitlab.com>"] }
}
]
```
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index bf25ee8182b..3703d8e1560 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -9513,6 +9513,30 @@ The edge type for [`CiStage`](#cistage).
| <a id="cistageedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="cistageedgenode"></a>`node` | [`CiStage`](#cistage) | The item at the end of the edge. |
+#### `CiSubscriptionsProjectConnection`
+
+The connection type for [`CiSubscriptionsProject`](#cisubscriptionsproject).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="cisubscriptionsprojectconnectioncount"></a>`count` | [`Int!`](#int) | Total count of collection. |
+| <a id="cisubscriptionsprojectconnectionedges"></a>`edges` | [`[CiSubscriptionsProjectEdge]`](#cisubscriptionsprojectedge) | A list of edges. |
+| <a id="cisubscriptionsprojectconnectionnodes"></a>`nodes` | [`[CiSubscriptionsProject]`](#cisubscriptionsproject) | A list of nodes. |
+| <a id="cisubscriptionsprojectconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `CiSubscriptionsProjectEdge`
+
+The edge type for [`CiSubscriptionsProject`](#cisubscriptionsproject).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="cisubscriptionsprojectedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="cisubscriptionsprojectedgenode"></a>`node` | [`CiSubscriptionsProject`](#cisubscriptionsproject) | The item at the end of the edge. |
+
#### `ClusterAgentActivityEventConnection`
The connection type for [`ClusterAgentActivityEvent`](#clusteragentactivityevent).
@@ -23718,6 +23742,8 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="projectcicdsettings"></a>`ciCdSettings` | [`ProjectCiCdSetting`](#projectcicdsetting) | CI/CD settings for the project. |
| <a id="projectciconfigpathordefault"></a>`ciConfigPathOrDefault` | [`String!`](#string) | Path of the CI configuration file. |
| <a id="projectcijobtokenscope"></a>`ciJobTokenScope` | [`CiJobTokenScopeType`](#cijobtokenscopetype) | The CI Job Tokens scope of access. |
+| <a id="projectcisubscribedprojects"></a>`ciSubscribedProjects` | [`CiSubscriptionsProjectConnection`](#cisubscriptionsprojectconnection) | Triggers a new pipeline in the downstream project when a pipeline successfullycompletes on the(upstream) project. (see [Connections](#connections)) |
+| <a id="projectcisubscriptionsprojects"></a>`ciSubscriptionsProjects` | [`CiSubscriptionsProjectConnection`](#cisubscriptionsprojectconnection) | Triggers a new pipeline in the(downstream) project when a pipeline successfullycompletes on the upstream project. (see [Connections](#connections)) |
| <a id="projectcodecoveragesummary"></a>`codeCoverageSummary` | [`CodeCoverageSummary`](#codecoveragesummary) | Code coverage summary associated with the project. |
| <a id="projectcomplianceframeworks"></a>`complianceFrameworks` | [`ComplianceFrameworkConnection`](#complianceframeworkconnection) | Compliance frameworks associated with the project. (see [Connections](#connections)) |
| <a id="projectcontainerexpirationpolicy"></a>`containerExpirationPolicy` | [`ContainerExpirationPolicy`](#containerexpirationpolicy) | Container expiration policy of the project. |
@@ -31056,6 +31082,7 @@ Name of the feature that the callout is for.
| <a id="usercalloutfeaturenameenumci_deprecation_warning_for_types_keyword"></a>`CI_DEPRECATION_WARNING_FOR_TYPES_KEYWORD` | Callout feature name for ci_deprecation_warning_for_types_keyword. |
| <a id="usercalloutfeaturenameenumcloud_licensing_subscription_activation_banner"></a>`CLOUD_LICENSING_SUBSCRIPTION_ACTIVATION_BANNER` | Callout feature name for cloud_licensing_subscription_activation_banner. |
| <a id="usercalloutfeaturenameenumcluster_security_warning"></a>`CLUSTER_SECURITY_WARNING` | Callout feature name for cluster_security_warning. |
+| <a id="usercalloutfeaturenameenumduo_chat_callout"></a>`DUO_CHAT_CALLOUT` | Callout feature name for duo_chat_callout. |
| <a id="usercalloutfeaturenameenumeoa_bronze_plan_banner"></a>`EOA_BRONZE_PLAN_BANNER` | Callout feature name for eoa_bronze_plan_banner. |
| <a id="usercalloutfeaturenameenumfeature_flags_new_version"></a>`FEATURE_FLAGS_NEW_VERSION` | Callout feature name for feature_flags_new_version. |
| <a id="usercalloutfeaturenameenumgcp_signup_offer"></a>`GCP_SIGNUP_OFFER` | Callout feature name for gcp_signup_offer. |
diff --git a/doc/architecture/blueprints/cells/index.md b/doc/architecture/blueprints/cells/index.md
index d4213706189..d2578072800 100644
--- a/doc/architecture/blueprints/cells/index.md
+++ b/doc/architecture/blueprints/cells/index.md
@@ -108,9 +108,9 @@ The first 2-3 quarters are required to define a general split of data, and build
The purpose is to perform a targeted decomposition of `users` and `projects`, because `projects` will be stored locally in the Cell.
-1. **User can create files in repository**
+1. **User can create Project with a README file**
- The purpose is to allow `users` to create files in a repository.
+ The purpose is to allow `users` to create README files in a project.
1. **User can change profile avatar that is shared in cluster.**
@@ -284,7 +284,7 @@ It is expected that initial iterations will be rather slow, because they require
- Data access layer: Data access layer.
- Routing: User can use single domain to interact with many Cells.
- Cell deployment: Extend GitLab Dedicated to support GCP.
-- Essential workflows: User can create files in repository.
+- Essential workflows: User can create Project with a README file.
- Essential workflows: User can push to Git repository.
- Essential workflows: User can run CI pipeline.
- Essential workflows: Instance-wide settings are shared across cluster.
diff --git a/doc/architecture/blueprints/new_diffs/index.md b/doc/architecture/blueprints/new_diffs/index.md
index 2aabfe4c618..836bb8e89e6 100644
--- a/doc/architecture/blueprints/new_diffs/index.md
+++ b/doc/architecture/blueprints/new_diffs/index.md
@@ -289,7 +289,7 @@ Each file table should include a short summary of changes that will read out:
The summary of the table content can be placed either within `<caption>` element, or before the table within an element referred as `aria-describedby`.
See <abbr>WAI</abbr> (Web Accessibility Initiative) for more information on both approaches:
-- [Nesting summary inside the <caption> element](https://www.w3.org/WAI/tutorials/tables/caption-summary/#nesting-summary-inside-the-caption-element)
+- [Nesting summary inside the `<caption>` element](https://www.w3.org/WAI/tutorials/tables/caption-summary/#nesting-summary-inside-the-caption-element)
- [Using aria-describedby to provide a table summary](https://www.w3.org/WAI/tutorials/tables/caption-summary/#using-aria-describedby-to-provide-a-table-summary)
However, if such a structure will compromise other functional aspects of displaying a diff,
diff --git a/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md b/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md
index 1820cf77841..afbeff412a9 100644
--- a/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md
+++ b/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md
@@ -15,9 +15,8 @@ GitLab CI/CD can be used with Bitbucket Cloud by:
To use GitLab CI/CD with a Bitbucket Cloud repository:
1. In GitLab, create a project:
- 1. On the left sidebar, select **Search or go to**.
- 1. Select **View all my projects**.
- 1. On the right of the page, select **New project**.
+
+ 1. On the left sidebar, at the top, select **Create new** (**{plus}**) and **New project/repository**.
1. Select **Run CI/CD for external repository**.
1. Select **Repository by URL**.
1. Fill in the fields with information from the repository in Bitbucket:
diff --git a/doc/ci/ci_cd_for_external_repos/github_integration.md b/doc/ci/ci_cd_for_external_repos/github_integration.md
index bc61990fcd8..0cb5ab68efd 100644
--- a/doc/ci/ci_cd_for_external_repos/github_integration.md
+++ b/doc/ci/ci_cd_for_external_repos/github_integration.md
@@ -34,9 +34,7 @@ repositories:
`repo` and `admin:repo_hook` so that GitLab can access your project,
update commit statuses, and create a web hook to notify GitLab of new commits.
1. In GitLab, create a project:
- 1. On the left sidebar, select **Search or go to**.
- 1. Select **View all my projects**.
- 1. On the right of the page, select **New project**.
+ 1. On the left sidebar, at the top, select **Create new** (**{plus}**) and **New project/repository**.
1. Select **Run CI/CD for external repository**.
1. Select **GitHub**.
1. For **Personal access token**, paste the token.
@@ -63,9 +61,7 @@ To manually enable GitLab CI/CD for your repository:
1. Enter a **Token description** and update the scope to allow
`repo` so that GitLab can access your project and update commit statuses.
1. In GitLab, create a project:
- 1. On the left sidebar, select **Search or go to**.
- 1. Select **View all my projects**.
- 1. Select **New project**.
+ 1. On the left sidebar, at the top, select **Create new** (**{plus}**) and **New project/repository**.
1. Select **Run CI/CD for external repository** and **Repository by URL**.
1. In the **Git repository URL** field, enter the HTTPS URL for your GitHub repository.
If your project is private, use the personal access token you just created for authentication.
diff --git a/doc/ci/ci_cd_for_external_repos/index.md b/doc/ci/ci_cd_for_external_repos/index.md
index 4ba87c8e6a1..3460b014ec6 100644
--- a/doc/ci/ci_cd_for_external_repos/index.md
+++ b/doc/ci/ci_cd_for_external_repos/index.md
@@ -24,9 +24,7 @@ snippets disabled. These features
To connect to an external repository:
-1. On the left sidebar, select **Search or go to**.
-1. Select **View all my projects**.
-1. Select **New project**.
+1. On the left sidebar, at the top, select **Create new** (**{plus}**) and **New project/repository**.
1. Select **Run CI/CD for external repository**.
1. Select **GitHub** or **Repository by URL**.
1. Complete the fields.
diff --git a/doc/ci/cloud_deployment/ecs/deploy_to_aws_ecs.md b/doc/ci/cloud_deployment/ecs/deploy_to_aws_ecs.md
index 4ccf8e5d276..6aee673e382 100644
--- a/doc/ci/cloud_deployment/ecs/deploy_to_aws_ecs.md
+++ b/doc/ci/cloud_deployment/ecs/deploy_to_aws_ecs.md
@@ -39,18 +39,12 @@ For the first step here, you create a demo application from a project template.
Use a GitLab project template to get started. As the name suggests, these projects provide a
bare-bones application built on some well-known frameworks.
-1. In GitLab, select the plus icon (**{plus-square}**) at the top of the navigation bar, and select
- **New project**.
-
+1. In GitLab on the left sidebar, at the top, select **Create new** (**{plus}**) and **New project/repository**.
1. Select **Create from template**, where you can choose from a Ruby on Rails, Spring, or
NodeJS Express project. For this guide, use the Ruby on Rails template.
-
- ![Select project template](img/rails-template.png)
-
1. Give your project a name. In this example, it's named `ecs-demo`. Make it public so that you can
take advantage of the features available in the
[GitLab Ultimate plan](https://about.gitlab.com/pricing/).
-
1. Select **Create project**.
Now that you created a demo project, you must containerize the application and push it to the
@@ -63,8 +57,8 @@ provide a containerized application image during the infrastructure build. To do
GitLab [Auto Build](../../../topics/autodevops/stages.md#auto-build)
and [Container Registry](../../../user/packages/container_registry/index.md).
-1. Go to **ecs-demo** project on GitLab.
-1. Select **Setup up CI/CD**. It brings you to a `.gitlab-ci.yml`
+1. On the left sidebar, select **Search or go to** and find your `ecs-demo` project.
+1. Select **Set up CI/CD**. It brings you to a `.gitlab-ci.yml`
creation form.
1. Copy and paste the following content into the empty `.gitlab-ci.yml`. This defines
a pipeline for continuous deployment to ECS.
@@ -184,7 +178,7 @@ Now, the demo application is accessible from the internet.
In this guide, HTTPS/SSL is **not** configured. You can access to the application through HTTP only
(for example, `http://<ec2-ipv4-address>`).
-## Setup Continuous Deployment from GitLab
+## Set up Continuous Deployment from GitLab
Now that you have an application running on ECS, you can set up continuous deployment from GitLab.
@@ -213,7 +207,7 @@ Do not share the secret access key in a public place. You must save it in a secu
You can register the access information in [GitLab CI/CD Variables](../../variables/index.md).
These variables are injected into the pipeline jobs and can access the ECS API.
-1. Go to **ecs-demo** project on GitLab.
+1. On the left sidebar, select **Search or go to** and find your `ecs-demo` project.
1. Go to **Settings > CI/CD > Variables**.
1. Select **Add Variable** and set the following key-value pairs.
@@ -230,8 +224,8 @@ These variables are injected into the pipeline jobs and can access the ECS API.
Change a file in the project and see if it's reflected in the demo application on ECS:
-1. Go to **ecs-demo** project on GitLab.
-1. Open the file at **app > views > welcome > `index.html.erb`**.
+1. On the left sidebar, select **Search or go to** and find your `ecs-demo` project.
+1. Open the `app/views/welcome/index.html.erb` file.
1. Select **Edit**.
1. Change the text to `You're on ECS!`.
1. Select **Commit Changes**. This automatically triggers a new pipeline. Wait until it finishes.
diff --git a/doc/ci/cloud_deployment/ecs/img/rails-template.png b/doc/ci/cloud_deployment/ecs/img/rails-template.png
deleted file mode 100644
index 02c67f8dd21..00000000000
--- a/doc/ci/cloud_deployment/ecs/img/rails-template.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/components/index.md b/doc/ci/components/index.md
index b6975280915..3b26d8ffe2c 100644
--- a/doc/ci/components/index.md
+++ b/doc/ci/components/index.md
@@ -313,13 +313,13 @@ ensure-job-added:
exit 1
fi
-# If we are tagging a release with a specific convention ("v" + number) and all
-# previous checks succeeded, we proceed with creating a release automatically.
+# If we are tagging a release with a semantic version and all previous checks succeeded,
+# we proceed with creating a release automatically.
create-release:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest
rules:
- - if: $CI_COMMIT_TAG =~ /^v\d+/
+ - if: $CI_COMMIT_TAG =~ /\d+/
script: echo "Creating release $CI_COMMIT_TAG"
release:
tag_name: $CI_COMMIT_TAG
diff --git a/doc/ci/examples/index.md b/doc/ci/examples/index.md
index ea3cb9fa1f7..93ac30c0171 100644
--- a/doc/ci/examples/index.md
+++ b/doc/ci/examples/index.md
@@ -150,7 +150,7 @@ For examples of others who have implemented GitLab CI/CD, see:
- [Test all the things in GitLab CI with Docker by example](https://about.gitlab.com/blog/2018/02/05/test-all-the-things-gitlab-ci-docker-examples/)
- [A Craftsman looks at continuous integration](https://about.gitlab.com/blog/2018/01/17/craftsman-looks-at-continuous-integration/)
- [Go tools and GitLab: How to do continuous integration like a boss](https://about.gitlab.com/blog/2017/11/27/go-tools-and-gitlab-how-to-do-continuous-integration-like-a-boss/)
-- [GitBot – automating boring Git operations with CI](https://about.gitlab.com/blog/2017/11/02/automating-boring-git-operations-gitlab-ci/)
+- [GitBot - automating boring Git operations with CI](https://about.gitlab.com/blog/2017/11/02/automating-boring-git-operations-gitlab-ci/)
- [How to use GitLab CI for Vue.js](https://about.gitlab.com/blog/2017/09/12/vuejs-app-gitlab/)
- Video: [GitLab CI/CD Deep Dive](https://youtu.be/pBe4t1CD8Fc?t=195)
- [Dockerizing GitLab Review Apps](https://about.gitlab.com/blog/2017/07/11/dockerizing-review-apps/)
diff --git a/doc/ci/pipeline_editor/index.md b/doc/ci/pipeline_editor/index.md
index 1dc6bc05e71..c7bd402bd23 100644
--- a/doc/ci/pipeline_editor/index.md
+++ b/doc/ci/pipeline_editor/index.md
@@ -45,7 +45,11 @@ The **Lint** tab is replaced with the **Validate** tab in GitLab 15.3. The lint
in a successful [pipeline simulation](#simulate-a-cicd-pipeline).
To test the validity of your GitLab CI/CD configuration before committing the changes,
-you can use the CI lint tool. To access it, go to **Build > Pipeline editor** and select the **Lint** tab.
+you can use the CI lint tool:
+
+1. On the left sidebar, select **Search or go to** and find your project.
+1. Select **Build > Pipeline editor**.
+1. Select the **Lint** tab.
This tool checks for syntax and logical errors but goes into more detail than the
automatic [validation](#validate-ci-configuration) in the editor.
diff --git a/doc/ci/pipelines/downstream_pipelines.md b/doc/ci/pipelines/downstream_pipelines.md
index 21ed66ef939..ec1b6a4dba3 100644
--- a/doc/ci/pipelines/downstream_pipelines.md
+++ b/doc/ci/pipelines/downstream_pipelines.md
@@ -671,9 +671,7 @@ the ones defined in the upstream project take precedence.
### Pass dotenv variables created in a job **(PREMIUM ALL)**
-You can pass variables to a downstream job with [`dotenv` variable inheritance](../variables/index.md#pass-an-environment-variable-to-another-job)
-and [`needs:project`](../yaml/index.md#needsproject). These variables are only available in
-the script of the job and can't be used to configure it, for example with `rules` or `artifact:paths`.
+You can pass variables to a downstream pipeline with [`dotenv` variable inheritance](../variables/index.md#pass-an-environment-variable-to-another-job).
For example, in a [multi-project pipeline](#multi-project-pipelines):
diff --git a/doc/ci/testing/browser_performance_testing.md b/doc/ci/testing/browser_performance_testing.md
index 23e8cf80d74..28d3c97166f 100644
--- a/doc/ci/testing/browser_performance_testing.md
+++ b/doc/ci/testing/browser_performance_testing.md
@@ -135,11 +135,11 @@ be extended for dynamic environments, but a few extra steps are required:
1. The `browser_performance` job should run after the dynamic environment has started.
1. In the `review` job:
- 1. Generate a URL list file with the dynamic URL.
- 1. Save the file as an artifact, for example with `echo $CI_ENVIRONMENT_URL > environment_url.txt`
- in your job's `script`.
- 1. Pass the list as the URL environment variable (which can be a URL or a file containing URLs)
- to the `browser_performance` job.
+ 1. Generate a URL list file with the dynamic URL.
+ 1. Save the file as an artifact, for example with `echo $CI_ENVIRONMENT_URL > environment_url.txt`
+ in your job's `script`.
+ 1. Pass the list as the URL environment variable (which can be a URL or a file containing URLs)
+ to the `browser_performance` job.
1. You can now run the sitespeed.io container against the desired hostname and
paths.
diff --git a/doc/ci/testing/code_quality.md b/doc/ci/testing/code_quality.md
index 1819361ea86..fd42496902a 100644
--- a/doc/ci/testing/code_quality.md
+++ b/doc/ci/testing/code_quality.md
@@ -520,15 +520,15 @@ Code Quality functionality can be extended by using Code Climate
For example, to use the [SonarJava analyzer](https://docs.codeclimate.com/docs/sonar-java):
1. Add a file named `.codeclimate.yml` to the root of your repository
-1. Add to the `.codeclimate.yml` the [enablement code](https://docs.codeclimate.com/docs/sonar-java#enable-the-plugin)
- for the plugin to the root of your repository:
+1. Add the [enablement code](https://docs.codeclimate.com/docs/sonar-java#enable-the-plugin)
+ for the plugin to the root of your repository to the `.codeclimate.yml` file:
- ```yaml
- version: "2"
- plugins:
- sonar-java:
- enabled: true
- ```
+ ```yaml
+ version: "2"
+ plugins:
+ sonar-java:
+ enabled: true
+ ```
This adds SonarJava to the `plugins:` section of the
[default `.codeclimate.yml`](https://gitlab.com/gitlab-org/ci-cd/codequality/-/blob/master/codeclimate_defaults/.codeclimate.yml.template)
diff --git a/doc/development/documentation/styleguide/word_list.md b/doc/development/documentation/styleguide/word_list.md
index ec7c3dc270c..a8f7759741d 100644
--- a/doc/development/documentation/styleguide/word_list.md
+++ b/doc/development/documentation/styleguide/word_list.md
@@ -294,9 +294,18 @@ Use **check out** as a verb. For the Git command, use `checkout`.
- Use `git checkout` to check out a branch locally.
- Check out the files you want to edit.
+## CI, CD
+
+When talking about GitLab features, use **CI/CD**. Do not use **CI** or **CD** alone.
+
## CI/CD
-CI/CD is always uppercase. No need to spell it out on first use.
+**CI/CD** is always uppercase. No need to spell it out on first use.
+
+You can omit **CI/CD** when the context is clear, especially after the first use. For example:
+
+- Test your code in a **CI/CD pipeline**. Configure the **pipeline** to run for merge requests.
+- Store the value in a **CI/CD variable**. Set the **variable** to masked.
## CI/CD minutes
@@ -651,6 +660,12 @@ of the fields at once. For example:
Learn more about [documenting multiple fields at once](index.md#documenting-multiple-fields-at-once).
+## file name
+
+Use two words for **file name**.
+
+([Vale](../testing.md#vale) rule: [`SubstitutionWarning.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/SubstitutionWarning.yml))
+
## filter
When you are viewing a list of items, like issues or merge requests, you filter the list by
diff --git a/doc/gitlab-basics/start-using-git.md b/doc/gitlab-basics/start-using-git.md
index 588c9125485..8a222087914 100644
--- a/doc/gitlab-basics/start-using-git.md
+++ b/doc/gitlab-basics/start-using-git.md
@@ -62,13 +62,13 @@ If your computer doesn't recognize `git` as a command, you must [install Git](..
## Configure Git
To start using Git from your computer, you must enter your credentials
-to identify yourself as the author of your work. The username and email address
+to identify yourself as the author of your work. The full name and email address
should match the ones you use in GitLab.
-1. In your shell, add your user name:
+1. In your shell, add your full name:
```shell
- git config --global user.name "your_username"
+ git config --global user.name "John Doe"
```
1. Add your email address:
diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md
index e29b33469ab..5539165d285 100644
--- a/doc/user/group/saml_sso/scim_setup.md
+++ b/doc/user/group/saml_sso/scim_setup.md
@@ -19,6 +19,8 @@ When SCIM is enabled for a GitLab group, membership of that group is synchronize
The [internal GitLab group SCIM API](../../../development/internal_api/index.md#group-scim-api) implements part of [the RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644).
Identity providers can use the [internal GitLab group SCIM API](../../../development/internal_api/index.md#group-scim-api) to develop a SCIM app.
+To set up SCIM on GitLab self-managed, see [Configure SCIM for self-managed GitLab instances](../../../administration/settings/scim_setup.md).
+
## Configure GitLab
Prerequisites:
diff --git a/lib/gitlab/ci/reports/sbom/source.rb b/lib/gitlab/ci/reports/sbom/source.rb
index b7af6ea17c3..7d284b5babf 100644
--- a/lib/gitlab/ci/reports/sbom/source.rb
+++ b/lib/gitlab/ci/reports/sbom/source.rb
@@ -5,28 +5,14 @@ module Gitlab
module Reports
module Sbom
class Source
+ include SourceHelper
+
attr_reader :source_type, :data
def initialize(type:, data:)
@source_type = type
@data = data
end
-
- def source_file_path
- data.dig('source_file', 'path')
- end
-
- def input_file_path
- data.dig('input_file', 'path')
- end
-
- def packager
- data.dig('package_manager', 'name')
- end
-
- def language
- data.dig('language', 'name')
- end
end
end
end
diff --git a/lib/gitlab/ci/reports/sbom/source_helper.rb b/lib/gitlab/ci/reports/sbom/source_helper.rb
new file mode 100644
index 00000000000..49b606f658b
--- /dev/null
+++ b/lib/gitlab/ci/reports/sbom/source_helper.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Reports
+ module Sbom
+ module SourceHelper
+ def source_file_path
+ data.dig('source_file', 'path')
+ end
+
+ def input_file_path
+ data.dig('input_file', 'path')
+ end
+
+ def packager
+ data.dig('package_manager', 'name')
+ end
+
+ def language
+ data.dig('language', 'name')
+ end
+
+ def image_name
+ data.dig('image', 'name')
+ end
+
+ def image_tag
+ data.dig('image', 'tag')
+ end
+
+ def operating_system_name
+ data.dig('operating_system', 'name')
+ end
+
+ def operating_system_version
+ data.dig('operating_system', 'version')
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/variables/downstream/generator.rb b/lib/gitlab/ci/variables/downstream/generator.rb
index 350d29958cf..b0e45ac0413 100644
--- a/lib/gitlab/ci/variables/downstream/generator.rb
+++ b/lib/gitlab/ci/variables/downstream/generator.rb
@@ -33,6 +33,7 @@ module Gitlab
# The order of this list refers to the priority of the variables
# The variables added later takes priority.
downstream_yaml_variables +
+ downstream_pipeline_dotenv_variables +
downstream_pipeline_variables +
downstream_pipeline_schedule_variables
end
@@ -57,6 +58,13 @@ module Gitlab
build_downstream_variables_from(pipeline_schedule_variables)
end
+ def downstream_pipeline_dotenv_variables
+ return [] unless bridge.forward_pipeline_variables?
+
+ pipeline_dotenv_variables = bridge.dependency_variables.to_a
+ build_downstream_variables_from(pipeline_dotenv_variables)
+ end
+
def build_downstream_variables_from(variables)
Gitlab::Ci::Variables::Collection.fabricate(variables).flat_map do |item|
if item.raw?
diff --git a/lib/gitlab/git.rb b/lib/gitlab/git.rb
index 37f593ed551..8cbd1a4ce72 100644
--- a/lib/gitlab/git.rb
+++ b/lib/gitlab/git.rb
@@ -12,6 +12,13 @@ module Gitlab
TAG_REF_PREFIX = "refs/tags/"
BRANCH_REF_PREFIX = "refs/heads/"
+ # NOTE: We don't use linguist anymore, but we'd still want to support it
+ # to be backward/GitHub compatible. Using `gitlab-*` prefixed overrides
+ # going forward would give us a better control and flexibility.
+ ATTRIBUTE_OVERRIDES = {
+ generated: %w[gitlab-generated linguist-generated]
+ }.freeze
+
CommandError = Class.new(BaseError)
CommitError = Class.new(BaseError)
OSError = Class.new(BaseError)
diff --git a/lib/gitlab/git/compare.rb b/lib/gitlab/git/compare.rb
index ab5245ba7cb..c6d678c9432 100644
--- a/lib/gitlab/git/compare.rb
+++ b/lib/gitlab/git/compare.rb
@@ -42,6 +42,16 @@ module Gitlab
options[:straight] = @straight
Gitlab::Git::Diff.between(@repository, @head.id, @base.id, options, *paths)
end
+
+ def generated_files
+ return Set.new unless @base && @head
+
+ changed_paths = @repository
+ .find_changed_paths([Gitlab::Git::DiffTree.new(@base.id, @head.id)])
+ .map(&:path)
+
+ @repository.detect_generated_files(@base.id, changed_paths)
+ end
end
end
end
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 5b41461c918..848705028ca 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -1207,6 +1207,7 @@ module Gitlab
gitaly_repository_client
.get_file_attributes(revision, file_paths, attributes)
.attribute_infos
+ .map(&:to_h)
end
end
@@ -1216,6 +1217,16 @@ module Gitlab
end
end
+ # rubocop: disable CodeReuse/ActiveRecord -- not an active record operation
+ def detect_generated_files(revision, paths)
+ return Set.new if paths.blank?
+
+ get_file_attributes(revision, paths, Gitlab::Git::ATTRIBUTE_OVERRIDES[:generated])
+ .pluck(:path)
+ .to_set
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
private
def repository_info_size_megabytes
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index dbdb65531de..d1dcf5af2ce 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -6690,6 +6690,9 @@ msgstr ""
msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
+msgid "Ask GitLab Duo"
+msgstr ""
+
msgid "Ask a maintainer to check the import status for more details."
msgstr ""
@@ -47769,14 +47772,23 @@ msgstr ""
msgid "TanukiBot|Give feedback"
msgstr ""
+msgid "TanukiBot|How to use GitLab"
+msgstr ""
+
msgid "TanukiBot|Source"
msgid_plural "TanukiBot|Sources"
msgstr[0] ""
msgstr[1] ""
+msgid "TanukiBot|The issue, epic, or code you're viewing"
+msgstr ""
+
msgid "TanukiBot|There was an error communicating with GitLab Duo Chat. Please try again later."
msgstr ""
+msgid "TanukiBot|Use AI to answer questions about things like:"
+msgstr ""
+
msgid "TanukiBot|What is a fork?"
msgstr ""
diff --git a/rubocop/cop/background_migration/dictionary_file.rb b/rubocop/cop/background_migration/dictionary_file.rb
index 9ae47260e79..90a42135c41 100644
--- a/rubocop/cop/background_migration/dictionary_file.rb
+++ b/rubocop/cop/background_migration/dictionary_file.rb
@@ -3,6 +3,8 @@
require_relative '../../migration_helpers'
require_relative '../../batched_background_migrations_dictionary'
+URL_PATTERN = %r{\Ahttps://gitlab\.com/gitlab-org/gitlab/-/merge_requests/\d+\z}
+
module RuboCop
module Cop
module BackgroundMigration
@@ -11,6 +13,7 @@ module RuboCop
include MigrationHelpers
MSG = {
+ invalid_url: "Invalid `%{key}` url for the dictionary. Please use the following format: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/XXX",
missing_key: "Mandatory key '%{key}' is missing from the dictionary. Please add with an appropriate value.",
missing_dictionary: <<-MESSAGE.delete("\n").squeeze(' ').strip
Missing %{file_name}.
@@ -49,6 +52,10 @@ module RuboCop
private
+ def valid_url?(url)
+ url.match?(URL_PATTERN)
+ end
+
def dictionary_file?(migration_class_name)
File.exist?(dictionary_file_path(migration_class_name))
end
@@ -67,6 +74,8 @@ module RuboCop
return [:missing_key, { key: :finalize_after }] unless bbm_dictionary.finalize_after.present?
return [:missing_key, { key: :introduced_by_url }] unless bbm_dictionary.introduced_by_url.present?
+
+ return [:invalid_url, { key: :introduced_by_url }] unless valid_url?(bbm_dictionary.introduced_by_url)
end
def rails_root
diff --git a/spec/factories/ci/reports/sbom/sources.rb b/spec/factories/ci/reports/sbom/sources.rb
index 688c0250b5f..a82dac1d7e2 100644
--- a/spec/factories/ci/reports/sbom/sources.rb
+++ b/spec/factories/ci/reports/sbom/sources.rb
@@ -2,21 +2,50 @@
FactoryBot.define do
factory :ci_reports_sbom_source, class: '::Gitlab::Ci::Reports::Sbom::Source' do
- type { :dependency_scanning }
+ dependency_scanning
- transient do
- sequence(:input_file_path) { |n| "subproject-#{n}/package-lock.json" }
- sequence(:source_file_path) { |n| "subproject-#{n}/package.json" }
+ trait :dependency_scanning do
+ type { :dependency_scanning }
+
+ transient do
+ sequence(:input_file_path) { |n| "subproject-#{n}/package-lock.json" }
+ sequence(:source_file_path) { |n| "subproject-#{n}/package.json" }
+ end
+
+ data do
+ {
+ 'category' => 'development',
+ 'input_file' => { 'path' => input_file_path },
+ 'source_file' => { 'path' => source_file_path },
+ 'package_manager' => { 'name' => 'npm' },
+ 'language' => { 'name' => 'JavaScript' }
+ }
+ end
end
- data do
- {
- 'category' => 'development',
- 'input_file' => { 'path' => input_file_path },
- 'source_file' => { 'path' => source_file_path },
- 'package_manager' => { 'name' => 'npm' },
- 'language' => { 'name' => 'JavaScript' }
- }
+ trait :container_scanning do
+ type { :container_scanning }
+
+ transient do
+ image_name { 'photon' }
+ sequence(:image_tag) { |n| "5.#{n}-12345678" }
+ operating_system_name { 'Photon OS' }
+ sequence(:operating_system_version) { |n| "5.#{n}" }
+ end
+
+ data do
+ {
+ 'category' => 'development',
+ 'image' => {
+ 'name' => image_name,
+ 'tag' => image_tag
+ },
+ 'operating_system' => {
+ 'name' => operating_system_name,
+ 'version' => operating_system_version
+ }
+ }
+ end
end
skip_create
diff --git a/spec/features/projects/settings/webhooks_settings_spec.rb b/spec/features/projects/settings/webhooks_settings_spec.rb
index af7c790c692..506f7666286 100644
--- a/spec/features/projects/settings/webhooks_settings_spec.rb
+++ b/spec/features/projects/settings/webhooks_settings_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Projects > Settings > Webhook Settings', feature_category: :groups_and_projects do
+RSpec.describe 'Projects > Settings > Webhook Settings', feature_category: :webhooks do
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:webhooks_path) { project_hooks_path(project) }
diff --git a/spec/frontend/content_editor/extensions/reference_spec.js b/spec/frontend/content_editor/extensions/reference_spec.js
index c25c7c41d75..d4b07d5127e 100644
--- a/spec/frontend/content_editor/extensions/reference_spec.js
+++ b/spec/frontend/content_editor/extensions/reference_spec.js
@@ -1,9 +1,15 @@
import Reference from '~/content_editor/extensions/reference';
+import ReferenceLabel from '~/content_editor/extensions/reference_label';
import AssetResolver from '~/content_editor/services/asset_resolver';
import {
RESOLVED_ISSUE_HTML,
RESOLVED_MERGE_REQUEST_HTML,
RESOLVED_EPIC_HTML,
+ RESOLVED_LABEL_HTML,
+ RESOLVED_SNIPPET_HTML,
+ RESOLVED_MILESTONE_HTML,
+ RESOLVED_USER_HTML,
+ RESOLVED_VULNERABILITY_HTML,
} from '../test_constants';
import {
createTestEditor,
@@ -17,6 +23,7 @@ describe('content_editor/extensions/reference', () => {
let doc;
let p;
let reference;
+ let referenceLabel;
let renderMarkdown;
let assetResolver;
@@ -25,33 +32,54 @@ describe('content_editor/extensions/reference', () => {
assetResolver = new AssetResolver({ renderMarkdown });
tiptapEditor = createTestEditor({
- extensions: [Reference.configure({ assetResolver })],
+ extensions: [Reference.configure({ assetResolver }), ReferenceLabel],
});
({
- builders: { doc, p, reference },
+ builders: { doc, p, reference, referenceLabel },
} = createDocBuilder({
tiptapEditor,
names: {
reference: { nodeType: Reference.name },
+ referenceLabel: { nodeType: ReferenceLabel.name },
},
}));
});
describe('when typing a valid reference input rule', () => {
- const buildExpectedDoc = (href, originalText, referenceType, text) =>
+ const buildExpectedDoc = (href, originalText, referenceType, text = originalText) =>
doc(p(reference({ className: null, href, originalText, referenceType, text }), ' '));
+ const buildExpectedDocForLabel = (href, originalText, text, color) =>
+ doc(
+ p(
+ referenceLabel({
+ className: null,
+ referenceType: 'label',
+ href,
+ originalText,
+ text,
+ color,
+ }),
+ ' ',
+ ),
+ );
+
it.each`
- inputRuleText | mockReferenceHtml | expectedDoc
- ${'#1 '} | ${RESOLVED_ISSUE_HTML} | ${() => buildExpectedDoc('/gitlab-org/gitlab/-/issues/1', '#1', 'issue', '#1 (closed)')}
- ${'#1+ '} | ${RESOLVED_ISSUE_HTML} | ${() => buildExpectedDoc('/gitlab-org/gitlab/-/issues/1', '#1+', 'issue', '500 error on MR approvers edit page (#1 - closed)')}
- ${'#1+s '} | ${RESOLVED_ISSUE_HTML} | ${() => buildExpectedDoc('/gitlab-org/gitlab/-/issues/1', '#1+s', 'issue', '500 error on MR approvers edit page (#1 - closed) • Unassigned')}
- ${'!1 '} | ${RESOLVED_MERGE_REQUEST_HTML} | ${() => buildExpectedDoc('/gitlab-org/gitlab/-/merge_requests/1', '!1', 'merge_request', '!1 (merged)')}
- ${'!1+ '} | ${RESOLVED_MERGE_REQUEST_HTML} | ${() => buildExpectedDoc('/gitlab-org/gitlab/-/merge_requests/1', '!1+', 'merge_request', 'Enhance the LDAP group synchronization (!1 - merged)')}
- ${'!1+s '} | ${RESOLVED_MERGE_REQUEST_HTML} | ${() => buildExpectedDoc('/gitlab-org/gitlab/-/merge_requests/1', '!1+s', 'merge_request', 'Enhance the LDAP group synchronization (!1 - merged) • John Doe')}
- ${'&1 '} | ${RESOLVED_EPIC_HTML} | ${() => buildExpectedDoc('/groups/gitlab-org/-/epics/1', '&1', 'epic', '&1')}
- ${'&1+ '} | ${RESOLVED_EPIC_HTML} | ${() => buildExpectedDoc('/groups/gitlab-org/-/epics/1', '&1+', 'epic', 'Approvals in merge request list (&1)')}
+ inputRuleText | mockReferenceHtml | expectedDoc
+ ${'#1'} | ${RESOLVED_ISSUE_HTML} | ${() => buildExpectedDoc('/gitlab-org/gitlab/-/issues/1', '#1', 'issue', '#1 (closed)')}
+ ${'#1+'} | ${RESOLVED_ISSUE_HTML} | ${() => buildExpectedDoc('/gitlab-org/gitlab/-/issues/1', '#1+', 'issue', '500 error on MR approvers edit page (#1 - closed)')}
+ ${'#1+s'} | ${RESOLVED_ISSUE_HTML} | ${() => buildExpectedDoc('/gitlab-org/gitlab/-/issues/1', '#1+s', 'issue', '500 error on MR approvers edit page (#1 - closed) • Unassigned')}
+ ${'!1'} | ${RESOLVED_MERGE_REQUEST_HTML} | ${() => buildExpectedDoc('/gitlab-org/gitlab/-/merge_requests/1', '!1', 'merge_request', '!1 (merged)')}
+ ${'!1+'} | ${RESOLVED_MERGE_REQUEST_HTML} | ${() => buildExpectedDoc('/gitlab-org/gitlab/-/merge_requests/1', '!1+', 'merge_request', 'Enhance the LDAP group synchronization (!1 - merged)')}
+ ${'!1+s'} | ${RESOLVED_MERGE_REQUEST_HTML} | ${() => buildExpectedDoc('/gitlab-org/gitlab/-/merge_requests/1', '!1+s', 'merge_request', 'Enhance the LDAP group synchronization (!1 - merged) • John Doe')}
+ ${'&1'} | ${RESOLVED_EPIC_HTML} | ${() => buildExpectedDoc('/groups/gitlab-org/-/epics/1', '&1', 'epic', '&1')}
+ ${'&1+'} | ${RESOLVED_EPIC_HTML} | ${() => buildExpectedDoc('/groups/gitlab-org/-/epics/1', '&1+', 'epic', 'Approvals in merge request list (&1)')}
+ ${'@root'} | ${RESOLVED_USER_HTML} | ${() => buildExpectedDoc('/root', '@root', 'user')}
+ ${'~Aquanix'} | ${RESOLVED_LABEL_HTML} | ${() => buildExpectedDocForLabel('/gitlab-org/gitlab-shell/-/issues?label_name=Aquanix', '~Aquanix', 'Aquanix', 'rgb(230, 84, 49)')}
+ ${'%v4.0'} | ${RESOLVED_MILESTONE_HTML} | ${() => buildExpectedDoc('/gitlab-org/gitlab-shell/-/milestones/5', '%v4.0', 'milestone')}
+ ${'$25'} | ${RESOLVED_SNIPPET_HTML} | ${() => buildExpectedDoc('/gitlab-org/gitlab-shell/-/snippets/25', '$25', 'snippet')}
+ ${'[vulnerability:1]'} | ${RESOLVED_VULNERABILITY_HTML} | ${() => buildExpectedDoc('/gitlab-org/gitlab-shell/-/security/vulnerabilities/1', '[vulnerability:1]', 'vulnerability')}
`(
'replaces the input rule ($inputRuleText) with a reference node',
async ({ inputRuleText, mockReferenceHtml, expectedDoc }) => {
@@ -61,8 +89,8 @@ describe('content_editor/extensions/reference', () => {
action() {
renderMarkdown.mockResolvedValueOnce(mockReferenceHtml);
- tiptapEditor.commands.insertContent({ type: 'text', text: inputRuleText });
- triggerNodeInputRule({ tiptapEditor, inputRuleText });
+ tiptapEditor.commands.insertContent({ type: 'text', text: `${inputRuleText} ` });
+ triggerNodeInputRule({ tiptapEditor, inputRuleText: `${inputRuleText} ` });
},
});
diff --git a/spec/frontend/content_editor/services/asset_resolver_spec.js b/spec/frontend/content_editor/services/asset_resolver_spec.js
index 292eec6db77..b0135a6bc9f 100644
--- a/spec/frontend/content_editor/services/asset_resolver_spec.js
+++ b/spec/frontend/content_editor/services/asset_resolver_spec.js
@@ -3,6 +3,11 @@ import {
RESOLVED_ISSUE_HTML,
RESOLVED_MERGE_REQUEST_HTML,
RESOLVED_EPIC_HTML,
+ RESOLVED_LABEL_HTML,
+ RESOLVED_SNIPPET_HTML,
+ RESOLVED_MILESTONE_HTML,
+ RESOLVED_USER_HTML,
+ RESOLVED_VULNERABILITY_HTML,
} from '../test_constants';
describe('content_editor/services/asset_resolver', () => {
@@ -48,6 +53,32 @@ describe('content_editor/services/asset_resolver', () => {
text: '!1 (merged)',
};
+ const resolvedLabel = {
+ backgroundColor: 'rgb(230, 84, 49)',
+ href: '/gitlab-org/gitlab-shell/-/issues?label_name=Aquanix',
+ text: 'Aquanix',
+ };
+
+ const resolvedSnippet = {
+ href: '/gitlab-org/gitlab-shell/-/snippets/25',
+ text: '$25',
+ };
+
+ const resolvedMilestone = {
+ href: '/gitlab-org/gitlab-shell/-/milestones/5',
+ text: '%v4.0',
+ };
+
+ const resolvedUser = {
+ href: '/root',
+ text: '@root',
+ };
+
+ const resolvedVulnerability = {
+ href: '/gitlab-org/gitlab-shell/-/security/vulnerabilities/1',
+ text: '[vulnerability:1]',
+ };
+
describe.each`
referenceType | referenceId | sentMarkdown | returnedHtml | resolvedReference
${'issue'} | ${'#1'} | ${'#1 #1+ #1+s'} | ${RESOLVED_ISSUE_HTML} | ${resolvedIssue}
@@ -59,7 +90,9 @@ describe('content_editor/services/asset_resolver', () => {
it(`resolves ${referenceType} reference to href, text, title and summary`, async () => {
renderMarkdown.mockResolvedValue(returnedHtml);
- expect(await assetResolver.resolveReference(referenceId)).toEqual(resolvedReference);
+ expect(await assetResolver.resolveReference(referenceId)).toMatchObject(
+ resolvedReference,
+ );
});
it.each`
@@ -74,6 +107,26 @@ describe('content_editor/services/asset_resolver', () => {
},
);
+ describe.each`
+ referenceType | referenceId | returnedHtml | resolvedReference
+ ${'label'} | ${'~Aquanix'} | ${RESOLVED_LABEL_HTML} | ${resolvedLabel}
+ ${'snippet'} | ${'$25'} | ${RESOLVED_SNIPPET_HTML} | ${resolvedSnippet}
+ ${'milestone'} | ${'%v4.0'} | ${RESOLVED_MILESTONE_HTML} | ${resolvedMilestone}
+ ${'user'} | ${'@root'} | ${RESOLVED_USER_HTML} | ${resolvedUser}
+ ${'vulnerability'} | ${'[vulnerability:1]'} | ${RESOLVED_VULNERABILITY_HTML} | ${resolvedVulnerability}
+ `(
+ 'for reference type $referenceType',
+ ({ referenceType, referenceId, returnedHtml, resolvedReference }) => {
+ it(`resolves ${referenceType} reference to href, text and additional props (if any)`, async () => {
+ renderMarkdown.mockResolvedValue(returnedHtml);
+
+ expect(await assetResolver.resolveReference(referenceId)).toMatchObject(
+ resolvedReference,
+ );
+ });
+ },
+ );
+
it.each`
case | sentMarkdown | returnedHtml
${'no html is returned'} | ${''} | ${''}
diff --git a/spec/frontend/content_editor/test_constants.js b/spec/frontend/content_editor/test_constants.js
index cbd4f555e97..255a7104eaf 100644
--- a/spec/frontend/content_editor/test_constants.js
+++ b/spec/frontend/content_editor/test_constants.js
@@ -44,3 +44,18 @@ export const RESOLVED_MERGE_REQUEST_HTML =
export const RESOLVED_EPIC_HTML =
'<p data-sourcepos="1:1-1:11" dir="auto"><a href="/groups/gitlab-org/-/epics/1" data-reference-type="epic" data-original="&amp;amp;1" data-link="false" data-link-reference="false" data-group="9970" data-epic="1" data-container="body" data-placement="top" title="Approvals in merge request list" class="gfm gfm-epic has-tooltip">&amp;1</a> <a href="/groups/gitlab-org/-/epics/1" data-reference-type="epic" data-original="&amp;amp;1+" data-link="false" data-link-reference="false" data-group="9970" data-epic="1" data-reference-format="+" data-container="body" data-placement="top" title="Approvals in merge request list" class="gfm gfm-epic has-tooltip">Approvals in merge request list (&amp;1)</a> <a href="/groups/gitlab-org/-/epics/1" data-reference-type="epic" data-original="&amp;amp;1+s" data-link="false" data-link-reference="false" data-group="9970" data-epic="1" data-reference-format="+s" data-container="body" data-placement="top" title="Approvals in merge request list" class="gfm gfm-epic has-tooltip">Approvals in merge request list (&amp;1)</a></p>';
+
+export const RESOLVED_LABEL_HTML =
+ '<p data-sourcepos="1:1-1:29" dir="auto"><span class="gl-label gl-label-sm"><a href="/gitlab-org/gitlab-shell/-/issues?label_name=Aquanix" data-reference-type="label" data-original="~Aquanix" data-link="false" data-link-reference="false" data-project="2" data-label="5" data-container="body" data-placement="top" title="" class="gfm gfm-label has-tooltip gl-link gl-label-link"><span class="gl-label-text gl-label-text-light" data-container="body" data-html="true" style="background-color: #e65431">Aquanix</span></a></span> <span class="gl-label gl-label-sm"><a href="/gitlab-org/gitlab-shell/-/issues?label_name=Aquanix" data-reference-type="label" data-original="~Aquanix" data-link="false" data-link-reference="false" data-project="2" data-label="5" data-container="body" data-placement="top" title="" class="gfm gfm-label has-tooltip gl-link gl-label-link"><span class="gl-label-text gl-label-text-light" data-container="body" data-html="true" style="background-color: #e65431">Aquanix</span></a></span>+ <span class="gl-label gl-label-sm"><a href="/gitlab-org/gitlab-shell/-/issues?label_name=Aquanix" data-reference-type="label" data-original="~Aquanix" data-link="false" data-link-reference="false" data-project="2" data-label="5" data-container="body" data-placement="top" title="" class="gfm gfm-label has-tooltip gl-link gl-label-link"><span class="gl-label-text gl-label-text-light" data-container="body" data-html="true" style="background-color: #e65431">Aquanix</span></a></span>+s</p>';
+
+export const RESOLVED_SNIPPET_HTML =
+ '<p data-sourcepos="1:1-1:14" dir="auto"><a href="/gitlab-org/gitlab-shell/-/snippets/25" data-reference-type="snippet" data-original="$25" data-link="false" data-link-reference="false" data-project="2" data-snippet="25" data-container="body" data-placement="top" title="test" class="gfm gfm-snippet has-tooltip">$25</a> <a href="/gitlab-org/gitlab-shell/-/snippets/25" data-reference-type="snippet" data-original="$25" data-link="false" data-link-reference="false" data-project="2" data-snippet="25" data-container="body" data-placement="top" title="test" class="gfm gfm-snippet has-tooltip">$25</a>+ <a href="/gitlab-org/gitlab-shell/-/snippets/25" data-reference-type="snippet" data-original="$25" data-link="false" data-link-reference="false" data-project="2" data-snippet="25" data-container="body" data-placement="top" title="test" class="gfm gfm-snippet has-tooltip">$25</a>+s</p>';
+
+export const RESOLVED_MILESTONE_HTML =
+ '<p data-sourcepos="1:1-1:20" dir="auto"><a href="/gitlab-org/gitlab-shell/-/milestones/5" data-reference-type="milestone" data-original="%v4.0" data-link="false" data-link-reference="false" data-project="2" data-milestone="10" data-container="body" data-placement="top" title="" class="gfm gfm-milestone has-tooltip">%v4.0</a> <a href="/gitlab-org/gitlab-shell/-/milestones/5" data-reference-type="milestone" data-original="%v4.0" data-link="false" data-link-reference="false" data-project="2" data-milestone="10" data-container="body" data-placement="top" title="" class="gfm gfm-milestone has-tooltip">%v4.0</a>+ %v4.0+s</p>';
+
+export const RESOLVED_USER_HTML =
+ '<p data-sourcepos="1:1-1:20" dir="auto"><a href="/root" data-reference-type="user" data-user="1" data-container="body" data-placement="top" class="gfm gfm-project_member js-user-link" title="Administrator">@root</a> <a href="/root" data-reference-type="user" data-user="1" data-container="body" data-placement="top" class="gfm gfm-project_member js-user-link" title="Administrator">@root</a>+ <a href="/root" data-reference-type="user" data-user="1" data-container="body" data-placement="top" class="gfm gfm-project_member js-user-link" title="Administrator">@root</a>+s</p>';
+
+export const RESOLVED_VULNERABILITY_HTML =
+ '<p data-sourcepos="1:1-1:56" dir="auto"><a href="/gitlab-org/gitlab-shell/-/security/vulnerabilities/1" data-reference-type="vulnerability" data-original="[vulnerability:1]" data-link="false" data-link-reference="false" data-project="2" data-vulnerability="1" data-container="body" data-placement="top" title="oh no!" class="gfm gfm-vulnerability has-tooltip">[vulnerability:1]</a> <a href="/gitlab-org/gitlab-shell/-/security/vulnerabilities/1" data-reference-type="vulnerability" data-original="[vulnerability:1]" data-link="false" data-link-reference="false" data-project="2" data-vulnerability="1" data-container="body" data-placement="top" title="oh no!" class="gfm gfm-vulnerability has-tooltip">[vulnerability:1]</a>+ <a href="/gitlab-org/gitlab-shell/-/security/vulnerabilities/1" data-reference-type="vulnerability" data-original="[vulnerability:1]" data-link="false" data-link-reference="false" data-project="2" data-vulnerability="1" data-container="body" data-placement="top" title="oh no!" class="gfm gfm-vulnerability has-tooltip">[vulnerability:1]</a>+s</p>';
diff --git a/spec/lib/gitlab/ci/reports/sbom/source_spec.rb b/spec/lib/gitlab/ci/reports/sbom/source_spec.rb
index c1eaea511b7..09a601833ad 100644
--- a/spec/lib/gitlab/ci/reports/sbom/source_spec.rb
+++ b/spec/lib/gitlab/ci/reports/sbom/source_spec.rb
@@ -5,47 +5,93 @@ require 'fast_spec_helper'
RSpec.describe Gitlab::Ci::Reports::Sbom::Source, feature_category: :dependency_management do
let(:attributes) do
{
- type: :dependency_scanning,
- data: {
- 'category' => 'development',
- 'input_file' => { 'path' => 'package-lock.json' },
- 'source_file' => { 'path' => 'package.json' },
- 'package_manager' => { 'name' => 'npm' },
- 'language' => { 'name' => 'JavaScript' }
- }
+ type: type,
+ data: { 'category' => 'development',
+ 'package_manager' => { 'name' => 'npm' },
+ 'language' => { 'name' => 'JavaScript' } }.merge(extra_attributes)
}
end
- subject { described_class.new(**attributes) }
+ subject(:source) { described_class.new(**attributes) }
- it 'has correct attributes' do
- expect(subject).to have_attributes(
- source_type: attributes[:type],
- data: attributes[:data]
- )
- end
+ shared_examples_for 'it has correct common attributes' do
+ it 'has correct type and data' do
+ expect(subject).to have_attributes(
+ source_type: type,
+ data: attributes[:data]
+ )
+ end
- describe '#source_file_path' do
- it 'returns the correct source_file_path' do
- expect(subject.source_file_path).to eq('package.json')
+ describe '#packager' do
+ it 'returns the correct package manager name' do
+ expect(subject.packager).to eq("npm")
+ end
end
- end
- describe '#input_file_path' do
- it 'returns the correct input_file_path' do
- expect(subject.input_file_path).to eq("package-lock.json")
+ describe '#language' do
+ it 'returns the correct language' do
+ expect(subject.language).to eq("JavaScript")
+ end
end
end
- describe '#packager' do
- it 'returns the correct package manager name' do
- expect(subject.packager).to eq("npm")
+ context 'when dependency scanning' do
+ let(:type) { :dependency_scanning }
+ let(:extra_attributes) do
+ {
+ 'input_file' => { 'path' => 'package-lock.json' },
+ 'source_file' => { 'path' => 'package.json' }
+ }
+ end
+
+ it_behaves_like 'it has correct common attributes'
+
+ describe '#source_file_path' do
+ it 'returns the correct source_file_path' do
+ expect(subject.source_file_path).to eq('package.json')
+ end
+ end
+
+ describe '#input_file_path' do
+ it 'returns the correct input_file_path' do
+ expect(subject.input_file_path).to eq("package-lock.json")
+ end
end
end
- describe '#language' do
- it 'returns the correct langauge' do
- expect(subject.language).to eq("JavaScript")
+ context 'when container scanning' do
+ let(:type) { :container_scanning }
+ let(:extra_attributes) do
+ {
+ "image" => { "name" => "rhel", "tag" => "7.1" },
+ "operating_system" => { "name" => "Red Hat Enterprise Linux", "version" => "7" }
+ }
+ end
+
+ it_behaves_like 'it has correct common attributes'
+
+ describe "#image_name" do
+ subject { source.image_name }
+
+ it { is_expected.to eq("rhel") }
+ end
+
+ describe "#image_tag" do
+ subject { source.image_tag }
+
+ it { is_expected.to eq("7.1") }
+ end
+
+ describe "#operating_system_name" do
+ subject { source.operating_system_name }
+
+ it { is_expected.to eq("Red Hat Enterprise Linux") }
+ end
+
+ describe "#operating_system_version" do
+ subject { source.operating_system_version }
+
+ it { is_expected.to eq("7") }
end
end
end
diff --git a/spec/lib/gitlab/ci/variables/downstream/generator_spec.rb b/spec/lib/gitlab/ci/variables/downstream/generator_spec.rb
index cd68b0cdf2b..f5845e492bc 100644
--- a/spec/lib/gitlab/ci/variables/downstream/generator_spec.rb
+++ b/spec/lib/gitlab/ci/variables/downstream/generator_spec.rb
@@ -39,6 +39,15 @@ RSpec.describe Gitlab::Ci::Variables::Downstream::Generator, feature_category: :
]
end
+ let(:pipeline_dotenv_variables) do
+ [
+ { key: 'PIPELINE_DOTENV_VAR1', value: 'variable 1' },
+ { key: 'PIPELINE_DOTENV_VAR2', value: 'variable 2' },
+ { key: 'PIPELINE_DOTENV_RAW_VAR3', value: '$REF1', raw: true },
+ { key: 'PIPELINE_DOTENV_INTERPOLATION_VAR4', value: 'interpolate $REF1 $REF2' }
+ ]
+ end
+
let(:bridge) do
instance_double(
'Ci::Bridge',
@@ -48,7 +57,8 @@ RSpec.describe Gitlab::Ci::Variables::Downstream::Generator, feature_category: :
expand_file_refs?: false,
yaml_variables: yaml_variables,
pipeline_variables: pipeline_variables,
- pipeline_schedule_variables: pipeline_schedule_variables
+ pipeline_schedule_variables: pipeline_schedule_variables,
+ dependency_variables: pipeline_dotenv_variables
)
end
@@ -69,7 +79,12 @@ RSpec.describe Gitlab::Ci::Variables::Downstream::Generator, feature_category: :
{ key: 'PIPELINE_SCHEDULE_VAR1', value: 'variable 1' },
{ key: 'PIPELINE_SCHEDULE_VAR2', value: 'variable 2' },
{ key: 'PIPELINE_SCHEDULE_RAW_VAR3', value: '$REF1', raw: true },
- { key: 'PIPELINE_SCHEDULE_INTERPOLATION_VAR4', value: 'interpolate ref 1 ref 2' }
+ { key: 'PIPELINE_SCHEDULE_INTERPOLATION_VAR4', value: 'interpolate ref 1 ref 2' },
+ { key: 'PIPELINE_DOTENV_VAR1', value: 'variable 1' },
+ { key: 'PIPELINE_DOTENV_VAR2', value: 'variable 2' },
+ { key: 'PIPELINE_DOTENV_RAW_VAR3', value: '$REF1', raw: true },
+ { key: 'PIPELINE_DOTENV_INTERPOLATION_VAR4', value: 'interpolate ref 1 ref 2' }
+
]
expect(generator.calculate).to contain_exactly(*expected)
@@ -79,6 +94,7 @@ RSpec.describe Gitlab::Ci::Variables::Downstream::Generator, feature_category: :
allow(bridge).to receive(:yaml_variables).and_return([])
allow(bridge).to receive(:pipeline_variables).and_return([])
allow(bridge).to receive(:pipeline_schedule_variables).and_return([])
+ allow(bridge).to receive(:dependency_variables).and_return([])
expect(generator.calculate).to be_empty
end
@@ -105,6 +121,10 @@ RSpec.describe Gitlab::Ci::Variables::Downstream::Generator, feature_category: :
[{ key: 'PIPELINE_SCHEDULE_INTERPOLATION_VAR', value: 'interpolate $REF1 $REF2 $FILE_REF3 $FILE_REF4' }]
end
+ let(:pipeline_dotenv_variables) do
+ [{ key: 'PIPELINE_DOTENV_INTERPOLATION_VAR', value: 'interpolate $REF1 $REF2 $FILE_REF3 $FILE_REF4' }]
+ end
+
context 'when expand_file_refs is true' do
before do
allow(bridge).to receive(:expand_file_refs?).and_return(true)
@@ -114,7 +134,8 @@ RSpec.describe Gitlab::Ci::Variables::Downstream::Generator, feature_category: :
expected = [
{ key: 'INTERPOLATION_VAR', value: 'interpolate ref 1 ref 3 ' },
{ key: 'PIPELINE_INTERPOLATION_VAR', value: 'interpolate ref 1 ref 3 ' },
- { key: 'PIPELINE_SCHEDULE_INTERPOLATION_VAR', value: 'interpolate ref 1 ref 3 ' }
+ { key: 'PIPELINE_SCHEDULE_INTERPOLATION_VAR', value: 'interpolate ref 1 ref 3 ' },
+ { key: 'PIPELINE_DOTENV_INTERPOLATION_VAR', value: 'interpolate ref 1 ref 3 ' }
]
expect(generator.calculate).to contain_exactly(*expected)
@@ -131,6 +152,7 @@ RSpec.describe Gitlab::Ci::Variables::Downstream::Generator, feature_category: :
{ key: 'INTERPOLATION_VAR', value: 'interpolate ref 1 $FILE_REF3 ' },
{ key: 'PIPELINE_INTERPOLATION_VAR', value: 'interpolate ref 1 $FILE_REF3 ' },
{ key: 'PIPELINE_SCHEDULE_INTERPOLATION_VAR', value: 'interpolate ref 1 $FILE_REF3 ' },
+ { key: 'PIPELINE_DOTENV_INTERPOLATION_VAR', value: 'interpolate ref 1 $FILE_REF3 ' },
{ key: 'FILE_REF3', value: 'ref 3', variable_type: :file }
]
diff --git a/spec/lib/gitlab/git/compare_spec.rb b/spec/lib/gitlab/git/compare_spec.rb
index 01079203c1f..5ee5e18d5af 100644
--- a/spec/lib/gitlab/git/compare_spec.rb
+++ b/spec/lib/gitlab/git/compare_spec.rb
@@ -3,10 +3,13 @@
require "spec_helper"
RSpec.describe Gitlab::Git::Compare, feature_category: :source_code_management do
- let_it_be(:repository) { create(:project, :repository).repository.raw }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:repository) { project.repository.raw }
- let(:compare) { described_class.new(repository, SeedRepo::BigCommit::ID, SeedRepo::Commit::ID, straight: false) }
- let(:compare_straight) { described_class.new(repository, SeedRepo::BigCommit::ID, SeedRepo::Commit::ID, straight: true) }
+ let(:compare) { described_class.new(repository, base, head, straight: false) }
+ let(:compare_straight) { described_class.new(repository, base, head, straight: true) }
+ let(:base) { SeedRepo::BigCommit::ID }
+ let(:head) { SeedRepo::Commit::ID }
describe '#commits' do
subject do
@@ -109,4 +112,103 @@ RSpec.describe Gitlab::Git::Compare, feature_category: :source_code_management d
it { is_expected.to include('files/ruby/popen.rb') }
it { is_expected.not_to include('LICENSE') }
end
+
+ describe '#generated_files' do
+ subject(:generated_files) { compare.generated_files }
+
+ context 'with a detected generated file' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:repository) { project.repository.raw }
+ let_it_be(:branch) { 'generated-file-test' }
+ let_it_be(:base) do
+ project
+ .repository
+ .create_file(
+ project.creator,
+ '.gitattributes',
+ "*.txt gitlab-generated\n",
+ branch_name: branch,
+ message: 'Add .gitattributes file')
+ end
+
+ let_it_be(:head) do
+ project
+ .repository
+ .create_file(
+ project.creator,
+ 'file1.rb',
+ "some content\n",
+ branch_name: branch,
+ message: 'Add file1')
+ project
+ .repository
+ .create_file(
+ project.creator,
+ 'file1.txt',
+ "some content\n",
+ branch_name: branch,
+ message: 'Add file2')
+ end
+
+ it 'sets the diff as generated' do
+ expect(generated_files).to eq Set.new(['file1.txt'])
+ end
+
+ context 'when base is nil' do
+ let(:base) { nil }
+
+ it 'does not try to detect generated files' do
+ expect(repository).not_to receive(:detect_generated_files)
+ expect(repository).not_to receive(:find_changed_paths)
+ expect(generated_files).to eq Set.new
+ end
+ end
+
+ context 'when head is nil' do
+ let(:head) { nil }
+
+ it 'does not try to detect generated files' do
+ expect(repository).not_to receive(:detect_generated_files)
+ expect(repository).not_to receive(:find_changed_paths)
+ expect(generated_files).to eq Set.new
+ end
+ end
+ end
+
+ context 'with updated .gitattributes in the HEAD' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:repository) { project.repository.raw }
+ let_it_be(:branch) { 'generated-file-test' }
+ let_it_be(:head) do
+ project
+ .repository
+ .create_file(
+ project.creator,
+ '.gitattributes',
+ "*.txt gitlab-generated\n",
+ branch_name: branch,
+ message: 'Add .gitattributes file')
+ project
+ .repository
+ .create_file(
+ project.creator,
+ 'file1.rb',
+ "some content\n",
+ branch_name: branch,
+ message: 'Add file1')
+ project
+ .repository
+ .create_file(
+ project.creator,
+ 'file1.txt',
+ "some content\n",
+ branch_name: branch,
+ message: 'Add file2')
+ end
+
+ it 'does not set any files as generated' do
+ expect(generated_files).to eq Set.new
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index 40c9bbeda77..cc07a16d362 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -2812,4 +2812,69 @@ RSpec.describe Gitlab::Git::Repository, feature_category: :source_code_managemen
subject { repository.get_file_attributes(rev, paths, attrs) }
end
end
+
+ describe '#detect_generated_files' do
+ let(:project) do
+ create(:project, :custom_repo, files: {
+ '.gitattributes' => gitattr_content,
+ 'file1.txt' => 'first file',
+ 'file2.txt' => 'second file'
+ })
+ end
+
+ let(:repository) { project.repository.raw }
+ let(:rev) { 'master' }
+ let(:paths) { ['file1.txt', 'file2.txt'] }
+
+ subject(:generated_files) { repository.detect_generated_files(rev, paths) }
+
+ context 'when the linguist-generated attribute is used' do
+ let(:gitattr_content) { "*.txt text\nfile1.txt linguist-generated\n" }
+
+ it 'returns generated files only' do
+ expect(generated_files).to contain_exactly('file1.txt')
+ end
+ end
+
+ context 'when the gitlab-generated attribute is used' do
+ let(:gitattr_content) { "*.txt text\nfile1.txt gitlab-generated\n" }
+
+ it 'returns generated files only' do
+ expect(generated_files).to contain_exactly('file1.txt')
+ end
+ end
+
+ context 'when both linguist-generated and gitlab-generated attribute are used' do
+ let(:gitattr_content) { "*.txt text\nfile1.txt linguist-generated gitlab-generated\n" }
+
+ it 'returns generated files only' do
+ expect(generated_files).to contain_exactly('file1.txt')
+ end
+ end
+
+ context 'when the all files are generated' do
+ let(:gitattr_content) { "*.txt gitlab-generated\n" }
+
+ it 'returns all generated files' do
+ expect(generated_files).to eq paths.to_set
+ end
+ end
+
+ context 'when empty paths are given' do
+ let(:paths) { [] }
+ let(:gitattr_content) { "*.txt gitlab-generated\n" }
+
+ it 'returns an empty set' do
+ expect(generated_files).to eq Set.new
+ end
+ end
+
+ context 'when no generated overrides are used' do
+ let(:gitattr_content) { "*.txt text\n" }
+
+ it 'returns an empty set' do
+ expect(generated_files).to eq Set.new
+ end
+ end
+ end
end
diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb
index 726c98ed704..4ddd17c6bae 100644
--- a/spec/models/ability_spec.rb
+++ b/spec/models/ability_spec.rb
@@ -518,6 +518,27 @@ RSpec.describe Ability do
end
describe '.allowed?' do
+ context "when used with 'read_namespace'" do
+ subject(:allowed?) { described_class.allowed?(nil, 'read_namespace') }
+
+ before do
+ allow(Gitlab::AppLogger).to receive(:info)
+ end
+
+ it 'logs the usage', :aggregate_failures do
+ allowed?
+
+ expect(Gitlab::AppLogger).to have_received(:info) do |args|
+ expect(args[:message]).to eq('Ability is in use')
+ expect(args[:ability]).to eq(:read_namespace)
+ expect(args[:caller_locations].first).to(
+ match(%r{spec/models/ability_spec.rb})
+ )
+ expect(args[:caller_locations].length).to eq(5)
+ end
+ end
+ end
+
context 'when used with :read_namespace' do
subject(:allowed?) { described_class.allowed?(nil, :read_namespace) }
@@ -532,7 +553,7 @@ RSpec.describe Ability do
expect(args[:message]).to eq('Ability is in use')
expect(args[:ability]).to eq(:read_namespace)
expect(args[:caller_locations].first).to(
- match(%r{/spec/models/ability_spec.rb:\d+:in `block \(4 levels\) in <top \(required\)>})
+ match(%r{spec/models/ability_spec.rb})
)
expect(args[:caller_locations].length).to eq(5)
end
diff --git a/spec/models/concerns/enums/sbom_spec.rb b/spec/models/concerns/enums/sbom_spec.rb
index e2f56cc637d..3bbdf619a8c 100644
--- a/spec/models/concerns/enums/sbom_spec.rb
+++ b/spec/models/concerns/enums/sbom_spec.rb
@@ -3,9 +3,9 @@
require "spec_helper"
RSpec.describe Enums::Sbom, feature_category: :dependency_management do
- describe '.purl_types' do
- using RSpec::Parameterized::TableSyntax
+ using RSpec::Parameterized::TableSyntax
+ describe '.purl_types' do
subject(:actual_purl_type) { described_class.purl_types[package_manager] }
where(:given_package_manager, :expected_purl_type) do
@@ -35,5 +35,63 @@ RSpec.describe Enums::Sbom, feature_category: :dependency_management do
expect(actual_purl_type).to eql(expected_purl_type)
end
end
+
+ it 'contains all of the dependency scanning and container scanning purl types' do
+ expect(described_class::DEPENDENCY_SCANNING_PURL_TYPES + described_class::CONTAINER_SCANNING_PURL_TYPES)
+ .to eql(described_class::PURL_TYPES.keys)
+ end
+ end
+
+ describe '.dependency_scanning_purl_type?' do
+ where(:purl_type, :expected) do
+ :composer | false
+ 'composer' | true
+ 'conan' | true
+ 'gem' | true
+ 'golang' | true
+ 'maven' | true
+ 'npm' | true
+ 'nuget' | true
+ 'pypi' | true
+ 'unknown' | false
+ 'apk' | false
+ 'rpm' | false
+ 'deb' | false
+ 'wolfi' | false
+ end
+
+ with_them do
+ it 'returns true if the purl_type is for dependency_scanning' do
+ actual = described_class.dependency_scanning_purl_type?(purl_type)
+ expect(actual).to eql(expected)
+ end
+ end
+ end
+
+ describe '.container_scanning_purl_type?' do
+ where(:purl_type, :expected) do
+ 'composer' | false
+ 'conan' | false
+ 'gem' | false
+ 'golang' | false
+ 'maven' | false
+ 'npm' | false
+ 'nuget' | false
+ 'pypi' | false
+ 'unknown' | false
+ :apk | false
+ 'apk' | true
+ 'rpm' | true
+ 'deb' | true
+ 'cbl-mariner' | true
+ 'wolfi' | true
+ end
+
+ with_them do
+ it 'returns true if the purl_type is for container_scanning' do
+ actual = described_class.container_scanning_purl_type?(purl_type)
+ expect(actual).to eql(expected)
+ end
+ end
end
end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 2c70b80074b..08679626c21 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -4052,59 +4052,4 @@ RSpec.describe Repository, feature_category: :source_code_management do
it { expect { file_attributes }.to raise_error(ArgumentError) }
end
end
-
- describe '#filter_generated_files' do
- let(:project) do
- create(:project, :custom_repo, files: {
- '.gitattributes' => gitattr_content,
- 'file1.txt' => 'first file',
- 'file2.txt' => 'second file'
- })
- end
-
- let(:rev) { 'master' }
- let(:paths) { ['file1.txt', 'file2.txt'] }
-
- subject(:generated_files) { repository.filter_generated_files(rev, paths) }
-
- context 'when the linguist-generated attribute is used' do
- let(:gitattr_content) { "*.txt text\nfile1.txt linguist-generated\n" }
-
- it 'returns generated files only' do
- expect(generated_files).to contain_exactly('file2.txt')
- end
- end
-
- context 'when the gitlab-generated attribute is used' do
- let(:gitattr_content) { "*.txt text\nfile1.txt gitlab-generated\n" }
-
- it 'returns generated files only' do
- expect(generated_files).to contain_exactly('file2.txt')
- end
- end
-
- context 'when both linguist-generated and gitlab-generated attribute are used' do
- let(:gitattr_content) { "*.txt text\nfile1.txt linguist-generated gitlab-generated\n" }
-
- it 'returns generated files only' do
- expect(generated_files).to contain_exactly('file2.txt')
- end
- end
-
- context 'when no generated overrides are used' do
- let(:gitattr_content) { "*.txt text\n" }
-
- it 'returns the original paths' do
- expect(generated_files).to eq paths
- end
- end
-
- context 'when the given files are generated' do
- let(:gitattr_content) { "*.txt gitlab-generated\n" }
-
- it 'returns an empty array' do
- expect(generated_files).to eq []
- end
- end
- end
end
diff --git a/spec/rubocop/cop/background_migration/dictionary_file_spec.rb b/spec/rubocop/cop/background_migration/dictionary_file_spec.rb
index 7becf9c09a4..4fa7dede093 100644
--- a/spec/rubocop/cop/background_migration/dictionary_file_spec.rb
+++ b/spec/rubocop/cop/background_migration/dictionary_file_spec.rb
@@ -134,7 +134,7 @@ RSpec.describe RuboCop::Cop::BackgroundMigration::DictionaryFile, feature_catego
end
context 'with dictionary file' do
- let(:introduced_by_url) { 'https://test_url' }
+ let(:introduced_by_url) { 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/132639' }
let(:finalize_after) { '20230507160251' }
before do
@@ -158,6 +158,25 @@ RSpec.describe RuboCop::Cop::BackgroundMigration::DictionaryFile, feature_catego
end
end
+ context 'when the `introduced_by_url` is not correct' do
+ let(:introduced_by_url) { 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/132639/invalid' }
+
+ it 'throws offense on having a correct url' do
+ expect_offense(<<~RUBY)
+ class QueueMyMigration < Gitlab::Database::Migration[2.1]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{format('Invalid `introduced_by_url` url for the dictionary. Please use the following format: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/XXX')}
+ def up
+ queue_batched_background_migration(
+ 'MyMigration',
+ :users,
+ :id
+ )
+ end
+ end
+ RUBY
+ end
+ end
+
context 'with required dictionary keys' do
it 'does not throw offense with appropriate dictionary file' do
expect_no_offenses(<<~RUBY)
diff --git a/spec/services/ml/create_model_version_service_spec.rb b/spec/services/ml/create_model_version_service_spec.rb
index ea3e2f654d4..4e71c538f7e 100644
--- a/spec/services/ml/create_model_version_service_spec.rb
+++ b/spec/services/ml/create_model_version_service_spec.rb
@@ -25,4 +25,41 @@ RSpec.describe ::Ml::CreateModelVersionService, feature_category: :mlops do
expect(model.reload.latest_version.version).to eq('4.0.0')
end
end
+
+ context 'when a version is created' do
+ it 'creates a package' do
+ expect { service }.to change { Ml::ModelVersion.count }.by(1).and change {
+ Packages::MlModel::Package.count
+ }.by(1)
+ expect(model.reload.latest_version.package.name).to eq(model.name)
+ expect(model.latest_version.package.version).to eq(model.latest_version.version)
+ end
+ end
+
+ context 'when a version is created and the package already exists' do
+ it 'does not creates a package' do
+ next_version = Ml::IncrementVersionService.new(model.latest_version.try(:version)).execute
+ create(:ml_model_package, name: model.name, version: next_version, project: model.project)
+
+ expect { service }.to change { Ml::ModelVersion.count }.by(1).and not_change {
+ Packages::MlModel::Package.count
+ }
+ expect(model.reload.latest_version.package.name).to eq(model.name)
+ expect(model.latest_version.package.version).to eq(model.latest_version.version)
+ end
+ end
+
+ context 'when a version is created and an existing package supplied' do
+ it 'does not creates a package' do
+ next_version = Ml::IncrementVersionService.new(model.latest_version.try(:version)).execute
+ package = create(:ml_model_package, name: model.name, version: next_version, project: model.project)
+ service = described_class.new(model, { package: package })
+
+ expect { service.execute }.to change { Ml::ModelVersion.count }.by(1).and not_change {
+ Packages::MlModel::Package.count
+ }
+ expect(model.reload.latest_version.package.name).to eq(model.name)
+ expect(model.latest_version.package.version).to eq(model.latest_version.version)
+ end
+ end
end