diff options
| -rw-r--r-- | CHANGELOG | 5 | ||||
| -rw-r--r-- | VERSION | 2 | ||||
| -rw-r--r-- | app/assets/stylesheets/base/mixins.scss | 72 | ||||
| -rw-r--r-- | app/assets/stylesheets/generic/common.scss | 2 | ||||
| -rw-r--r-- | app/assets/stylesheets/generic/typography.scss | 8 | ||||
| -rw-r--r-- | app/controllers/help_controller.rb | 5 | ||||
| -rw-r--r-- | app/controllers/projects/merge_requests_controller.rb | 3 | ||||
| -rw-r--r-- | app/helpers/ci_status_helper.rb | 34 | ||||
| -rw-r--r-- | app/helpers/commits_helper.rb | 2 | ||||
| -rw-r--r-- | app/models/project.rb | 14 | ||||
| -rw-r--r-- | app/models/project_services/gitlab_ci_service.rb | 2 | ||||
| -rw-r--r-- | app/services/git_push_service.rb | 12 | ||||
| -rw-r--r-- | app/views/help/index.html.haml | 6 | ||||
| -rw-r--r-- | app/views/projects/commits/_commit.html.haml | 10 | ||||
| -rw-r--r-- | app/views/projects/graphs/commits.html.haml | 76 | ||||
| -rw-r--r-- | app/views/projects/merge_requests/widget/_merged.html.haml | 2 | ||||
| -rw-r--r-- | doc/README.md | 2 | ||||
| -rw-r--r-- | doc/markdown/markdown.md | 1 | ||||
| -rw-r--r-- | lib/api/users.rb | 11 | ||||
| -rw-r--r-- | spec/helpers/ci_status_helper_spec.rb | 18 | ||||
| -rw-r--r-- | spec/models/project_spec.rb | 20 | ||||
| -rw-r--r-- | spec/requests/api/users_spec.rb | 14 |
22 files changed, 248 insertions, 73 deletions
diff --git a/CHANGELOG b/CHANGELOG index fff641fcb48..1a3b102f4e1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,8 +1,13 @@ Please view this file on the master branch, on stable branches it's out of date. +v 8.1.0 (unreleased) + - Show CI status on all pages where commits list is rendered + - Automatically enable CI when push .gitlab-ci.yml file to repository + v 8.0.1 - Fix cases where Markdown did not render links in activity feed (Stan Hu) - Improve CI migration procedure and documentation + - Make commit graphs responsive to window width changes (Stan Hu) v 8.0.0 - Fix Markdown links not showing up in dashboard activity feed (Stan Hu) @@ -1 +1 @@ -8.0.0.pre +8.1.0.pre diff --git a/app/assets/stylesheets/base/mixins.scss b/app/assets/stylesheets/base/mixins.scss index a2f6c3e21f4..421588f64d8 100644 --- a/app/assets/stylesheets/base/mixins.scss +++ b/app/assets/stylesheets/base/mixins.scss @@ -93,46 +93,87 @@ } h1 { - margin-top: 45px; - font-size: 2.5em; + font-size: 1.3em; + font-weight: 600; + margin: 24px 0 12px 0; + padding: 0 0 10px 0; + border-bottom: 1px solid #e7e9ed; + color: #313236; } h2 { - margin-top: 40px; - font-size: 2em; + font-size: 1.2em; + font-weight: 600; + margin: 24px 0 12px 0; + color: #313236; } h3 { - margin-top: 35px; - font-size: 1.5em; + margin: 24px 0 12px 0; + font-size: 1.25em; } h4 { - margin-top: 30px; - font-size: 1.2em; + margin: 24px 0 12px 0; + font-size: 1.1em; + } + + h5 { + margin: 24px 0 12px 0; + font-size: 1em; + } + + h6 { + margin: 24px 0 12px 0; + font-size: 0.90em; } blockquote { - color: #888; + padding: 8px 21px; + margin: 12px 0 12px; + border-left: 3px solid #e7e9ed; + } + + blockquote p { + color: #7f8fa4 !important; font-size: 15px; line-height: 1.5; } - + + p { + color:#5c5d5e; + margin:6px 0 0 0; + } + table { @extend .table; @extend .table-bordered; + margin: 12px 0 12px 0; + color: #5c5d5e; th { - background: #EEE; - } + background: #f8fafc; + } + } + + pre { + margin: 12px 0 12px 0 !important; + background-color: #f8fafc !important; + font-size: 13px !important; + color: #5b6169 !important; + line-height: 1.6em !important; } p > code { - font-size: inherit; font-weight: inherit; } + + ul { + color: #5c5d5e; + } + li { - line-height: 1.5; + line-height: 1.6em; } a[href*="/uploads/"], a[href*="storage.googleapis.com/google-code-attachments/"] { @@ -152,6 +193,7 @@ } } + @mixin str-truncated($max_width: 82%) { display: inline-block; overflow: hidden; @@ -183,7 +225,7 @@ &.active { background: #f9f9f9; a { - font-weight: bold; + font-weight: 600; } } diff --git a/app/assets/stylesheets/generic/common.scss b/app/assets/stylesheets/generic/common.scss index 48fad7701ef..b659717b4e1 100644 --- a/app/assets/stylesheets/generic/common.scss +++ b/app/assets/stylesheets/generic/common.scss @@ -302,7 +302,7 @@ table { } .btn-sign-in { - margin-top: 15px; + margin-top: 8px; text-shadow: none; } diff --git a/app/assets/stylesheets/generic/typography.scss b/app/assets/stylesheets/generic/typography.scss index d5f0d86a307..7a8a17ced99 100644 --- a/app/assets/stylesheets/generic/typography.scss +++ b/app/assets/stylesheets/generic/typography.scss @@ -55,6 +55,7 @@ a > code { @include md-typography; word-wrap: break-word; + padding: 7px; /* Link to current header. */ h1, h2, h3, h4, h5, h6 { @@ -83,9 +84,12 @@ a > code { } } - ul { + ul,ol { padding: 0; - margin: 0 0 9px 25px !important; + margin: 6px 0 6px 18px !important; + } + ol { + color: #5c5d5e; } } diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb index ad00948da51..55050615473 100644 --- a/app/controllers/help_controller.rb +++ b/app/controllers/help_controller.rb @@ -4,6 +4,11 @@ class HelpController < ApplicationController layout 'help' def index + @help_index = File.read(Rails.root.join('doc', 'README.md')) + + # Prefix Markdown links with `help/` unless they already have been + # See http://rubular.com/r/nwwhzH6Z8X + @help_index.gsub!(/(\]\()(?!help\/)([^\)\(]+)(\))/, '\1help/\2\3') end def show diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index c1231994f25..7574842cd43 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -258,8 +258,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController @commits = @merge_request.commits @merge_request_diff = @merge_request.merge_request_diff - @source_branch = @merge_request.source_project.repository.find_branch(@merge_request.source_branch).try(:name) - + if @merge_request.locked_long_ago? @merge_request.unlock_mr @merge_request.close diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb new file mode 100644 index 00000000000..18c30ddb281 --- /dev/null +++ b/app/helpers/ci_status_helper.rb @@ -0,0 +1,34 @@ +module CiStatusHelper + def ci_status_path(ci_commit) + ci_project_ref_commits_path(ci_commit.project, ci_commit.ref, ci_commit) + end + + def ci_status_icon(ci_commit) + icon_name = + case ci_commit.status + when 'success' + 'check' + when 'failed' + 'close' + when 'running', 'pending' + 'clock-o' + else + 'circle' + end + + icon(icon_name) + end + + def ci_status_color(ci_commit) + case ci_commit.status + when 'success' + 'green' + when 'failed' + 'red' + when 'running', 'pending' + 'yellow' + else + 'gray' + end + end +end diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index d13d80be293..9df20c9fce5 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -135,7 +135,7 @@ module CommitsHelper # size: size of the avatar image in px def commit_person_link(commit, options = {}) user = commit.send(options[:source]) - + source_name = clean(commit.send "#{options[:source]}_name".to_sym) source_email = clean(commit.send "#{options[:source]}_email".to_sym) diff --git a/app/models/project.rb b/app/models/project.rb index 1a5c1c978c9..a7ea1236b86 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -735,4 +735,18 @@ class Project < ActiveRecord::Base errors.add(:base, 'Failed create wiki') false end + + def ci_commit(sha) + gitlab_ci_project.commits.find_by(sha: sha) if gitlab_ci? + end + + def enable_ci(user) + # Enable service + service = gitlab_ci_service || create_gitlab_ci_service + service.active = true + service.save + + # Create Ci::Project + Ci::CreateProjectService.new.execute(user, self) + end end diff --git a/app/models/project_services/gitlab_ci_service.rb b/app/models/project_services/gitlab_ci_service.rb index 9e2b3bcd873..ec3bd44024f 100644 --- a/app/models/project_services/gitlab_ci_service.rb +++ b/app/models/project_services/gitlab_ci_service.rb @@ -72,7 +72,7 @@ class GitlabCiService < CiService }) ci_project = Ci::Project.find_by!(gitlab_id: project.id) - + Ci::CreateProjectService.new.execute( current_user, params, diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index 0a73244774a..8193b6e192d 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -55,6 +55,12 @@ class GitPushService @push_data = build_push_data(oldrev, newrev, ref) + # If CI was disabled but .gitlab-ci.yml file was pushed + # we enable CI automatically + if !project.gitlab_ci? && gitlab_ci_yaml?(newrev) + project.enable_ci(user) + end + EventCreateService.new.push(project, user, @push_data) project.execute_hooks(@push_data.dup, :push_hooks) project.execute_services(@push_data.dup, :push_hooks) @@ -143,4 +149,10 @@ class GitPushService def commit_user(commit) commit.author || user end + + def gitlab_ci_yaml?(sha) + @project.repository.blob_at(sha, '.gitlab-ci.yml') + rescue Rugged::ReferenceError + nil + end end diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml index f492aaf4c0a..ab7ed1b5d95 100644 --- a/app/views/help/index.html.haml +++ b/app/views/help/index.html.haml @@ -27,11 +27,7 @@ .col-md-8 .documentation-index = preserve do - - readme_text = File.read(Rails.root.join("doc", "README.md")) - - text = readme_text.dup - - readme_text.scan(/\]\(([^(]+)\)/) { |match| text.gsub!(match.first, "help/#{match.first}") } - = markdown text - + = markdown(@help_index) .col-md-4 .panel.panel-default .panel-heading diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml index 74f8d8b15cf..efad4cb1473 100644 --- a/app/views/projects/commits/_commit.html.haml +++ b/app/views/projects/commits/_commit.html.haml @@ -4,7 +4,11 @@ - notes = commit.notes - note_count = notes.user.count -= cache [project.id, commit.id, note_count] do +- ci_commit = project.ci_commit(commit.sha) +- cache_key = [project.id, commit.id, note_count] +- cache_key.push(ci_commit.status) if ci_commit + += cache(cache_key) do %li.commit.js-toggle-container .commit-row-title %strong.str-truncated @@ -13,6 +17,10 @@ %a.text-expander.js-toggle-button ... .pull-right + - if ci_commit + = link_to ci_status_path(ci_commit), class: "c#{ci_status_color(ci_commit)}" do + = ci_status_icon(ci_commit) + = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id" .notes_count diff --git a/app/views/projects/graphs/commits.html.haml b/app/views/projects/graphs/commits.html.haml index bf0cac539b8..112be875b6b 100644 --- a/app/views/projects/graphs/commits.html.haml +++ b/app/views/projects/graphs/commits.html.haml @@ -32,61 +32,55 @@ %div %p.slead Commits per day of month - %canvas#month-chart{width: 800, height: 400} + %canvas#month-chart .row .col-md-6 %div %p.slead Commits per day hour (UTC) - %canvas#hour-chart{width: 800, height: 400} + %canvas#hour-chart .col-md-6 %div %p.slead Commits per weekday - %canvas#weekday-chart{width: 800, height: 400} + %canvas#weekday-chart :coffeescript - data = { - labels : #{@commits_per_time.keys.to_json}, - datasets : [{ - fillColor : "rgba(220,220,220,0.5)", - strokeColor : "rgba(220,220,220,1)", - barStrokeWidth: 1, - barValueSpacing: 1, - barDatasetSpacing: 1, - data : #{@commits_per_time.values.to_json} - }] - } + responsiveChart = (selector, data) -> + options = { "scaleOverlay": true, responsive: true, pointHitDetectionRadius: 2, maintainAspectRatio: false } - ctx = $("#hour-chart").get(0).getContext("2d"); - new Chart(ctx).Bar(data,{"scaleOverlay": true, responsive: true, pointHitDetectionRadius: 2}) + # get selector by context + ctx = selector.get(0).getContext("2d") + # pointing parent container to make chart.js inherit its width + container = $(selector).parent() - data = { - labels : #{@commits_per_week_days.keys.to_json}, - datasets : [{ - fillColor : "rgba(220,220,220,0.5)", - strokeColor : "rgba(220,220,220,1)", - barStrokeWidth: 1, - barValueSpacing: 1, - barDatasetSpacing: 1, - data : #{@commits_per_week_days.values.to_json} - }] - } + generateChart = -> + selector.attr('width', $(container).width()) + new Chart(ctx).Bar(data, options) + + # enabling auto-resizing + $(window).resize( generateChart ) - ctx = $("#weekday-chart").get(0).getContext("2d"); - new Chart(ctx).Bar(data,{"scaleOverlay": true, responsive: true, pointHitDetectionRadius: 2}) + generateChart() - data = { - labels : #{@commits_per_month.keys.to_json}, - datasets : [{ - fillColor : "rgba(220,220,220,0.5)", - strokeColor : "rgba(220,220,220,1)", - barStrokeWidth: 1, - barValueSpacing: 1, - barDatasetSpacing: 1, - data : #{@commits_per_month.values.to_json} - }] + chartData = (keys, values) -> + data = { + labels : keys, + datasets : [{ + fillColor : "rgba(220,220,220,0.5)", + strokeColor : "rgba(220,220,220,1)", + barStrokeWidth: 1, + barValueSpacing: 1, + barDatasetSpacing: 1, + data : values + }] } - ctx = $("#month-chart").get(0).getContext("2d"); - new Chart(ctx).Bar(data, {"scaleOverlay": true, responsive: true, pointHitDetectionRadius: 2}) + hourData = chartData(#{@commits_per_time.keys.to_json}, #{@commits_per_time.values.to_json}) + responsiveChart($('#hour-chart'), hourData) + + dayData = chartData(#{@commits_per_week_days.keys.to_json}, #{@commits_per_week_days.values.to_json}) + responsiveChart($('#weekday-chart'), dayData) + + monthData = chartData(#{@commits_per_month.keys.to_json}, #{@commits_per_month.values.to_json}) + responsiveChart($('#month-chart'), monthData) diff --git a/app/views/projects/merge_requests/widget/_merged.html.haml b/app/views/projects/merge_requests/widget/_merged.html.haml index d22dfa085b8..f223f687def 100644 --- a/app/views/projects/merge_requests/widget/_merged.html.haml +++ b/app/views/projects/merge_requests/widget/_merged.html.haml @@ -20,7 +20,7 @@ The changes were merged into %span.label-branch= @merge_request.target_branch You can remove the source branch now. - = link_to namespace_project_branch_path(@merge_request.source_project.namespace, @merge_request.source_project, @source_branch), remote: true, method: :delete, class: "btn btn-primary btn-sm remove_source_branch" do + = link_to namespace_project_branch_path(@merge_request.source_project.namespace, @merge_request.source_project, @merge_request.source_branch), remote: true, method: :delete, class: "btn btn-primary btn-sm remove_source_branch" do %i.fa.fa-times Remove Source Branch diff --git a/doc/README.md b/doc/README.md index 5f38086b8e3..a0ff856ebb6 100644 --- a/doc/README.md +++ b/doc/README.md @@ -51,7 +51,7 @@ ### Administrator documentation -+ [User permissions](permissions/README.md) ++ [User permissions](permissions/permissions.md) + [API](api/README.md) ## Contributor documentation diff --git a/doc/markdown/markdown.md b/doc/markdown/markdown.md index 6fdb2fe1491..d83838127c9 100644 --- a/doc/markdown/markdown.md +++ b/doc/markdown/markdown.md @@ -33,7 +33,6 @@ For GitLab we developed something we call "GitLab Flavored Markdown" (GFM). It e You can use GFM in -- commit messages - comments - issues - merge requests diff --git a/lib/api/users.rb b/lib/api/users.rb index 813cc379e43..a98d668e02d 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -121,6 +121,17 @@ module API User.where(username: attrs[:username]). where.not(id: user.id).count > 0 + identity_attrs = attributes_for_keys [:provider, :extern_uid] + if identity_attrs.any? + identity = user.identities.find_by(provider: identity_attrs[:provider]) + if identity + identity.update_attributes(identity_attrs) + else + identity = user.identities.build(identity_attrs) + identity.save + end + end + if user.update_attributes(attrs) present user, with: Entities::UserFull else diff --git a/spec/helpers/ci_status_helper_spec.rb b/spec/helpers/ci_status_helper_spec.rb new file mode 100644 index 00000000000..7fc53eb1472 --- /dev/null +++ b/spec/helpers/ci_status_helper_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +describe CiStatusHelper do + include IconsHelper + + let(:success_commit) { double("Ci::Commit", status: 'success') } + let(:failed_commit) { double("Ci::Commit", status: 'failed') } + + describe 'ci_status_color' do + it { expect(ci_status_icon(success_commit)).to include('fa-check') } + it { expect(ci_status_icon(failed_commit)).to include('fa-close') } + end + + describe 'ci_status_color' do + it { expect(ci_status_color(success_commit)).to eq('green') } + it { expect(ci_status_color(failed_commit)).to eq('red') } + end +end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 2fcbd5ae108..9e7b6f5cb30 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -401,4 +401,24 @@ describe Project do it { should eq "http://localhost#{avatar_path}" } end end + + describe :ci_commit do + let(:project) { create :project } + let(:ci_project) { create :ci_project, gl_project: project } + let(:commit) { create :ci_commit, project: ci_project } + + before { project.create_gitlab_ci_service(active: true) } + + it { expect(project.ci_commit(commit.sha)).to eq(commit) } + end + + describe :enable_ci do + let(:project) { create :project } + let(:user) { create :user } + + before { project.enable_ci(user) } + + it { expect(project.gitlab_ci?).to be_truthy } + it { expect(project.gitlab_ci_project).to be_a(Ci::Project) } + end end diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index f9bc63680ba..d26a300ed82 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -7,6 +7,7 @@ describe API::API, api: true do let(:admin) { create(:admin) } let(:key) { create(:key, user: user) } let(:email) { create(:email, user: user) } + let(:omniauth_user) { create(:omniauth_user) } describe "GET /users" do context "when unauthenticated" do @@ -230,6 +231,19 @@ describe API::API, api: true do expect(user.reload.username).to eq(user.username) end + it "should update user's existing identity" do + put api("/users/#{omniauth_user.id}", admin), provider: 'ldapmain', extern_uid: '654321' + expect(response.status).to eq(200) + expect(omniauth_user.reload.identities.first.extern_uid).to eq('654321') + end + + it 'should update user with new identity' do + put api("/users/#{user.id}", admin), provider: 'github', extern_uid: '67890' + expect(response.status).to eq(200) + expect(user.reload.identities.first.extern_uid).to eq('67890') + expect(user.reload.identities.first.provider).to eq('github') + end + it "should update admin status" do put api("/users/#{user.id}", admin), { admin: true } expect(response.status).to eq(200) |
