Commit 77bda265 authored by Valery Sizov's avatar Valery Sizov

Merge branch 'ci-and-ce-sitting-in-a-tree-k-i-s-s-i-n-g' of...

Merge branch 'ci-and-ce-sitting-in-a-tree-k-i-s-s-i-n-g' of gitlab.com:gitlab-org/gitlab-ce into ci-and-ce-sitting-in-a-tree-k-i-s-s-i-n-g
parents d1914c1e 2ed2ef92
......@@ -52,3 +52,11 @@ pre.trace {
color: #777;
}
}
.alert-disabled {
background: #EEE;
a {
color: #3084bb !important;
}
}
......@@ -4,14 +4,8 @@ module Ci
"app/helpers/ci"
end
include Ci::UserSessionsHelper
rescue_from Ci::Network::UnauthorizedError, with: :invalid_token
before_filter :default_headers
helper_method :gl_project
protect_from_forgery
private
def authenticate_public_page!
......@@ -75,27 +69,6 @@ module Ci
}
end
def check_config
redirect_to oauth2_ci_help_path unless valid_config?
end
def valid_config?
server = GitlabCi.config.gitlab_server
if server.blank? || server.url.blank? || server.app_id.blank? || server.app_secret.blank?
false
else
true
end
rescue Settingslogic::MissingSetting, NoMethodError
false
end
def invalid_token
reset_session
redirect_to ci_root_path
end
def gl_project
::Project.find(@project.gitlab_id)
end
......
......@@ -21,7 +21,7 @@ module Ci
def cancel
commit.builds.running_or_pending.each(&:cancel)
redirect_to ci_project_ref_commit_path(project, commit.ref, commit.sha)
redirect_to ci_project_ref_commits_path(project, commit.ref, commit.sha)
end
private
......
......@@ -35,8 +35,6 @@ module Ci
pager_json("ci/projects/gitlab", @total_count)
end
end
rescue Ci::Network::UnauthorizedError
raise
rescue
@error = 'Failed to fetch GitLab projects'
end
......@@ -82,8 +80,8 @@ module Ci
end
def destroy
project.gl_project.gitlab_ci_service.update_attributes(active: false)
project.destroy
Ci::Network.new.disable_ci(project.gitlab_id, current_user.authenticate_options)
Ci::EventService.new.remove_project(current_user, project)
......
......@@ -15,8 +15,12 @@ module Ci
end
end
def ci_commit_path(commit)
ci_project_ref_commits_path(commit.project, commit.ref, commit.sha)
end
def commit_link(commit)
link_to(commit.short_sha, ci_project_ref_commits_path(commit.project, commit.ref, commit.sha))
link_to(commit.short_sha, ci_commit_path(commit))
end
def truncate_first_line(message, length = 50)
......
module Ci
module UserSessionsHelper
def generate_oauth_salt
SecureRandom.hex(16)
end
def generate_oauth_hmac(salt, return_to)
return unless return_to
digest = OpenSSL::Digest.new('sha256')
key = Gitlab::Application.secrets.db_key_base + salt
OpenSSL::HMAC.hexdigest(digest, key, return_to)
end
def generate_oauth_state(return_to)
return unless return_to
salt = generate_oauth_salt
hmac = generate_oauth_hmac(salt, return_to)
"#{salt}:#{hmac}:#{return_to}"
end
def get_ouath_state_return_to(state)
state.split(':', 3)[2] if state
end
def is_oauth_state_valid?(state)
return true unless state
salt, hmac, return_to = state.split(':', 3)
return false unless return_to
hmac == generate_oauth_hmac(salt, return_to)
end
end
end
module Ci
class Network
class UnauthorizedError < StandardError; end
include HTTParty
API_PREFIX = '/api/v3/'
def authenticate(api_opts)
opts = {
query: api_opts
}
endpoint = File.join(url, API_PREFIX, 'user')
response = self.class.get(endpoint, default_opts.merge(opts))
build_response(response)
end
def projects(api_opts, scope = :owned)
# Dont load archived projects
api_opts.merge!(archived: false)
opts = {
query: api_opts
}
query = if scope == :owned
'projects/owned.json'
else
'projects.json'
end
endpoint = File.join(url, API_PREFIX, query)
response = self.class.get(endpoint, default_opts.merge(opts))
build_response(response)
end
def project(api_opts, project_id)
opts = {
query: api_opts
}
query = "projects/#{project_id}.json"
endpoint = File.join(url, API_PREFIX, query)
response = self.class.get(endpoint, default_opts.merge(opts))
build_response(response)
end
def project_hooks(api_opts, project_id)
opts = {
query: api_opts
}
query = "projects/#{project_id}/hooks.json"
endpoint = File.join(url, API_PREFIX, query)
response = self.class.get(endpoint, default_opts.merge(opts))
build_response(response)
end
def enable_ci(project_id, data, api_opts)
opts = {
body: data.to_json,
query: api_opts
}
query = "projects/#{project_id}/services/gitlab-ci.json"
endpoint = File.join(url, API_PREFIX, query)
response = self.class.put(endpoint, default_opts.merge(opts))
case response.code
when 200
true
when 401
raise UnauthorizedError
else
nil
end
end
def disable_ci(project_id, api_opts)
opts = {
query: api_opts
}
query = "projects/#{project_id}/services/gitlab-ci.json"
endpoint = File.join(url, API_PREFIX, query)
response = self.class.delete(endpoint, default_opts.merge(opts))
build_response(response)
end
private
def url
Gitlab.config.gitlab.url
end
def default_opts
{
headers: { "Content-Type" => "application/json" },
}
end
def build_response(response)
case response.code
when 200
response.parsed_response
when 401
raise UnauthorizedError
else
nil
end
end
end
end
......@@ -31,6 +31,8 @@ module Ci
include Ci::ProjectStatus
belongs_to :gl_project, class_name: '::Project', foreign_key: :gitlab_id
has_many :commits, ->() { order(:committed_at) }, dependent: :destroy, class_name: 'Ci::Commit'
has_many :builds, through: :commits, dependent: :destroy, class_name: 'Ci::Build'
has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject'
......@@ -90,11 +92,13 @@ module Ci
project
end
# TODO: remove
def from_gitlab(user, scope = :owned, options)
opts = user.authenticate_options
opts.merge! options
projects = Ci::Network.new.projects(opts.compact, scope)
raise 'Implement me of fix'
#projects = Ci::Network.new.projects(opts.compact, scope)
if projects
projects.map { |pr| OpenStruct.new(pr) }
......
......@@ -13,9 +13,9 @@ module Ci
project_url: project_route.gsub(":project_id", @project.id.to_s),
}
unless Ci::Network.new.enable_ci(@project.gitlab_id, data, {private_token: current_user.private_token})
raise ActiveRecord::Rollback
end
gl_project = ::Project.find(@project.gitlab_id)
gl_project.build_missing_services
gl_project.gitlab_ci_service.update_attributes(data.merge(active: true))
end
if forked_project
......
......@@ -43,7 +43,7 @@ FactoryGirl.define do
"git@demo.gitlab.com:gitlab/gitlab-shell#{n}.git"
end
sequence :gitlab_id
gl_project factory: :project
factory :ci_project do
token 'iPWx6WM4lhHNedGfBpPJNP'
......
require 'spec_helper'
describe "Builds" do
context :private_project do
before do
@project = FactoryGirl.create :project
@commit = FactoryGirl.create :commit, project: @project
@build = FactoryGirl.create :build, commit: @commit
@project = FactoryGirl.create :ci_project
@commit = FactoryGirl.create :ci_commit, project: @project
@build = FactoryGirl.create :ci_build, commit: @commit
login_as :user
@project.gl_project.team << [@user, :master]
end
describe "GET /:project/builds/:id" do
before do
login_as :user
visit project_build_path(@project, @build)
visit ci_project_build_path(@project, @build)
end
it { expect(page).to have_content @commit.sha[0..7] }
......@@ -20,9 +22,8 @@ describe "Builds" do
describe "GET /:project/builds/:id/cancel" do
before do
login_as :user
@build.run!
visit cancel_project_build_path(@project, @build)
visit cancel_ci_project_build_path(@project, @build)
end
it { expect(page).to have_content 'canceled' }
......@@ -31,27 +32,29 @@ describe "Builds" do
describe "POST /:project/builds/:id/retry" do
before do
login_as :user
@build.cancel!
visit project_build_path(@project, @build)
visit ci_project_build_path(@project, @build)
click_link 'Retry'
end
it { expect(page).to have_content 'pending' }
it { expect(page).to have_content 'Cancel' }
end
end
context :public_project do
describe "Show page public accessible" do
before do
@project = FactoryGirl.create :public_project
@commit = FactoryGirl.create :commit, project: @project
@runner = FactoryGirl.create :specific_runner
@build = FactoryGirl.create :build, commit: @commit, runner: @runner
@project = FactoryGirl.create :ci_public_project
@commit = FactoryGirl.create :ci_commit, project: @project
@runner = FactoryGirl.create :ci_specific_runner
@build = FactoryGirl.create :ci_build, commit: @commit, runner: @runner
stub_gitlab_calls
visit project_build_path(@project, @build)
visit ci_project_build_path(@project, @build)
end
it { expect(page).to have_content @commit.sha[0..7] }
end
end
end
require 'spec_helper'
describe "Commits" do
include Ci::CommitsHelper
context "Authenticated user" do
before do
login_as :user
@project = FactoryGirl.create :ci_project
@commit = FactoryGirl.create :ci_commit, project: @project
@build = FactoryGirl.create :ci_build, commit: @commit
login_as :user
@project.gl_project.team << [@user, :master]
end
describe "GET /:project/commits/:sha" do
before do
visit ci_project_ref_commit_path(@project, @commit.ref, @commit.sha)
visit ci_commit_path(@commit)
end
it { expect(page).to have_content @commit.sha[0..7] }
......@@ -21,7 +24,7 @@ describe "Commits" do
describe "Cancel commit" do
it "cancels commit" do
visit ci_project_ref_commit_path(@project, @commit.ref, @commit.sha)
visit ci_commit_path(@commit)
click_on "Cancel"
expect(page).to have_content "canceled"
......@@ -30,7 +33,7 @@ describe "Commits" do
describe ".gitlab-ci.yml not found warning" do
it "does not show warning" do
visit ci_project_ref_commit_path(@project, @commit.ref, @commit.sha)
visit ci_commit_path(@commit)
expect(page).not_to have_content ".gitlab-ci.yml not found in this commit"
end
......@@ -39,7 +42,7 @@ describe "Commits" do
@commit.push_data[:ci_yaml_file] = nil
@commit.save
visit ci_project_ref_commit_path(@project, @commit.ref, @commit.sha)
visit ci_commit_path(@commit)
expect(page).to have_content ".gitlab-ci.yml not found in this commit"
end
......@@ -55,7 +58,7 @@ describe "Commits" do
describe "GET /:project/commits/:sha" do
before do
visit ci_project_ref_commit_path(@project, @commit.ref, @commit.sha)
visit ci_commit_path(@commit)
end
it { expect(page).to have_content @commit.sha[0..7] }
......
require 'spec_helper'
describe Ci::UserHelper do
describe :user_avatar_url do
let (:user) { User.new({'avatar_url' => avatar_url}) }
context 'no avatar' do
let (:avatar_url) { nil }
it 'should return a generic avatar' do
user_avatar_url(user).should == 'ci/no_avatar.png'
end
end
context 'plain gravatar' do
let (:base_url) { 'http://www.gravatar.com/avatar/abcdefgh' }
let (:avatar_url) { "#{base_url}?s=40&d=mm" }
it 'should return gravatar with default size' do
user_avatar_url(user).should == "#{base_url}?s=40&d=identicon"
end
it 'should return gravatar with custom size' do
user_avatar_url(user, 120).should == "#{base_url}?s=120&d=identicon"
end
end
context 'secure gravatar' do
let (:base_url) { 'https://secure.gravatar.com/avatar/abcdefgh' }
let (:avatar_url) { "#{base_url}?s=40&d=mm" }
it 'should return gravatar with default size' do
user_avatar_url(user).should == "#{base_url}?s=40&d=identicon"
end
it 'should return gravatar with custom size' do
user_avatar_url(user, 120).should == "#{base_url}?s=120&d=identicon"
end
end
context 'custom avatar' do
let (:avatar_url) { 'http://example.local/avatar.png' }
it 'should return custom avatar' do
user_avatar_url(user).should == avatar_url
end
end
end
end
require 'spec_helper'
describe Ci::UserSessionsHelper do
describe :generate_oauth_hmac do
let (:salt) { 'a' }
let (:salt2) { 'b' }
let (:return_to) { 'b' }
it 'should return null if return_to is also null' do
generate_oauth_hmac(salt, nil).should be_nil
end
it 'should return not null if return_to is also not null' do
generate_oauth_hmac(salt, return_to).should_not be_nil
end
it 'should return different hmacs for different salts' do
secret1 = generate_oauth_hmac(salt, return_to)
secret2 = generate_oauth_hmac(salt2, return_to)
secret1.should_not eq(secret2)
end
end
describe :generate_oauth_state do
let (:return_to) { 'b' }
it 'should return null if return_to is also null' do
generate_oauth_state(nil).should be_nil
end
it 'should return two different states for same return_to' do
state1 = generate_oauth_state(return_to)
state2 = generate_oauth_state(return_to)
state1.should_not eq(state2)
end
end
describe :get_ouath_state_return_to do
let (:return_to) { 'a' }
let (:state) { generate_oauth_state(return_to) }
it 'should return return_to' do
get_ouath_state_return_to(state).should eq(return_to)
end
end
describe :is_oauth_state_valid? do
let (:return_to) { 'a' }
let (:state) { generate_oauth_state(return_to) }
let (:forged) { "forged#{state}" }
let (:invalid) { 'aa' }
let (:invalid2) { 'aa:bb' }
let (:invalid3) { 'aa:bb:' }
it 'should validate oauth state' do
is_oauth_state_valid?(state).should be_true
end
it 'should not validate forged state' do
is_oauth_state_valid?(forged).should be_false
end
it 'should not validate invalid state' do
is_oauth_state_valid?(invalid).should be_false
is_oauth_state_valid?(invalid2).should be_false
is_oauth_state_valid?(invalid3).should be_false
end
end
end
require 'spec_helper'
describe Ci::Ansi2html do
subject { Ci::Ansi2html }
it "prints non-ansi as-is" do
Ansi2html::convert("Hello").should == 'Hello'
expect(subject.convert("Hello")).to eq('Hello')
end
it "strips non-color-changing controll sequences" do
Ansi2html::convert("Hello \e[2Kworld").should == 'Hello world'
expect(subject.convert("Hello \e[2Kworld")).to eq('Hello world')
end
it "prints simply red" do
Ansi2html::convert("\e[31mHello\e[0m").should == '<span class="term-fg-red">Hello</span>'
expect(subject.convert("\e[31mHello\e[0m")).to eq('<span class="term-fg-red">Hello</span>')
end
it "prints simply red without trailing reset" do
Ansi2html::convert("\e[31mHello").should == '<span class="term-fg-red">Hello</span>'
expect(subject.convert("\e[31mHello")).to eq('<span class="term-fg-red">Hello</span>')
end
it "prints simply yellow" do
Ansi2html::convert("\e[33mHello\e[0m").should == '<span class="term-fg-yellow">Hello</span>'
expect(subject.convert("\e[33mHello\e[0m")).to eq('<span class="term-fg-yellow">Hello</span>')
end
it "prints default on blue" do
Ansi2html::convert("\e[39;44mHello").should == '<span class="term-bg-blue">Hello</span>'
expect(subject.convert("\e[39;44mHello")).to eq('<span class="term-bg-blue">Hello</span>')
end
it "prints red on blue" do
Ansi2html::convert("\e[31;44mHello").should == '<span class="term-fg-red term-bg-blue">Hello</span>'
expect(subject.convert("\e[31;44mHello")).to eq('<span class="term-fg-red term-bg-blue">Hello</span>')
end
it "resets colors after red on blue" do
Ansi2html::convert("\e[31;44mHello\e[0m world").should == '<span class="term-fg-red term-bg-blue">Hello</span> world'
expect(subject.convert("\e[31;44mHello\e[0m world")).to eq('<span class="term-fg-red term-bg-blue">Hello</span> world')
end
it "performs color change from red/blue to yellow/blue" do
Ansi2html::convert("\e[31;44mHello \e[33mworld").should == '<span class="term-fg-red term-bg-blue">Hello </span><span class="term-fg-yellow term-bg-blue">world</span>'
expect(subject.convert("\e[31;44mHello \e[33mworld")).to eq('<span class="term-fg-red term-bg-blue">Hello </span><span class="term-fg-yellow term-bg-blue">world</span>')
end
it "performs color change from red/blue to yellow/green" do
Ansi2html::convert("\e[31;44mHello \e[33;42mworld").should == '<span class="term-fg-red term-bg-blue">Hello </span><span class="term-fg-yellow term-bg-green">world</span>'
expect(subject.convert("\e[31;44mHello \e[33;42mworld")).to eq('<span class="term-fg-red term-bg-blue">Hello </span><span class="term-fg-yellow term-bg-green">world</span>')
end
it "performs color change from red/blue to reset to yellow/green" do
Ansi2html::convert("\e[31;44mHello\e[0m \e[33;42mworld").should == '<span class="term-fg-red term-bg-blue">Hello</span> <span class="term-fg-yellow term-bg-green">world</span>'
expect(subject.convert("\e[31;44mHello\e[0m \e[33;42mworld")).to eq('<span class="term-fg-red term-bg-blue">Hello</span> <span class="term-fg-yellow term-bg-green">world</span>')
end
it "ignores unsupported codes" do
Ansi2html::convert("\e[51mHello\e[0m").should == 'Hello'
expect(subject.convert("\e[51mHello\e[0m")).to eq('Hello')
end
it "prints light red" do
Ansi2html::convert("\e[91mHello\e[0m").should == '<span class="term-fg-l-red">Hello</span>'
expect(subject.convert("\e[91mHello\e[0m")).to eq('<span class="term-fg-l-red">Hello</span>')
end
it "prints default on light red" do
Ansi2html::convert("\e[101mHello\e[0m").should == '<span class="term-bg-l-red">Hello</span>'
expect(subject.convert("\e[101mHello\e[0m")).to eq('<span class="term-bg-l-red">Hello</span>')
end
it "performs color change from red/blue to default/blue" do
Ansi2html::convert("\e[31;44mHello \e[39mworld").should == '<span class="term-fg-red term-bg-blue">Hello </span><span class="term-bg-blue">world</span>'
expect(subject.convert("\e[31;44mHello \e[39mworld")).to eq('<span class="term-fg-red term-bg-blue">Hello </span><span class="term-bg-blue">world</span>')
end
it "performs color change from light red/blue to default/blue" do
Ansi2html::convert("\e[91;44mHello \e[39mworld").should == '<span class="term-fg-l-red term-bg-blue">Hello </span><span class="term-bg-blue">world</span>'
expect(subject.convert("\e[91;44mHello \e[39mworld")).to eq('<span class="term-fg-l-red term-bg-blue">Hello </span><span class="term-bg-blue">world</span>')
end
it "prints bold text" do
Ansi2html::convert("\e[1mHello").should == '<span class="term-bold">Hello</span>'
expect(subject.convert("\e[1mHello")).to eq('<span class="term-bold">Hello</span>')
end
it "resets bold text" do
Ansi2html::convert("\e[1mHello\e[21m world").should == '<span class="term-bold">Hello</span> world'
Ansi2html::convert("\e[1mHello\e[22m world").should == '<span class="term-bold">Hello</span> world'
expect(subject.convert("\e[1mHello\e[21m world")).to eq('<span class="term-bold">Hello</span> world')
expect(subject.convert("\e[1mHello\e[22m world")).to eq('<span class="term-bold">Hello</span> world')
end
it "prints italic text" do
Ansi2html::convert("\e[3mHello").should == '<span class="term-italic">Hello</span>'
expect(subject.convert("\e[3mHello")).to eq('<span class="term-italic">Hello</span>')
end
it "resets italic text" do
Ansi2html::convert("\e[3mHello\e[23m world").should == '<span class="term-italic">Hello</span> world'
expect(subject.convert("\e[3mHello\e[23m world")).to eq('<span class="term-italic">Hello</span> world')
end
it "prints underlined text" do
Ansi2html::convert("\e[4mHello").should == '<span class="term-underline">Hello</span>'
expect(subject.convert("\e[4mHello")).to eq('<span class="term-underline">Hello</span>')
end
it "resets underlined text" do
Ansi2html::convert("\e[4mHello\e[24m world").should == '<span class="term-underline">Hello</span> world'
expect(subject.convert("\e[4mHello\e[24m world")).to eq('<span class="term-underline">Hello</span> world')
end
it "prints concealed text" do
Ansi2html::convert("\e[8mHello").should == '<span class="term-conceal">Hello</span>'
expect(subject.convert("\e[8mHello")).to eq('<span class="term-conceal">Hello</span>')
end
it "resets concealed text" do
Ansi2html::convert("\e[8mHello\e[28m world").should == '<span class="term-conceal">Hello</span> world'
expect(subject.convert("\e[8mHello\e[28m world")).to eq('<span class="term-conceal">Hello</span> world')
end
it "prints crossed-out text" do
Ansi2html::convert("\e[9mHello").should == '<span class="term-cross">Hello</span>'
expect(subject.convert("\e[9mHello")).to eq('<span class="term-cross">Hello</span>')
end
it "resets crossed-out text" do
Ansi2html::convert("\e[9mHello\e[29m world").should == '<span class="term-cross">Hello</span> world'
expect(subject.convert("\e[9mHello\e[29m world")).to eq('<span class="term-cross">Hello</span> world')
end
it "can print 256 xterm fg colors" do
Ansi2html::convert("\e[38;5;16mHello").should == '<span class="xterm-fg-16">Hello</span>'
expect(subject.convert("\e[38;5;16mHello")).to eq('<span class="xterm-fg-16">Hello</span>')
end
it "can print 256 xterm fg colors on normal magenta background" do
Ansi2html::convert("\e[38;5;16;45mHello").should == '<span class="xterm-fg-16 term-bg-magenta">Hello</span>'
expect(subject.convert("\e[38;5;16;45mHello")).to eq('<span class="xterm-fg-16 term-bg-magenta">Hello</span>')
end
it "can print 256 xterm bg colors" do
Ansi2html::convert("\e[48;5;240mHello").should == '<span class="xterm-bg-240">Hello</span>'
expect(subject.convert("\e[48;5;240mHello")).to eq('<span class="xterm-bg-240">Hello</span>')
end
it "can print 256 xterm bg colors on normal magenta foreground" do
Ansi2html::convert("\e[48;5;16;35mHello").should == '<span class="term-fg-magenta xterm-bg-16">Hello</span>'
expect(subject.convert("\e[48;5;16;35mHello")).to eq('<span class="term-fg-magenta xterm-bg-16">Hello</span>')
end
it "prints bold colored text vividly" do
Ansi2html::convert("\e[1;31mHello\e[0m").should == '<span class="term-fg-l-red term-bold">Hello</span>'
expect(subject.convert("\e[1;31mHello\e[0m")).to eq('<span class="term-fg-l-red term-bold">Hello</span>')
end
it "prints bold light colored text correctly" do
Ansi2html::convert("\e[1;91mHello\e[0m").should == '<span class="term-fg-l-red term-bold">Hello</span>'
expect(subject.convert("\e[1;91mHello\e[0m")).to eq('<span class="term-fg-l-red term-bold">Hello</span>')
end
end
require 'spec_helper'
describe Network do
let(:network) { Network.new }
describe :enable_ci do
subject { network.enable_ci '', '', '' }
context 'on success' do
before do
response = double
allow(response).to receive(:code) { 200 }
allow(network.class).to receive(:put) { response }
end
it { is_expected.to be_truthy }
end
context 'on failure' do
before do
response = double
allow(response).to receive(:code) { 404 }
allow(network.class).to receive(:put) { response }
end
it { is_expected.to be_nil }
end
end
describe :disable_ci do
let(:response) { double }
subject { network.disable_ci '', '' }
context 'on success' do
let(:parsed_response) { 'parsed' }
before do
allow(response).to receive(:code) { 200 }
allow(response).to receive(:parsed_response) { parsed_response }
allow(network.class).to receive(:delete) { response }
end
it { is_expected.to equal(parsed_response) }
end
context 'on failure' do
before do
allow(response).to receive(:code) { 404 }
allow(network.class).to receive(:delete) { response }
end
it { is_expected.to be_nil }
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