Commit 8391fa37 authored by Kamil Trzciński's avatar Kamil Trzciński

Merge branch...

Merge branch '12818-expose-simple-cicd-status-endpoints-with-status-serializer-gitlab-ci-status-for-pipeline-job-and-merge-request' into 'master'

Expose CI/CD status API endpoints with Gitlab::Ci::Status facility on pipeline, job and merge request for favicon

See merge request !9561
parents 856d2991 b3375a49
......@@ -74,7 +74,9 @@ class Projects::BuildsController < Projects::ApplicationController
end
def status
render json: @build.to_json(only: [:status, :id, :sha, :coverage], methods: :sha)
render json: BuildSerializer
.new(project: @project, user: @current_user)
.represent_status(@build)
end
def erase
......
......@@ -10,7 +10,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
before_action :module_enabled
before_action :merge_request, only: [
:edit, :update, :show, :diffs, :commits, :conflicts, :conflict_for_path, :pipelines, :merge, :merge_check,
:ci_status, :ci_environments_status, :toggle_subscription, :cancel_merge_when_pipeline_succeeds, :remove_wip, :resolve_conflicts, :assign_related_issues
:ci_status, :pipeline_status, :ci_environments_status, :toggle_subscription, :cancel_merge_when_pipeline_succeeds, :remove_wip, :resolve_conflicts, :assign_related_issues
]
before_action :validates_merge_request, only: [:show, :diffs, :commits, :pipelines]
before_action :define_show_vars, only: [:show, :diffs, :commits, :conflicts, :conflict_for_path, :builds, :pipelines]
......@@ -473,6 +473,12 @@ class Projects::MergeRequestsController < Projects::ApplicationController
render json: response
end
def pipeline_status
render json: PipelineSerializer
.new(project: @project, user: @current_user)
.represent_status(@merge_request.head_pipeline)
end
def ci_environments_status
environments =
begin
......
......@@ -72,6 +72,12 @@ class Projects::PipelinesController < Projects::ApplicationController
end
end
def status
render json: PipelineSerializer
.new(project: @project, user: @current_user)
.represent_status(@pipeline)
end
def stage
@stage = pipeline.stage(params[:stage])
return not_found unless @stage
......
......@@ -18,10 +18,17 @@ class BuildEntity < Grape::Entity
expose :created_at
expose :updated_at
expose :detailed_status, as: :status, with: StatusEntity
private
alias_method :build, :object
def path_to(route, build)
send("#{route}_path", build.project.namespace, build.project, build)
end
def detailed_status
build.detailed_status(request.user)
end
end
class BuildSerializer < BaseSerializer
entity BuildEntity
def represent_status(resource)
data = represent(resource, { only: [:status] })
data.fetch(:status, {})
end
end
......@@ -12,12 +12,7 @@ class PipelineEntity < Grape::Entity
end
expose :details do
expose :status do |pipeline, options|
StatusEntity.represent(
pipeline.detailed_status(request.user),
options)
end
expose :detailed_status, as: :status, with: StatusEntity
expose :duration
expose :finished_at
expose :stages, using: StageEntity
......@@ -82,4 +77,8 @@ class PipelineEntity < Grape::Entity
pipeline.cancelable? &&
can?(request.user, :update_pipeline, pipeline)
end
def detailed_status
pipeline.detailed_status(request.user)
end
end
......@@ -22,4 +22,11 @@ class PipelineSerializer < BaseSerializer
super(resource, opts)
end
end
def represent_status(resource)
return {} unless resource.present?
data = represent(resource, { only: [{ details: [:status] }] })
data.dig(:details, :status) || {}
end
end
class StatusEntity < Grape::Entity
include RequestAwareEntity
expose :icon, :text, :label, :group
expose :icon, :favicon, :text, :label, :group
expose :has_details?, as: :has_details
expose :details_path
......
---
title: Expose CI/CD status API endpoints with Gitlab::Ci::Status facility on pipeline,
job and merge request for favicon
merge_request: 9561
author: dosuken123
......@@ -102,6 +102,7 @@ constraints(ProjectUrlConstrainer.new) do
get :merge_widget_refresh
post :cancel_merge_when_pipeline_succeeds
get :ci_status
get :pipeline_status
get :ci_environments_status
post :toggle_subscription
post :remove_wip
......@@ -152,6 +153,7 @@ constraints(ProjectUrlConstrainer.new) do
post :cancel
post :retry
get :builds
get :status
end
end
......
......@@ -13,6 +13,10 @@ module Gitlab
def icon
'icon_status_canceled'
end
def favicon
'favicon_status_canceled'
end
end
end
end
......
......@@ -18,6 +18,10 @@ module Gitlab
raise NotImplementedError
end
def favicon
raise NotImplementedError
end
def label
raise NotImplementedError
end
......
......@@ -13,6 +13,10 @@ module Gitlab
def icon
'icon_status_created'
end
def favicon
'favicon_status_created'
end
end
end
end
......
......@@ -13,6 +13,10 @@ module Gitlab
def icon
'icon_status_failed'
end
def favicon
'favicon_status_failed'
end
end
end
end
......
......@@ -13,6 +13,10 @@ module Gitlab
def icon
'icon_status_manual'
end
def favicon
'favicon_status_manual'
end
end
end
end
......
......@@ -13,6 +13,10 @@ module Gitlab
def icon
'icon_status_pending'
end
def favicon
'favicon_status_pending'
end
end
end
end
......
......@@ -13,6 +13,10 @@ module Gitlab
def icon
'icon_status_running'
end
def favicon
'favicon_status_running'
end
end
end
end
......
......@@ -13,6 +13,10 @@ module Gitlab
def icon
'icon_status_skipped'
end
def favicon
'favicon_status_skipped'
end
end
end
end
......
......@@ -13,6 +13,10 @@ module Gitlab
def icon
'icon_status_success'
end
def favicon
'favicon_status_success'
end
end
end
end
......
require 'spec_helper'
describe Projects::BuildsController do
include ApiHelpers
let(:user) { create(:user) }
let(:project) { create(:empty_project, :public) }
before do
sign_in(user)
end
describe 'GET status.json' do
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:build) { create(:ci_build, pipeline: pipeline) }
let(:status) { build.detailed_status(double('user')) }
before do
get :status, namespace_id: project.namespace,
project_id: project,
id: build.id,
format: :json
end
it 'return a detailed build status in json' do
expect(response).to have_http_status(:ok)
expect(json_response['text']).to eq status.text
expect(json_response['label']).to eq status.label
expect(json_response['icon']).to eq status.icon
expect(json_response['favicon']).to eq status.favicon
end
end
end
......@@ -1178,4 +1178,42 @@ describe Projects::MergeRequestsController do
end
end
end
describe 'GET pipeline_status.json' do
context 'when head_pipeline exists' do
let!(:pipeline) do
create(:ci_pipeline, project: merge_request.source_project,
ref: merge_request.source_branch,
sha: merge_request.diff_head_sha)
end
let(:status) { pipeline.detailed_status(double('user')) }
before { get_pipeline_status }
it 'return a detailed head_pipeline status in json' do
expect(response).to have_http_status(:ok)
expect(json_response['text']).to eq status.text
expect(json_response['label']).to eq status.label
expect(json_response['icon']).to eq status.icon
expect(json_response['favicon']).to eq status.favicon
end
end
context 'when head_pipeline does not exist' do
before { get_pipeline_status }
it 'return empty' do
expect(response).to have_http_status(:ok)
expect(json_response).to be_empty
end
end
def get_pipeline_status
get :pipeline_status, namespace_id: project.namespace,
project_id: project,
id: merge_request.iid,
format: :json
end
end
end
......@@ -69,4 +69,24 @@ describe Projects::PipelinesController do
format: :json
end
end
describe 'GET status.json' do
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:status) { pipeline.detailed_status(double('user')) }
before do
get :status, namespace_id: project.namespace,
project_id: project,
id: pipeline.id,
format: :json
end
it 'return a detailed pipeline status in json' do
expect(response).to have_http_status(:ok)
expect(json_response['text']).to eq status.text
expect(json_response['label']).to eq status.label
expect(json_response['icon']).to eq status.icon
expect(json_response['favicon']).to eq status.favicon
end
end
end
......@@ -27,6 +27,7 @@ describe Gitlab::Ci::Status::Build::Factory do
it 'fabricates status with correct details' do
expect(status.text).to eq 'passed'
expect(status.icon).to eq 'icon_status_success'
expect(status.favicon).to eq 'favicon_status_success'
expect(status.label).to eq 'passed'
expect(status).to have_details
expect(status).to have_action
......@@ -53,6 +54,7 @@ describe Gitlab::Ci::Status::Build::Factory do
it 'fabricates status with correct details' do
expect(status.text).to eq 'failed'
expect(status.icon).to eq 'icon_status_failed'
expect(status.favicon).to eq 'favicon_status_failed'
expect(status.label).to eq 'failed'
expect(status).to have_details
expect(status).to have_action
......@@ -79,6 +81,7 @@ describe Gitlab::Ci::Status::Build::Factory do
it 'fabricates status with correct details' do
expect(status.text).to eq 'failed'
expect(status.icon).to eq 'icon_status_warning'
expect(status.favicon).to eq 'favicon_status_failed'
expect(status.label).to eq 'failed (allowed to fail)'
expect(status).to have_details
expect(status).to have_action
......@@ -107,6 +110,7 @@ describe Gitlab::Ci::Status::Build::Factory do
it 'fabricates status with correct details' do
expect(status.text).to eq 'canceled'
expect(status.icon).to eq 'icon_status_canceled'
expect(status.favicon).to eq 'favicon_status_canceled'
expect(status.label).to eq 'canceled'
expect(status).to have_details
expect(status).to have_action
......@@ -132,6 +136,7 @@ describe Gitlab::Ci::Status::Build::Factory do
it 'fabricates status with correct details' do
expect(status.text).to eq 'running'
expect(status.icon).to eq 'icon_status_running'
expect(status.favicon).to eq 'favicon_status_running'
expect(status.label).to eq 'running'
expect(status).to have_details
expect(status).to have_action
......@@ -157,6 +162,7 @@ describe Gitlab::Ci::Status::Build::Factory do
it 'fabricates status with correct details' do
expect(status.text).to eq 'pending'
expect(status.icon).to eq 'icon_status_pending'
expect(status.favicon).to eq 'favicon_status_pending'
expect(status.label).to eq 'pending'
expect(status).to have_details
expect(status).to have_action
......@@ -181,6 +187,7 @@ describe Gitlab::Ci::Status::Build::Factory do
it 'fabricates status with correct details' do
expect(status.text).to eq 'skipped'
expect(status.icon).to eq 'icon_status_skipped'
expect(status.favicon).to eq 'favicon_status_skipped'
expect(status.label).to eq 'skipped'
expect(status).to have_details
expect(status).not_to have_action
......@@ -208,6 +215,7 @@ describe Gitlab::Ci::Status::Build::Factory do
expect(status.text).to eq 'manual'
expect(status.group).to eq 'manual'
expect(status.icon).to eq 'icon_status_manual'
expect(status.favicon).to eq 'favicon_status_manual'
expect(status.label).to eq 'manual play action'
expect(status).to have_details
expect(status).to have_action
......@@ -235,6 +243,7 @@ describe Gitlab::Ci::Status::Build::Factory do
expect(status.text).to eq 'manual'
expect(status.group).to eq 'manual'
expect(status.icon).to eq 'icon_status_manual'
expect(status.favicon).to eq 'favicon_status_manual'
expect(status.label).to eq 'manual stop action'
expect(status).to have_details
expect(status).to have_action
......
......@@ -17,6 +17,10 @@ describe Gitlab::Ci::Status::Canceled do
it { expect(subject.icon).to eq 'icon_status_canceled' }
end
describe '#favicon' do
it { expect(subject.favicon).to eq 'favicon_status_canceled' }
end
describe '#group' do
it { expect(subject.group).to eq 'canceled' }
end
......
......@@ -17,6 +17,10 @@ describe Gitlab::Ci::Status::Created do
it { expect(subject.icon).to eq 'icon_status_created' }
end
describe '#favicon' do
it { expect(subject.favicon).to eq 'favicon_status_created' }
end
describe '#group' do
it { expect(subject.group).to eq 'created' }
end
......
......@@ -17,6 +17,10 @@ describe Gitlab::Ci::Status::Failed do
it { expect(subject.icon).to eq 'icon_status_failed' }
end
describe '#favicon' do
it { expect(subject.favicon).to eq 'favicon_status_failed' }
end
describe '#group' do
it { expect(subject.group).to eq 'failed' }
end
......
......@@ -17,6 +17,10 @@ describe Gitlab::Ci::Status::Manual do
it { expect(subject.icon).to eq 'icon_status_manual' }
end
describe '#favicon' do
it { expect(subject.favicon).to eq 'favicon_status_manual' }
end
describe '#group' do
it { expect(subject.group).to eq 'manual' }
end
......
......@@ -17,6 +17,10 @@ describe Gitlab::Ci::Status::Pending do
it { expect(subject.icon).to eq 'icon_status_pending' }
end
describe '#favicon' do
it { expect(subject.favicon).to eq 'favicon_status_pending' }
end
describe '#group' do
it { expect(subject.group).to eq 'pending' }
end
......
......@@ -17,6 +17,10 @@ describe Gitlab::Ci::Status::Running do
it { expect(subject.icon).to eq 'icon_status_running' }
end
describe '#favicon' do
it { expect(subject.favicon).to eq 'favicon_status_running' }
end
describe '#group' do
it { expect(subject.group).to eq 'running' }
end
......
......@@ -17,6 +17,10 @@ describe Gitlab::Ci::Status::Skipped do
it { expect(subject.icon).to eq 'icon_status_skipped' }
end
describe '#favicon' do
it { expect(subject.favicon).to eq 'favicon_status_skipped' }
end
describe '#group' do
it { expect(subject.group).to eq 'skipped' }
end
......
......@@ -17,6 +17,10 @@ describe Gitlab::Ci::Status::Success do
it { expect(subject.icon).to eq 'icon_status_success' }
end
describe '#favicon' do
it { expect(subject.favicon).to eq 'favicon_status_success' }
end
describe '#group' do
it { expect(subject.group).to eq 'success' }
end
......
require 'spec_helper'
describe BuildEntity do
let(:user) { create(:user) }
let(:build) { create(:ci_build) }
let(:request) { double('request') }
before do
allow(request).to receive(:user).and_return(user)
end
let(:entity) do
described_class.new(build, request: double)
described_class.new(build, request: request)
end
subject { entity.as_json }
......@@ -22,6 +28,11 @@ describe BuildEntity do
expect(subject).to include(:created_at, :updated_at)
end
it 'contains details' do
expect(subject).to include :status
expect(subject[:status]).to include :icon, :favicon, :text, :label
end
context 'when build is a regular job' do
it 'does not contain path to play action' do
expect(subject).not_to include(:play_path)
......
require 'spec_helper'
describe BuildSerializer do
let(:user) { create(:user) }
let(:serializer) do
described_class.new(user: user)
end
subject { serializer.represent(resource) }
describe '#represent' do
context 'when a single object is being serialized' do
let(:resource) { create(:ci_build) }
it 'serializers the pipeline object' do
expect(subject[:id]).to eq resource.id
end
end
context 'when multiple objects are being serialized' do
let(:resource) { create_list(:ci_build, 2) }
it 'serializers the array of pipelines' do
expect(subject).not_to be_empty
end
end
end
describe '#represent_status' do
context 'when represents only status' do
let(:resource) { create(:ci_build) }
let(:status) { resource.detailed_status(double('user')) }
subject { serializer.represent_status(resource) }
it 'serializes only status' do
expect(subject[:text]).to eq(status.text)
expect(subject[:label]).to eq(status.label)
expect(subject[:icon]).to eq(status.icon)
expect(subject[:favicon]).to eq(status.favicon)
end
end
end
end
require 'spec_helper'
describe DeploymentEntity do
let(:user) { create(:user) }
let(:request) { double('request') }
before do
allow(request).to receive(:user).and_return(user)
end
let(:entity) do
described_class.new(deployment, request: double)
described_class.new(deployment, request: request)
end
let(:deployment) { create(:deployment) }
......
......@@ -30,7 +30,7 @@ describe PipelineEntity do
.to include :duration, :finished_at
expect(subject[:details])
.to include :stages, :artifacts, :manual_actions
expect(subject[:details][:status]).to include :icon, :text, :label
expect(subject[:details][:status]).to include :icon, :favicon, :text, :label
end
it 'contains flags' do
......
......@@ -94,4 +94,20 @@ describe PipelineSerializer do
end
end
end
describe '#represent_status' do
context 'when represents only status' do
let(:resource) { create(:ci_pipeline) }
let(:status) { resource.detailed_status(double('user')) }
subject { serializer.represent_status(resource) }
it 'serializes only status' do
expect(subject[:text]).to eq(status.text)
expect(subject[:label]).to eq(status.label)
expect(subject[:icon]).to eq(status.icon)
expect(subject[:favicon]).to eq(status.favicon)
end
end
end
end
......@@ -16,7 +16,7 @@ describe StatusEntity do
subject { entity.as_json }
it 'contains status details' do
expect(subject).to include :text, :icon, :label, :group
expect(subject).to include :text, :icon, :favicon, :label, :group
expect(subject).to include :has_details, :details_path
end
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment