diff --git a/.travis.yml b/.travis.yml index 8cb9e317..bcffcdd4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,10 +11,16 @@ env: matrix: - RAKE_TASK=spec global: - secure: BdVC3OHqYcgePLrkKIk28Ewn/dxCYFf3Cx+Q8P+BCDj6UPJyRSbKmILBzuX96H5xhKmUFo0A/upUhJI9UUP9aXHO7MzRe04/c88QdO4wGacVUaIyB20S0pr262zbc/nA50K9cVgpmWc64n6uQR1tgM6ZyyBnBeXkLzCAOHPq99I= + - secure: BdVC3OHqYcgePLrkKIk28Ewn/dxCYFf3Cx+Q8P+BCDj6UPJyRSbKmILBzuX96H5xhKmUFo0A/upUhJI9UUP9aXHO7MzRe04/c88QdO4wGacVUaIyB20S0pr262zbc/nA50K9cVgpmWc64n6uQR1tgM6ZyyBnBeXkLzCAOHPq99I= + - PATH=/snap/bin:$PATH + +before_install: + - gem uninstall -v '>=2' -i $(rvm gemdir)@global -ax bundler || true + - gem install bundler -v '2.3.7' + - gem install rubygems-update -v 3.4.22 addons: - apt: + - apt: packages: - rabbitmq-server @@ -27,7 +33,8 @@ jobs: - stage: "testing time" script: bundle exec rspec spec - stage: ":ship: it to quay.io" - dist: bionic + dist: focal + group: edge ruby: services: addons: @@ -35,4 +42,4 @@ jobs: before_script: skip install: skip script: make ship - if: commit_message =~ /ship:docker/ OR env(SHIP_DOCKER) = true + if: (branch = master and type = push ) OR commit_message =~ /ship:docker/ OR env(SHIP_DOCKER) = true diff --git a/Dockerfile.tcie b/Dockerfile.tcie new file mode 100644 index 00000000..4869ce73 --- /dev/null +++ b/Dockerfile.tcie @@ -0,0 +1,36 @@ +FROM ruby:3.2.2-slim + +LABEL maintainer Travis CI GmbH + +RUN ( \ + bundle config set no-cache 'true'; \ + bundle config --global frozen 1; \ + bundle config set deployment 'true'; \ + mkdir -p /app; \ +) +WORKDIR /app +COPY Gemfile* /app/ +ARG bundle_gems__contribsys__com +RUN ( \ + apt-get update ; \ + apt-get upgrade -y ; \ + apt-get install -y --no-install-recommends git make gcc g++ libpq-dev libjemalloc-dev libcurl4 \ + && rm -rf /var/lib/apt/lists/*; \ + gem update --system; \ + gem install bundler -v '2.3.24'; \ + bundle config https://gems.contribsys.com/ $bundle_gems__contribsys__com; \ + bundle config set without 'development test'; \ + bundle install; \ + bundle config --delete https://gems.contribsys.com; \ + gem install --user-install executable-hooks \ + apt-get remove -y gcc g++ make git perl && apt-get -y autoremove; \ + bundle clean && rm -rf /app/vendor/bundle/ruby/2.7.0/cache/*; \ + for i in `find /app/vendor/ -name \*.o -o -name \*.c -o -name \*.h`; do rm -f $i; done; \ +) + +ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 + +# throw errors if Gemfile has been modified since Gemfile.lock +COPY . /app + +CMD ["bundle", "exec", "bin/sidekiq-pgbouncer", "${SIDEKIQ_CONCURRENCY:-5}", "${SIDEKIQ_QUEUE:-scheduler}"] diff --git a/Makefile b/Makefile index d95431ab..34dd4f32 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ DOCKER ?= docker .PHONY: docker-build docker-build: - $(DOCKER) build --build-arg bundle_gems__contribsys__com=$(BUNDLE_GEMS__CONTRIBSYS__COM) -t $(DOCKER_DEST) . + $(DOCKER) build --no-cache --pull --build-arg bundle_gems__contribsys__com=$(BUNDLE_GEMS__CONTRIBSYS__COM) -t $(DOCKER_DEST) . -f Dockerfile.tcie .PHONY: docker-login docker-login: @@ -52,7 +52,7 @@ docker-push-branch: .PHONY: ship ship: docker-build docker-login -ifeq ($(BRANCH),master) +ifeq ($(TRAVIS_BRANCH),master) ifeq ($(TRAVIS_PULL_REQUEST),false) ship: docker-push-latest-master endif diff --git a/bin/sidekiq b/bin/sidekiq index 043a256d..1ce63c16 100755 --- a/bin/sidekiq +++ b/bin/sidekiq @@ -1,7 +1,6 @@ #!/bin/bash threads=${SIDEKIQ_THREADS:-8} -index=$(echo ${DYNO:-1} | sed 's/.*\.//') queues=$@ export RUBYOPT="-Ilib $RUBYOPT" diff --git a/lib/travis/amqp/publisher.rb b/lib/travis/amqp/publisher.rb index dc0bff58..17641697 100644 --- a/lib/travis/amqp/publisher.rb +++ b/lib/travis/amqp/publisher.rb @@ -25,6 +25,7 @@ def initialize(routing_key, options = {}) def publish(data, options = {}) return unless data + Amqp.logger.warn "Queue #{routing_key} doesn't exist!" if ENV['AMQP_QUEUE_VALIDATION'] && !Amqp.connection.queue_exists?(routing_key) data = MultiJson.encode(data) exchange.publish(data, deep_merge(default_data, options)) debug "Published AMQP message to #{routing_key}." diff --git a/lib/travis/queue/matcher.rb b/lib/travis/queue/matcher.rb index 701b9a70..b172b459 100644 --- a/lib/travis/queue/matcher.rb +++ b/lib/travis/queue/matcher.rb @@ -37,7 +37,7 @@ def paid job.paid? end - def repo_private + def repo_private job.private? end @@ -90,7 +90,7 @@ def resources end def arch - return nil if job.private? && OSS_ONLY_ARCH.include?(job.config[:arch]) + return nil if job.private? && OSS_ONLY_ARCH.include?(job.config[:arch]) && !enterprise? job.config[:arch] end @@ -99,7 +99,7 @@ def virt job.config[:virt] end - def vm_size + def vm_size job.config[:vm][:size] if job.config[:vm] end @@ -115,6 +115,10 @@ def check_unknown_matchers(used) unknown = used - KEYS logger.warn format(MSGS[:unknown_matchers], used, unknown, repo.slug) if logger && unknown.any? end + + def enterprise? + !!Travis::Scheduler.context.config[:enterprise] + end end end end diff --git a/lib/travis/scheduler/billing/client.rb b/lib/travis/scheduler/billing/client.rb index aac553fc..7e29acdd 100644 --- a/lib/travis/scheduler/billing/client.rb +++ b/lib/travis/scheduler/billing/client.rb @@ -60,11 +60,14 @@ def request(method, path, params) def get(path, params = {}) body = request(:get, path, params).body - body&.length&.to_i > 0 && body.is_a?(String) ? JSON.parse(body) : body + return {} unless body&.length&.to_i > 0 + + body.is_a?(String) ? JSON.parse(body) : body end def post(path, params = {}) body = request(:post, path, params).body + body&.length&.to_i > 0 && body.is_a?(String) ? JSON.parse(body) : body end diff --git a/lib/travis/scheduler/config.rb b/lib/travis/scheduler/config.rb index 19a4a55b..40ad8e85 100644 --- a/lib/travis/scheduler/config.rb +++ b/lib/travis/scheduler/config.rb @@ -13,7 +13,7 @@ class Config < Travis::Config enterprise: false, github: { api_url: 'https://api.github.com', source_host: 'github.com' }, billing: { url: 'http://localhost:9292/', auth_key: 'auth_keys' }, - host: 'https://travis-ci.com', + billing: { url: 'http://localhost:9292/', auth_key: 'auth_keys' },host: 'https://travis-ci.com', interval: 2, limit: { public: 5, education: 1, default: 5, by_owner: {}, delegate: {} }, lock: { strategy: :redis, ttl: 150 }, diff --git a/lib/travis/scheduler/jobs/capacity/plan.rb b/lib/travis/scheduler/jobs/capacity/plan.rb index bfc996a0..53e1a453 100644 --- a/lib/travis/scheduler/jobs/capacity/plan.rb +++ b/lib/travis/scheduler/jobs/capacity/plan.rb @@ -12,7 +12,6 @@ def applicable? def report(status, job) super.merge(max:) end - def accept?(job) super if !on_metered_plan? || billing_allowed?(job) end diff --git a/lib/travis/scheduler/record/job.rb b/lib/travis/scheduler/record/job.rb index 33d25a97..515812d9 100644 --- a/lib/travis/scheduler/record/job.rb +++ b/lib/travis/scheduler/record/job.rb @@ -101,6 +101,7 @@ def public? def config record = super + record = JSON.parse(record) if record.is_a?(String) config = record&.config_json if record.respond_to?(:config_json) # TODO: remove once we've rolled over config ||= record&.config config ||= read_attribute(:config) if has_attribute?(:config) @@ -112,4 +113,10 @@ def config def name config[:name] end + + def new_queueable + return if repository_id.blank? # to avoid trying save objects without repository_id + saved = new_record? ? save : true # saves if it is a new record + create_queueable if saved # it is allowed to create queueable records only for jobs which are persisting in the database + end end diff --git a/lib/travis/scheduler/record/repository/settings.rb b/lib/travis/scheduler/record/repository/settings.rb index 48df87fa..de46da44 100644 --- a/lib/travis/scheduler/record/repository/settings.rb +++ b/lib/travis/scheduler/record/repository/settings.rb @@ -101,7 +101,7 @@ def custom_timeouts?(settings) validates_with TimeoutsValidator - def update_attributes!(attrs) + def update!(attrs) attrs.each { |key, value| send(:"#{key}=", value) } save end diff --git a/lib/travis/scheduler/record/user.rb b/lib/travis/scheduler/record/user.rb index 4e8d7659..2ff06977 100644 --- a/lib/travis/scheduler/record/user.rb +++ b/lib/travis/scheduler/record/user.rb @@ -40,18 +40,21 @@ def paid? end def paid_new_plan? - redis_key = "user:#{id}:plan" + redis_key = "user:#{self.id}:plan" plan = if redis.exists?(redis_key) JSON.parse(redis.get(redis_key)) else - p = billing_client.get_plan(self) - p.length > 0 ? p.to_h : {} + billing_client.get_plan(self).to_h end return false if plan[:error] || plan['plan_name'].nil? plan['hybrid'] || !plan['plan_name'].include?('free') end + def enterprise? + !!context.config[:enterprise] + end + def default_worker_timeout # When the user is a paid user ("subscribed") or has an active trial, they # are granted a different default timeout on their jobs. @@ -60,7 +63,7 @@ def default_worker_timeout # those enforced by workers themselves, but we plan to sometime in the # following weeks/months. # - if paid? || educational? + if enterprise? || paid? || educational? Travis.logger.info "Default Timeout: DEFAULT_SUBSCRIBED_TIMEOUT for owner=#{id}" DEFAULT_SUBSCRIBED_TIMEOUT else diff --git a/lib/travis/scheduler/serialize/worker/config/decrypt.rb b/lib/travis/scheduler/serialize/worker/config/decrypt.rb index 3a9b4264..6c2c02dc 100644 --- a/lib/travis/scheduler/serialize/worker/config/decrypt.rb +++ b/lib/travis/scheduler/serialize/worker/config/decrypt.rb @@ -19,7 +19,7 @@ def apply private - def force_vault_to_be_secure!(config) + def force_vault_to_be_secure!(config) config[:vault].delete(:token) if config.dig(:vault, :token).is_a?(String) end diff --git a/lib/travis/scheduler/serialize/worker/job.rb b/lib/travis/scheduler/serialize/worker/job.rb index dd3fd855..74ef9364 100644 --- a/lib/travis/scheduler/serialize/worker/job.rb +++ b/lib/travis/scheduler/serialize/worker/job.rb @@ -97,10 +97,12 @@ def vm_configs def job_repository return job.repository if job.source.event_type != 'pull_request' || job.source.request.pull_request.head_repo_slug == job.source.request.pull_request.base_repo_slug + return repository if repository.settings.share_encrypted_env_with_forks + owner_name, repo_name = job.source.request.pull_request.head_repo_slug.split('/') return if owner_name.nil? || owner_name.empty? || repo_name.nil? || repo_name.empty? - ::Repository.find_by(owner_name:, name: repo_name) + ::Repository.find_by(owner_name: owner_name, name: repo_name) end def repository_key diff --git a/lib/travis/scheduler/serialize/worker/repo.rb b/lib/travis/scheduler/serialize/worker/repo.rb index 98c13630..2fda6152 100644 --- a/lib/travis/scheduler/serialize/worker/repo.rb +++ b/lib/travis/scheduler/serialize/worker/repo.rb @@ -79,7 +79,12 @@ def hard_limit_timeout end def timeout(type) - return unless timeout = repo.settings.send(:"timeout_#{type}") + timeout = repo.settings.send(:"timeout_#{type}") + if timeout == nil + config = Travis.config.settings&.timeouts&.defaults + timeout = config[type] if config + end + return unless timeout timeout = Integer(timeout) timeout * 60 # worker handles timeouts in seconds diff --git a/lib/travis/scheduler/service/notify.rb b/lib/travis/scheduler/service/notify.rb index c364661b..00a42349 100644 --- a/lib/travis/scheduler/service/notify.rb +++ b/lib/travis/scheduler/service/notify.rb @@ -49,7 +49,8 @@ def notify_job_board def notify_rabbitmq info :publish, job.id, job.queue, 'rabbitmq' - amqp.publish(worker_payload, properties: { type: 'test', persistent: true }) + w = worker_payload + amqp.publish(w, properties: { type: 'test', persistent: true }) end def notify_live @@ -101,7 +102,7 @@ def amqp def redirect_queue queue = redirections[job.queue] or return info format(MSGS[:redirect], job.queue, queue) - job.update_attributes!(queue:) + job.update!(queue:) end def redirections diff --git a/lib/travis/scheduler/service/set_queue.rb b/lib/travis/scheduler/service/set_queue.rb index 167b7d2e..80829cad 100644 --- a/lib/travis/scheduler/service/set_queue.rb +++ b/lib/travis/scheduler/service/set_queue.rb @@ -12,7 +12,8 @@ class SetQueue < Struct.new(:context, :job, :opts) MSGS = { redirect: 'Found job.queue: %s. Redirecting to: %s', - queue: 'Setting queue to %s for job=%s' + queue: 'Setting queue to %s for job=%s', + canceled: 'Build %s has been canceled, job %s being canceled' }.freeze def run @@ -23,7 +24,18 @@ def run private def queue - @queue ||= redirect(Queue.new(job, config, logger).select) + if job.stage.present? && job.stage.state == "canceled" + info MSGS[:canceled] % [job.source.id, job.id] + payload = { id: job.id, source: 'scheduler' } + Hub.push('job:cancel', payload) + else + @queue ||= redirect(Queue.new(job, config, logger).select) + end + rescue => e + puts "ERROR while trying to queue: #{e.message}" + puts "Backtrace:" + puts e.backtrace.join("\n") + @queue ||= redirect(Queue.new(job, config, logger).select) end # TODO: confirm we don't need queue redirection any more diff --git a/lib/travis/service.rb b/lib/travis/service.rb index 8523e87a..56a642b7 100644 --- a/lib/travis/service.rb +++ b/lib/travis/service.rb @@ -11,7 +11,7 @@ def self.push(*args) 'queue' => ENV['SIDEKIQ_QUEUE'] || 'scheduler', 'class' => 'Travis::Scheduler::Worker', 'args' => args.map! { |arg| arg.to_json }, - 'at' => args.last.is_a?(Hash) ? args.last.delete(:at) : Time.now.to_f + 'at' => args.last.is_a?(Hash) ? (args.last.delete(:at) || Time.now.to_i) : Time.now.to_i ) end end diff --git a/lib/travis/service/job_board.rb b/lib/travis/service/job_board.rb index fe959ad1..8def9ddc 100644 --- a/lib/travis/service/job_board.rb +++ b/lib/travis/service/job_board.rb @@ -30,7 +30,7 @@ class JobBoard < Struct.new(:job_id, :data, :config, :logger) def post response = http.post(PATH, JSON.dump(payload)) log response.status - rescue Faraday::ClientError => e + rescue Faraday::ClientError, Faraday::ServerError => e log e.response[:status], e.response[:body] raise rescue Faraday::ServerError => e diff --git a/spec/travis/scheduler/jobs_spec.rb b/spec/travis/scheduler/jobs_spec.rb index 44893d36..9b38a47c 100644 --- a/spec/travis/scheduler/jobs_spec.rb +++ b/spec/travis/scheduler/jobs_spec.rb @@ -503,7 +503,7 @@ def subscribe(plan, owner = user) describe 'with a boost of 5 and a repo settings limit 3' do before do redis.set("scheduler.owner.limit.#{user.login}", 5) - repo.settings.update_attributes!(maximum_number_of_builds: 3) + repo.settings.update!(maximum_number_of_builds: 3) end describe 'with private jobs only' do @@ -569,7 +569,7 @@ def subscribe(plan, owner = user) before do subscribe(:two) redis.set("scheduler.owner.limit.#{user.login}", 4) - repo.settings.update_attributes!(maximum_number_of_builds: 3) + repo.settings.update!(maximum_number_of_builds: 3) end describe 'with private jobs only' do diff --git a/spec/travis/scheduler/record/user_spec.rb b/spec/travis/scheduler/record/user_spec.rb index 289f3fc0..350838fd 100644 --- a/spec/travis/scheduler/record/user_spec.rb +++ b/spec/travis/scheduler/record/user_spec.rb @@ -4,6 +4,8 @@ let(:user) { FactoryBot.create(:user) } let(:repo) { FactoryBot.create(:repository) } let(:authorize_build_url) { "http://localhost:9292/users/#{user.id}/plan" } + let(:repo) { FactoryBot.create(:repository) } + let(:authorize_build_url) { "http://localhost:9292/users/#{user.id}/plan" } describe 'constants' do # It isn't often that we see tests for constants, but these are special. @@ -82,6 +84,19 @@ end end + context "paid_new_plan? == true" do + before do + user.stubs(:paid_new_plan?).returns(true) + stub_request(:get, authorize_build_url).to_return( + body: MultiJson.dump(plan_name: 'two_concurrent_plan', hybrid: true, free: false, status: 'subscribed', metered: false) + ) + end + + it "returns the DEFAULT_SUBSCRIBED_TIMEOUT" do + expect(user.default_worker_timeout).to eq Organization::DEFAULT_SUBSCRIBED_TIMEOUT + end + end + context 'paid_new_plan? == true' do before do user.stubs(:paid_new_plan?).returns(true) diff --git a/spec/travis/scheduler/serialize/worker/config_spec.rb b/spec/travis/scheduler/serialize/worker/config_spec.rb index d4b6e8e1..3937e786 100644 --- a/spec/travis/scheduler/serialize/worker/config_spec.rb +++ b/spec/travis/scheduler/serialize/worker/config_spec.rb @@ -96,6 +96,16 @@ def encrypt(string) it { is_expected.to eql vault: {} } end + + describe 'decrypts vault secure token' do + let(:config) { { vault: { token: { secure: encrypt('my_key') } } } } + it { should eql vault: {token: 'my_key'} } + end + + describe 'clears vault unsecure token' do + let(:config) { { vault: { token: 'my_key' } } } + it { should eql vault: {} } + end end describe 'with secure env disabled' do diff --git a/spec/travis/scheduler/serialize/worker/job_spec.rb b/spec/travis/scheduler/serialize/worker/job_spec.rb index 5d5a5a74..923cf194 100644 --- a/spec/travis/scheduler/serialize/worker/job_spec.rb +++ b/spec/travis/scheduler/serialize/worker/job_spec.rb @@ -39,13 +39,11 @@ describe 'with secure env allowed in the PR' do before { repo.settings.stubs(:share_encrypted_env_with_forks).returns(true) } - it { expect(subject.secure_env?).to eq(true) } end describe 'with secure env forbidden in the PR' do before { repo.settings.stubs(:share_encrypted_env_with_forks).returns(false) } - it { expect(subject.secure_env?).to eq(false) } end end @@ -163,4 +161,59 @@ end end end + + describe 'decrypted config' do + context 'when in a pull request' do + let(:config) do + { + env: [ + { :BAR => 'bar' }, + { secure: Base64.encode64(repo.key.encrypt('MAIN=1')) }, + ] + } + end + let(:request) { Request.new(pull_request: pull_request) } + + before do + build.event_type = 'pull_request' + end + + context 'when head repo is present' do + let(:head_repo) { FactoryBot.create(:repository, github_id: 549744) } + let(:head_repo_key) { OpenSSL::PKey::RSA.generate(4096) } + let(:pull_request) { PullRequest.new(base_repo_slug: 'travis-ci/travis-yml', head_repo_slug: "#{head_repo.owner_name}/#{head_repo.name}") } + + it do + expect(subject.decrypted_config[:env]).to eq(['BAR=bar', 'SECURE MAIN=1']) + end + end + + context 'when head repo is not found' do + let(:pull_request) { PullRequest.new(base_repo_slug: 'travis-ci/travis-yml', head_repo_slug: 'mytest/letssee') } + + it 'returns garbage' do + expect(subject.decrypted_config[:env]).to eq(['BAR=bar', 'SECURE [unable to decrypt]']) + end + end + end + + context 'when in a push' do + let(:config) do + { + env: [ + { :BAR => 'bar' }, + { secure: Base64.encode64(repo.key.encrypt('MAIN=1')) }, + ] + } + end + + before do + build.event_type = 'push' + end + + it do + expect(subject.decrypted_config[:env]).to eq(['BAR=bar', 'SECURE MAIN=1']) + end + end + end end diff --git a/spec/travis/scheduler/serialize/worker_spec.rb b/spec/travis/scheduler/serialize/worker_spec.rb index 22723386..8f244dfb 100644 --- a/spec/travis/scheduler/serialize/worker_spec.rb +++ b/spec/travis/scheduler/serialize/worker_spec.rb @@ -47,8 +47,8 @@ def encrypted(value) it 'data' do expect(data).to eq( type: :test, - vm_type: :default, vm_config: {}, + vm_type: :default, vm_size: nil, queue: 'builds.gce', config: { @@ -95,9 +95,9 @@ def encrypted(value) source_url: 'https://github.com/svenfuchs/gem-release.git', source_host: 'github.com', api_url: 'https://api.github.com/repos/svenfuchs/gem-release', + last_build_number: '2', last_build_started_at: '2016-01-01T10:00:00Z', last_build_finished_at: '2016-01-01T11:00:00Z', - last_build_number: '2', last_build_duration: 60, last_build_state: 'passed', default_branch: 'branch', @@ -242,8 +242,8 @@ def encrypted(value) it 'data' do expect(data).to eq( type: :test, - vm_type: :default, vm_config: {}, + vm_type: :default, vm_size: nil, queue: 'builds.gce', config: { @@ -274,6 +274,8 @@ def encrypted(value) allow_failure:, stage_name: nil, name: 'jobname', + pull_request_head_branch: 'head_branch', + pull_request_head_sha: '62aaef', pull_request_head_slug: 'travis-ci/gem-release', pull_request_base_slug: nil, pull_request_base_ref: nil, @@ -295,9 +297,9 @@ def encrypted(value) source_url: 'https://github.com/svenfuchs/gem-release.git', source_host: 'github.com', api_url: 'https://api.github.com/repos/svenfuchs/gem-release', + last_build_number: '2', last_build_started_at: '2016-01-01T10:00:00Z', last_build_finished_at: '2016-01-01T11:00:00Z', - last_build_number: '2', last_build_duration: 60, last_build_state: 'passed', default_branch: 'branch', @@ -451,13 +453,11 @@ def encrypted(value) describe 'outside enterprise' do describe 'on a public repo' do before { repo.update!(private: false) } - include_examples 'does not include an ssh key' end describe 'on a private repo' do before { repo.update!(private: true) } - include_examples 'includes an ssh key' end end @@ -467,13 +467,11 @@ def encrypted(value) describe 'on a public repo' do before { repo.update!(private: false) } - include_examples 'includes an ssh key' end describe 'on a private repo' do before { repo.update!(private: true) } - include_examples 'includes an ssh key' end end @@ -486,13 +484,11 @@ def encrypted(value) describe 'preference set to true' do before { repo.owner.update(preferences: { keep_netrc: true }) } - it { expect(data[:keep_netrc]).to be true } end describe 'preference set to false' do before { repo.owner.update(preferences: { keep_netrc: false }) } - it { expect(data[:keep_netrc]).to be false } end end diff --git a/spec/travis/scheduler/service/enqueue_owners_spec.rb b/spec/travis/scheduler/service/enqueue_owners_spec.rb index 5c876555..c1313a81 100644 --- a/spec/travis/scheduler/service/enqueue_owners_spec.rb +++ b/spec/travis/scheduler/service/enqueue_owners_spec.rb @@ -5,6 +5,8 @@ let(:repo) { FactoryBot.create(:repo, owner:) } let(:owner) { FactoryBot.create(:user) } let(:commit) { FactoryBot.create(:commit) } + let(:build) { FactoryBot.create(:build, repository: repo, owner: owner, jobs: [job]) } + let(:job_stage) { FactoryBot.create(:stage) } let(:job) { Job.first } let(:config) { Travis::Scheduler.context.config } let(:data) { { owner_type: 'User', owner_id: owner.id, jid: '1234' } } diff --git a/spec/travis/scheduler/service/event_spec.rb b/spec/travis/scheduler/service/event_spec.rb index e6b8f336..60be7da1 100644 --- a/spec/travis/scheduler/service/event_spec.rb +++ b/spec/travis/scheduler/service/event_spec.rb @@ -5,7 +5,8 @@ let(:repo) { FactoryBot.create(:repo) } let(:owner) { FactoryBot.create(:user) } let(:build) { FactoryBot.create(:build, repository: repo, owner:, jobs: [job]) } - let(:job) { FactoryBot.create(:job, private: true, state: :created, config: config.to_h) } + let(:job_stage) { FactoryBot.create(:stage) } + let(:job) { FactoryBot.create(:job, private: true, state: :created, config: config.to_h, stage_id: job_stage.id) } let(:config) { Travis::Scheduler.context.config } let(:data) { { id: build.id, jid: '1234' } } let(:event) { 'build:created' } diff --git a/spec/travis/scheduler/service/notify_spec.rb b/spec/travis/scheduler/service/notify_spec.rb index 62b1ac48..83490c4d 100644 --- a/spec/travis/scheduler/service/notify_spec.rb +++ b/spec/travis/scheduler/service/notify_spec.rb @@ -1,7 +1,9 @@ # frozen_string_literal: false describe Travis::Scheduler::Service::Notify do - let(:job) { FactoryBot.create(:job, state: :queued, queued_at: Time.parse('2016-01-01T10:30:00Z'), config: {}) } + let(:build) { FactoryBot.create(:build, repository: repo, owner: owner, jobs: [job]) } + let(:job_stage) { FactoryBot.create(:stage) } + let(:job) { FactoryBot.create(:job, state: :queued, queued_at: Time.parse('2016-01-01T10:30:00Z'), config: {}, stage_id: job_stage.id) } let(:data) { { job: { id: job.id } } } let(:context) { Travis::Scheduler.context } let(:service) { described_class.new(context, data) } @@ -144,7 +146,9 @@ def rescueing let(:status) { 500 } let(:body) { nil } - include_examples 'raises_server' + it 'raises_server' do + expect { service.run }.to raise_error(Faraday::ServerError) + end it 'logs' do rescueing { service.run } @@ -163,7 +167,7 @@ def rescueing describe 'sets the queue' do let(:config) { { language: 'objective-c', os: 'osx', osx_image: 'xcode8', group: 'stable', dist: 'osx' } } let(:job) do - FactoryBot.create(:job, state: :queued, config:, queue: nil, queued_at: Time.parse('2016-01-01T10:30:00Z')) + FactoryBot.create(:job, state: :queued, config:, queue: nil, queued_at: Time.parse('2016-01-01T10:30:00Z'), stage_id: job_stage.id) end before do