diff --git a/app/graphql/types/packages/package_base_type.rb b/app/graphql/types/packages/package_base_type.rb
index 2dc4a2a2bb6..9ec4bb73c47 100644
--- a/app/graphql/types/packages/package_base_type.rb
+++ b/app/graphql/types/packages/package_base_type.rb
@@ -12,6 +12,8 @@ module Types
field :id, ::Types::GlobalIDType[::Packages::Package], null: false, description: 'ID of the package.'
+ field :_links, Types::Packages::PackageLinksType, null: false, method: :itself,
+ description: 'Map of links to perform actions on the package.'
field :can_destroy, GraphQL::Types::Boolean, null: false, description: 'Whether the user can destroy the package.'
field :created_at, Types::TimeType, null: false, description: 'Date of creation.'
field :metadata, Types::Packages::MetadataType,
diff --git a/app/graphql/types/packages/package_links_type.rb b/app/graphql/types/packages/package_links_type.rb
new file mode 100644
index 00000000000..f16937530b9
--- /dev/null
+++ b/app/graphql/types/packages/package_links_type.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Types
+ module Packages
+ class PackageLinksType < BaseObject
+ graphql_name 'PackageLinks'
+ description 'Represents links to perform actions on the package'
+ authorize :read_package
+
+ include ::Routing::PackagesHelper
+
+ field :web_path, GraphQL::Types::String, null: true, description: 'Path to the package details page.'
+
+ def web_path
+ package_path(object)
+ end
+ end
+ end
+end
diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb
index 1be395437ea..178e9d0ab74 100644
--- a/app/helpers/gitlab_routing_helper.rb
+++ b/app/helpers/gitlab_routing_helper.rb
@@ -17,6 +17,7 @@ module GitlabRoutingHelper
include ::Routing::WikiHelper
include ::Routing::GraphqlHelper
include ::Routing::PseudonymizationHelper
+ include ::Routing::PackagesHelper
included do
Gitlab::Routing.includes_helpers(self)
end
diff --git a/app/helpers/routing/packages_helper.rb b/app/helpers/routing/packages_helper.rb
new file mode 100644
index 00000000000..4e76be3b5a3
--- /dev/null
+++ b/app/helpers/routing/packages_helper.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Routing
+ module PackagesHelper
+ def package_path(package, **options)
+ Gitlab::UrlBuilder.build(package, only_path: true, **options)
+ end
+ end
+end
diff --git a/app/models/ci/group_variable.rb b/app/models/ci/group_variable.rb
index e11edbda6dc..508aaa5a63c 100644
--- a/app/models/ci/group_variable.rb
+++ b/app/models/ci/group_variable.rb
@@ -5,6 +5,7 @@ module Ci
include Ci::HasVariable
include Presentable
include Ci::Maskable
+ include Ci::RawVariable
prepend HasEnvironmentScope
belongs_to :group, class_name: "::Group"
diff --git a/app/models/ci/instance_variable.rb b/app/models/ci/instance_variable.rb
index da9d4dea537..3e572dbe18f 100644
--- a/app/models/ci/instance_variable.rb
+++ b/app/models/ci/instance_variable.rb
@@ -5,6 +5,7 @@ module Ci
extend Gitlab::ProcessMemoryCache::Helper
include Ci::NewHasVariable
include Ci::Maskable
+ include Ci::RawVariable
include Limitable
self.limit_name = 'ci_instance_level_variables'
diff --git a/app/models/ci/job_variable.rb b/app/models/ci/job_variable.rb
index 44bd3fe8901..332a78b66ae 100644
--- a/app/models/ci/job_variable.rb
+++ b/app/models/ci/job_variable.rb
@@ -3,6 +3,7 @@
module Ci
class JobVariable < Ci::ApplicationRecord
include Ci::NewHasVariable
+ include Ci::RawVariable
include BulkInsertSafe
belongs_to :job, class_name: "Ci::Build", foreign_key: :job_id
diff --git a/app/models/ci/pipeline_schedule_variable.rb b/app/models/ci/pipeline_schedule_variable.rb
index 84a24609cc7..718ed14edeb 100644
--- a/app/models/ci/pipeline_schedule_variable.rb
+++ b/app/models/ci/pipeline_schedule_variable.rb
@@ -3,6 +3,7 @@
module Ci
class PipelineScheduleVariable < Ci::ApplicationRecord
include Ci::HasVariable
+ include Ci::RawVariable
belongs_to :pipeline_schedule
diff --git a/app/models/ci/pipeline_variable.rb b/app/models/ci/pipeline_variable.rb
index 6e4418bc360..8e83b41cd0b 100644
--- a/app/models/ci/pipeline_variable.rb
+++ b/app/models/ci/pipeline_variable.rb
@@ -4,6 +4,7 @@ module Ci
class PipelineVariable < Ci::ApplicationRecord
include Ci::Partitionable
include Ci::HasVariable
+ include Ci::RawVariable
belongs_to :pipeline
diff --git a/app/models/ci/variable.rb b/app/models/ci/variable.rb
index c80c2ebe69a..f4e17b5d812 100644
--- a/app/models/ci/variable.rb
+++ b/app/models/ci/variable.rb
@@ -5,6 +5,7 @@ module Ci
include Ci::HasVariable
include Presentable
include Ci::Maskable
+ include Ci::RawVariable
prepend HasEnvironmentScope
belongs_to :project
diff --git a/app/models/concerns/ci/raw_variable.rb b/app/models/concerns/ci/raw_variable.rb
new file mode 100644
index 00000000000..5cfc781c9f1
--- /dev/null
+++ b/app/models/concerns/ci/raw_variable.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Ci
+ module RawVariable
+ extend ActiveSupport::Concern
+
+ included do
+ validates :raw, inclusion: { in: [true, false] }
+ end
+
+ private
+
+ def uncached_runner_variable
+ super.merge(raw: raw?)
+ end
+ end
+end
diff --git a/app/views/admin/users/_users.html.haml b/app/views/admin/users/_users.html.haml
index 8c77cb394ba..6d85ff50fbe 100644
--- a/app/views/admin/users/_users.html.haml
+++ b/app/views/admin/users/_users.html.haml
@@ -54,7 +54,7 @@
= hidden_field_tag "filter", h(params[:filter])
.search-holder
.search-field-holder.gl-mb-4
- = search_field_tag :search_query, params[:search_query], placeholder: s_('AdminUsers|Search by name, email or username'), class: 'form-control search-text-input js-search-input', spellcheck: false, data: { qa_selector: 'user_search_field' }
+ = search_field_tag :search_query, params[:search_query], placeholder: s_('AdminUsers|Search by name, email, or username'), class: 'form-control search-text-input js-search-input', spellcheck: false, data: { qa_selector: 'user_search_field' }
- if @sort.present?
= hidden_field_tag :sort, @sort
= sprite_icon('search', css_class: 'search-icon')
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index adea0d05308..23c36796f16 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -15696,6 +15696,7 @@ Represents a package with pipelines in the Package Registry.
| Name | Type | Description |
| ---- | ---- | ----------- |
+| `_links` | [`PackageLinks!`](#packagelinks) | Map of links to perform actions on the package. |
| `canDestroy` | [`Boolean!`](#boolean) | Whether the user can destroy the package. |
| `createdAt` | [`Time!`](#time) | Date of creation. |
| `id` | [`PackagesPackageID!`](#packagespackageid) | ID of the package. |
@@ -15717,6 +15718,7 @@ Represents a package in the Package Registry.
| Name | Type | Description |
| ---- | ---- | ----------- |
+| `_links` | [`PackageLinks!`](#packagelinks) | Map of links to perform actions on the package. |
| `canDestroy` | [`Boolean!`](#boolean) | Whether the user can destroy the package. |
| `createdAt` | [`Time!`](#time) | Date of creation. |
| `id` | [`PackagesPackageID!`](#packagespackageid) | ID of the package. |
@@ -15775,6 +15777,7 @@ Represents a package details in the Package Registry.
| Name | Type | Description |
| ---- | ---- | ----------- |
+| `_links` | [`PackageLinks!`](#packagelinks) | Map of links to perform actions on the package. |
| `canDestroy` | [`Boolean!`](#boolean) | Whether the user can destroy the package. |
| `composerConfigRepositoryUrl` | [`String`](#string) | Url of the Composer setup endpoint. |
| `composerUrl` | [`String`](#string) | Url of the Composer endpoint. |
@@ -15893,6 +15896,16 @@ Represents the contents of a Helm Chart.yml file.
| `type` | [`String`](#string) | Type of the chart. |
| `version` | [`String!`](#string) | Version of the chart. |
+### `PackageLinks`
+
+Represents links to perform actions on the package.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| `webPath` | [`String`](#string) | Path to the package details page. |
+
### `PackageSettings`
Namespace-level Package Registry settings.
diff --git a/doc/development/database/adding_database_indexes.md b/doc/development/database/adding_database_indexes.md
index 040c6780316..d4cd807ef22 100644
--- a/doc/development/database/adding_database_indexes.md
+++ b/doc/development/database/adding_database_indexes.md
@@ -215,6 +215,42 @@ def down
end
```
+## Indexes for partitioned tables
+
+Indexes [cannot be created](https://www.postgresql.org/docs/15/ddl-partitioning.html#DDL-PARTITIONING-DECLARATIVE-MAINTENANCE)
+**concurrently** on a partitioned table. You must use `CONCURRENTLY` to avoid service disruption in a hot system.
+
+To create an index on a partitioned table, use `add_concurrent_partitioned_index`, provided by the database team.
+
+Under the hood, `add_concurrent_partitioned_index`:
+
+1. Creates indexes on each partition using `CONCURRENTLY`.
+1. Creates an index on the parent table.
+
+A Rails migration example:
+
+```ruby
+# in db/post_migrate/
+
+class AddIndexToPartitionedTable < Gitlab::Database::Migration[2.0]
+ include Gitlab::Database::PartitioningMigrationHelpers
+
+ disable_ddl_transaction!
+
+ TABLE_NAME = :table_name
+ COLUMN_NAMES = [:partition_id, :id]
+ INDEX_NAME = :index_name
+
+ def up
+ add_concurrent_partitioned_index(TABLE_NAME, COLUMN_NAMES, name: INDEX_NAME)
+ end
+
+ def down
+ remove_concurrent_partitioned_index_by_name(TABLE_NAME, INDEX_NAME)
+ end
+end
+```
+
## Create indexes asynchronously
For very large tables, index creation can be a challenge to manage.
diff --git a/doc/update/index.md b/doc/update/index.md
index 06609f03952..38c0df68fc5 100644
--- a/doc/update/index.md
+++ b/doc/update/index.md
@@ -376,6 +376,8 @@ Upgrading across multiple GitLab versions in one go is *only possible by accepti
The following examples assume downtime is acceptable while upgrading.
If you don't want any downtime, read how to [upgrade with zero downtime](zero_downtime.md).
+For a dynamic view of examples of supported upgrade paths, try the [Upgrade Path tool](https://gitlab-com.gitlab.io/support/toolbox/upgrade-path/) maintained by the [GitLab Support team](https://about.gitlab.com/handbook/support/#about-the-support-team). To share feedback and help improve the tool, create an issue or MR in the [upgrade-path project](https://gitlab.com/gitlab-com/support/toolbox/upgrade-path).
+
Find where your version sits in the upgrade path below, and upgrade GitLab
accordingly, while also consulting the
[version-specific upgrade instructions](#version-specific-upgrading-instructions):
@@ -392,8 +394,6 @@ The following table, while not exhaustive, shows some examples of the supported
upgrade paths.
Additional steps between the mentioned versions are possible. We list the minimally necessary steps only.
-For a dynamic view of examples of supported upgrade paths, try the [Upgrade Path tool](https://gitlab-com.gitlab.io/support/toolbox/upgrade-path/). The Upgrade Path tool is maintained by the [GitLab Support team](https://about.gitlab.com/handbook/support/#about-the-support-team). Share feedback and help improve the tool by raising an issue or MR in the [upgrade-path project](https://gitlab.com/gitlab-com/support/toolbox/upgrade-path).
-
| Target version | Your version | Supported upgrade path | Note |
| -------------- | ------------ | ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `15.1.0` | `14.6.2` | `14.6.2` -> `14.9.5` -> `14.10.5` -> `15.0.2` -> `15.1.0` | Three intermediate versions are required: `14.9` and `14.10`, `15.0`, then `15.1.0`. |
diff --git a/lib/api/entities/package.rb b/lib/api/entities/package.rb
index 18fc0576dd4..9b73a142fcd 100644
--- a/lib/api/entities/package.rb
+++ b/lib/api/entities/package.rb
@@ -4,6 +4,7 @@ module API
module Entities
class Package < Grape::Entity
include ::API::Helpers::RelatedResourcesHelpers
+ include ::Routing::PackagesHelper
extend ::API::Entities::EntityHelpers
expose :id
@@ -25,12 +26,8 @@ module API
expose :status
expose :_links do
- expose :web_path do |package, opts|
- if package.infrastructure_package?
- ::Gitlab::Routing.url_helpers.namespace_project_infrastructure_registry_path(opts[:namespace], package.project, package)
- else
- ::Gitlab::Routing.url_helpers.project_package_path(package.project, package)
- end
+ expose :web_path do |package|
+ package_path(package)
end
expose :delete_api_path, if: can_destroy(:package, &:project) do |package|
diff --git a/lib/gitlab/ci/variables/collection/item.rb b/lib/gitlab/ci/variables/collection/item.rb
index ea2aa8f2db8..45faf4f63eb 100644
--- a/lib/gitlab/ci/variables/collection/item.rb
+++ b/lib/gitlab/ci/variables/collection/item.rb
@@ -48,9 +48,8 @@ module Gitlab
end
##
- # If `file: true` has been provided we expose it, otherwise we
- # don't expose `file` attribute at all (stems from what the runner
- # expects).
+ # If `file: true` or `raw: true` has been provided we expose it, otherwise we
+ # don't expose `file` and `raw` attributes at all (stems from what the runner expects).
#
def to_runner_variable
@variable.reject do |hash_key, hash_value|
diff --git a/lib/gitlab/url_builder.rb b/lib/gitlab/url_builder.rb
index a6d6cffec17..e203fb486e7 100644
--- a/lib/gitlab/url_builder.rb
+++ b/lib/gitlab/url_builder.rb
@@ -52,6 +52,8 @@ module Gitlab
wiki_page_url(object.wiki, object, **options)
when ::DesignManagement::Design
design_url(object, **options)
+ when ::Packages::Package
+ package_url(object, **options)
else
raise NotImplementedError, "No URL builder defined for #{object.inspect}"
end
@@ -133,6 +135,17 @@ module Gitlab
instance.project_design_management_designs_raw_image_url(design.project, design, ref, **options)
end
end
+
+ def package_url(package, **options)
+ project = package.project
+
+ if package.infrastructure_package?
+ return instance.project_infrastructure_registry_url(project, package,
+**options)
+ end
+
+ instance.project_package_url(project, package, **options)
+ end
end
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index cbc567249fb..bbd4f8c4bf1 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -3301,7 +3301,7 @@ msgstr ""
msgid "AdminUsers|Restore user access to the account, including web, Git and API."
msgstr ""
-msgid "AdminUsers|Search by name, email or username"
+msgid "AdminUsers|Search by name, email, or username"
msgstr ""
msgid "AdminUsers|Search users"
diff --git a/spec/fixtures/api/schemas/graphql/packages/package_details.json b/spec/fixtures/api/schemas/graphql/packages/package_details.json
index 33eb67a0280..1f3de0e0ff5 100644
--- a/spec/fixtures/api/schemas/graphql/packages/package_details.json
+++ b/spec/fixtures/api/schemas/graphql/packages/package_details.json
@@ -14,7 +14,8 @@
"versions",
"status",
"canDestroy",
- "lastDownloadedAt"
+ "lastDownloadedAt",
+ "_links"
],
"properties": {
"id": {
@@ -177,6 +178,15 @@
},
"lastDownloadedAt": {
"type": ["string", "null"]
+ },
+ "_links": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "webPath": {
+ "type": ["string", "null"]
+ }
+ }
}
}
}
diff --git a/spec/helpers/routing/packages_helper_spec.rb b/spec/helpers/routing/packages_helper_spec.rb
new file mode 100644
index 00000000000..fa5d34fed73
--- /dev/null
+++ b/spec/helpers/routing/packages_helper_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Routing::PackagesHelper do
+ describe '#package_path' do
+ let(:package) { build_stubbed(:package) }
+
+ it "creates package's path" do
+ expect(helper.package_path(package)).to eq("/#{package.project.full_path}/-/packages/#{package.id}")
+ end
+ end
+end
diff --git a/spec/lib/gitlab/url_builder_spec.rb b/spec/lib/gitlab/url_builder_spec.rb
index d4f96f1a37f..d6a1b207c87 100644
--- a/spec/lib/gitlab/url_builder_spec.rb
+++ b/spec/lib/gitlab/url_builder_spec.rb
@@ -56,6 +56,7 @@ RSpec.describe Gitlab::UrlBuilder do
:discussion_note_on_project_snippet | ->(note) { "/#{note.project.full_path}/-/snippets/#{note.noteable_id}#note_#{note.id}" }
:discussion_note_on_personal_snippet | ->(note) { "/-/snippets/#{note.noteable_id}#note_#{note.id}" }
:note_on_personal_snippet | ->(note) { "/-/snippets/#{note.noteable_id}#note_#{note.id}" }
+ :package | ->(package) { "/#{package.project.full_path}/-/packages/#{package.id}" }
end
with_them do
@@ -196,6 +197,18 @@ RSpec.describe Gitlab::UrlBuilder do
end
end
+ context 'when passing Packages::Package' do
+ let(:package) { build_stubbed(:terraform_module_package) }
+
+ context 'with infrastructure package' do
+ it 'returns the url for infrastucture registry' do
+ url = subject.build(package)
+
+ expect(url).to eq "#{Gitlab.config.gitlab.url}/#{package.project.full_path}/-/infrastructure_registry/#{package.id}"
+ end
+ end
+ end
+
context 'when passing a DesignManagement::Design' do
let(:design) { build_stubbed(:design) }
diff --git a/spec/models/concerns/ci/has_variable_spec.rb b/spec/models/concerns/ci/has_variable_spec.rb
index bf699119a37..861d8f3b974 100644
--- a/spec/models/concerns/ci/has_variable_spec.rb
+++ b/spec/models/concerns/ci/has_variable_spec.rb
@@ -84,6 +84,7 @@ RSpec.describe Ci::HasVariable do
key: subject.key,
value: subject.value,
public: false,
+ raw: false,
masked: false
}
end
diff --git a/spec/requests/api/graphql/packages/package_spec.rb b/spec/requests/api/graphql/packages/package_spec.rb
index e9f82d66775..02a3206f587 100644
--- a/spec/requests/api/graphql/packages/package_spec.rb
+++ b/spec/requests/api/graphql/packages/package_spec.rb
@@ -206,5 +206,25 @@ RSpec.describe 'package details' do
expect(graphql_data_at(:package, :composer_config_repository_url)).to eq("localhost/#{group.id}")
end
end
+
+ context 'web_path' do
+ before do
+ subject
+ end
+
+ it 'returns web_path correctly' do
+ expect(graphql_data_at(:package, :_links, :web_path)).to eq("/#{project.full_path}/-/packages/#{composer_package.id}")
+ end
+
+ context 'with terraform module' do
+ let_it_be(:terraform_package) { create(:terraform_module_package, project: project) }
+
+ let(:package_global_id) { global_id_of(terraform_package) }
+
+ it 'returns web_path correctly' do
+ expect(graphql_data_at(:package, :_links, :web_path)).to eq("/#{project.full_path}/-/infrastructure_registry/#{terraform_package.id}")
+ end
+ end
+ end
end
end