Add deployment information in job API
closes https://gitlab.com/gitlab-org/gitlab-ce/issues/50460
This commit is contained in:
parent
c7d1eef671
commit
3bc5f71133
|
@ -654,8 +654,31 @@ module Ci
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Virtual deployment status depending on the environment status.
|
||||||
|
def deployment_status
|
||||||
|
return nil unless starts_environment?
|
||||||
|
|
||||||
|
if success?
|
||||||
|
return successful_deployment_status
|
||||||
|
elsif complete? && !success?
|
||||||
|
return :failed
|
||||||
|
end
|
||||||
|
|
||||||
|
:creating
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def successful_deployment_status
|
||||||
|
if success? && last_deployment&.last?
|
||||||
|
return :last
|
||||||
|
elsif success? && last_deployment.present?
|
||||||
|
return :out_of_date
|
||||||
|
end
|
||||||
|
|
||||||
|
:creating
|
||||||
|
end
|
||||||
|
|
||||||
def each_test_report
|
def each_test_report
|
||||||
Ci::JobArtifact::TEST_REPORT_FILE_TYPES.each do |file_type|
|
Ci::JobArtifact::TEST_REPORT_FILE_TYPES.each do |file_type|
|
||||||
public_send("job_artifacts_#{file_type}").each_blob do |blob| # rubocop:disable GitlabSecurity/PublicSend
|
public_send("job_artifacts_#{file_type}").each_blob do |blob| # rubocop:disable GitlabSecurity/PublicSend
|
||||||
|
|
|
@ -1,12 +1,26 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class BuildDetailsEntity < JobEntity
|
class BuildDetailsEntity < JobEntity
|
||||||
|
include EnvironmentHelper
|
||||||
|
include RequestAwareEntity
|
||||||
|
include CiStatusHelper
|
||||||
|
|
||||||
expose :coverage, :erased_at, :duration
|
expose :coverage, :erased_at, :duration
|
||||||
expose :tag_list, as: :tags
|
expose :tag_list, as: :tags
|
||||||
expose :user, using: UserEntity
|
expose :user, using: UserEntity
|
||||||
expose :runner, using: RunnerEntity
|
expose :runner, using: RunnerEntity
|
||||||
expose :pipeline, using: PipelineEntity
|
expose :pipeline, using: PipelineEntity
|
||||||
|
|
||||||
|
expose :deployment_status, if: -> (*) { build.has_environment? } do
|
||||||
|
expose :deployment_status, as: :status
|
||||||
|
|
||||||
|
expose :icon do |build|
|
||||||
|
ci_label_for_status(build.status)
|
||||||
|
end
|
||||||
|
|
||||||
|
expose :persisted_environment, as: :environment, with: EnvironmentEntity
|
||||||
|
end
|
||||||
|
|
||||||
expose :metadata, using: BuildMetadataEntity
|
expose :metadata, using: BuildMetadataEntity
|
||||||
|
|
||||||
expose :artifact, if: -> (*) { can?(current_user, :read_build, build) } do
|
expose :artifact, if: -> (*) { can?(current_user, :read_build, build) } do
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Send deployment information in job API
|
||||||
|
merge_request: 21307
|
||||||
|
author:
|
||||||
|
type: other
|
|
@ -86,7 +86,7 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
|
||||||
def create_job(name, status)
|
def create_job(name, status)
|
||||||
pipeline = create(:ci_pipeline, project: project)
|
pipeline = create(:ci_pipeline, project: project)
|
||||||
create(:ci_build, :tags, :triggered, :artifacts,
|
create(:ci_build, :tags, :triggered, :artifacts,
|
||||||
pipeline: pipeline, name: name, status: status)
|
pipeline: pipeline, name: name, status: status)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -206,6 +206,29 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
|
||||||
expect(json_response['status']['illustration']).to have_key('title')
|
expect(json_response['status']['illustration']).to have_key('title')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with no deployment' do
|
||||||
|
let(:job) { create(:ci_build, :success, pipeline: pipeline) }
|
||||||
|
|
||||||
|
it 'does not exposes the deployment information' do
|
||||||
|
expect(response).to have_gitlab_http_status(:ok)
|
||||||
|
expect(json_response['deployment_status']).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with deployment' do
|
||||||
|
let(:merge_request) { create(:merge_request, source_project: project) }
|
||||||
|
let(:environment) { create(:environment, project: project, name: 'staging', state: :available) }
|
||||||
|
let(:job) { create(:ci_build, :success, environment: environment.name, pipeline: pipeline) }
|
||||||
|
|
||||||
|
it 'exposes the deployment information' do
|
||||||
|
expect(response).to have_gitlab_http_status(:ok)
|
||||||
|
expect(json_response).to match_schema('job/job_details')
|
||||||
|
expect(json_response['deployment_status']["status"]).to eq 'creating'
|
||||||
|
expect(json_response['deployment_status']["icon"]).to eq 'passed'
|
||||||
|
expect(json_response['deployment_status']["environment"]).not_to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when requesting JSON job is triggered' do
|
context 'when requesting JSON job is triggered' do
|
||||||
|
|
|
@ -1,45 +1,31 @@
|
||||||
{
|
{
|
||||||
"additionalProperties": false,
|
"type": "object",
|
||||||
"properties": {
|
"required": [
|
||||||
"created_at": {
|
"sha",
|
||||||
"type": "string"
|
"created_at",
|
||||||
},
|
"iid",
|
||||||
"id": {
|
"tag",
|
||||||
"type": "integer"
|
"last?",
|
||||||
},
|
"ref",
|
||||||
"iid": {
|
"id"
|
||||||
"type": "integer"
|
],
|
||||||
},
|
"properties": {
|
||||||
"last?": {
|
"created_at": { "type": "string" },
|
||||||
"type": "boolean"
|
"id": { "type": "integer" },
|
||||||
},
|
"iid": { "type": "integer" },
|
||||||
"ref": {
|
"last?": { "type": "boolean" },
|
||||||
"additionalProperties": false,
|
"ref": {
|
||||||
"properties": {
|
"type": "object",
|
||||||
"name": {
|
"required": [
|
||||||
"type": "string"
|
"name"
|
||||||
}
|
],
|
||||||
},
|
"properties": {
|
||||||
"required": [
|
"name": { "type": "string" }
|
||||||
"name"
|
},
|
||||||
],
|
"additionalProperties": false
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"sha": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"tag": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"required": [
|
"sha": { "type": "string" },
|
||||||
"sha",
|
"tag": { "type": "boolean" }
|
||||||
"created_at",
|
},
|
||||||
"iid",
|
"additionalProperties": false
|
||||||
"tag",
|
|
||||||
"last?",
|
|
||||||
"ref",
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"allOf": [
|
||||||
|
{ "$ref": "../public_api/v4/commit/basic.json" },
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"author_gravatar_url",
|
||||||
|
"commit_url",
|
||||||
|
"commit_path",
|
||||||
|
"author"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"author_gravatar_url": { "type": "string" },
|
||||||
|
"commit_url": { "type": "string" },
|
||||||
|
"commit_path": { "type": "string" },
|
||||||
|
"author": {
|
||||||
|
"oneOf": [
|
||||||
|
{ "type": "null" },
|
||||||
|
{ "type": "user.json" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -5,13 +5,19 @@
|
||||||
"state",
|
"state",
|
||||||
"avatar_url",
|
"avatar_url",
|
||||||
"web_url",
|
"web_url",
|
||||||
"path"
|
"path",
|
||||||
|
"name",
|
||||||
|
"username"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"id": { "type": "integer" },
|
"id": { "type": "integer" },
|
||||||
"state": { "type": "string" },
|
"state": { "type": "string" },
|
||||||
"avatar_url": { "type": "string" },
|
"avatar_url": { "type": "string" },
|
||||||
"web_url": { "type": "string" },
|
"web_url": { "type": "string" },
|
||||||
"path": { "type": "string" }
|
"path": { "type": "string" },
|
||||||
}
|
"name": { "type": "string" },
|
||||||
|
"username": { "type": "string" },
|
||||||
|
"status_tooltip_html": { "$ref": "../types/nullable_string.json" }
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"state",
|
||||||
|
"external_url",
|
||||||
|
"environment_type",
|
||||||
|
"has_stop_action",
|
||||||
|
"environment_path",
|
||||||
|
"stop_path",
|
||||||
|
"folder_path",
|
||||||
|
"created_at",
|
||||||
|
"updated_at",
|
||||||
|
"can_stop"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"id": { "type": "integer" },
|
||||||
|
"name": { "type": "string" },
|
||||||
|
"state": { "type": "string" },
|
||||||
|
"external_url": { "$ref": "types/nullable_string.json" },
|
||||||
|
"environment_type": { "$ref": "types/nullable_string.json" },
|
||||||
|
"has_stop_action": { "type": "boolean" },
|
||||||
|
"environment_path": { "type": "string" },
|
||||||
|
"stop_path": { "type": "string" },
|
||||||
|
"folder_path": { "type": "string" },
|
||||||
|
"created_at": { "type": "string", "format": "date-time" },
|
||||||
|
"updated_at": { "type": "string", "format": "date-time" },
|
||||||
|
"can_stop": { "type": "boolean" },
|
||||||
|
"last_deployment": {
|
||||||
|
"oneOf": [
|
||||||
|
{ "type": "null" },
|
||||||
|
{ "$ref": "deployment.json" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"status",
|
||||||
|
"icon",
|
||||||
|
"environment"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"last",
|
||||||
|
"creating",
|
||||||
|
"failed",
|
||||||
|
"out_of_date"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ "type": "null" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"icon": { "type": "string" },
|
||||||
|
"environment": { "$ref": "../environment.json" }
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
|
@ -6,6 +6,7 @@
|
||||||
"properties": {
|
"properties": {
|
||||||
"artifact": { "$ref": "artifact.json" },
|
"artifact": { "$ref": "artifact.json" },
|
||||||
"terminal_path": { "type": "string" },
|
"terminal_path": { "type": "string" },
|
||||||
"trigger": { "$ref": "trigger.json" }
|
"trigger": { "$ref": "trigger.json" },
|
||||||
|
"deployment_status": { "$ref": "deployment_status.json" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"oneOf": [
|
||||||
|
{ "type": "null" },
|
||||||
|
{ "type": "string" }
|
||||||
|
]
|
||||||
|
}
|
|
@ -2981,4 +2981,46 @@ describe Ci::Build do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#deployment_status' do
|
||||||
|
context 'when build is a last deployment' do
|
||||||
|
let(:build) { create(:ci_build, :success, environment: 'production') }
|
||||||
|
let(:environment) { create(:environment, name: 'production', project: build.project) }
|
||||||
|
let!(:deployment) { create(:deployment, environment: environment, project: environment.project, deployable: build) }
|
||||||
|
|
||||||
|
it { expect(build.deployment_status).to eq(:last) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when there is a newer build with deployment' do
|
||||||
|
let(:build) { create(:ci_build, :success, environment: 'production') }
|
||||||
|
let(:environment) { create(:environment, name: 'production', project: build.project) }
|
||||||
|
let!(:deployment) { create(:deployment, environment: environment, project: environment.project, deployable: build) }
|
||||||
|
let!(:last_deployment) { create(:deployment, environment: environment, project: environment.project) }
|
||||||
|
|
||||||
|
it { expect(build.deployment_status).to eq(:out_of_date) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when build with deployment has failed' do
|
||||||
|
let(:build) { create(:ci_build, :failed, environment: 'production') }
|
||||||
|
let(:environment) { create(:environment, name: 'production', project: build.project) }
|
||||||
|
let!(:deployment) { create(:deployment, environment: environment, project: environment.project, deployable: build) }
|
||||||
|
|
||||||
|
it { expect(build.deployment_status).to eq(:failed) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when build with deployment is running' do
|
||||||
|
let(:build) { create(:ci_build, environment: 'production') }
|
||||||
|
let(:environment) { create(:environment, name: 'production', project: build.project) }
|
||||||
|
let!(:deployment) { create(:deployment, environment: environment, project: environment.project, deployable: build) }
|
||||||
|
|
||||||
|
it { expect(build.deployment_status).to eq(:creating) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when build is successful but deployment is not ready yet' do
|
||||||
|
let(:build) { create(:ci_build, :success, environment: 'production') }
|
||||||
|
let(:environment) { create(:environment, name: 'production', project: build.project) }
|
||||||
|
|
||||||
|
it { expect(build.deployment_status).to eq(:creating) }
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue