Compare commits

..

1 Commits

Author SHA1 Message Date
Renée Hendricksen
7c25396776 this fixes the count problem, but I'm not 100% on the logic of the active column 2016-07-07 21:11:40 -04:00
310 changed files with 2538 additions and 917 deletions

View File

@ -1,2 +1,3 @@
https://github.com/heroku/heroku-buildpack-ruby.git
https://github.com/ryandotsmith/nginx-buildpack.git
https://github.com/drogus/last-commit-sha-buildpack.git
https://dl.signalsciences.net/heroku/sigsci-buildpack-nginx.tgz

3
.gitignore vendored
View File

@ -4,7 +4,10 @@ config/nginx.conf
config/skylight.yml
tmp/
log/
logs/
!vendor/travis-core/lib/travis/logs/
!vendor/travis-core/lib/travis/model/log/
.yardoc
.coverage

View File

@ -3,6 +3,7 @@ gemspec
gem 's3', github: 'travis-ci/s3'
gem 'travis-core', path: 'vendor/travis-core'
gem 'travis-support', github: 'travis-ci/travis-support'
gem 'travis-amqp', github: 'travis-ci/travis-amqp'
gem 'travis-config', '~> 0.1.0'

View File

@ -96,11 +96,33 @@ PATH
simple_states (~> 1.0.0)
sinatra (~> 1.3)
sinatra-contrib (~> 1.3)
tool
travis-support
useragent
virtus (~> 1.0.0)
PATH
remote: vendor/travis-core
specs:
travis-core (0.0.1)
activerecord (~> 3.2.19)
coder (~> 0.4.0)
data_migrations (~> 0.0.1)
gh
google-api-client (~> 0.9.4)
hashr
metriks (~> 0.9.7)
multi_json
pusher (~> 0.14.0)
railties (~> 3.2.19)
rake
redis (~> 3.0)
rollout (~> 1.1.0)
s3 (~> 0.3)
simple_states (~> 1.0.0)
thor
travis-config (~> 0.1.0)
virtus (~> 1.0.0)
GEM
remote: https://rubygems.org/
specs:
@ -149,6 +171,9 @@ GEM
customerio (1.0.0)
multi_json (~> 1.0)
dalli (2.7.6)
data_migrations (0.0.1)
activerecord
rake
database_cleaner (0.8.0)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
@ -386,6 +411,7 @@ DEPENDENCIES
travis-amqp!
travis-api!
travis-config (~> 0.1.0)
travis-core!
travis-migrations!
travis-settings!
travis-sidekiqs!

View File

@ -77,4 +77,5 @@ If you have problems with Nginx because the websocket is already in use, try res
### API documentation
v3 documentation can be found at https://developer.travis-ci.org which is a repository that can be found at https://github.com/travis-pro/developer
We use source code comments to add documentation. If the server is running, you
can browse an HTML documentation at [`/docs`](http://localhost:5000/docs).

View File

@ -18,7 +18,7 @@ end
# t.pattern = 'spec_core/**{,/*/**}/*_spec.rb'
# end
#
# task :default => [:spec]
# task :default => [:spec, :spec_core]
# rescue LoadError => e
# puts e.inspect
# end
@ -27,8 +27,18 @@ end
namespace :spec do
desc 'Run all specs'
task :all do
sh 'bundle exec rspec -r spec_helper spec spec_core'
end
desc 'Run api specs'
task :api do
sh 'bundle exec rspec -r spec_helper spec'
end
desc 'Run core specs'
task :core do
sh 'bundle exec rspec -r spec_helper spec_core'
end
end
task :default => :'spec:all'

View File

@ -13,6 +13,10 @@ http {
gzip_comp_level 2;
gzip_min_length 512;
<% unless ENV['SIGSCI_ENABLED'].nil? || ENV['SIGSCI_ENABLED'].empty? %>
include "../sigsci-module-nginx/sigsci.conf";
<% end %>
server_tokens off;
log_format l2met 'measure#nginx.service=$request_time request_id=$http_x_request_id';

Binary file not shown.

View File

@ -1,6 +1,7 @@
require 'pusher'
require 'travis/support'
require 'travis/support/database'
require 'travis/version'
require 'travis/redis_pool'
require 'travis/errors'
@ -18,6 +19,7 @@ module Travis
require 'travis/model'
require 'travis/task'
require 'travis/event'
require 'travis/addons'
require 'travis/api/serialize'
require 'travis/config/defaults'
require 'travis/features'
@ -41,6 +43,7 @@ module Travis
Travis.logger.info('Setting up Travis::Core')
Github.setup
Addons.register
Services.register
Github::Services.register
end

View File

@ -26,7 +26,6 @@ require 'metriks/reporter/logger'
require 'metriks/librato_metrics_reporter'
require 'travis/support/log_subscriber/active_record_metrics'
require 'fileutils'
require 'securerandom'
module Travis::Api
end
@ -82,7 +81,11 @@ module Travis::Api
end
def self.deploy_sha
@deploy_sha ||= ENV['HEROKU_SLUG_COMMIT'] || SecureRandom.hex(5)
@deploy_sha ||= File.exist?(deploy_sha_path) ? File.read(deploy_sha_path)[0..7] : 'deploy-sha'
end
def self.deploy_sha_path
File.expand_path('../../../../.deploy-sha', __FILE__)
end
attr_accessor :app

View File

@ -179,8 +179,7 @@ class Travis::Api::App
:created_at => user.created_at.to_i,
:github_id => user.github_id,
:education => user.education,
:first_logged_in_at => user.first_logged_in_at.to_i,
:travis_domain => Travis.config.client_domain
:first_logged_in_at => user.first_logged_in_at.to_i
}
customerio.identify(payload)

View File

@ -23,6 +23,11 @@ class Travis::Api::App
Metriks.meter("api.request.cancel_build").mark
service = Travis::Enqueue::Services::CancelModel.new(current_user, { build_id: params[:id] })
repository_owner = service.target.repository.owner
if !Travis::Features.enabled_for_all?(:enqueue_to_hub) && !Travis::Features.owner_active?(:enqueue_to_hub, repository_owner)
service = self.service(:cancel_build, params.merge(source: 'api'))
end
if !service.authorized?
json = { error: {
@ -43,8 +48,11 @@ class Travis::Api::App
respond_with json
else
payload = { id: params[:id], user_id: current_user.id, source: 'api' }
service.push("build:cancel", payload)
if service.respond_to?(:push)
service.push("build:cancel", payload)
else
Travis::Sidekiq::BuildCancellation.perform_async(payload)
end
Metriks.meter("api.request.cancel_build.success").mark
status 204
@ -54,15 +62,24 @@ class Travis::Api::App
post '/:id/restart' do
Metriks.meter("api.request.restart_build").mark
service = Travis::Enqueue::Services::RestartModel.new(current_user, build_id: params[:id])
repository_owner = service.target.repository.owner
if !Travis::Features.enabled_for_all?(:enqueue_to_hub) && !Travis::Features.owner_active?(:enqueue_to_hub, repository_owner)
service = self.service(:reset_model, build_id: params[:id])
end
result = if !service.accept?
status 400
false
else
elsif service.respond_to?(:push)
payload = { id: params[:id], user_id: current_user.id }
service.push("build:restart", payload)
status 202
true
else
Travis::Sidekiq::BuildRestart.perform_async(id: params[:id], user_id: current_user.id)
status 202
true
end
respond_with(result: result, flash: service.messages)

View File

@ -30,6 +30,10 @@ class Travis::Api::App
Metriks.meter("api.request.cancel_job").mark
service = Travis::Enqueue::Services::CancelModel.new(current_user, { job_id: params[:id] })
repository_owner = service.target.repository.owner
if !Travis::Features.enabled_for_all?(:enqueue_to_hub) && !Travis::Features.owner_active?(:enqueue_to_hub, repository_owner)
service = self.service(:cancel_job, params.merge(source: 'api'))
end
if !service.authorized?
json = { error: {
@ -50,7 +54,11 @@ class Travis::Api::App
respond_with json
else
payload = { id: params[:id], user_id: current_user.id, source: 'api' }
service.push("job:cancel", payload)
if service.respond_to?(:push)
service.push("job:cancel", payload)
else
Travis::Sidekiq::JobCancellation.perform_async(payload)
end
Metriks.meter("api.request.cancel_job.success").mark
status 204
@ -61,15 +69,23 @@ class Travis::Api::App
Metriks.meter("api.request.restart_job").mark
service = Travis::Enqueue::Services::RestartModel.new(current_user, { job_id: params[:id] })
repository_owner = service.target.repository.owner
if !Travis::Features.enabled_for_all?(:enqueue_to_hub) && !Travis::Features.owner_active?(:enqueue_to_hub, repository_owner)
service = self.service(:reset_model, job_id: params[:id])
end
result = if !service.accept?
status 400
false
else
elsif service.respond_to?(:push)
payload = {id: params[:id], user_id: current_user.id}
service.push("job:restart", payload)
status 202
true
else
Travis::Sidekiq::JobRestart.perform_async(id: params[:id], user_id: current_user.id)
status 202
result = true
end
respond_with(result: result, flash: service.messages)

View File

@ -1,6 +1,5 @@
require 'travis/api/app'
require 'travis/api/app/services/schedule_request'
require 'travis/api/enqueue/services/restart_model'
class Travis::Api::App
class Endpoint
@ -29,14 +28,18 @@ class Travis::Api::App
#
# I think we need to properly deprecate this by publishing a blog post.
Metriks.meter("api.request.restart").mark
service = Travis::Enqueue::Services::RestartModel.new(current_user, params)
params[:user_id] = service.target.repository.owner.id
type = params[:build_id] ? 'build' : 'job'
params[:id] = params[:build_id] || params[:job_id]
service = Travis::Enqueue::Services::RestartModel.new(current_user, { build_id: params[:build_id] })
repository_owner = service.target.repository.owner
service.push("#{type}:restart", params)
respond_with(result: true, flash: service.messages)
if !Travis::Features.enabled_for_all?(:enqueue_to_hub) && !Travis::Features.owner_active?(:enqueue_to_hub, repository_owner)
respond_with service(:reset_model, params)
elsif service.respond_to?(:push)
payload = {id: params[:build_id], user_id: current_user.id}
service.push("job:restart", payload)
status 202
true
end
end
end
end

View File

@ -4,15 +4,15 @@ module Travis::Api::App::Responders
class Atom < Base
ATOM_FEED_ERB = ERB.new <<-EOF
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><%= resource.first.repository.slug %> Builds</title>
<link href="<%= endpoint.url %>" type="application/atom+xml" rel = "self" />
<id>repo:<%= resource.first.repository.id %></id>
<rights>Copyright (c) <%= DateTime.now.strftime("%Y") %> Travis CI GmbH</rights>
<updated><%= DateTime.now.rfc3339 %></updated>
<% resource.each do |build| %>
<entry>
<title><%= build.repository.slug %> Build #<%= build.number %></title>
@ -21,7 +21,7 @@ module Travis::Api::App::Responders
<updated><%= ::DateTime.parse(build.updated_at.to_s).rfc3339 %></updated>
<summary type="html">
&lt;p&gt;
<%= build.commit.message.encode(:xml => :text) if build.commit.message %> (<%= build.commit.committer_name %>)
<%= build.commit.message.encode(:xml => :text) %> (<%= build.commit.committer_name %>)
&lt;br/&gt;&lt;br/&gt;
State: <%= build.state %>
&lt;br/&gt;
@ -36,7 +36,7 @@ module Travis::Api::App::Responders
</author>
</entry>
<% end %>
</feed>
EOF

View File

@ -31,7 +31,6 @@ module Travis
AlreadySyncing = ClientError .create('sync already in progress', status: 409)
BuildAlreadyRunning = ClientError .create('build already running, cannot restart', status: 409)
BuildNotCancelable = ClientError .create('build is not running, cannot cancel', status: 409)
DuplicateResource = ClientError .create('resource already exists', status: 409)
EntityMissing = NotFound .create(type: 'not_found')
InsufficientAccess = ClientError .create(status: 403)
JobAlreadyRunning = ClientError .create('job already running, cannot restart', status: 409)

View File

@ -30,10 +30,6 @@ module Travis::API::V3
false
end
def full_access_or_logged_in?
full_access? || logged_in?
end
def visible_repositories(list)
# naïve implementation, replaced with smart implementation in specific subclasses
return list if full_access?
@ -96,15 +92,14 @@ module Travis::API::V3
private_repository_visible?(repository)
end
def settings_visible?(settings)
repository_visible?(settings.repository)
end
def private_repository_visible?(repository)
false
end
def repository_attr_visible?(record)
repository_visible?(record.repository)
end
[:settings_visible?, :env_vars_visible?, :env_var_visible?].each { |m| alias_method m, :repository_attr_visible? }
def public_api?
!Travis.config.private_api
end

View File

@ -0,0 +1,109 @@
require 'securerandom'
require 'base64'
module Travis::API::V3
module Extensions
class EncryptedColumn
attr_reader :disable, :options
alias disabled? disable
def initialize(options = {})
@options = options || {}
@disable = self.options[:disable]
@key = self.options[:key]
end
def enabled?
!disabled?
end
def load(data)
return nil unless data
data = data.to_s
decrypt?(data) ? decrypt(data) : data
end
def dump(data)
encrypt?(data) ? encrypt(data.to_s) : data
end
def key
@key || config.key
end
def iv
SecureRandom.hex(8)
end
def prefix
'--ENCR--'
end
def decrypt?(data)
data.present? && (!use_prefix? || prefix_used?(data))
end
def encrypt?(data)
data.present? && enabled?
end
def prefix_used?(data)
data[0..7] == prefix
end
def decrypt(data)
data = data[8..-1] if prefix_used?(data)
data = decode data
iv = data[-16..-1]
data = data[0..-17]
aes = create_aes :decrypt, key.to_s, iv
result = aes.update(data) + aes.final
end
def encrypt(data)
iv = self.iv
aes = create_aes :encrypt, key.to_s, iv
encrypted = aes.update(data) + aes.final
encrypted = "#{encrypted}#{iv}"
encrypted = encode encrypted
encrypted = "#{prefix}#{encrypted}" if use_prefix?
encrypted
end
def use_prefix?
options.has_key?(:use_prefix) ? options[:use_prefix] : Travis::Features.feature_inactive?(:db_encryption_prefix)
end
def create_aes(mode = :encrypt, key, iv)
aes = OpenSSL::Cipher::AES.new(256, :CBC)
aes.send(mode)
aes.key = key
aes.iv = iv
aes
end
def config
Travis.config.encryption
end
def decode(str)
Base64.strict_decode64 str
end
def encode(str)
Base64.strict_encode64 str
end
end
end
end

View File

@ -49,15 +49,5 @@ module Travis::API::V3
gh.post(hooks_url, payload)
end
end
def upload_key(repository)
keys_path = "repos/#{repository.slug}/keys"
key = gh[keys_path].
detect { |e| e['key'] == repository.key.encoded_public_key }
unless key
gh.post keys_path, title: Travis.config.host.to_s, key: repository.key.encoded_public_key
end
end
end
end

View File

@ -1,5 +0,0 @@
module Travis::API::V3
class Models::AdminSettings < Travis::Settings::Model
attribute :api_builds_rate_limit, Integer
end
end

View File

@ -13,7 +13,7 @@ module Travis::API::V3
elsif last_cron_build_date >= planned_time(LastBuild)
planned_time(ThisBuild)
else
Time.now - 5.minutes
Time.now
end
end

View File

@ -1,18 +0,0 @@
module Travis::API::V3
class Models::EnvVar < Travis::Settings::Model
attribute :id, Integer
attribute :name, String
attribute :value, Travis::Settings::EncryptedValue
attribute :public, Boolean
attribute :repository_id, Integer
def repository
@repository ||= Models::Repository.find(repository_id)
end
validates_each :id, :name do |record, attr, value|
others = record.repository.env_vars.select { |ev| ev.id != record.id }
record.errors.add(:base, :duplicate_resource) if others.find { |ev| ev.send(attr) == record.send(attr) }
end
end
end

View File

@ -1,11 +0,0 @@
module Travis::API::V3
class Models::EnvVars < Travis::Settings::Collection
model Models::EnvVar
def repository
@repository ||= Models::Repository.find(additional_attributes[:repository_id])
end
undef :to_hash
end
end

View File

@ -12,7 +12,6 @@ module Travis::API::V3
belongs_to :last_build, class_name: 'Travis::API::V3::Models::Build'.freeze
belongs_to :current_build, class_name: 'Travis::API::V3::Models::Build'.freeze
has_one :key, class_name: 'Travis::API::V3::Models::SSLKey'.freeze
has_one :default_branch,
foreign_key: [:repository_id, :name],
primary_key: [:id, :default_branch],
@ -66,21 +65,7 @@ module Travis::API::V3
end
def settings
@settings ||= JSON.load(super || '{}'.freeze)
end
def user_settings
@user_settings ||= Models::UserSettings.new(settings)
end
def admin_settings
@admin_settings ||= Models::AdminSettings.new(settings)
end
def env_vars
@env_vars ||= Models::EnvVars.new.tap do |vars|
vars.load(settings.fetch('env_vars', []), repository_id: self.id)
end
@settings ||= JSON.load(super)
end
end
end

View File

@ -1,5 +1,12 @@
module Travis::API::V3
class Models::Settings
DEFAULTS = {
'builds_only_with_travis_yml' => false,
'build_pushes' => true,
'build_pull_requests' => true,
'maximum_number_of_builds' => 0
}.freeze
attr_reader :repository
def initialize(repository)
@ -7,11 +14,13 @@ module Travis::API::V3
end
def to_h
repository.user_settings.to_hash
DEFAULTS.merge(repository.settings || {})
end
def update(settings = {})
repository.user_settings.update(settings)
settings = to_h.merge(settings)
repository.settings.clear
settings.each { |k, v| repository.settings[k] = v }
repository.save!
end
end

View File

@ -1,29 +1,5 @@
module Travis::API::V3
class Models::SSLKey < Model
belongs_to :repository
serialize :private_key, Travis::Settings::EncryptedColumn.new
def encoded_public_key
key = build_key.public_key
['ssh-rsa ', "\0\0\0\assh-rsa#{sized_bytes(key.e)}#{sized_bytes(key.n)}"].pack('a*m').gsub("\n", '')
end
private
def build_key
@build_key ||= OpenSSL::PKey::RSA.new(private_key)
end
def sized_bytes(value)
bytes = to_byte_array(value.to_i)
[bytes.size, *bytes].pack('NC*')
end
def to_byte_array(num, *significant)
return significant if num.between?(-1, 0) and significant[0][7] == num[7]
to_byte_array(*num.divmod(256)) + significant
end
end
end

View File

@ -2,7 +2,7 @@ module Travis::API::V3
class Models::Token < Model
belongs_to :user
validate :token, presence: true
serialize :token, Travis::Settings::EncryptedColumn.new(disable: true)
serialize :token, Extensions::EncryptedColumn.new(disable: true)
before_validation :generate_token, on: :create
protected

View File

@ -9,7 +9,7 @@ module Travis::API::V3
has_many :stars
has_one :subscription, as: :owner
serialize :github_oauth_token, Travis::Settings::EncryptedColumn.new(disable: true)
serialize :github_oauth_token, Extensions::EncryptedColumn.new(disable: true)
def token
tokens.first_or_create.token

View File

@ -1,8 +0,0 @@
module Travis::API::V3
class Models::UserSettings < Travis::Settings::Model
attribute :builds_only_with_travis_yml, Boolean, default: false
attribute :build_pushes, Boolean, default: true
attribute :build_pull_requests, Boolean, default: true
attribute :maximum_number_of_builds, Integer, default: 0
end
end

View File

@ -12,19 +12,26 @@ module Travis::API::V3
def cancel(user)
raise BuildNotCancelable if %w(passed failed canceled errored).include? find.state
payload = { id: id, user_id: user.id, source: 'api' }
service = Travis::Enqueue::Services::CancelModel.new(user, { build_id: id })
service.push("build:cancel", payload)
if Travis::Features.enabled_for_all?(:enqueue_to_hub) || Travis::Features.owner_active?(:enqueue_to_hub, find.repository.owner)
service = Travis::Enqueue::Services::CancelModel.new(user, { build_id: id })
service.push("build:cancel", payload)
else
perform_async(:build_cancellation, payload)
end
payload
end
def restart(user)
raise BuildAlreadyRunning if %w(received queued started).include? find.state
service = Travis::Enqueue::Services::RestartModel.new(user, { build_id: id })
payload = { id: id, user_id: user.id }
service.push("build:restart", payload)
if Travis::Features.enabled_for_all?(:enqueue_to_hub) || Travis::Features.owner_active?(:enqueue_to_hub, find.repository.owner)
service = Travis::Enqueue::Services::RestartModel.new(user, { build_id: id })
payload = { id: id, user_id: user.id }
service.push("build:restart", payload)
else
payload = { id: id, user_id: user.id, source: 'api' }
perform_async(:build_restart, payload)
end
payload
end
end

View File

@ -7,14 +7,7 @@ module Travis::API::V3
def start_all()
Models::Cron.all.select do |cron|
begin
@cron = cron
start(cron) if cron.next_enqueuing <= Time.now
rescue => e
Raven.capture_exception(e, tags: { 'cron_id' => @cron.try(:id) })
sleep(10) # This ensures the dyno does not spin down before the http request to send the error to sentry completes
next
end
start(cron) if cron.next_enqueuing <= Time.now
end
end
@ -26,8 +19,7 @@ module Travis::API::V3
return false
end
user_id = branch.repository.users.detect { |u| u.github_oauth_token }.try(:id)
user_id ||= branch.repository.owner.id
user_id = branch.repository.users.detect { |u| u.github_oauth_token }.id
payload = {
repository: { id: branch.repository.github_id, owner_name: branch.repository.owner_name, name: branch.repository.name },
@ -38,6 +30,8 @@ module Travis::API::V3
class_name, queue = Query.sidekiq_queue(:build_request)
::Sidekiq::Client.push('queue'.freeze => queue, 'class'.freeze => class_name, 'args'.freeze => [{type: 'cron'.freeze, payload: JSON.dump(payload), credentials: {}}])
true
rescue => e
puts e.message, e.backtrace
end
end
end

View File

@ -1,21 +0,0 @@
module Travis::API::V3
class Queries::EnvVar < Query
params :id, :name, :value, :public, prefix: :env_var
def find(repository)
repository.env_vars.find(id)
end
def update(repository)
if env_var = find(repository)
env_var.update(env_var_params)
repository.save!
env_var
end
end
def delete(repository)
repository.env_vars.destroy(id)
end
end
end

View File

@ -1,25 +0,0 @@
module Travis::API::V3
class Queries::EnvVars < Query
params :id, :name, :value, :public, prefix: :env_var
def find(repository)
repository.env_vars
end
def create(repository)
env_var = repository.env_vars.create(env_var_params)
handle_errors(env_var) unless env_var.valid?
repository.save!
env_var
end
private
def handle_errors(env_var)
base = env_var.errors[:base]
raise WrongParams if base.include?(:format)
raise DuplicateResource if base.include?(:duplicate_resource)
raise ServerError
end
end
end

View File

@ -12,19 +12,28 @@ module Travis::API::V3
def cancel(user)
raise JobNotCancelable if %w(passed failed canceled errored).include? find.state
payload = { id: id, user_id: user.id, source: 'api' }
service = Travis::Enqueue::Services::CancelModel.new(user, { job_id: id })
service.push("job:cancel", payload)
#look for repo.owner instead and look if the user belongs to the repo, instead of using user for the feature flag
if Travis::Features.enabled_for_all?(:enqueue_to_hub) || Travis::Features.owner_active?(:enqueue_to_hub, find.repository.owner)
service = Travis::Enqueue::Services::CancelModel.new(user, { job_id: id })
service.push("job:cancel", payload)
else
perform_async(:job_cancellation, payload)
end
payload
end
def restart(user)
raise JobAlreadyRunning if %w(received queued started).include? find.state
service = Travis::Enqueue::Services::RestartModel.new(user, { job_id: id })
payload = { id: id, user_id: user.id }
service.push("job:restart", payload)
if Travis::Features.enabled_for_all?(:enqueue_to_hub) || Travis::Features.owner_active?(:enqueue_to_hub, find.repository.owner)
service = Travis::Enqueue::Services::RestartModel.new(user, { job_id: id })
payload = { id: id, user_id: user.id }
service.push("job:restart", payload)
else
payload = { id: id, user_id: user.id, source: 'api' }
perform_async(:job_restart, payload)
end
payload
end
end

View File

@ -10,7 +10,7 @@ module Travis::API::V3
extend self
def clear(**args)
args.compact
args.select { |key, value| !value.nil? }
end
def href(type, string_args = nil, script_name: nil, **args)
@ -49,7 +49,6 @@ module Travis::API::V3
when Model then render_model(value, **options)
when ActiveRecord::Relation then render_value(value.to_a, **options)
when ActiveRecord::Associations::CollectionProxy then render_value(value.to_a, **options)
when Travis::Settings::EncryptedValue then value.decrypt
else raise ArgumentError, 'cannot render %p (%p)' % [value.class, value]
end
end

View File

@ -1,5 +0,0 @@
module Travis::API::V3
class Renderer::EnvVar < Renderer::ModelRenderer
representation :standard, :id, :name, :value, :public
end
end

View File

@ -1,6 +0,0 @@
module Travis::API::V3
class Renderer::EnvVars < Renderer::CollectionRenderer
type :env_vars
collection_key :env_vars
end
end

View File

@ -110,7 +110,6 @@ module Travis::API::V3
end
fields.each do |field|
next if field == :value && !@model.public?
value = Renderer.render_value(send(field),
access_control: access_control,
script_name: script_name,

View File

@ -18,6 +18,7 @@ module Travis::API::V3
env_params = params(env)
factory, params = routes.factory_for(env['REQUEST_METHOD'.freeze], env['PATH_INFO'.freeze])
raise NotFound unless factory
metrics.name_after(factory)

View File

@ -123,19 +123,6 @@ module Travis::API::V3
get :find
patch :update
end
resource :env_vars do
route '/env_vars'
get :for_repository
post :create
end
resource :env_var do
route '/env_var/{env_var.id}'
get :find
patch :update
delete :delete
end
end
resource :user do

View File

@ -66,11 +66,6 @@ module Travis::API::V3
object
end
def check_login_and_find(*args)
raise LoginRequired unless access_control.full_access_or_logged_in?
find(*args) or raise NotFound
end
def not_found(actually_not_found = false, type = nil)
type, actually_not_found = actually_not_found, false if actually_not_found.is_a? Symbol
error = actually_not_found ? EntityMissing : NotFound

View File

@ -11,8 +11,6 @@ module Travis::API::V3
Builds = Module.new { extend Services }
Cron = Module.new { extend Services }
Crons = Module.new { extend Services }
EnvVar = Module.new { extend Services }
EnvVars = Module.new { extend Services }
Job = Module.new { extend Services }
Jobs = Module.new { extend Services }
Lint = Module.new { extend Services }

View File

@ -2,7 +2,8 @@ module Travis::API::V3
class Services::Build::Cancel < Service
def run
build = check_login_and_find(:build)
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless build = find(:build)
access_control.permissions(build).cancel!
query.cancel(access_control.user)

View File

@ -2,7 +2,8 @@ module Travis::API::V3
class Services::Build::Restart < Service
def run
build = check_login_and_find(:build)
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless build = find(:build)
access_control.permissions(build).restart!
query.restart(access_control.user)

View File

@ -4,7 +4,8 @@ module Travis::API::V3
params :interval, :disable_by_build
def run!
repository = check_login_and_find(:repository)
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless repository = find(:repository)
raise NotFound unless branch = find(:branch, repository)
raise Error.new('Crons can only be set up for branches existing on GitHub!', status: 422) unless branch.exists_on_github
raise Error.new('Invalid value for interval. Interval must be "daily", "weekly" or "monthly"!', status: 422) unless ["daily", "weekly", "monthly"].include?(params["interval"])

View File

@ -3,7 +3,8 @@ module Travis::API::V3
#params :id
def run!
cron = check_login_and_find
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
cron = find
access_control.permissions(cron).delete!
cron.destroy
end

View File

@ -1,11 +0,0 @@
module Travis::API::V3
class Services::EnvVar::Delete < Service
params :id, prefix: :repository
params :id, prefix: :env_var
def run!
repository = check_login_and_find(:repository)
query.delete(repository)
end
end
end

View File

@ -1,11 +0,0 @@
module Travis::API::V3
class Services::EnvVar::Find < Service
params :id, prefix: :repository
params :id, prefix: :env_var
def run!
repository = check_login_and_find(:repository)
query.find(repository)
end
end
end

View File

@ -1,11 +0,0 @@
module Travis::API::V3
class Services::EnvVar::Update < Service
params :id, prefix: :repository
params :id, :name, :value, :public, prefix: :env_var
def run!
repository = check_login_and_find(:repository)
query.update(repository)
end
end
end

View File

@ -1,12 +0,0 @@
module Travis::API::V3
class Services::EnvVars::Create < Service
params :id, prefix: :repository
params :id, :name, :value, :public, prefix: :env_var
def run!
repository = check_login_and_find(:repository)
env_var = query(:env_vars).create(repository)
result(:env_var, env_var, status: 201)
end
end
end

View File

@ -1,8 +0,0 @@
module Travis::API::V3
class Services::EnvVars::ForRepository < Service
def run!
repository = check_login_and_find(:repository)
find(:env_vars, repository)
end
end
end

View File

@ -2,7 +2,8 @@ module Travis::API::V3
class Services::Job::Cancel < Service
def run
job = check_login_and_find(:job)
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless job = find(:job)
access_control.permissions(job).cancel!
query.cancel(access_control.user)

View File

@ -5,7 +5,8 @@ module Travis::API::V3
attr_reader :job
def run
@job = check_login_and_find(:job)
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless @job = find(:job)
raise WrongCredentials unless Travis.config.debug_tools_enabled or Travis::Features.active?(:debug_tools, job.repository)
access_control.permissions(job).debug!

View File

@ -2,7 +2,8 @@ module Travis::API::V3
class Services::Job::Restart < Service
def run
job = check_login_and_find(:job)
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless job = find(:job)
access_control.permissions(job).restart!
query.restart(access_control.user)

View File

@ -1,7 +1,8 @@
module Travis::API::V3
class Services::Repository::Disable < Service
def run!(activate = false)
repository = check_login_and_find(:repository)
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless repository = find(:repository)
check_access(repository)
admin = access_control.admin_for(repository)

View File

@ -1,14 +1,7 @@
module Travis::API::V3
class Services::Repository::Enable < Services::Repository::Disable
def run!
repository = super(true)
if repository.private?
admin = access_control.admin_for(repository)
github(admin).upload_key(repository)
end
repository
super(true)
end
def check_access(repository)

View File

@ -1,7 +1,8 @@
module Travis::API::V3
class Services::Repository::Star < Service
def run!
repository = check_login_and_find(:repository)
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless repository = find(:repository)
check_access(repository)
current_user = access_control.user
query.star(current_user)

View File

@ -1,7 +1,8 @@
module Travis::API::V3
class Services::Repository::Unstar < Service
def run!
repository = check_login_and_find(:repository)
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless repository = find(:repository)
check_access(repository)
current_user = access_control.user
query.unstar(current_user)

View File

@ -8,7 +8,8 @@ module Travis::API::V3
params "request", "user", :config, :message, :branch, :token
def run
repository = check_login_and_find(:repository)
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless repository = find(:repository)
access_control.permissions(repository).create_request!
user = find(:user) if access_control.full_access? and params_for? 'user'.freeze
@ -22,7 +23,11 @@ module Travis::API::V3
end
def limit(repository)
repository.admin_settings.api_builds_rate_limit || Travis.config.requests_create_api_limit || LIMIT
if repository.settings.nil?
Travis.config.requests_create_api_limit || LIMIT
else
repository.settings["api_builds_rate_limit"] || Travis.config.requests_create_api_limit || LIMIT
end
end
def remaining_requests(repository)

View File

@ -1,7 +1,8 @@
module Travis::API::V3
class Services::Settings::Find < Service
def run!
repo = check_login_and_find(:repository)
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless repo = find(:repository)
find(:settings, repo)
end
end

View File

@ -3,7 +3,8 @@ module Travis::API::V3
params :builds_only_with_travis_yml, :build_pushes, :build_pull_requests, :maximum_number_of_builds, prefix: :settings
def run!
repository = check_login_and_find(:repository)
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless repository = find(:repository)
query.update(repository)
end
end

View File

@ -2,7 +2,8 @@ module Travis::API::V3
class Services::User::Sync < Service
def run!
user = check_login_and_find(:user)
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
raise NotFound unless user = find(:user)
access_control.permissions(user).sync!
query.sync(user)

View File

@ -19,8 +19,6 @@ module Travis
end
end
Amqps = Amqp
class << self
def parse(url)
return Generic.new if url.nil? || url.empty?

Binary file not shown.

View File

@ -97,6 +97,20 @@ describe 'Builds', set_app: true do
build.update_attribute(:state, 'created')
end
context 'from the Core' do
before { Travis::Sidekiq::BuildCancellation.stubs(:perform_async) }
it 'cancels the build' do
Travis::Sidekiq::BuildCancellation.expects(:perform_async).with( id: build.id.to_s, user_id: user.id, source: 'api')
post "/builds/#{build.id}/cancel", {}, headers
end
it 'responds with 204' do
response = post "/builds/#{build.id}/cancel", {}, headers
response.status.should == 204
end
end
context 'and enqueues cancel event for the Hub' do
before { Travis::Features.activate_owner(:enqueue_to_hub, repo.owner) }
@ -159,6 +173,23 @@ describe 'Builds', set_app: true do
body.should == {"result"=>true, "flash"=>[{"notice"=>"The build was successfully restarted."}]}
end
end
describe 'Restart from the Core' do
before { Travis::Sidekiq::BuildRestart.stubs(:perform_async) }
it 'restarts the build' do
Travis::Sidekiq::BuildRestart.expects(:perform_async).with(id: build.id.to_s, user_id: user.id)
response = post "/builds/#{build.id}/restart", {}, headers
response.status.should == 202
end
it 'sends the correct response body' do
Travis::Sidekiq::BuildRestart.expects(:perform_async).with(id: build.id.to_s, user_id: user.id)
response = post "/builds/#{build.id}/restart", {}, headers
body = JSON.parse(response.body)
body.should == {"result"=>true, "flash"=>[{"notice"=>"The build was successfully restarted."}]}
end
end
end
end
end

View File

@ -262,6 +262,16 @@ describe 'Jobs', set_app: true do
job.update_attribute(:state, 'created')
end
it 'cancels the job' do
Travis::Sidekiq::JobCancellation.expects(:perform_async).with( id: job.id.to_s, user_id: user.id, source: 'api')
post "/jobs/#{job.id}/cancel", {}, headers
end
it 'responds with 204' do
response = post "/jobs/#{job.id}/cancel", {}, headers
response.status.should == 204
end
context 'and enqueues cancel event for the Hub' do
before { Travis::Features.activate_owner(:enqueue_to_hub, job.repository.owner) }
@ -309,6 +319,22 @@ describe 'Jobs', set_app: true do
context 'when job passed' do
before { job.update_attribute(:state, 'passed') }
context 'Restart from travis-core' do
before { Travis::Sidekiq::JobCancellation.stubs(:perform_async) }
it 'restarts the job' do
Travis::Sidekiq::JobRestart.expects(:perform_async).with(id: job.id.to_s, user_id: user.id)
response = post "/jobs/#{job.id}/restart", {}, headers
response.status.should == 202
end
it 'sends the correct response body' do
Travis::Sidekiq::JobRestart.expects(:perform_async).with(id: job.id.to_s, user_id: user.id)
response = post "/jobs/#{job.id}/restart", {}, headers
body = JSON.parse(response.body)
body.should == {"result"=>true, "flash"=>[{"notice"=>"The job was successfully restarted."}]}
end
end
context 'Enqueues restart event for the Hub' do
before { Travis::Features.activate_owner(:enqueue_to_hub, job.repository.owner) }

View File

@ -28,16 +28,16 @@ describe 'Requests', set_app: true do
end
describe 'POST /requests' do
it 'triggers a build request using Hub' do
it 'triggers a build request using Core code' do
response = post "/requests", { build_id: build.id }, headers
response.status.should be(200)
end
end
it 'triggers a job request' do
payload = { job_id: build.matrix.first.id, user_id: repo.owner.id }
response = post "/requests", payload, headers
response.status.should be(200)
end
it 'triggers a build request using Hub' do
Travis::Features.activate_owner(:enqueue_to_hub, repo.owner)
response = post "/requests", { build_id: build.id }, headers
response.status.should be(202)
end
end
end

View File

@ -1,163 +0,0 @@
require 'spec_helper'
require 'active_support/core_ext/hash/slice'
describe Travis::Config do
let(:config) { Travis::Config.load(:files, :env, :heroku, :docker) }
describe 'endpoints' do
it 'returns an object even without endpoints entry' do
config.endpoints.foo.should be_nil
end
it 'returns endpoints if it is set' do
ENV['travis_config'] = YAML.dump('endpoints' => { 'ssh_key' => true })
config.endpoints.ssh_key.should be_truthy
end
it 'allows to set keys on enpoints when it is nil' do
config.endpoints.foo.should be_nil
config.endpoints.foo = true
config.endpoints.foo.should be_truthy
end
end
describe 'defaults' do
it 'notifications defaults to []' do
config.notifications.should == []
end
it 'notifications.email defaults to {}' do
config.email.should == {}
end
it 'queues defaults to []' do
config.queues.should == []
end
it 'ampq.host defaults to "localhost"' do
config.amqp.host.should == 'localhost'
end
it 'ampq.prefetch defaults to 1' do
config.amqp.prefetch.should == 1
end
it 'queue.limit.by_owner defaults to {}' do
config.queue.limit.by_owner.should == {}
end
it 'queue.limit.default defaults to 5' do
config.queue.limit.default.should == 5
end
it 'queue.interval defaults to 3' do
config.queue.interval.should == 3
end
it 'queue.interval defaults to 3' do
config.queue.interval.should == 3
end
it 'logs.shards defaults to 1' do
config.logs.shards.should == 1
end
it 'database' do
config.database.should == {
:adapter => 'postgresql',
:database => 'travis_test',
:encoding => 'unicode',
:min_messages => 'warning',
:variables => { :statement_timeout => 10000 }
}
end
end
describe 'resource urls' do
describe 'with a TRAVIS_DATABASE_URL set' do
before { ENV['TRAVIS_DATABASE_URL'] = 'postgres://username:password@host:1234/database' }
after { ENV.delete('TRAVIS_DATABASE_URL') }
it { config.database.username.should == 'username' }
it { config.database.password.should == 'password' }
it { config.database.host.should == 'host' }
it { config.database.port.should == 1234 }
it { config.database.database.should == 'database' }
it { config.database.encoding.should == 'unicode' }
end
describe 'with a DATABASE_URL set' do
before { ENV['DATABASE_URL'] = 'postgres://username:password@host:1234/database' }
after { ENV.delete('DATABASE_URL') }
it { config.database.username.should == 'username' }
it { config.database.password.should == 'password' }
it { config.database.host.should == 'host' }
it { config.database.port.should == 1234 }
it { config.database.database.should == 'database' }
it { config.database.encoding.should == 'unicode' }
end
describe 'with a TRAVIS_LOGS_DATABASE_URL set' do
before { ENV['TRAVIS_LOGS_DATABASE_URL'] = 'postgres://username:password@host:1234/database' }
after { ENV.delete('TRAVIS_LOGS_DATABASE_URL') }
it { config.logs_database.username.should == 'username' }
it { config.logs_database.password.should == 'password' }
it { config.logs_database.host.should == 'host' }
it { config.logs_database.port.should == 1234 }
it { config.logs_database.database.should == 'database' }
it { config.logs_database.encoding.should == 'unicode' }
end
describe 'with a LOGS_DATABASE_URL set' do
before { ENV['LOGS_DATABASE_URL'] = 'postgres://username:password@host:1234/database' }
after { ENV.delete('LOGS_DATABASE_URL') }
it { config.logs_database.username.should == 'username' }
it { config.logs_database.password.should == 'password' }
it { config.logs_database.host.should == 'host' }
it { config.logs_database.port.should == 1234 }
it { config.logs_database.database.should == 'database' }
it { config.logs_database.encoding.should == 'unicode' }
end
describe 'with a TRAVIS_RABBITMQ_URL set' do
before { ENV['TRAVIS_RABBITMQ_URL'] = 'amqp://username:password@host:1234/vhost' }
after { ENV.delete('TRAVIS_RABBITMQ_URL') }
it { config.amqp.username.should == 'username' }
it { config.amqp.password.should == 'password' }
it { config.amqp.host.should == 'host' }
it { config.amqp.port.should == 1234 }
it { config.amqp.vhost.should == 'vhost' }
end
describe 'with a RABBITMQ_URL set' do
before { ENV['RABBITMQ_URL'] = 'amqp://username:password@host:1234/vhost' }
after { ENV.delete('RABBITMQ_URL') }
it { config.amqp.username.should == 'username' }
it { config.amqp.password.should == 'password' }
it { config.amqp.host.should == 'host' }
it { config.amqp.port.should == 1234 }
it { config.amqp.vhost.should == 'vhost' }
end
describe 'with a TRAVIS_REDIS_URL set' do
before { ENV['TRAVIS_REDIS_URL'] = 'redis://username:password@host:1234' }
after { ENV.delete('TRAVIS_REDIS_URL') }
it { config.redis.url.should == 'redis://username:password@host:1234' }
end
describe 'with a REDIS_URL set' do
before { ENV['REDIS_URL'] = 'redis://username:password@host:1234' }
after { ENV.delete('REDIS_URL') }
it { config.redis.url.should == 'redis://username:password@host:1234' }
end
end
end

View File

@ -23,35 +23,6 @@ require 'support/payloads'
require 'support/private_key'
require 'support/s3'
require 'support/test_helpers'
require 'support/shared_examples'
module TestHelpers
include Sinatra::TestHelpers
def custom_endpoints
@custom_endpoints ||= []
end
def add_settings_endpoint(name, options = {})
if options[:singleton]
Travis::Api::App::SingletonSettingsEndpoint.subclass(name)
else
Travis::Api::App::SettingsEndpoint.subclass(name)
end
set_app Travis::Api::App.new
end
def add_endpoint(prefix, &block)
endpoint = Sinatra.new(Travis::Api::App::Endpoint, &block)
endpoint.set(prefix: prefix)
set_app Travis::Api::App.new
custom_endpoints << endpoint
end
def parsed_body
MultiJson.decode(body)
end
end
RSpec.configure do |c|
c.mock_framework = :mocha
@ -91,12 +62,3 @@ RSpec.configure do |c|
end
end
end
require 'timecop'
Timecop.freeze(Time.now.utc)
describe Time do
let(:time) { Time.now.utc }
example { expect(Time.now.utc).to eq(time) }
example { expect(Time.now.utc + 5.minutes ).to eq(time + 5.minutes) }
end

View File

@ -1,34 +0,0 @@
RSpec.shared_examples 'not authenticated' do
example { expect(last_response.status).to eq(403) }
example do
expect(JSON.load(body)).to eq(
'@type' => 'error',
'error_type' => 'login_required',
'error_message' => 'login required'
)
end
end
RSpec.shared_examples 'missing repo' do
example { expect(last_response.status).to eq(404) }
example do
expect(JSON.load(body)).to eq(
'@type' => 'error',
'error_message' => 'repository not found (or insufficient access)',
'error_type' => 'not_found',
'resource_type' => 'repository'
)
end
end
RSpec.shared_examples 'missing env_var' do
example { expect(last_response.status).to eq 404 }
example do
expect(JSON.load(body)).to eq(
'@type' => 'error',
'error_message' => 'env_var not found (or insufficient access)',
'error_type' => 'not_found',
'resource_type' => 'env_var'
)
end
end

View File

@ -2,7 +2,6 @@ describe Travis::Api::Serialize::V2::Http::Jobs do
include Travis::Testing::Stubs, Support::Formats
let(:data) { described_class.new([test]).data }
let!(:time) { Time.now.utc }
it 'jobs' do
data['jobs'].first.should == {
@ -14,8 +13,8 @@ describe Travis::Api::Serialize::V2::Http::Jobs do
'log_id' => 1,
'number' => '2.1',
'state' => 'passed',
'started_at' => json_format_time(time - 1.minute),
'finished_at' => json_format_time(time),
'started_at' => json_format_time(Time.now.utc - 1.minute),
'finished_at' => json_format_time(Time.now.utc),
'config' => { 'rvm' => '1.8.7', 'gemfile' => 'test/Gemfile.rails-2.3.x' },
'queue' => 'builds.linux',
'allow_failure' => false,
@ -29,7 +28,7 @@ describe Travis::Api::Serialize::V2::Http::Jobs do
'sha' => '62aae5f70ceee39123ef',
'branch' => 'master',
'message' => 'the commit message',
'committed_at' => json_format_time(time - 1.hour),
'committed_at' => json_format_time(Time.now.utc - 1.hour),
'committer_name' => 'Sven Fuchs',
'committer_email' => 'svenfuchs@artweb-design.de',
'author_name' => 'Sven Fuchs',
@ -51,3 +50,4 @@ describe Travis::Api::Serialize::V2::Http::Jobs, 'using Travis::Services::Jobs::
lambda { data }.should issue_queries(4)
end
end

View File

@ -6,6 +6,8 @@ describe Travis::API::V3::ServiceIndex, set_app: true do
let(:resources) { json.fetch('resources') }
it "handles wrong HTTP method with 405 status" do
response.status.should == 405
end
end

View File

@ -1,3 +1,5 @@
require 'timecop'
describe Travis::API::V3::Models::Cron do
let(:repo) { Travis::API::V3::Models::Repository.where(owner_name: 'svenfuchs', name: 'minimal').first }
let(:branch) { Travis::API::V3::Models::Branch.create(repository: repo, name: 'cron test') }
@ -5,13 +7,11 @@ describe Travis::API::V3::Models::Cron do
describe "next build time is calculated correctly on year changes" do
before do
Timecop.return
Timecop.travel(DateTime.new(2015, 12, 31, 16))
end
after do
Timecop.return
Timecop.freeze(Time.now.utc)
end
it "for daily builds" do
@ -43,13 +43,11 @@ describe Travis::API::V3::Models::Cron do
describe "push build is ignored if disable by build is false" do
before do
Timecop.return
Timecop.travel(DateTime.new(2015, 12, 31, 16))
end
after do
Timecop.return
Timecop.freeze(Time.now.utc)
end
it "for daily builds" do
@ -87,13 +85,11 @@ describe Travis::API::V3::Models::Cron do
describe "disable by build works with build" do
before do
Timecop.return
Timecop.travel(DateTime.new(2015, 12, 31, 16))
end
after do
Timecop.return
Timecop.freeze(Time.now.utc)
end
it "for daily builds" do
@ -125,13 +121,11 @@ describe Travis::API::V3::Models::Cron do
describe "disable by build works without build" do
before do
Timecop.return
Timecop.travel(DateTime.new(2015, 12, 31, 16))
end
after do
Timecop.return
Timecop.freeze(Time.now.utc)
end
it "for daily builds" do
@ -163,12 +157,12 @@ describe Travis::API::V3::Models::Cron do
describe "build starts now if next build time is in the past" do
before do
Timecop.return
# nothing, this time
# time freeze is performed in examples
end
after do
Timecop.return
Timecop.freeze(Time.now.utc)
end
it "for daily builds with disable_by_build true" do
@ -176,7 +170,7 @@ describe Travis::API::V3::Models::Cron do
cron = Travis::API::V3::Models::Cron.create(branch_id: branch.id, interval: 'daily', disable_by_build: true)
build = Travis::API::V3::Models::Build.create(:repository_id => repo.id, :branch_name => branch.name, :event_type => 'cron')
Timecop.freeze(DateTime.new(2016, 1, 1, 19))
expect(cron.next_enqueuing).to be == DateTime.now - 5.minutes
expect(cron.next_enqueuing).to be == DateTime.now
build.destroy
cron.destroy
end
@ -186,7 +180,7 @@ describe Travis::API::V3::Models::Cron do
cron = Travis::API::V3::Models::Cron.create(branch_id: branch.id, interval: 'daily', disable_by_build: false)
build = Travis::API::V3::Models::Build.create(:repository_id => repo.id, :branch_name => branch.name, :event_type => 'cron')
Timecop.freeze(DateTime.new(2016, 1, 1, 19))
expect(cron.next_enqueuing).to be == DateTime.now - 5.minutes
expect(cron.next_enqueuing).to be == DateTime.now
build.destroy
cron.destroy
end
@ -196,7 +190,7 @@ describe Travis::API::V3::Models::Cron do
cron = Travis::API::V3::Models::Cron.create(branch_id: branch.id, interval: 'weekly', disable_by_build: true)
build = Travis::API::V3::Models::Build.create(:repository_id => repo.id, :branch_name => branch.name, :event_type => 'cron')
Timecop.freeze(DateTime.new(2016, 1, 7, 19))
expect(cron.next_enqueuing).to be == DateTime.now - 5.minutes
expect(cron.next_enqueuing).to be == DateTime.now
build.destroy
cron.destroy
end
@ -206,7 +200,7 @@ describe Travis::API::V3::Models::Cron do
cron = Travis::API::V3::Models::Cron.create(branch_id: branch.id, interval: 'weekly', disable_by_build: false)
build = Travis::API::V3::Models::Build.create(:repository_id => repo.id, :branch_name => branch.name, :event_type => 'cron')
Timecop.freeze(DateTime.new(2016, 1, 7, 19))
expect(cron.next_enqueuing).to be == DateTime.now - 5.minutes
expect(cron.next_enqueuing).to be == DateTime.now
build.destroy
cron.destroy
end
@ -216,7 +210,7 @@ describe Travis::API::V3::Models::Cron do
cron = Travis::API::V3::Models::Cron.create(branch_id: branch.id, interval: 'monthly', disable_by_build: true)
build = Travis::API::V3::Models::Build.create(:repository_id => repo.id, :branch_name => branch.name, :event_type => 'cron')
Timecop.freeze(DateTime.new(2016, 1, 31, 19))
expect(cron.next_enqueuing).to be == DateTime.now - 5.minutes
expect(cron.next_enqueuing).to be == DateTime.now
build.destroy
cron.destroy
end
@ -226,7 +220,7 @@ describe Travis::API::V3::Models::Cron do
cron = Travis::API::V3::Models::Cron.create(branch_id: branch.id, interval: 'monthly', disable_by_build: false)
build = Travis::API::V3::Models::Build.create(:repository_id => repo.id, :branch_name => branch.name, :event_type => 'cron')
Timecop.freeze(DateTime.new(2016, 1, 31, 19))
expect(cron.next_enqueuing).to be == DateTime.now - 5.minutes
expect(cron.next_enqueuing).to be == DateTime.now
build.destroy
cron.destroy
end

View File

@ -1,10 +1,7 @@
require 'sentry-raven'
describe Travis::API::V3::Queries::Crons do
let(:user) { Travis::API::V3::Models::User.find_by_login('svenfuchs') }
let(:repo) { Travis::API::V3::Models::Repository.where(owner_name: 'svenfuchs', name: 'minimal').first }
let(:existing_branch) { Travis::API::V3::Models::Branch.create(repository: repo, name: 'cron-test-existing', exists_on_github: true) }
let(:existing_branch2) { Travis::API::V3::Models::Branch.create(repository: repo, name: 'cron-test-existing2', exists_on_github: true) }
let(:non_existing_branch) { Travis::API::V3::Models::Branch.create(repository: repo, name: 'cron-test-non-existing', exists_on_github: false) }
let(:query) { Travis::API::V3::Queries::Crons.new({}, 'Overview')
}
@ -15,6 +12,7 @@ describe Travis::API::V3::Queries::Crons do
it "starts crons on existing branches" do
cron = Travis::API::V3::Models::Cron.create(branch_id: existing_branch.id, interval: 'daily', disable_by_build: false)
expect(query.start_all).to include(cron)
end
it "delete crons on branches not existing on GitHub" do
@ -22,27 +20,6 @@ describe Travis::API::V3::Queries::Crons do
expect(query.start_all).to_not include(cron)
expect(Travis::API::V3::Models::Cron.where(id: cron.id).length).to equal(0)
end
it 'enques error into a thread' do
cron = Travis::API::V3::Models::Cron.create(branch_id: existing_branch.id, interval: 'daily', disable_by_build: false)
error = StandardError.new('Konstantin broke all the thingz!')
Travis::API::V3::Queries::Crons.any_instance.expects(:sleep).with(10)
Travis::API::V3::Models::Cron.any_instance.stubs(:branch).raises(error)
Raven.expects(:capture_exception).with(error, tags: {'cron_id' => cron.id })
query.start_all
end
it 'continues running crons if one breaks' do
cron = Travis::API::V3::Models::Cron.create(branch_id: existing_branch.id, interval: 'daily', disable_by_build: false)
cron2 = Travis::API::V3::Models::Cron.create(branch_id: existing_branch2.id, interval: 'daily', disable_by_build: false)
error = StandardError.new('Konstantin broke all the thingz!')
Travis::API::V3::Models::Cron.any_instance.stubs(:branch).raises(error)
Travis::API::V3::Queries::Crons.any_instance.expects(:sleep).twice.with(10)
Raven.expects(:capture_exception).with(error, tags: {'cron_id' => cron.id })
Raven.expects(:capture_exception).with(error, tags: {'cron_id' => cron2.id })
query.start_all
end
end
end

View File

@ -1,7 +1,8 @@
describe Travis::API::V3::Services::Build::Cancel, set_app: true do
let(:repo) { Travis::API::V3::Models::Repository.where(owner_name: 'svenfuchs', name: 'minimal').first }
let(:build) { repo.builds.first }
let(:payload) { { 'id'=> "#{build.id}", 'user_id' => 1, 'source' => 'api' } }
let(:sidekiq_payload) { JSON.load(Sidekiq::Client.last['args'].last.to_json) }
let(:sidekiq_params) { Sidekiq::Client.last['args'].last.deep_symbolize_keys }
before do
Travis::Features.stubs(:owner_active?).returns(true)
@ -130,6 +131,101 @@ describe Travis::API::V3::Services::Build::Cancel, set_app: true do
end
end
describe "existing repository, push access, cancelable" do
let(:params) {{}}
let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) }
let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }}
before { Travis::API::V3::Models::Permission.create(repository: repo, user: repo.owner, push: true) }
describe "started state" do
before { build.update_attribute(:state, "started") }
before { post("/v3/build/#{build.id}/cancel", params, headers) }
example { expect(last_response.status).to be == 202 }
example { expect(JSON.load(body).to_s).to include(
"@type",
"build",
"@href",
"@representation",
"minimal",
"cancel",
"id",
"state_change")
}
example { expect(sidekiq_payload).to be == {
"id" => "#{build.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
}
example { expect(Sidekiq::Client.last['queue']).to be == 'build_cancellations' }
example { expect(Sidekiq::Client.last['class']).to be == 'Travis::Sidekiq::BuildCancellation' }
end
describe "queued state" do
before { build.update_attribute(:state, "queued") }
before { post("/v3/build/#{build.id}/cancel", params, headers) }
example { expect(last_response.status).to be == 202 }
example { expect(JSON.load(body).to_s).to include(
"@type",
"build",
"@href",
"@representation",
"minimal",
"cancel",
"id",
"state_change")
}
example { expect(sidekiq_payload).to be == {
"id" => "#{build.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
}
example { expect(Sidekiq::Client.last['queue']).to be == 'build_cancellations' }
example { expect(Sidekiq::Client.last['class']).to be == 'Travis::Sidekiq::BuildCancellation' }
end
describe "received state" do
before { build.update_attribute(:state, "received") }
before { post("/v3/build/#{build.id}/cancel", params, headers) }
example { expect(last_response.status).to be == 202 }
example { expect(JSON.load(body).to_s).to include(
"@type",
"build",
"@href",
"@representation",
"minimal",
"cancel",
"id",
"state_change")
}
example { expect(sidekiq_payload).to be == {
"id" => "#{build.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
}
example { expect(Sidekiq::Client.last['queue']).to be == 'build_cancellations' }
example { expect(Sidekiq::Client.last['class']).to be == 'Travis::Sidekiq::BuildCancellation' }
end
describe "setting id has no effect" do
let(:params) {{ id: 42 }}
before { post("/v3/build/#{build.id}/cancel", params, headers) }
example { expect(sidekiq_payload).to be == {
"id" => "#{build.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
}
end
end
describe "existing repository, push & pull access, cancelable, enqueues message for Hub" do
let(:params) {{}}
let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) }
@ -155,7 +251,7 @@ describe Travis::API::V3::Services::Build::Cancel, set_app: true do
"state_change")
}
example { expect(payload).to be == {
example { expect(sidekiq_payload).to be == {
"id" => "#{build.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
@ -181,7 +277,7 @@ describe Travis::API::V3::Services::Build::Cancel, set_app: true do
"state_change")
}
example { expect(payload).to be == {
example { expect(sidekiq_payload).to be == {
"id" => "#{build.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
@ -207,7 +303,7 @@ describe Travis::API::V3::Services::Build::Cancel, set_app: true do
"state_change")
}
example { expect(payload).to be == {
example { expect(sidekiq_payload).to be == {
"id" => "#{build.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
@ -220,7 +316,7 @@ describe Travis::API::V3::Services::Build::Cancel, set_app: true do
describe "setting id has no effect" do
let(:params) {{ id: 42 }}
before { post("/v3/build/#{build.id}/cancel", params, headers) }
example { expect(payload).to be == {
example { expect(sidekiq_payload).to be == {
"id" => "#{build.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
@ -257,7 +353,7 @@ describe Travis::API::V3::Services::Build::Cancel, set_app: true do
# describe 'setting user' do
# let(:params) {{ user: { id: repo.owner.id } }}
# example { expect(last_response.status).to be == 202 }
# example { expect(payload).to be == {
# example { expect(sidekiq_payload).to be == {
# # repository: { id: repo.id, owner_name: 'svenfuchs', name: 'minimal' },
# # user: { id: repo.owner.id },
# # message: nil,

View File

@ -1,7 +1,8 @@
describe Travis::API::V3::Services::Build::Restart, set_app: true do
let(:repo) { Travis::API::V3::Models::Repository.where(owner_name: 'svenfuchs', name: 'minimal').first }
let(:build) { repo.builds.first }
let(:payload) { { 'id'=> "#{build.id}", 'user_id' => 1 } }
let(:sidekiq_payload) { JSON.load(Sidekiq::Client.last['args'].last.to_json) }
let(:sidekiq_params) { Sidekiq::Client.last['args'].last.deep_symbolize_keys }
before do
Travis::Features.stubs(:owner_active?).returns(true)
@ -118,6 +119,131 @@ describe Travis::API::V3::Services::Build::Restart, set_app: true do
end
end
describe "existing repository, push access, build not already running" do
let(:params) {{}}
let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) }
let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }}
before { Travis::API::V3::Models::Permission.create(repository: repo, user: repo.owner, push: true) }
describe "errored state" do
before { build.update_attribute(:state, "errored") }
before { post("/v3/build/#{build.id}/restart", params, headers) }
example { expect(last_response.status).to be == 202 }
example { expect(JSON.load(body).to_s).to include(
"@type",
"pending",
"build",
"@href",
"@representation",
"minimal",
"restart",
"id",
"state_change")
}
example { expect(sidekiq_payload).to be == {
"id" => "#{build.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
}
example { expect(Sidekiq::Client.last['queue']).to be == 'build_restarts' }
example { expect(Sidekiq::Client.last['class']).to be == 'Travis::Sidekiq::BuildRestart' }
end
describe "passed state" do
before { build.update_attribute(:state, "passed") }
before { post("/v3/build/#{build.id}/restart", params, headers) }
example { expect(last_response.status).to be == 202 }
example { expect(JSON.load(body).to_s).to include(
"@type",
"pending",
"build",
"@href",
"@representation",
"minimal",
"restart",
"id",
"state_change")
}
example { expect(sidekiq_payload).to be == {
"id" => "#{build.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
}
example { expect(Sidekiq::Client.last['queue']).to be == 'build_restarts' }
example { expect(Sidekiq::Client.last['class']).to be == 'Travis::Sidekiq::BuildRestart' }
end
describe "failed state" do
before { build.update_attribute(:state, "failed") }
before { post("/v3/build/#{build.id}/restart", params, headers) }
example { expect(last_response.status).to be == 202 }
example { expect(JSON.load(body).to_s).to include(
"@type",
"pending",
"build",
"@href",
"@representation",
"minimal",
"restart",
"id",
"state_change")
}
example { expect(sidekiq_payload).to be == {
"id" => "#{build.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
}
example { expect(Sidekiq::Client.last['queue']).to be == 'build_restarts' }
example { expect(Sidekiq::Client.last['class']).to be == 'Travis::Sidekiq::BuildRestart' }
end
describe "canceled state" do
before { build.update_attribute(:state, "canceled") }
before { post("/v3/build/#{build.id}/restart", params, headers) }
example { expect(last_response.status).to be == 202 }
example { expect(JSON.load(body).to_s).to include(
"@type",
"pending",
"build",
"@href",
"@representation",
"minimal",
"restart",
"id",
"state_change")
}
example { expect(sidekiq_payload).to be == {
"id" => "#{build.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
}
example { expect(Sidekiq::Client.last['queue']).to be == 'build_restarts' }
example { expect(Sidekiq::Client.last['class']).to be == 'Travis::Sidekiq::BuildRestart' }
end
describe "setting id has no effect" do
before { post("/v3/build/#{build.id}/restart", params, headers) }
let(:params) {{ id: 42 }}
example { expect(sidekiq_payload).to be == {
"id" => "#{build.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
}
end
end
describe "existing repository, push access, build not already running, enqueues message for Hub" do
let(:params) {{}}
let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) }
@ -146,7 +272,7 @@ describe Travis::API::V3::Services::Build::Restart, set_app: true do
"state_change")
}
example { expect(payload).to be == {
example { expect(sidekiq_payload).to be == {
"id" => "#{build.id}",
"user_id"=> repo.owner_id}
}
@ -172,7 +298,7 @@ describe Travis::API::V3::Services::Build::Restart, set_app: true do
"state_change")
}
example { expect(payload).to be == {
example { expect(sidekiq_payload).to be == {
"id" => "#{build.id}",
"user_id"=> repo.owner_id}
}
@ -198,7 +324,7 @@ describe Travis::API::V3::Services::Build::Restart, set_app: true do
"state_change")
}
example { expect(payload).to be == {
example { expect(sidekiq_payload).to be == {
"id" => "#{build.id}",
"user_id"=> repo.owner_id}
}
@ -224,7 +350,7 @@ describe Travis::API::V3::Services::Build::Restart, set_app: true do
"state_change")
}
example { expect(payload).to be == {
example { expect(sidekiq_payload).to be == {
"id" => "#{build.id}",
"user_id"=> repo.owner_id}
}
@ -238,7 +364,7 @@ describe Travis::API::V3::Services::Build::Restart, set_app: true do
before { post("/v3/build/#{build.id}/restart", params, headers) }
let(:params) {{ id: 42 }}
example { expect(payload).to be == {
example { expect(sidekiq_payload).to be == {
"id" => "#{build.id}",
"user_id"=> repo.owner_id}
}
@ -271,7 +397,7 @@ describe Travis::API::V3::Services::Build::Restart, set_app: true do
# describe 'setting user' do
# let(:params) {{ user: { id: repo.owner.id } }}
# example { expect(last_response.status).to be == 202 }
# example { expect(payload).to be == {
# example { expect(sidekiq_payload).to be == {
# # repository: { id: repo.id, owner_name: 'svenfuchs', name: 'minimal' },
# # user: { id: repo.owner.id },
# # message: nil,

View File

@ -1,33 +0,0 @@
require 'spec_helper'
describe Travis::API::V3::Services::EnvVar::Delete, set_app: true do
let(:repo) { Travis::API::V3::Models::Repository.where(owner_name: 'svenfuchs', name: 'minimal').first_or_create }
let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) }
let(:env_var) { { id: 'abc', name: 'FOO', value: Travis::Settings::EncryptedValue.new('bar'), public: true, repository_id: repo.id } }
let(:auth_headers) { { 'HTTP_AUTHORIZATION' => "token #{token}" } }
describe 'not authenticated' do
before { delete("/v3/repo/#{repo.id}/env_var/#{env_var[:id]}") }
include_examples 'not authenticated'
end
describe 'authenticated, missing repo' do
before { delete("/v3/repo/999999999/env_var/foo", {}, auth_headers) }
include_examples 'missing repo'
end
describe 'authenticated, missing repo, missing env var' do
before { delete("/v3/repo/#{repo.id}/env_var/#{env_var[:id]}", {}, auth_headers) }
include_examples 'missing env_var'
end
describe 'authenticated, missing repo, existing env var' do
before do
repo.update_attributes(settings: JSON.generate(env_vars: [env_var]))
delete("/v3/repo/#{repo.id}/env_var/#{env_var[:id]}", {}, auth_headers)
end
example { expect(last_response.status).to eq 200 }
example { expect(JSON.parse(last_response.body)["id"]).to eq(env_var[:id]) }
end
end

View File

@ -1,43 +0,0 @@
require 'spec_helper'
describe Travis::API::V3::Services::EnvVar::Find, set_app: true do
let(:repo) { Travis::API::V3::Models::Repository.where(owner_name: 'svenfuchs', name: 'minimal').first_or_create }
let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) }
let(:env_var) { { id: 'abc', name: 'FOO', value: Travis::Settings::EncryptedValue.new('bar'), public: true, repository_id: repo.id } }
let(:auth_headers) { { 'HTTP_AUTHORIZATION' => "token #{token}" } }
describe 'not authenticated' do
before { get("/v3/repo/#{repo.id}/env_var/#{env_var[:id]}") }
include_examples 'not authenticated'
end
describe 'authenticated, missing repo' do
before { get("/v3/repo/999999999/env_var/foo", {}, auth_headers) }
include_examples 'missing repo'
end
describe 'authenticated, existing repo, missing env var' do
before { get("/v3/repo/#{repo.id}/env_var/#{env_var[:id]}", {}, auth_headers) }
include_examples 'missing env_var'
end
describe 'authenticated, existing repo, existing env var' do
before do
repo.update_attributes(settings: JSON.generate(env_vars: [env_var]))
get("/v3/repo/#{repo.id}/env_var/#{env_var[:id]}", {}, auth_headers)
end
example { expect(last_response.status).to eq 200 }
example do
expect(JSON.load(body)).to eq(
'@type' => 'env_var',
'@href' => "/v3/repo/#{repo.id}/env_var/#{env_var[:id]}",
'@representation' => 'standard',
'id' => env_var[:id],
'name' => env_var[:name],
'public' => env_var[:public],
'value' => env_var[:value].decrypt
)
end
end
end

View File

@ -1,50 +0,0 @@
require 'spec_helper'
describe Travis::API::V3::Services::EnvVar::Update, set_app: true do
let(:repo) { Travis::API::V3::Models::Repository.where(owner_name: 'svenfuchs', name: 'minimal').first_or_create }
let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) }
let(:env_var) { { id: 'abc', name: 'FOO', value: Travis::Settings::EncryptedValue.new('bar'), public: true, repository_id: repo.id } }
let(:auth_headers) { { 'HTTP_AUTHORIZATION' => "token #{token}" } }
let(:json_headers) { { 'CONTENT_TYPE' => 'application/json' } }
describe 'not authenticated' do
before { patch("/v3/repo/#{repo.id}/env_var/#{env_var[:id]}") }
include_examples 'not authenticated'
end
describe 'authenticated, missing repo' do
before { patch("/v3/repo/999999999/env_var/#{env_var[:id]}", {}, auth_headers) }
include_examples 'missing repo'
end
describe 'authenticated, existing repo, missing env var' do
before { patch("/v3/repo/#{repo.id}/env_var/foo", {}, auth_headers) }
include_examples 'missing env_var'
end
describe 'authenticated, existing repo, existing env var' do
let(:params) do
{
'env_var.name' => 'QUX'
}
end
before do
repo.update_attributes(settings: JSON.generate(env_vars: [env_var]))
patch("/v3/repo/#{repo.id}/env_var/#{env_var[:id]}", JSON.generate(params), auth_headers.merge(json_headers))
end
example { expect(last_response.status).to eq 200 }
example do
expect(JSON.load(body)).to eq(
'@type' => 'env_var',
'@href' => '/v3/repo/1/env_var/abc',
'@representation' => 'standard',
'id' => env_var[:id],
'name' => params['env_var.name'],
'value' => env_var[:value].decrypt,
'public' => env_var[:public]
)
end
end
end

View File

@ -1,93 +0,0 @@
require 'spec_helper'
describe Travis::API::V3::Services::EnvVars::Create, set_app: true do
let(:repo) { Travis::API::V3::Models::Repository.where(owner_name: 'svenfuchs', name: 'minimal').first_or_create }
let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) }
let(:auth_headers) { { 'HTTP_AUTHORIZATION' => "token #{token}" } }
let(:json_headers) { { 'CONTENT_TYPE' => 'application/json' } }
describe 'not authenticated' do
before { post("/v3/repo/#{repo.id}/env_vars", {}) }
include_examples 'not authenticated'
end
describe 'authenticated, repo missing' do
before { post("/v3/repo/99999999/env_vars", {}, auth_headers) }
include_examples 'missing repo'
end
describe 'authenticated, existing repo, env var already exists' do
let(:params) do
{
'env_var.name' => 'FOO',
'env_var.value' => 'bar',
'env_var.public' => false
}
end
before do
repo.update_attributes(settings: JSON.generate(env_vars: [{ id: 'abc', name: 'FOO', value: Travis::Settings::EncryptedValue.new('bar'), public: false }]))
post("/v3/repo/#{repo.id}/env_vars", JSON.generate(params), auth_headers.merge(json_headers))
end
example { expect(last_response.status).to eq 409 }
example do
expect(JSON.load(body)).to eq(
'@type' => 'error',
'error_message' => 'resource already exists',
'error_type' => 'duplicate_resource'
)
end
end
describe 'authenticated, existing repo, env var is new' do
describe 'private' do
let(:params) do
{
'env_var.name' => 'FOO',
'env_var.value' => 'bar',
'env_var.public' => false
}
end
before { post("/v3/repo/#{repo.id}/env_vars", JSON.generate(params), auth_headers.merge(json_headers)) }
example { expect(last_response.status).to eq 201 }
example do
response = JSON.load(body)
expect(response).to include(
'@type' => 'env_var',
'@representation' => 'standard',
'name' => 'FOO',
'public' => false
)
expect(response).to include('@href', 'id')
end
end
describe 'public' do
let(:params) do
{
'env_var.name' => 'FOO',
'env_var.value' => 'bar',
'env_var.public' => true
}
end
before { post("/v3/repo/#{repo.id}/env_vars", JSON.generate(params), auth_headers.merge(json_headers)) }
example { expect(last_response.status).to eq 201 }
example do
response = JSON.load(body)
expect(response).to include(
'@type' => 'env_var',
'@representation' => 'standard',
'name' => 'FOO',
'value' => 'bar',
'public' => true
)
expect(response).to include('@href', 'id')
end
end
end
end

View File

@ -1,59 +0,0 @@
require 'spec_helper'
describe Travis::API::V3::Services::EnvVars::ForRepository, set_app: true do
let(:repo) { Travis::API::V3::Models::Repository.where(owner_name: 'svenfuchs', name: 'minimal').first_or_create }
let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) }
let(:env_var) { { id: 'abc', name: 'FOO', value: Travis::Settings::EncryptedValue.new('bar'), public: true, repository_id: repo.id } }
let(:auth_headers) { { 'HTTP_AUTHORIZATION' => "token #{token}" } }
describe 'not authenticated' do
before { get("/v3/repo/#{repo.id}/env_vars") }
include_examples 'not authenticated'
end
describe 'authenticated, missing repo' do
before { get("/v3/repo/999999999/env_vars", {}, auth_headers) }
include_examples 'missing repo'
end
describe 'authenticated, existing repo, no env vars' do
before do
get("/v3/repo/#{repo.id}/env_vars", {}, auth_headers)
end
example { expect(last_response.status).to eq(200) }
example do
expect(JSON.load(body)).to eq(
'@type' => 'env_vars',
'@href' => "/v3/repo/#{repo.id}/env_vars",
'@representation' => 'standard',
'env_vars' => []
)
end
end
describe 'authenticated, existing repo, existing env vars' do
before do
repo.update_attributes(settings: JSON.generate(env_vars: [env_var]))
get("/v3/repo/#{repo.id}/env_vars", {}, auth_headers)
end
example { expect(last_response.status).to eq(200) }
example do
expect(JSON.load(body)).to eq(
'@type' => 'env_vars',
'@href' => "/v3/repo/#{repo.id}/env_vars",
'@representation' => 'standard',
'env_vars' => [
{
'@type' => 'env_var',
'@href' => "/v3/repo/#{repo.id}/env_var/#{env_var[:id]}",
'@representation' => 'standard',
'id' => env_var[:id],
'name' => env_var[:name],
'value' => env_var[:value].decrypt,
'public' => env_var[:public]
}
]
)
end
end
end

View File

@ -2,7 +2,8 @@ describe Travis::API::V3::Services::Job::Cancel, set_app: true do
let(:repo) { Travis::API::V3::Models::Repository.where(owner_name: 'svenfuchs', name: 'minimal').first }
let(:build) { repo.builds.first }
let(:job) { build.jobs.first}
let(:payload) { { 'id'=> "#{job.id}", 'user_id' => 1, 'source' => 'api' } }
let(:sidekiq_payload) { JSON.load(Sidekiq::Client.last['args'].last.to_json) }
let(:sidekiq_params) { Sidekiq::Client.last['args'].last.deep_symbolize_keys }
before do
Travis::Features.stubs(:owner_active?).returns(true)
@ -76,6 +77,103 @@ describe Travis::API::V3::Services::Job::Cancel, set_app: true do
}}
end
describe "existing repository, push access, job cancelable" do
let(:params) {{}}
let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) }
let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }}
before { Travis::API::V3::Models::Permission.create(repository: repo, user: repo.owner, push: true) }
describe "started state" do
before { job.update_attribute(:state, "started") }
before { post("/v3/job/#{job.id}/cancel", params, headers) }
example { expect(last_response.status).to be == 202 }
example { expect(JSON.load(body).to_s).to include(
"@type",
"pending",
"job",
"@href",
"@representation",
"minimal",
"cancel",
"id",
"state_change")
}
example { expect(sidekiq_payload).to be == {
"id" => "#{job.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
}
example { expect(Sidekiq::Client.last['queue']).to be == 'job_cancellations' }
example { expect(Sidekiq::Client.last['class']).to be == 'Travis::Sidekiq::JobCancellation' }
end
describe "queued state" do
before { job.update_attribute(:state, "queued") }
before { post("/v3/job/#{job.id}/cancel", params, headers) }
example { expect(last_response.status).to be == 202 }
example { expect(JSON.load(body).to_s).to include(
"@type",
"pending",
"job",
"@href",
"@representation",
"minimal",
"cancel",
"id",
"state_change")
}
example { expect(sidekiq_payload).to be == {
"id" => "#{job.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
}
example { expect(Sidekiq::Client.last['queue']).to be == 'job_cancellations' }
example { expect(Sidekiq::Client.last['class']).to be == 'Travis::Sidekiq::JobCancellation' }
end
describe "received state" do
before { job.update_attribute(:state, "received") }
before { post("/v3/job/#{job.id}/cancel", params, headers) }
example { expect(last_response.status).to be == 202 }
example { expect(JSON.load(body).to_s).to include(
"@type",
"pending",
"job",
"@href",
"@representation",
"minimal",
"cancel",
"id",
"state_change")
}
example { expect(sidekiq_payload).to be == {
"id" => "#{job.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
}
example { expect(Sidekiq::Client.last['queue']).to be == 'job_cancellations' }
example { expect(Sidekiq::Client.last['class']).to be == 'Travis::Sidekiq::JobCancellation' }
end
describe "setting id has no effect" do
before { post("/v3/job/#{job.id}/cancel", params, headers) }
let(:params) {{ id: 42 }}
example { expect(sidekiq_payload).to be == {
"id" => "#{job.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
}
end
end
describe "existing repository, push access, job cancelable, enqueues message for Hub" do
let(:params) {{}}
let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) }
@ -102,7 +200,7 @@ describe Travis::API::V3::Services::Job::Cancel, set_app: true do
"state_change")
}
example { expect(payload).to be == {
example { expect(sidekiq_payload).to be == {
"id" => "#{job.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
@ -128,7 +226,7 @@ describe Travis::API::V3::Services::Job::Cancel, set_app: true do
"state_change")
}
example { expect(payload).to be == {
example { expect(sidekiq_payload).to be == {
"id" => "#{job.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
@ -155,7 +253,7 @@ describe Travis::API::V3::Services::Job::Cancel, set_app: true do
"state_change")
}
example { expect(payload).to be == {
example { expect(sidekiq_payload).to be == {
"id" => "#{job.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
@ -168,7 +266,7 @@ describe Travis::API::V3::Services::Job::Cancel, set_app: true do
describe "setting id has no effect" do
before { post("/v3/job/#{job.id}/cancel", params, headers) }
let(:params) {{ id: 42 }}
example { expect(payload).to be == {
example { expect(sidekiq_payload).to be == {
"id" => "#{job.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
@ -257,7 +355,7 @@ describe Travis::API::V3::Services::Job::Cancel, set_app: true do
# describe 'setting user' do
# let(:params) {{ user: { id: repo.owner.id } }}
# example { expect(last_response.status).to be == 202 }
# example { expect(payload).to be == {
# example { expect(sidekiq_payload).to be == {
# # repository: { id: repo.id, owner_name: 'svenfuchs', name: 'minimal' },
# # user: { id: repo.owner.id },
# # message: nil,

View File

@ -2,7 +2,8 @@ describe Travis::API::V3::Services::Job::Restart, set_app: true do
let(:repo) { Travis::API::V3::Models::Repository.where(owner_name: 'svenfuchs', name: 'minimal').first }
let(:build) { repo.builds.first }
let(:job) { build.jobs.first }
let(:payload) { { 'id'=> "#{job.id}", 'user_id' => 1 } }
let(:sidekiq_payload) { JSON.load(Sidekiq::Client.last['args'].last.to_json) }
let(:sidekiq_params) { Sidekiq::Client.last['args'].last.deep_symbolize_keys }
before do
Travis::Features.stubs(:owner_active?).returns(true)
@ -76,6 +77,128 @@ describe Travis::API::V3::Services::Job::Restart, set_app: true do
}}
end
describe "existing repository, push access, job not already running" do
let(:params) {{}}
let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) }
let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }}
before { Travis::API::V3::Models::Permission.create(repository: repo, user: repo.owner, push: true) }
describe "canceled state" do
before { job.update_attribute(:state, "canceled") }
before { post("/v3/job/#{job.id}/restart", params, headers) }
example { expect(last_response.status).to be == 202 }
example { expect(JSON.load(body).to_s).to include(
"@type",
"pending",
"job",
"@href",
"@representation",
"minimal",
"restart",
"id",
"state_change")
}
example { expect(sidekiq_payload).to be == {
"id" => "#{job.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
}
example { expect(Sidekiq::Client.last['queue']).to be == 'job_restarts' }
example { expect(Sidekiq::Client.last['class']).to be == 'Travis::Sidekiq::JobRestart' }
end
describe "errored state" do
before { job.update_attribute(:state, "errored") }
before { post("/v3/job/#{job.id}/restart", params, headers) }
example { expect(last_response.status).to be == 202 }
example { expect(JSON.load(body).to_s).to include(
"@type",
"pending",
"job",
"@href",
"@representation",
"minimal",
"restart",
"id",
"state_change")
}
example { expect(sidekiq_payload).to be == {
"id" => "#{job.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
}
example { expect(Sidekiq::Client.last['queue']).to be == 'job_restarts' }
example { expect(Sidekiq::Client.last['class']).to be == 'Travis::Sidekiq::JobRestart' }
end
describe "failed state" do
before { job.update_attribute(:state, "failed") }
before { post("/v3/job/#{job.id}/restart", params, headers) }
example { expect(last_response.status).to be == 202 }
example { expect(JSON.load(body).to_s).to include(
"@type",
"pending",
"job",
"@href",
"@representation",
"minimal",
"restart",
"id",
"state_change")
}
example { expect(sidekiq_payload).to be == {
"id" => "#{job.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
}
example { expect(Sidekiq::Client.last['queue']).to be == 'job_restarts' }
example { expect(Sidekiq::Client.last['class']).to be == 'Travis::Sidekiq::JobRestart' }
end
describe "passed state" do
before { job.update_attribute(:state, "passed") }
before { post("/v3/job/#{job.id}/restart", params, headers) }
example { expect(last_response.status).to be == 202 }
example { expect(JSON.load(body).to_s).to include(
"@type",
"pending",
"job",
"@href",
"@representation",
"minimal",
"restart",
"id",
"state_change")
}
example { expect(sidekiq_payload).to be == {
"id" => "#{job.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
}
example { expect(Sidekiq::Client.last['queue']).to be == 'job_restarts' }
example { expect(Sidekiq::Client.last['class']).to be == 'Travis::Sidekiq::JobRestart' }
end
describe "setting id has no effect" do
before { post("/v3/job/#{job.id}/restart", params, headers) }
let(:params) {{ id: 42 }}
example { expect(sidekiq_payload).to be == {
"id" => "#{job.id}",
"user_id"=> repo.owner_id,
"source" => "api"}
}
end
end
describe "existing repository, push access, job not already running, enqueues message for Hub" do
let(:params) {{}}
let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) }
@ -102,7 +225,7 @@ describe Travis::API::V3::Services::Job::Restart, set_app: true do
"state_change")
}
example { expect(payload).to be == {
example { expect(sidekiq_payload).to be == {
"id" => "#{job.id}",
"user_id"=> repo.owner_id}
}
@ -127,7 +250,7 @@ describe Travis::API::V3::Services::Job::Restart, set_app: true do
"state_change")
}
example { expect(payload).to be == {
example { expect(sidekiq_payload).to be == {
"id" => "#{job.id}",
"user_id"=> repo.owner_id}
}
@ -152,7 +275,7 @@ describe Travis::API::V3::Services::Job::Restart, set_app: true do
"state_change")
}
example { expect(payload).to be == {
example { expect(sidekiq_payload).to be == {
"id" => "#{job.id}",
"user_id"=> repo.owner_id}
}
@ -177,7 +300,7 @@ describe Travis::API::V3::Services::Job::Restart, set_app: true do
"state_change")
}
example { expect(payload).to be == {
example { expect(sidekiq_payload).to be == {
"id" => "#{job.id}",
"user_id"=> repo.owner_id}
}
@ -193,7 +316,7 @@ describe Travis::API::V3::Services::Job::Restart, set_app: true do
end
let(:params) {{ id: 42 }}
example { expect(payload).to be == {
example { expect(sidekiq_payload).to be == {
"id" => "#{job.id}",
"user_id"=> repo.owner_id}
}
@ -269,7 +392,7 @@ describe Travis::API::V3::Services::Job::Restart, set_app: true do
# describe 'setting user' do
# let(:params) {{ user: { id: repo.owner.id } }}
# example { expect(last_response.status).to be == 202 }
# example { expect(payload).to be == {
# example { expect(sidekiq_payload).to be == {
# # repository: { id: repo.id, owner_name: 'svenfuchs', name: 'minimal' },
# # user: { id: repo.owner.id },
# # message: nil,

View File

@ -7,7 +7,14 @@ describe Travis::API::V3::Services::Settings, set_app: true do
describe :Find do
describe 'not authenticated' do
before { get("/v3/repo/#{repo.id}/settings") }
include_examples 'not authenticated'
example { expect(last_response.status).to eq(403) }
example do
expect(JSON.load(body)).to eq(
'@type' => 'error',
'error_type' => 'login_required',
'error_message' => 'login required'
)
end
end
describe 'authenticated, missing repo' do

View File

@ -57,24 +57,44 @@ describe Build::States do
build.receive(data)
build.state.should == :received
end
it 'notifies observers' do
Travis::Event.expects(:dispatch).with('build:received', build, data)
build.receive(data)
end
end
describe 'when the build is already received' do
before :each do
build.state = :received
end
it 'does not notify observers' do
Travis::Event.expects(:dispatch).never
build.receive(data)
end
end
describe 'when the build has failed' do
before :each do
build.state = :failed
end
it 'does not notify observers' do
Travis::Event.expects(:dispatch).never
build.receive(data)
end
end
describe 'when the build has errored' do
before :each do
build.state = :errored
end
it 'does not notify observers' do
Travis::Event.expects(:dispatch).never
build.receive(data)
end
end
end
@ -91,6 +111,11 @@ describe Build::States do
build.expects(:denormalize)
build.start(data)
end
it 'notifies observers' do
Travis::Event.expects(:dispatch).with('build:started', build, data)
build.start(data)
end
end
describe 'when the build is already started' do
@ -102,6 +127,11 @@ describe Build::States do
build.expects(:denormalize).never
build.start(data)
end
it 'does not notify observers' do
Travis::Event.expects(:dispatch).never
build.start(data)
end
end
describe 'when the build has failed' do
@ -113,6 +143,11 @@ describe Build::States do
build.expects(:denormalize).never
build.start(data)
end
it 'does not notify observers' do
Travis::Event.expects(:dispatch).never
build.start(data)
end
end
describe 'when the build has errored' do
@ -124,6 +159,11 @@ describe Build::States do
build.expects(:denormalize).never
build.start(data)
end
it 'does not notify observers' do
Travis::Event.expects(:dispatch).never
build.start(data)
end
end
end
@ -144,6 +184,11 @@ describe Build::States do
build.expects(:denormalize).never
build.finish(data)
end
it 'does not notify observers' do
Travis::Event.expects(:dispatch).never
build.finish(data)
end
end
end
@ -172,6 +217,11 @@ describe Build::States do
build.expects(:denormalize).with(:finish, data)
build.finish(data)
end
it 'notifies observers' do
Travis::Event.expects(:dispatch).with('build:finished', build, data)
build.finish(data)
end
end
describe 'when the build has already finished' do
@ -183,6 +233,11 @@ describe Build::States do
build.expects(:denormalize).never
build.finish(data)
end
it 'does not notify observers' do
Travis::Event.expects(:dispatch).never
build.finish(data)
end
end
end
end

View File

@ -325,6 +325,11 @@ describe Build do
build.matrix.each { |job| job.expects(:reset).never }
build.reset
end
it 'notifies obsevers' do
Travis::Event.expects(:dispatch).with('build:created', build)
build.reset
end
end
end
end

Some files were not shown because too many files have changed in this diff Show More