Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
de671a855f
commit
3ff1605f7d
|
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Resolvers
|
||||
module Ml
|
||||
class ModelDetailResolver < Resolvers::BaseResolver
|
||||
extension ::Gitlab::Graphql::Limit::FieldCallCount, limit: 1
|
||||
|
||||
type ::Types::Ml::ModelType, null: true
|
||||
|
||||
argument :id, ::Types::GlobalIDType[::Ml::Model],
|
||||
required: true,
|
||||
description: 'ID of the model.'
|
||||
|
||||
def resolve(id:)
|
||||
Gitlab::Graphql::Lazy.with_value(find_object(id: id)) do |ml_model|
|
||||
ml_model if current_user.can?(:read_model_registry, ml_model&.project)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Types
|
||||
module Ml
|
||||
# rubocop: disable Graphql/AuthorizeTypes -- authorization in ModelDetailsResolver
|
||||
class ModelType < ::Types::BaseObject
|
||||
graphql_name 'MlModel'
|
||||
description 'Machine learning model in the model registry'
|
||||
|
||||
field :id, ::Types::GlobalIDType[::Ml::Model], null: false, description: 'ID of the model.'
|
||||
|
||||
field :name, ::GraphQL::Types::String, null: false, description: 'Name of the model.'
|
||||
|
||||
field :versions, ::Types::Ml::ModelVersionType.connection_type, null: true,
|
||||
description: 'Versions of the model.'
|
||||
end
|
||||
# rubocop: enable Graphql/AuthorizeTypes
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Types
|
||||
module Ml
|
||||
# rubocop: disable Graphql/AuthorizeTypes -- authorization in ModelDetailsResolver
|
||||
class ModelVersionLinksType < BaseObject
|
||||
graphql_name 'MLModelVersionLinks'
|
||||
description 'Represents links to perform actions on the model version'
|
||||
|
||||
present_using ::Ml::ModelVersionPresenter
|
||||
|
||||
field :show_path, GraphQL::Types::String,
|
||||
null: true, description: 'Path to the details page of the model version.', method: :path
|
||||
end
|
||||
# rubocop: enable Graphql/AuthorizeTypes
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Types
|
||||
module Ml
|
||||
# rubocop: disable Graphql/AuthorizeTypes -- authorization in ModelDetailsResolver
|
||||
class ModelVersionType < ::Types::BaseObject
|
||||
graphql_name 'MlModelVersion'
|
||||
description 'Version of a machine learning model'
|
||||
|
||||
connection_type_class Types::LimitedCountableConnectionType
|
||||
|
||||
field :id, ::Types::GlobalIDType[::Ml::ModelVersion], null: false, description: 'ID of the model version.'
|
||||
|
||||
field :created_at, Types::TimeType, null: false, description: 'Date of creation.'
|
||||
field :version, ::GraphQL::Types::String, null: false, description: 'Name of the version.'
|
||||
|
||||
field :_links, ::Types::Ml::ModelVersionLinksType, null: false, method: :itself,
|
||||
description: 'Map of links to perform actions on the model version.'
|
||||
end
|
||||
# rubocop: enable Graphql/AuthorizeTypes
|
||||
end
|
||||
end
|
||||
|
|
@ -212,6 +212,12 @@ module Types
|
|||
description: 'Abuse report labels.',
|
||||
resolver: Resolvers::AbuseReportLabelsResolver
|
||||
|
||||
field :ml_model, ::Types::Ml::ModelType,
|
||||
null: true,
|
||||
alpha: { milestone: '16.7' },
|
||||
description: 'Find machine learning models.',
|
||||
resolver: Resolvers::Ml::ModelDetailResolver
|
||||
|
||||
def design_management
|
||||
DesignManagementObject.new(nil)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
= render 'groups/settings/subgroup_creation_level', f: f, group: @group
|
||||
= render_if_exists 'groups/settings/prevent_forking', f: f, group: @group
|
||||
= render_if_exists 'groups/settings/service_access_tokens_expiration_enforced', f: f, group: @group
|
||||
= render_if_exists 'groups/settings/enforce_ssh_certificates', f: f, group: @group
|
||||
= render 'groups/settings/two_factor_auth', f: f, group: @group
|
||||
= render_if_exists 'groups/personal_access_token_expiration_policy', f: f, group: @group
|
||||
= render 'groups/settings/membership', f: f, group: @group
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: approval_rules_disable_joins
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/136588
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/431564
|
||||
milestone: '16.7'
|
||||
type: development
|
||||
group: group::source code
|
||||
default_enabled: false
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: duo_chat_absolute_doc_links
|
||||
introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/136240'
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/431338
|
||||
milestone: '16.6'
|
||||
type: development
|
||||
group: group::ai framework
|
||||
default_enabled: false
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: enforce_ssh_certificates_via_settings
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/136498
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/426235
|
||||
milestone: '16.7'
|
||||
type: development
|
||||
group: group::source code
|
||||
default_enabled: false
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddEnforceSshCertificatesToNamespaceSettings < Gitlab::Database::Migration[2.2]
|
||||
enable_lock_retries!
|
||||
|
||||
milestone '16.7'
|
||||
|
||||
def change
|
||||
add_column :namespace_settings, :enforce_ssh_certificates, :boolean, default: false, null: false
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
2d3abd070d856db04eea298bbbe82681ca01912e19f978de876fce68ed2ada26
|
||||
|
|
@ -19463,6 +19463,7 @@ CREATE TABLE namespace_settings (
|
|||
service_access_tokens_expiration_enforced boolean DEFAULT true NOT NULL,
|
||||
product_analytics_enabled boolean DEFAULT false NOT NULL,
|
||||
allow_merge_without_pipeline boolean DEFAULT false NOT NULL,
|
||||
enforce_ssh_certificates boolean DEFAULT false NOT NULL,
|
||||
CONSTRAINT check_0ba93c78c7 CHECK ((char_length(default_branch_name) <= 255)),
|
||||
CONSTRAINT namespace_settings_unique_project_download_limit_alertlist_size CHECK ((cardinality(unique_project_download_limit_alertlist) <= 100)),
|
||||
CONSTRAINT namespace_settings_unique_project_download_limit_allowlist_size CHECK ((cardinality(unique_project_download_limit_allowlist) <= 100))
|
||||
|
|
|
|||
|
|
@ -584,6 +584,22 @@ Returns [`Milestone`](#milestone).
|
|||
| ---- | ---- | ----------- |
|
||||
| <a id="querymilestoneid"></a>`id` | [`MilestoneID!`](#milestoneid) | Find a milestone by its ID. |
|
||||
|
||||
### `Query.mlModel`
|
||||
|
||||
Find machine learning models.
|
||||
|
||||
WARNING:
|
||||
**Introduced** in 16.7.
|
||||
This feature is an Experiment. It can be changed or removed at any time.
|
||||
|
||||
Returns [`MlModel`](#mlmodel).
|
||||
|
||||
#### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="querymlmodelid"></a>`id` | [`MlModelID!`](#mlmodelid) | ID of the model. |
|
||||
|
||||
### `Query.namespace`
|
||||
|
||||
Find a namespace.
|
||||
|
|
@ -11364,6 +11380,43 @@ The edge type for [`Milestone`](#milestone).
|
|||
| <a id="milestoneedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
|
||||
| <a id="milestoneedgenode"></a>`node` | [`Milestone`](#milestone) | The item at the end of the edge. |
|
||||
|
||||
#### `MlModelVersionConnection`
|
||||
|
||||
The connection type for [`MlModelVersion`](#mlmodelversion).
|
||||
|
||||
##### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mlmodelversionconnectionedges"></a>`edges` | [`[MlModelVersionEdge]`](#mlmodelversionedge) | A list of edges. |
|
||||
| <a id="mlmodelversionconnectionnodes"></a>`nodes` | [`[MlModelVersion]`](#mlmodelversion) | A list of nodes. |
|
||||
| <a id="mlmodelversionconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
|
||||
|
||||
##### Fields with arguments
|
||||
|
||||
###### `MlModelVersionConnection.count`
|
||||
|
||||
Limited count of collection. Returns limit + 1 for counts greater than the limit.
|
||||
|
||||
Returns [`Int!`](#int).
|
||||
|
||||
####### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mlmodelversionconnectioncountlimit"></a>`limit` | [`Int`](#int) | Limit value to be applied to the count query. Default is 1000. |
|
||||
|
||||
#### `MlModelVersionEdge`
|
||||
|
||||
The edge type for [`MlModelVersion`](#mlmodelversion).
|
||||
|
||||
##### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mlmodelversionedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
|
||||
| <a id="mlmodelversionedgenode"></a>`node` | [`MlModelVersion`](#mlmodelversion) | The item at the end of the edge. |
|
||||
|
||||
#### `NamespaceCommitEmailConnection`
|
||||
|
||||
The connection type for [`NamespaceCommitEmail`](#namespacecommitemail).
|
||||
|
|
@ -20332,6 +20385,16 @@ Represents an entry from the Cloud License history.
|
|||
| <a id="locationblobpath"></a>`blobPath` | [`String`](#string) | HTTP URI path to view the input file in GitLab. |
|
||||
| <a id="locationpath"></a>`path` | [`String`](#string) | Path, relative to the root of the repository, of the filewhich was analyzed to detect the dependency. |
|
||||
|
||||
### `MLModelVersionLinks`
|
||||
|
||||
Represents links to perform actions on the model version.
|
||||
|
||||
#### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mlmodelversionlinksshowpath"></a>`showPath` | [`String`](#string) | Path to the details page of the model version. |
|
||||
|
||||
### `MavenMetadata`
|
||||
|
||||
Maven metadata.
|
||||
|
|
@ -21911,6 +21974,31 @@ Contains statistics about a milestone.
|
|||
| <a id="milestonestatsclosedissuescount"></a>`closedIssuesCount` | [`Int`](#int) | Number of closed issues associated with the milestone. |
|
||||
| <a id="milestonestatstotalissuescount"></a>`totalIssuesCount` | [`Int`](#int) | Total number of issues associated with the milestone. |
|
||||
|
||||
### `MlModel`
|
||||
|
||||
Machine learning model in the model registry.
|
||||
|
||||
#### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mlmodelid"></a>`id` | [`MlModelID!`](#mlmodelid) | ID of the model. |
|
||||
| <a id="mlmodelname"></a>`name` | [`String!`](#string) | Name of the model. |
|
||||
| <a id="mlmodelversions"></a>`versions` | [`MlModelVersionConnection`](#mlmodelversionconnection) | Versions of the model. (see [Connections](#connections)) |
|
||||
|
||||
### `MlModelVersion`
|
||||
|
||||
Version of a machine learning model.
|
||||
|
||||
#### Fields
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="mlmodelversion_links"></a>`_links` | [`MLModelVersionLinks!`](#mlmodelversionlinks) | Map of links to perform actions on the model version. |
|
||||
| <a id="mlmodelversioncreatedat"></a>`createdAt` | [`Time!`](#time) | Date of creation. |
|
||||
| <a id="mlmodelversionid"></a>`id` | [`MlModelVersionID!`](#mlmodelversionid) | ID of the model version. |
|
||||
| <a id="mlmodelversionversion"></a>`version` | [`String!`](#string) | Name of the version. |
|
||||
|
||||
### `Namespace`
|
||||
|
||||
#### Fields
|
||||
|
|
@ -31232,6 +31320,18 @@ A `MilestoneID` is a global ID. It is encoded as a string.
|
|||
|
||||
An example `MilestoneID` is: `"gid://gitlab/Milestone/1"`.
|
||||
|
||||
### `MlModelID`
|
||||
|
||||
A `MlModelID` is a global ID. It is encoded as a string.
|
||||
|
||||
An example `MlModelID` is: `"gid://gitlab/Ml::Model/1"`.
|
||||
|
||||
### `MlModelVersionID`
|
||||
|
||||
A `MlModelVersionID` is a global ID. It is encoded as a string.
|
||||
|
||||
An example `MlModelVersionID` is: `"gid://gitlab/Ml::ModelVersion/1"`.
|
||||
|
||||
### `NamespaceID`
|
||||
|
||||
A `NamespaceID` is a global ID. It is encoded as a string.
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@ module Banzai
|
|||
module Filter
|
||||
# HTML filter that converts relative urls into absolute ones.
|
||||
class AbsoluteLinkFilter < HTML::Pipeline::Filter
|
||||
CSS = 'a.gfm'
|
||||
CSS = 'a.gfm'
|
||||
XPATH = Gitlab::Utils::Nokogiri.css_to_xpath(CSS).freeze
|
||||
|
||||
def call
|
||||
return doc unless context[:only_path] == false
|
||||
return doc if skip?
|
||||
|
||||
doc.xpath(XPATH).each do |el|
|
||||
doc.xpath(self.class::XPATH).each do |el|
|
||||
process_link_attr el.attribute('href')
|
||||
end
|
||||
|
||||
|
|
@ -21,17 +21,21 @@ module Banzai
|
|||
|
||||
protected
|
||||
|
||||
def skip?
|
||||
context[:only_path] != false
|
||||
end
|
||||
|
||||
def process_link_attr(html_attr)
|
||||
return if html_attr.blank?
|
||||
return if html_attr.value.start_with?('//')
|
||||
|
||||
uri = URI(html_attr.value)
|
||||
html_attr.value = absolute_link_attr(uri) if uri.relative?
|
||||
html_attr.value = convert_link_href(uri) if uri.relative?
|
||||
rescue URI::Error
|
||||
# noop
|
||||
end
|
||||
|
||||
def absolute_link_attr(uri)
|
||||
def convert_link_href(uri)
|
||||
# Here we really want to expand relative path to absolute path
|
||||
URI.join(Gitlab.config.gitlab.url, uri).to_s
|
||||
end
|
||||
|
|
|
|||
|
|
@ -23284,6 +23284,9 @@ msgstr ""
|
|||
msgid "GroupSettings|Enabling these features is your acceptance of the %{link_start}GitLab Testing Agreement%{link_end}."
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupSettings|Enforce SSH Certificates"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupSettings|Experiment and Beta features"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Resolvers::Ml::ModelDetailResolver, feature_category: :mlops do
|
||||
include GraphqlHelpers
|
||||
|
||||
describe '#resolve' do
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:model) { create(:ml_models, project: project) }
|
||||
let_it_be(:user) { project.owner }
|
||||
|
||||
let(:args) { { id: global_id_of(model) } }
|
||||
let(:read_model_registry) { true }
|
||||
|
||||
before do
|
||||
allow(Ability).to receive(:allowed?).and_call_original
|
||||
allow(Ability).to receive(:allowed?)
|
||||
.with(user, :read_model_registry, project)
|
||||
.and_return(read_model_registry)
|
||||
end
|
||||
|
||||
subject { force(resolve(described_class, ctx: { current_user: user }, args: args)) }
|
||||
|
||||
context 'when user is allowed and model exists' do
|
||||
it { is_expected.to eq(model) }
|
||||
end
|
||||
|
||||
context 'when user does not have permission' do
|
||||
let(:read_model_registry) { false }
|
||||
|
||||
it { is_expected.to be_nil }
|
||||
end
|
||||
|
||||
context 'when model does not exist' do
|
||||
let(:args) { { id: global_id_of(id: non_existing_record_id, model_name: 'Ml::Model') } }
|
||||
|
||||
it { is_expected.to be_nil }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe GitlabSchema.types['MlModel'], feature_category: :mlops do
|
||||
specify { expect(described_class.description).to eq('Machine learning model in the model registry') }
|
||||
|
||||
it 'includes all the package fields' do
|
||||
expected_fields = %w[id name versions]
|
||||
|
||||
expect(described_class).to include_graphql_fields(*expected_fields)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe GitlabSchema.types['MLModelVersionLinks'], feature_category: :mlops do
|
||||
it 'has the expected fields' do
|
||||
expected_fields = %w[showPath]
|
||||
|
||||
expect(described_class).to include_graphql_fields(*expected_fields)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe GitlabSchema.types['MlModelVersion'], feature_category: :mlops do
|
||||
specify { expect(described_class.description).to eq('Version of a machine learning model') }
|
||||
|
||||
it 'includes all the package fields' do
|
||||
expected_fields = %w[id version created_at _links]
|
||||
|
||||
expect(described_class).to include_graphql_fields(*expected_fields)
|
||||
end
|
||||
end
|
||||
|
|
@ -137,4 +137,14 @@ RSpec.describe GitlabSchema.types['Query'], feature_category: :shared do
|
|||
is_expected.to have_graphql_resolver(Resolvers::BoardListResolver)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'mlModel field' do
|
||||
subject { described_class.fields['mlModel'] }
|
||||
|
||||
it 'returns metadata', :aggregate_failures do
|
||||
is_expected.to have_graphql_type(Types::Ml::ModelType)
|
||||
is_expected.to have_graphql_arguments(:id)
|
||||
is_expected.to have_graphql_resolver(Resolvers::Ml::ModelDetailResolver)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue