diff options
-rw-r--r-- | .gitlab-ci.yml | 46 | ||||
-rw-r--r-- | CHANGELOG | 2 | ||||
-rw-r--r-- | app/controllers/ci/projects_controller.rb | 6 | ||||
-rw-r--r-- | app/controllers/projects/badges_controller.rb | 11 | ||||
-rw-r--r-- | app/controllers/projects/builds_controller.rb | 15 | ||||
-rw-r--r-- | app/services/ci/image_for_build_service.rb | 19 | ||||
-rw-r--r-- | config/routes.rb | 8 | ||||
-rw-r--r-- | db/fixtures/development/14_builds.rb | 39 | ||||
-rw-r--r-- | doc/api/merge_requests.md | 62 | ||||
-rw-r--r-- | doc/ci/docker/using_docker_images.md | 2 | ||||
-rw-r--r-- | doc/ci/quick_start/README.md | 8 | ||||
-rw-r--r-- | features/project/badges/build.feature | 22 | ||||
-rw-r--r-- | features/steps/project/badges/build.rb | 28 | ||||
-rw-r--r-- | features/steps/shared/builds.rb | 16 | ||||
-rw-r--r-- | lib/api/merge_requests.rb | 13 | ||||
-rw-r--r-- | lib/tasks/gitlab/check.rake | 18 | ||||
-rwxr-xr-x | scripts/prepare_build.sh | 12 | ||||
-rw-r--r-- | spec/requests/api/merge_requests_spec.rb | 22 |
18 files changed, 284 insertions, 65 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5dfeb8a1f90..1c4d98ea3f6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,6 +5,11 @@ services: - postgres:latest - redis:latest +cache: + key: "ruby22" + paths: + - vendor + variables: MYSQL_ALLOW_EMPTY_PASSWORD: "1" @@ -144,6 +149,10 @@ spec:feature:ruby21: script: - RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null - RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:feature + cache: + key: "ruby21" + paths: + - vendor tags: - ruby - mysql @@ -154,6 +163,10 @@ spec:api:ruby21: - master script: - RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:api + cache: + key: "ruby21" + paths: + - vendor tags: - ruby - mysql @@ -164,6 +177,10 @@ spec:models:ruby21: - master script: - RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:models + cache: + key: "ruby21" + paths: + - vendor tags: - ruby - mysql @@ -174,6 +191,10 @@ spec:lib:ruby21: - master script: - RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:lib + cache: + key: "ruby21" + paths: + - vendor tags: - ruby - mysql @@ -184,6 +205,10 @@ spec:services:ruby21: - master script: - RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:services + cache: + key: "ruby21" + paths: + - vendor tags: - ruby - mysql @@ -194,6 +219,10 @@ spec:benchmark:ruby21: - master script: - RAILS_ENV=test bundle exec rake spec:benchmark + cache: + key: "ruby21" + paths: + - vendor tags: - ruby - mysql @@ -205,6 +234,10 @@ spec:other:ruby21: - master script: - RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:other + cache: + key: "ruby21" + paths: + - vendor tags: - ruby - mysql @@ -215,6 +248,10 @@ spinach:project:half:ruby21: - master script: - RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project:half + cache: + key: "ruby21" + paths: + - vendor tags: - ruby - mysql @@ -225,6 +262,10 @@ spinach:project:rest:ruby21: - master script: - RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project:rest + cache: + key: "ruby21" + paths: + - vendor tags: - ruby - mysql @@ -235,6 +276,11 @@ spinach:other:ruby21: - master script: - RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:other + cache: + key: "ruby21" + paths: + - vendor tags: - ruby - mysql + diff --git a/CHANGELOG b/CHANGELOG index ceb5c17cae9..db6f200c379 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -14,6 +14,7 @@ v 8.5.0 (unreleased) - New UI for pagination - Don't prevent sign out when 2FA enforcement is enabled and user hasn't yet set it up + - API: Added "merge_requests/:merge_request_id/closes_issues" (Gal Schlezinger) - Fix diff comments loaded by AJAX to load comment with diff in discussion tab - Whitelist raw "abbr" elements when parsing Markdown (Benedict Etzel) - Fix label links for a merge request pointing to issues list @@ -48,6 +49,7 @@ v 8.5.0 (unreleased) - Title for milestones should be unique (Zeger-Jan van de Weg) - Validate correctness of maximum attachment size application setting - Replaces "Create merge request" link with one to the "Merge Request" when one exists + - Fix CI builds badge, add a new link to builds badge, deprecate the old one v 8.4.4 - Update omniauth-saml gem to 1.4.2 diff --git a/app/controllers/ci/projects_controller.rb b/app/controllers/ci/projects_controller.rb index 711c2847d5e..d1824b481d7 100644 --- a/app/controllers/ci/projects_controller.rb +++ b/app/controllers/ci/projects_controller.rb @@ -12,9 +12,13 @@ module Ci # Project status badge # Image with build status for sha or ref + # + # This action in DEPRECATED, this is here only for backwards compatibility + # with projects migrated from GitLab CI. + # def badge + return render_404 unless @project image = Ci::ImageForBuildService.new.execute(@project, params) - send_file image.path, filename: image.name, disposition: 'inline', type:"image/svg+xml" end diff --git a/app/controllers/projects/badges_controller.rb b/app/controllers/projects/badges_controller.rb new file mode 100644 index 00000000000..a4dd94b941c --- /dev/null +++ b/app/controllers/projects/badges_controller.rb @@ -0,0 +1,11 @@ +class Projects::BadgesController < Projects::ApplicationController + def build + respond_to do |format| + format.html { render_404 } + format.svg do + image = Ci::ImageForBuildService.new.execute(project, ref: params[:ref]) + send_file(image.path, filename: image.name, disposition: 'inline', type: 'image/svg+xml') + end + end + end +end diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb index 9e89296e71d..ec379c53b8f 100644 --- a/app/controllers/projects/builds_controller.rb +++ b/app/controllers/projects/builds_controller.rb @@ -1,10 +1,8 @@ class Projects::BuildsController < Projects::ApplicationController before_action :build, except: [:index, :cancel_all] - before_action :authorize_read_build!, except: [:cancel, :cancel_all, :retry] before_action :authorize_update_build!, except: [:index, :show, :status] - - layout "project" + layout 'project' def index @scope = params[:scope] @@ -24,7 +22,6 @@ class Projects::BuildsController < Projects::ApplicationController def cancel_all @project.builds.running_or_pending.each(&:cancel) - redirect_to namespace_project_builds_path(project.namespace, project) end @@ -47,20 +44,18 @@ class Projects::BuildsController < Projects::ApplicationController end build = Ci::Build.retry(@build) - redirect_to build_path(build) end - def status - render json: @build.to_json(only: [:status, :id, :sha, :coverage], methods: :sha) - end - def cancel @build.cancel - redirect_to build_path(@build) end + def status + render json: @build.to_json(only: [:status, :id, :sha, :coverage], methods: :sha) + end + private def build diff --git a/app/services/ci/image_for_build_service.rb b/app/services/ci/image_for_build_service.rb index f469b13e902..005a5c4661c 100644 --- a/app/services/ci/image_for_build_service.rb +++ b/app/services/ci/image_for_build_service.rb @@ -1,28 +1,23 @@ module Ci class ImageForBuildService - def execute(project, params) - sha = params[:sha] - sha ||= - if params[:ref] - project.commit(params[:ref]).try(:sha) - end + def execute(project, opts) + sha = opts[:sha] || ref_sha(project, opts[:ref]) commit = project.ci_commits.ordered.find_by(sha: sha) image_name = image_for_commit(commit) image_path = Rails.root.join('public/ci', image_name) - - OpenStruct.new( - path: image_path, - name: image_name - ) + OpenStruct.new(path: image_path, name: image_name) end private + def ref_sha(project, ref) + project.commit(ref).try(:sha) if ref + end + def image_for_commit(commit) return 'build-unknown.svg' unless commit - 'build-' + commit.status + ".svg" end end diff --git a/config/routes.rb b/config/routes.rb index 3f6561a1fe0..507bcbc53d7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -608,7 +608,7 @@ Rails.application.routes.draw do resource :variables, only: [:show, :update] resources :triggers, only: [:index, :create, :destroy] - resources :builds, only: [:index, :show] do + resources :builds, only: [:index, :show], constraints: { id: /\d+/ } do collection do post :cancel_all end @@ -697,6 +697,12 @@ Rails.application.routes.draw do end resources :runner_projects, only: [:create, :destroy] + resources :badges, only: [], path: 'badges/*ref', + constraints: { ref: Gitlab::Regex.git_reference_regex } do + collection do + get :build, constraints: { format: /svg/ } + end + end end end end diff --git a/db/fixtures/development/14_builds.rb b/db/fixtures/development/14_builds.rb index 03a12323845..e3ca2b4eea3 100644 --- a/db/fixtures/development/14_builds.rb +++ b/db/fixtures/development/14_builds.rb @@ -1,24 +1,13 @@ class Gitlab::Seeder::Builds - BUILD_STATUSES = %w(running pending success failed canceled) - def initialize(project) @project = project end def seed! ci_commits.each do |ci_commit| - build = Ci::Build.new(build_attributes_for(ci_commit)) - - artifacts_cache_file(artifacts_archive_path) do |file| - build.artifacts_file = file - end - - artifacts_cache_file(artifacts_metadata_path) do |file| - build.artifacts_metadata = file - end - begin - build.save! + build_create!(ci_commit, name: 'test build 1') + build_create!(ci_commit, status: 'success', name: 'test build 2') print '.' rescue ActiveRecord::RecordInvalid print 'F' @@ -36,6 +25,28 @@ class Gitlab::Seeder::Builds [] end + def build_create!(ci_commit, opts = {}) + attributes = build_attributes_for(ci_commit).merge(opts) + build = Ci::Build.new(attributes) + + if %w(success failed).include?(build.status) + artifacts_cache_file(artifacts_archive_path) do |file| + build.artifacts_file = file + end + + artifacts_cache_file(artifacts_metadata_path) do |file| + build.artifacts_metadata = file + end + end + + build.save! + + if %w(running success failed).include?(build.status) + # We need to set build trace after saving a build (id required) + build.trace = FFaker::Lorem.paragraphs(6).join("\n\n") + end + end + def build_attributes_for(ci_commit) { name: 'test build', commands: "$ build command", stage: 'test', stage_idx: 1, ref: 'master', @@ -49,7 +60,7 @@ class Gitlab::Seeder::Builds end def build_status - BUILD_STATUSES.sample + Ci::Build::AVAILABLE_STATUSES.sample end def artifacts_archive_path diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index b4dca6dd35e..29446ea73eb 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -516,3 +516,65 @@ Parameters: ## Comments on merge requets Comments are done via the [notes](notes.md) resource. + +## List issues that will close on merge + +Get all the issues that would be closed by merging the provided merge request. + +``` +GET /projects/:id/merge_requests/:merge_request_id/closes_issues +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer | yes | The ID of a project | +| `merge_request_id` | integer | yes | The ID of the merge request | + +```bash +curl -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/76/merge_requests/1/closes_issues +``` + +Example response: + +```json +[ + { + "state" : "opened", + "description" : "Ratione dolores corrupti mollitia soluta quia.", + "author" : { + "state" : "active", + "id" : 18, + "web_url" : "https://gitlab.example.com/u/eileen.lowe", + "name" : "Alexandra Bashirian", + "avatar_url" : null, + "username" : "eileen.lowe" + }, + "milestone" : { + "project_id" : 1, + "description" : "Ducimus nam enim ex consequatur cumque ratione.", + "state" : "closed", + "due_date" : null, + "iid" : 2, + "created_at" : "2016-01-04T15:31:39.996Z", + "title" : "v4.0", + "id" : 17, + "updated_at" : "2016-01-04T15:31:39.996Z" + }, + "project_id" : 1, + "assignee" : { + "state" : "active", + "id" : 1, + "name" : "Administrator", + "web_url" : "https://gitlab.example.com/u/root", + "avatar_url" : null, + "username" : "root" + }, + "updated_at" : "2016-01-04T15:31:51.081Z", + "id" : 76, + "title" : "Consequatur vero maxime deserunt laboriosam est voluptas dolorem.", + "created_at" : "2016-01-04T15:31:51.081Z", + "iid" : 6, + "labels" : [] + }, +] +``` diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md index 63fe840b369..bd748f1b986 100644 --- a/doc/ci/docker/using_docker_images.md +++ b/doc/ci/docker/using_docker_images.md @@ -270,7 +270,7 @@ This will forcefully (`-f`) remove the `build` container, the two service containers as well as all volumes (`-v`) that were created with the container creation. -[Docker Fundamentals]: https://docs.docker.com/engine/introduction/understanding-docker/ +[Docker Fundamentals]: https://docs.docker.com/engine/understanding-docker/ [hub]: https://hub.docker.com/ [linking-containers]: https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/ [tutum/wordpress]: https://registry.hub.docker.com/u/tutum/wordpress/ diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md index a9b36139de9..ae7b760fa67 100644 --- a/doc/ci/quick_start/README.md +++ b/doc/ci/quick_start/README.md @@ -184,6 +184,14 @@ you expected. You are also able to view the status of any commit in the various pages in GitLab, such as **Commits** and **Merge Requests**. +## Builds badge + +You can access a builds badge image using following link: + +``` +http://example.gitlab.com/namespace/project/badges/branch/build.svg +``` + ## Next steps Awesome! You started using CI in GitLab! diff --git a/features/project/badges/build.feature b/features/project/badges/build.feature new file mode 100644 index 00000000000..9417f62d680 --- /dev/null +++ b/features/project/badges/build.feature @@ -0,0 +1,22 @@ +Feature: Project Badges Build + Background: + Given I sign in as a user + And I own a project + And project has CI enabled + And project has a recent build + + Scenario: I want to see a badge for successfully built project + Given recent build is successful + When I display builds badge for a master branch + Then I should see a build success badge + + Scenario: I want to see a badge for project with failed builds + Given recent build failed + When I display builds badge for a master branch + Then I should see a build failed badge + + Scenario: I want to see a badge for project with running builds + Given recent build is successful + And project has another build that is running + When I display builds badge for a master branch + Then I should see a build running badge diff --git a/features/steps/project/badges/build.rb b/features/steps/project/badges/build.rb new file mode 100644 index 00000000000..cbfc35bed65 --- /dev/null +++ b/features/steps/project/badges/build.rb @@ -0,0 +1,28 @@ +class Spinach::Features::ProjectBadgesBuild < Spinach::FeatureSteps + include SharedAuthentication + include SharedProject + include SharedBuilds + include RepoHelpers + + step 'I display builds badge for a master branch' do + visit build_namespace_project_badges_path(@project.namespace, @project, ref: :master, format: :svg) + end + + step 'I should see a build success badge' do + expect_badge('success') + end + + step 'I should see a build failed badge' do + expect_badge('failed') + end + + step 'I should see a build running badge' do + expect_badge('running') + end + + def expect_badge(status) + svg = Nokogiri::XML.parse(page.body) + expect(page.response_headers).to include('Content-Type' => 'image/svg+xml') + expect(svg.at(%Q{text:contains("#{status}")})).to be_truthy + end +end diff --git a/features/steps/shared/builds.rb b/features/steps/shared/builds.rb index 726e2e814ad..fa54c93df0f 100644 --- a/features/steps/shared/builds.rb +++ b/features/steps/shared/builds.rb @@ -6,8 +6,20 @@ module SharedBuilds end step 'project has a recent build' do - ci_commit = create :ci_commit, project: @project, sha: sample_commit.id - @build = create :ci_build, commit: ci_commit + @ci_commit = create(:ci_commit, project: @project, sha: @project.commit.sha) + @build = create(:ci_build, commit: @ci_commit) + end + + step 'recent build is successful' do + @build.update_column(:status, 'success') + end + + step 'recent build failed' do + @build.update_column(:status, 'failed') + end + + step 'project has another build that is running' do + create(:ci_build, commit: @ci_commit, name: 'second build', status: 'running') end step 'I visit recent build details page' do diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index dd7f24f3279..4230c68abb2 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -300,6 +300,19 @@ module API render_api_error!("Failed to save note #{note.errors.messages}", 400) end end + + # List issues that will close on merge + # + # Parameters: + # id (required) - The ID of a project + # merge_request_id (required) - ID of MR + # Examples: + # GET /projects/:id/merge_requests/:merge_request_id/closes_issues + get "#{path}/closes_issues" do + merge_request = user_project.merge_requests.find(params[:merge_request_id]) + issues = ::Kaminari.paginate_array(merge_request.closes_issues(current_user)) + present paginate(issues), with: Entities::Issue + end end end end diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 2dc2953e328..54d95cd62a5 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -90,24 +90,6 @@ namespace :gitlab do end end - def check_database_is_not_sqlite - print "Database is SQLite ... " - - database_config_file = Rails.root.join("config", "database.yml") - - unless File.read(database_config_file) =~ /adapter:\s+sqlite/ - puts "no".green - else - puts "yes".red - puts "Please fix this by removing the SQLite entry from the database.yml".blue - for_more_information( - "https://github.com/gitlabhq/gitlabhq/wiki/Migrate-from-SQLite-to-MySQL", - see_database_guide - ) - fix_and_rerun - end - end - def check_gitlab_config_exists print "GitLab config exists? ... " diff --git a/scripts/prepare_build.sh b/scripts/prepare_build.sh index 5987988dc8e..b6f076a90c3 100755 --- a/scripts/prepare_build.sh +++ b/scripts/prepare_build.sh @@ -1,15 +1,15 @@ #!/bin/bash if [ -f /.dockerinit ]; then - # Docker runners use `/cache` folder which is persisted every build - if [ ! -e /cache/phantomjs_1.9.8-0jessie_amd64.deb ]; then + mkdir -p vendor + if [ ! -e vendor/phantomjs_1.9.8-0jessie_amd64.deb ]; then wget -q https://gitlab.com/axil/phantomjs-debian/raw/master/phantomjs_1.9.8-0jessie_amd64.deb - mv phantomjs_1.9.8-0jessie_amd64.deb /cache + mv phantomjs_1.9.8-0jessie_amd64.deb vendor/ fi - dpkg -i /cache/phantomjs_1.9.8-0jessie_amd64.deb + dpkg -i vendor/phantomjs_1.9.8-0jessie_amd64.deb apt-get update -qq - apt-get -o dir::cache::archives="/cache/apt" install -y -qq --force-yes \ + apt-get -o dir::cache::archives="vendor/apt" install -y -qq --force-yes \ libicu-dev libkrb5-dev cmake nodejs postgresql-client mysql-client unzip cp config/database.yml.mysql config/database.yml @@ -20,7 +20,7 @@ if [ -f /.dockerinit ]; then cp config/resque.yml.example config/resque.yml sed -i 's/localhost/redis/g' config/resque.yml - export FLAGS=(--path /cache) + export FLAGS=(--path vendor) else export PATH=$HOME/bin:/usr/local/bin:/usr/bin:/bin cp config/database.yml.mysql config/database.yml diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index a91a8696831..c64542ba6fb 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -449,6 +449,28 @@ describe API::API, api: true do end end + describe 'GET :id/merge_requests/:merge_request_id/closes_issues' do + it 'returns the issue that will be closed on merge' do + issue = create(:issue, project: project) + mr = merge_request.tap do |mr| + mr.update_attribute(:description, "Closes #{issue.to_reference(mr.project)}") + end + + get api("/projects/#{project.id}/merge_requests/#{mr.id}/closes_issues", user) + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['id']).to eq(issue.id) + end + + it 'returns an empty array when there are no issues to be closed' do + get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/closes_issues", user) + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(0) + end + end + def mr_with_later_created_and_updated_at_time merge_request merge_request.created_at += 1.hour |