Commit f4865940 authored by Dmytro Zaporozhets (DZ)'s avatar Dmytro Zaporozhets (DZ)

Merge branch 'mo-add-downloadable-artifacts-endpoint' into 'master'

Add downloadable artifacts endpoint

See merge request gitlab-org/gitlab!59813
parents 08300508 2581bbda
......@@ -19,7 +19,7 @@ class Projects::PipelinesController < Projects::ApplicationController
push_frontend_feature_flag(:graphql_pipeline_details_users, current_user, type: :development, default_enabled: :yaml)
push_frontend_feature_flag(:jira_for_vulnerabilities, project, type: :development, default_enabled: :yaml)
end
before_action :ensure_pipeline, only: [:show]
before_action :ensure_pipeline, only: [:show, :downloadable_artifacts]
# Will be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/225596
before_action :redirect_for_legacy_scope_filter, only: [:index], if: -> { request.format.html? }
......@@ -205,6 +205,13 @@ class Projects::PipelinesController < Projects::ApplicationController
end
end
def downloadable_artifacts
render json: Ci::DownloadableArtifactSerializer.new(
project: project,
current_user: current_user
).represent(@pipeline)
end
private
def serialize_pipelines
......
# frozen_string_literal: true
module Ci
class DownloadableArtifactEntity < Grape::Entity
include RequestAwareEntity
expose :artifacts do |pipeline, options|
artifacts = pipeline.downloadable_artifacts
if Feature.enabled?(:non_public_artifacts)
artifacts = artifacts.select { |artifact| can?(request.current_user, :read_job_artifacts, artifact.job) }
end
BuildArtifactEntity.represent(artifacts, options.merge(project: pipeline.project))
end
end
end
# frozen_string_literal: true
module Ci
class DownloadableArtifactSerializer < BaseSerializer
entity DownloadableArtifactEntity
end
end
......@@ -19,6 +19,7 @@ resources :pipelines, only: [:index, :new, :create, :show, :destroy] do
get :failures
get :status
get :test_report
get :downloadable_artifacts
end
resources :stages, only: [], param: :name, controller: 'pipelines/stages' do
......
......@@ -1247,4 +1247,59 @@ RSpec.describe Projects::PipelinesController do
format: :json
end
end
describe 'GET downloadable_artifacts.json' do
context 'when pipeline is empty' do
let(:pipeline) { create(:ci_empty_pipeline) }
it 'returns status not_found' do
get_downloadable_artifacts_json
expect(response).to have_gitlab_http_status(:not_found)
end
end
context 'when pipeline exists' do
context 'when pipeline does not have any downloadable artifacts' do
let(:pipeline) { create(:ci_pipeline, project: project) }
it 'returns an empty array' do
get_downloadable_artifacts_json
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['artifacts']).to be_empty
end
end
context 'when pipeline has downloadable artifacts' do
let(:pipeline) { create(:ci_pipeline, :with_codequality_reports, project: project) }
before do
create(:ci_build, name: 'rspec', pipeline: pipeline).tap do |build|
create(:ci_job_artifact, :junit, job: build)
end
end
it 'returns an array of artifacts' do
get_downloadable_artifacts_json
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['artifacts']).to be_kind_of(Array)
expect(json_response['artifacts'].size).to eq(2)
end
end
end
private
def get_downloadable_artifacts_json
get :downloadable_artifacts,
params: {
namespace_id: project.namespace,
project_id: project,
id: pipeline.id
},
format: :json
end
end
end
{
"type": "object",
"required": ["artifacts"],
"properties": {
"artifacts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": { "type": "string" },
"expire_at": { "type": ["string", "null"], "format": "date-time" },
"expired": { "type": "boolean" },
"path": { "type": "string" }
}
}
}
},
"additionalProperties": false
}
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Ci::DownloadableArtifactEntity do
let(:pipeline) { create(:ci_pipeline, :with_codequality_reports) }
let(:user) { create(:user) }
let(:request) { EntityRequest.new({ current_user: user }) }
let(:entity) { described_class.new(pipeline, request: request) }
describe '#as_json' do
subject { entity.as_json }
it 'contains required fields', :aggregate_failures do
expect(subject).to include(:artifacts)
expect(subject[:artifacts].size).to eq(1)
end
context 'when user cannot read job artifact' do
let!(:build) { create(:ci_build, :success, :artifacts, :non_public_artifacts, pipeline: pipeline) }
it 'returns only artifacts readable by user', :aggregate_failures do
expect(subject[:artifacts].size).to eq(1)
expect(subject[:artifacts].first[:name]).to eq("test:codequality")
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Ci::DownloadableArtifactSerializer do
let(:pipeline) { create(:ci_pipeline, :with_codequality_reports) }
let(:user) { create(:user) }
let(:serializer) { described_class.new(current_user: user).represent(pipeline) }
describe '#as_json' do
subject { serializer.as_json }
it 'matches schema' do
expect(subject).to match_schema('entities/downloadable_artifact')
end
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