Skip to content
Snippets Groups Projects
Commit 238d22c0 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 6b75320f
No related branches found
No related tags found
No related merge requests found
Showing
with 340 additions and 35 deletions
Loading
Loading
@@ -11,7 +11,7 @@ class Projects::JobsController < Projects::ApplicationController
before_action :authorize_erase_build!, only: [:erase]
before_action :authorize_use_build_terminal!, only: [:terminal, :terminal_websocket_authorize]
before_action :verify_api_request!, only: :terminal_websocket_authorize
before_action only: [:trace] do
before_action only: [:show] do
push_frontend_feature_flag(:job_log_json)
end
 
Loading
Loading
@@ -67,38 +67,27 @@ class Projects::JobsController < Projects::ApplicationController
# rubocop: enable CodeReuse/ActiveRecord
 
def trace
if Feature.enabled?(:job_log_json, @project)
json_trace
else
html_trace
end
end
def html_trace
build.trace.read do |stream|
respond_to do |format|
format.json do
result = {
id: @build.id, status: @build.status, complete: @build.complete?
}
if stream.valid?
stream.limit
state = params[:state].presence
trace = stream.html_with_state(state)
result.merge!(trace.to_h)
end
render json: result
# TODO: when the feature flag is removed we should not pass
# content_format to serialize method.
content_format = Feature.enabled?(:job_log_json, @project) ? :json : :html
build_trace = Ci::BuildTrace.new(
build: @build,
stream: stream,
state: params[:state],
content_format: content_format)
render json: BuildTraceSerializer
.new(project: @project, current_user: @current_user)
.represent(build_trace)
end
end
end
end
 
def json_trace
# will be implemented with https://gitlab.com/gitlab-org/gitlab-foss/issues/66454
end
def retry
return respond_422 unless @build.retryable?
 
Loading
Loading
Loading
Loading
@@ -33,6 +33,8 @@ class TodosFinder
end
 
def execute
return Todo.none if current_user.nil?
items = current_user.todos
items = by_action_id(items)
items = by_action(items)
Loading
Loading
@@ -180,11 +182,9 @@ class TodosFinder
end
 
def by_group(items)
if group?
items.for_group_and_descendants(group)
else
items
end
return items unless group?
items.for_group_ids_and_descendants(params[:group_id])
end
 
def by_state(items)
Loading
Loading
# frozen_string_literal: true
module Mutations
module ResolvesGroup
extend ActiveSupport::Concern
def resolve_group(full_path:)
resolver.resolve(full_path: full_path)
end
def resolver
Resolvers::GroupResolver.new(object: nil, context: context)
end
end
end
# frozen_string_literal: true
module Resolvers
class TodoResolver < BaseResolver
type Types::TodoType, null: true
alias_method :user, :object
argument :action, [Types::TodoActionEnum],
required: false,
description: 'The action to be filtered'
argument :author_id, [GraphQL::ID_TYPE],
required: false,
description: 'The ID of an author'
argument :project_id, [GraphQL::ID_TYPE],
required: false,
description: 'The ID of a project'
argument :group_id, [GraphQL::ID_TYPE],
required: false,
description: 'The ID of a group'
argument :state, [Types::TodoStateEnum],
required: false,
description: 'The state of the todo'
argument :type, [Types::TodoTargetEnum],
required: false,
description: 'The type of the todo'
def resolve(**args)
return Todo.none if user != context[:current_user]
TodosFinder.new(user, todo_finder_params(args)).execute
end
private
# TODO: Support multiple queries for e.g. state and type on TodosFinder:
#
# https://gitlab.com/gitlab-org/gitlab/merge_requests/18487
# https://gitlab.com/gitlab-org/gitlab/merge_requests/18518
#
# As soon as these MR's are merged, we can refactor this to query by
# multiple contents.
#
def todo_finder_params(args)
{
state: first_state(args),
type: first_type(args),
group_id: first_group_id(args),
author_id: first_author_id(args),
action_id: first_action(args),
project_id: first_project(args)
}
end
def first_project(args)
first_query_field(args, :project_id)
end
def first_action(args)
first_query_field(args, :action)
end
def first_author_id(args)
first_query_field(args, :author_id)
end
def first_group_id(args)
first_query_field(args, :group_id)
end
def first_state(args)
first_query_field(args, :state)
end
def first_type(args)
first_query_field(args, :type)
end
def first_query_field(query, field)
return unless query.key?(field)
query[field].first if query[field].respond_to?(:first)
end
end
end
Loading
Loading
@@ -14,6 +14,11 @@ module Types
resolver: Resolvers::GroupResolver,
description: "Find a group"
 
field :current_user, Types::UserType,
null: true,
resolve: -> (_obj, _args, context) { context[:current_user] },
description: "Get information about current user"
field :namespace, Types::NamespaceType,
null: true,
resolver: Resolvers::NamespaceResolver,
Loading
Loading
# frozen_string_literal: true
module Types
class TodoActionEnum < BaseEnum
value 'assigned', value: 1
value 'mentioned', value: 2
value 'build_failed', value: 3
value 'marked', value: 4
value 'approval_required', value: 5
value 'unmergeable', value: 6
value 'directly_addressed', value: 7
end
end
# frozen_string_literal: true
module Types
class TodoStateEnum < BaseEnum
value 'pending'
value 'done'
end
end
# frozen_string_literal: true
module Types
class TodoTargetEnum < BaseEnum
value 'Issue'
value 'MergeRequest'
value 'Epic'
end
end
# frozen_string_literal: true
module Types
class TodoType < BaseObject
graphql_name 'Todo'
description 'Representing a todo entry'
present_using TodoPresenter
authorize :read_todo
field :id, GraphQL::ID_TYPE,
description: 'Id of the todo',
null: false
field :project, Types::ProjectType,
description: 'The project this todo is associated with',
null: true,
authorize: :read_project,
resolve: -> (todo, args, context) { Gitlab::Graphql::Loaders::BatchModelLoader.new(Project, todo.project_id).find }
field :group, Types::GroupType,
description: 'Group this todo is associated with',
null: true,
authorize: :read_group,
resolve: -> (todo, args, context) { Gitlab::Graphql::Loaders::BatchModelLoader.new(Group, todo.group_id).find }
field :author, Types::UserType,
description: 'The owner of this todo',
null: false,
resolve: -> (todo, args, context) { Gitlab::Graphql::Loaders::BatchModelLoader.new(User, todo.author_id).find }
field :action, Types::TodoActionEnum,
description: 'Action of the todo',
null: false
field :target_type, Types::TodoTargetEnum,
description: 'Target type of the todo',
null: false
field :body, GraphQL::STRING_TYPE,
description: 'Body of the todo',
null: false
field :state, Types::TodoStateEnum,
description: 'State of the todo',
null: false
field :created_at, Types::TimeType,
description: 'Timestamp this todo was created',
null: false
end
end
Loading
Loading
@@ -12,5 +12,8 @@ module Types
field :username, GraphQL::STRING_TYPE, null: false # rubocop:disable Graphql/Descriptions
field :avatar_url, GraphQL::STRING_TYPE, null: false # rubocop:disable Graphql/Descriptions
field :web_url, GraphQL::STRING_TYPE, null: false # rubocop:disable Graphql/Descriptions
field :todos, Types::TodoType.connection_type, null: false,
resolver: Resolvers::TodoResolver,
description: 'Todos of this user'
end
end
# frozen_string_literal: true
module Ci
class BuildTrace
CONVERTERS = {
html: Gitlab::Ci::Ansi2html,
json: Gitlab::Ci::Ansi2json
}.freeze
attr_reader :trace, :build
delegate :state, :append, :truncated, :offset, :size, :total, to: :trace, allow_nil: true
delegate :id, :status, :complete?, to: :build, prefix: true
def initialize(build:, stream:, state:, content_format:)
@build = build
@content_format = content_format
if stream.valid?
stream.limit
@trace = CONVERTERS.fetch(content_format).convert(stream.stream, state)
end
end
def json?
@content_format == :json
end
def html?
@content_format == :html
end
def json_lines
@trace&.lines if json?
end
def html_lines
@trace&.html if html?
end
end
end
# frozen_string_literal: true
class Evidence < ApplicationRecord
include ShaAttribute
belongs_to :release
before_validation :generate_summary_and_sha
default_scope { order(created_at: :asc) }
sha_attribute :summary_sha
def milestones
@milestones ||= release.milestones.includes(:issues)
end
private
def generate_summary_and_sha
summary = Evidences::EvidenceSerializer.new.represent(self) # rubocop: disable CodeReuse/Serializer
return unless summary
self.summary = summary
self.summary_sha = Gitlab::CryptoHelper.sha256(summary)
end
end
Loading
Loading
@@ -473,6 +473,12 @@ class Group < Namespace
 
errors.add(:visibility_level, "#{visibility} is not allowed since there are sub-groups with higher visibility.")
end
def self.groups_including_descendants_by(group_ids)
Gitlab::ObjectHierarchy
.new(Group.where(id: group_ids))
.base_and_descendants
end
end
 
Group.prepend_if_ee('EE::Group')
Loading
Loading
@@ -13,7 +13,7 @@ class WebHook < ApplicationRecord
algorithm: 'aes-256-gcm',
key: Settings.attr_encrypted_db_key_base_32
 
has_many :web_hook_logs, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :web_hook_logs
 
validates :url, presence: true
validates :url, public_url: true, unless: ->(hook) { hook.is_a?(SystemHook) }
Loading
Loading
Loading
Loading
@@ -14,6 +14,7 @@ class Release < ApplicationRecord
 
has_many :milestone_releases
has_many :milestones, through: :milestone_releases
has_one :evidence
 
default_value_for :released_at, allows_nil: false do
Time.zone.now
Loading
Loading
@@ -28,6 +29,8 @@ class Release < ApplicationRecord
 
delegate :repository, to: :project
 
after_commit :create_evidence!, on: :create
def commit
strong_memoize(:commit) do
repository.commit(actual_sha)
Loading
Loading
@@ -66,6 +69,10 @@ class Release < ApplicationRecord
repository.find_tag(tag)
end
end
def create_evidence!
CreateEvidenceWorker.perform_async(self.id)
end
end
 
Release.prepend_if_ee('EE::Release')
Loading
Loading
@@ -75,13 +75,13 @@ class Todo < ApplicationRecord
after_save :keep_around_commit, if: :commit_id
 
class << self
# Returns all todos for the given group and its descendants.
# Returns all todos for the given group ids and their descendants.
#
# group - A `Group` to retrieve todos for.
# group_ids - Group Ids to retrieve todos for.
#
# Returns an `ActiveRecord::Relation`.
def for_group_and_descendants(group)
groups = group.self_and_descendants
def for_group_ids_and_descendants(group_ids)
groups = Group.groups_including_descendants_by(group_ids)
 
from_union([
for_project(Project.for_group(groups)),
Loading
Loading
# frozen_string_literal: true
class TodoPolicy < BasePolicy
desc 'User can only read own todos'
condition(:own_todo) do
@user && @subject.user_id == @user.id
end
rule { own_todo }.enable :read_todo
end
# frozen_string_literal: true
class TodoPresenter < Gitlab::View::Presenter::Delegated
include GlobalID::Identification
presents :todo
end
# frozen_string_literal: true
class BuildTraceEntity < Grape::Entity
expose :build_id, as: :id
expose :build_status, as: :status
expose :build_complete?, as: :complete
expose :state
expose :append
expose :truncated
expose :offset
expose :size
expose :total
expose :json_lines, as: :lines, if: ->(*) { object.json? }
expose :html_lines, as: :html, if: ->(*) { object.html? }
end
# frozen_string_literal: true
class BuildTraceSerializer < BaseSerializer
entity BuildTraceEntity
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment