GitLab steht aufgrund wichtiger Wartungsarbeiten am Montag, den 8. März, zwischen 17:00 und 19:00 Uhr nicht zur Verfügung.

Commit ac652d82 authored by Kamil Trzcinski's avatar Kamil Trzcinski

Let the CI runner know about builds that this build depends on

This allows us to implement artifacts passing: runner will download artifacts from all prior builds
parent ba42b033
......@@ -20,6 +20,7 @@ v 8.4.0 (unreleased)
- Don't notify users twice if they are both project watchers and subscribers (Stan Hu)
- Implement new UI for group page
- Implement search inside emoji picker
- Let the CI runner know about builds that this build depends on
- Add API support for looking up a user by username (Stan Hu)
- Add project permissions to all project API endpoints (Stan Hu)
- Link to milestone in "Milestone changed" system note
......
......@@ -128,6 +128,14 @@ def retried?
!self.commit.latest_builds_for_ref(self.ref).include?(self)
end
def depends_on_builds
# Get builds of the same type
latest_builds = self.commit.builds.similar(self).latest
# Return builds from previous stages
latest_builds.where('stage_idx < ?', stage_idx)
end
def trace_html
html = Ci::Ansi2html::convert(trace) if trace.present?
html || ''
......
......@@ -32,6 +32,10 @@ def file_storage?
self.class.storage == CarrierWave::Storage::File
end
def filename
file.try(:filename)
end
def exists?
file.try(:exists?)
end
......
......@@ -18,18 +18,64 @@ Returns:
```json
{
"id" : 79,
"commands" : "",
"path" : "",
"ref" : "",
"sha" : "",
"project_id" : 6,
"repo_url" : "git@demo.gitlab.com:gitlab/gitlab-shell.git",
"before_sha" : ""
"id": 48584,
"ref": "0.1.1",
"tag": true,
"sha": "d63117656af6ff57d99e50cc270f854691f335ad",
"status": "success",
"name": "pages",
"token": "9dd60b4f1a439d1765357446c1084c",
"stage": "test",
"project_id": 479,
"project_name": "test",
"commands": "echo commands",
"repo_url": "http://gitlab-ci-token:token@gitlab.example/group/test.git",
"before_sha": "0000000000000000000000000000000000000000",
"allow_git_fetch": false,
"options": {
"image": "docker:image",
"artifacts": {
"paths": [
"public"
]
},
"cache": {
"paths": [
"vendor"
]
}
},
"timeout": 3600,
"variables": [
{
"key": "CI_BUILD_TAG",
"value": "0.1.1",
"public": true
}
],
"dependencies": {
"builds": [
{
"id": 48584,
"ref": "0.1.1",
"tag": true,
"sha": "d63117656af6ff57d99e50cc270f854691f335ad",
"status": "success",
"name": "build",
"token": "9dd60b4f1a439d1765357446c1084c",
"stage": "build",
"project_id": 479,
"project_name": "test",
"artifacts_file": {
"filename": "artifacts.zip",
"size": 0
}
}
]
}
}
```
### Update details of an existing build
PUT /ci/builds/:id
......
......@@ -20,7 +20,7 @@ class Builds < Grape::API
if build
update_runner_info
present build, with: Entities::Build
present build, with: Entities::BuildDetails
else
not_found!
end
......@@ -111,7 +111,7 @@ class Builds < Grape::API
build.artifacts_metadata = metadata
if build.save
present(build, with: Entities::Build)
present(build, with: Entities::BuildDetails)
else
render_validation_error!(build)
end
......
......@@ -16,10 +16,19 @@ class ArtifactFile < Grape::Entity
end
class Build < Grape::Entity
expose :id, :commands, :ref, :sha, :status, :project_id, :repo_url,
:before_sha, :allow_git_fetch, :project_name
expose :id, :ref, :tag, :sha, :status
expose :name, :token, :stage
expose :project_id
expose :project_name
expose :artifacts_file, using: ArtifactFile, if: lambda { |build, opts| build.artifacts_file.exists? }
end
class BuildDetails < Build
expose :commands
expose :repo_url
expose :before_sha
expose :allow_git_fetch
expose :token
expose :options do |model|
model.options
......@@ -30,7 +39,9 @@ class Build < Grape::Entity
end
expose :variables
expose :artifacts_file, using: ArtifactFile
expose :dependencies do
expose :depends_on_builds, as: :builds, using: Build
end
end
class Runner < Grape::Entity
......
......@@ -426,6 +426,30 @@
it { is_expected.to include(project.web_url[7..-1]) }
end
describe :depends_on_builds do
let!(:build) { FactoryGirl.create :ci_build, commit: commit, name: 'build', stage_idx: 0, stage: 'build' }
let!(:rspec_test) { FactoryGirl.create :ci_build, commit: commit, name: 'rspec', stage_idx: 1, stage: 'test' }
let!(:rubocop_test) { FactoryGirl.create :ci_build, commit: commit, name: 'rubocop', stage_idx: 1, stage: 'test' }
let!(:staging) { FactoryGirl.create :ci_build, commit: commit, name: 'staging', stage_idx: 2, stage: 'deploy' }
it 'to have no dependents if this is first build' do
expect(build.depends_on_builds).to be_empty
end
it 'to have one dependent if this is test' do
expect(rspec_test.depends_on_builds.map(&:id)).to contain_exactly(build.id)
end
it 'to have all builds from build and test stage if this is last' do
expect(staging.depends_on_builds.map(&:id)).to contain_exactly(build.id, rspec_test.id, rubocop_test.id)
end
it 'to have retried builds instead the original ones' do
retried_rspec = Ci::Build.retry(rspec_test)
expect(staging.depends_on_builds.map(&:id)).to contain_exactly(build.id, retried_rspec.id, rubocop_test.id)
end
end
def create_mr(build, commit, factory: :merge_request, created_at: Time.now)
FactoryGirl.create(factory,
source_project_id: commit.gl_project_id,
......
......@@ -101,6 +101,18 @@
{ "key" => "TRIGGER_KEY", "value" => "TRIGGER_VALUE", "public" => false },
])
end
it "returns dependent builds" do
commit = FactoryGirl.create(:ci_commit, project: project)
commit.create_builds('master', false, nil, nil)
commit.builds.where(stage: 'test').each(&:success)
post ci_api("/builds/register"), token: runner.token, info: { platform: :darwin }
expect(response.status).to eq(201)
expect(json_response["dependencies"]["builds"].count).to eq(2)
expect(json_response["dependencies"]["builds"][0]["name"]).to eq("rspec")
end
end
describe "PUT /builds/:id" do
......
......@@ -36,8 +36,8 @@ staging:
script: "cap deploy stating"
type: deploy
tags:
- capistrano
- debian
- ruby
- mysql
except:
- stable
......@@ -47,8 +47,8 @@ production:
- cap deploy production
- cap notify
tags:
- capistrano
- debian
- ruby
- mysql
only:
- master
- /^deploy-.*$/
......
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