class NdrDevSupport::Daemon::CIServer

Wrapper around Rake based CI testing loop

Constants

GIT_SVN_REMOTE_BRANCH_NAME
MASTER_BRANCH_NAME
ORIGIN_MASTER_BRANCH_NAME

Attributes

repo[R]

Public Class Methods

friendly_revision_name(commit) click to toggle source
# File lib/ndr_dev_support/daemon/ci_server.rb, line 36
def self.friendly_revision_name(commit)
  if (matchdata = commit.message.match(/\bgit-svn-id: [^@]+@(\d+)\s/))
    matchdata[1]
  else
    commit.oid[0, 7]
  end
end
from_args(env) click to toggle source
# File lib/ndr_dev_support/daemon/ci_server.rb, line 20
def self.from_args(env)
  name = env['WORKER_NAME'].to_s

  new(name: name)
end
new(name:) click to toggle source
Calls superclass method NdrDevSupport::Daemon::Stoppable::new
# File lib/ndr_dev_support/daemon/ci_server.rb, line 26
def initialize(name:)
  super

  # Worker name can be used for clear logging:
  @name = name
  raise ArgumentError, 'No WORKER_NAME specified!' if name.blank?

  @repo = Rugged::Repository.new('.')
end

Private Instance Methods

bundle_install() click to toggle source
# File lib/ndr_dev_support/daemon/ci_server.rb, line 136
def bundle_install
  return unless File.file?('Gemfile')
  return if system('bundle check')

  system('rbenv exec bundle install --local --jobs=3')
  return if $CHILD_STATUS.exitstatus.zero? || ENV['SLACK_WEBHOOK_URL'].nil?

  slack_publisher = NdrDevSupport::SlackMessagePublisher.new(ENV['SLACK_WEBHOOK_URL'],
                                                             username: 'Rake CI',
                                                             icon_emoji: ':robot_face:',
                                                             channel: ENV['SLACK_CHANNEL'])

  attachment = {
    color: 'danger',
    fallback: 'Failure running bundle install --local',
    text: 'Failure running `bundle install --local`',
    footer: 'bundle exec rake ci:bundle_install'
  }

  slack_publisher.post(attachments: [attachment])

  raise 'Failure running `bundle install --local`'
end
git_branch_name() click to toggle source
# File lib/ndr_dev_support/daemon/ci_server.rb, line 75
def git_branch_name
  ENV.fetch('RAKE_CI_BRANCH_NAME', MASTER_BRANCH_NAME)
end
git_checkout(oid) click to toggle source
# File lib/ndr_dev_support/daemon/ci_server.rb, line 83
def git_checkout(oid)
  Open3.popen3('git', 'checkout', oid) do |_stdin, _stdout, stderr, wait_thr|
    msg = stderr.read.strip
    log(msg) unless msg == "Already on '#{oid}'"

    process_status = wait_thr.value
    raise msg unless process_status.exited?
  end
end
git_discard_changes() click to toggle source
# File lib/ndr_dev_support/daemon/ci_server.rb, line 97
def git_discard_changes
  # git clean would remove all unstaged files
  stash_output = `git stash`
  return if stash_output.start_with?('No local changes to save')
  `git stash drop stash@{0}`
end
git_fetch() click to toggle source
# File lib/ndr_dev_support/daemon/ci_server.rb, line 79
def git_fetch
  system(svn_remote? ? 'git svn fetch' : 'git fetch')
end
git_rebase(oid) click to toggle source
# File lib/ndr_dev_support/daemon/ci_server.rb, line 93
def git_rebase(oid)
  system("git rebase #{Shellwords.escape(oid)}") || raise('Unable to rebase!')
end
objectids_between_master_and_remote() click to toggle source
# File lib/ndr_dev_support/daemon/ci_server.rb, line 121
def objectids_between_master_and_remote
  walker = Rugged::Walker.new(@repo)
  walker.push(repo.branches[remote_branch].target_id)
  current_target_id = repo.branches[git_branch_name].target_id

  revisions = []
  # walk backwards from the most recent commit, breaking at the current one
  walker.each do |commit|
    break if commit.oid == current_target_id
    revisions << commit.oid
  end

  revisions.reverse
end
remote_branch() click to toggle source
# File lib/ndr_dev_support/daemon/ci_server.rb, line 108
def remote_branch
  return @remote_branch if @remote_branch

  remote_branches = repo.branches.each_name(:remote)
  if remote_branches.count == 1
    @remote_branch = remote_branches.first
  elsif remote_branches.include?(ORIGIN_MASTER_BRANCH_NAME)
    @remote_branch = ORIGIN_MASTER_BRANCH_NAME
  else
    raise "One remote branch expected (#{remote_branches.to_a.inspect})"
  end
end
run_once() click to toggle source
# File lib/ndr_dev_support/daemon/ci_server.rb, line 46
      def run_once
        log('running once...')

        git_fetch
        git_discard_changes
        git_checkout(git_branch_name)

        objectids_between_master_and_remote.each do |oid|
          log("testing #{oid}...")
          git_discard_changes
          git_rebase(oid)

          WithCleanRbenv.with_clean_rbenv do
            # TODO: rbenv_install
            bundle_install
            system('rbenv exec bundle exec rake ci:all --trace')
          end
        end

        log('completed single run.')
      rescue => exception
        log(<<~MSG)
          Unhandled exception! #{exception.class}: #{exception.message}
          #{(exception.backtrace || []).join("\n")}
        MSG

        raise exception
      end
svn_remote?() click to toggle source
# File lib/ndr_dev_support/daemon/ci_server.rb, line 104
def svn_remote?
  GIT_SVN_REMOTE_BRANCH_NAME == remote_branch
end