class PuppetfileUpdater::RakeTask

Public: A Rake task that can be loaded and used with everything you need.

Examples

require 'librarian-sync-puppet'
PuppetfileUpdater::RakeTask.new

Attributes

debug[RW]
gh_login[RW]
gh_password[RW]
gh_token[RW]
major[RW]
module[RW]
skip_git[RW]
user[RW]

Public Class Methods

new(*args, &task_block) click to toggle source

Public: Initialise a new PuppetfileUpdater::RakeTask.

Example

PuppetfileUpdater::RakeTask.new
# File lib/puppetfile-updater/task.rb, line 28
def initialize(*args, &task_block)
  @name = args.shift || :lint

  define(args, &task_block)
end

Public Instance Methods

define(args, &task_block) click to toggle source
# File lib/puppetfile-updater/task.rb, line 34
def define(args, &task_block)
  desc 'Update module references in the Puppetfile'

  task_block.call(*[self, args].slice(0, task_block.arity)) if task_block

  # clear any (auto-)pre-existing task
  Rake::Task[@name].clear if Rake::Task.task_defined?(@name)

  task @name do
    require 'augeas'
    require 'octokit'
    require 'puppet_forge'

    @user ||= '.*'

    gh_opts = {}

    unless @gh_user.nil?
      gh_opts = {
        :login    => @gh_login,
        :password => @gh_password,
      }
    end

    unless @gh_token.nil?
      gh_opts = {
        :access_token => @gh_token,
      }
    end

    github = Octokit::Client.new gh_opts

    libdir = File.dirname(__FILE__)
    lens_dir = File.expand_path(File.join(libdir, '..', '..', 'augeas', 'lenses'))
    Augeas.open(Dir.pwd, lens_dir, Augeas::NO_MODL_AUTOLOAD) do |aug|
      aug.transform(
        :incl => '/Puppetfile',
        :excl => [],
        :lens => 'Puppetfile.lns',
        :name => 'Puppetfile',
      )
      aug.load!

      error_path = '/augeas/files/Puppetfile/error'
      unless aug.match(error_path).size == 0
        msg = "Failed to parse Puppetfile at line #{aug.get(error_path+'/line')}, "
        msg << "character #{aug.get(error_path+'/char')}: "
        msg << aug.get(error_path+'/message')
        abort msg
      end

      unless @skip_git
        # Update from GitHub
        aug.match("/files/Puppetfile/*[git=~regexp('.*/#{@user}[/-].*')]").each do |mpath|
          m = aug.get(mpath)
          puts "D: Considering #{m} for git update" if @debug
          next if !@module.nil? && @module != m.gsub(%r{.*[-/]}, '')
          puts "D: #{m} selected by filters" if @debug

          warn "W: #{m} is a fork!" unless m =~ /#{@user}/

          git_url = aug.get("#{mpath}/git")
          repo = Octokit::Repository.from_url(git_url.gsub(/\.git$/, ''))
          commits = github.commits(repo)
          ref = commits[0].sha[0...7]
          puts "D: New ref for #{m} is #{ref}" if @debug
          aug.set("#{mpath}/ref", ref)
        end
      end

      # Update from Forge
      PuppetForge.user_agent = 'Puppetfile-Updater/0.1.0'
      aug.match("/files/Puppetfile/*[label()!='#comment' and .=~regexp('#{@user}[/-].*') and @version]").each do |mpath|
        m = aug.get(mpath).gsub('/', '-')
        puts "D: Considering #{m} for forge update" if @debug
        next if !@module.nil? && @module != m.gsub(%r{.*[-/]}, '')
        puts "D: #{m} selected by filters" if @debug
        v = aug.get("#{mpath}/@version")
        forge_m = PuppetForge::Module.find(m)
        release = forge_m.releases.select { |r| r.deleted_at.nil? }[0]
        new_v = release.version
        puts "D: New version for #{m} is #{new_v}" if @debug

        warn "W: #{m} looks abandoned (version = #{new_v})" if new_v =~ /^99/
        if new_v.split('.')[0] != v.split('.')[0]
          if @major
            warn "W: #{m} has incompatible changes between #{v} and #{new_v}"
            aug.set("#{mpath}/@version", new_v)
          else
            warn "W: Not upgrading #{m} from #{v} to new major version #{new_v}"
          end
        else
          warn "W: #{m} got new features between #{v} and #{new_v}" if new_v.split('.')[1] != v.split('.')[1]
          aug.set("#{mpath}/@version", new_v)
        end
      end

      aug.save!
    end
  end
end