Created
July 19, 2018 04:28
-
-
Save sj26/a251f1b3ec2454b07cc6ce8e79fca558 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def link_to(url, content = nil) | |
if ENV["BUILDKITE"] | |
"\e]1339;url=#{url.gsub(";", "%3b")}#{";content=#{content.gsub(";", "%3b")}" if content}\a" | |
else | |
url | |
end | |
end | |
def system!(*args) | |
system(*args) or fail("Command exited with status #{$?.exitstatus}: #{args.join(" ")}") | |
end | |
def capture!(*args) | |
IO.popen(args, &:read).tap do | |
$?.success? or fail("Command exited with status #{$?.exitstatus}: #{args.join(" ")}") | |
end | |
end | |
def meta_data_get(name) | |
capture!("buildkite-agent", "meta-data", "get", name.to_s).chomp | |
end | |
def meta_data_set(name, value) | |
system!("buildkite-agent", "meta-data", "set", name.to_s, value.to_s) | |
end | |
require "buildkit" | |
token = ENV.fetch("BUILDKITE_TOKEN") | |
$buildkit = Buildkit.new(token: token) | |
templates = [] | |
if ENV["PACKER"] && %w(0 n no f false).include?(ENV["PACKER"].strip.downcase) | |
puts "--- :fast_forward: You've asked me not to build anything" | |
elsif ENV["PACKER"] && %w(1 y yes t true).include?(ENV["PACKER"].strip.downcase) | |
puts "--- :allthethings: You've asked me to build everything" | |
templates = Dir["packer/*.json"].map { |path| File.basename(path, ".json") } | |
elsif ENV["PACKER"] && !ENV["PACKER"].strip.empty? | |
puts "--- :bow: You've asked me to build #{ENV["PACKER"]}" | |
templates = ENV["PACKER"].split(",").map(&:strip) | |
else | |
puts "+++ :thinking_face: Seeing if we need to build new images" | |
organization = ENV.fetch("BUILDKITE_ORGANIZATION_SLUG") | |
pipeline = ENV.fetch("BUILDKITE_PIPELINE_SLUG") | |
branch = ENV.fetch("BUILDKITE_BRANCH") | |
commit = ENV.fetch("BUILDKITE_COMMIT") | |
Dir["packer/*.json"].each do |path| | |
template = File.basename(path, ".json") | |
previous_build = nil | |
# If this is not the master branch then it's probably a pull request | |
# to look at the history of this branch for a packer build and diff | |
# from the previously built commit | |
if branch != "master" | |
previous_build = $buildkit.pipeline_builds(organization, pipeline, branch: branch, "meta_data[packer:build:#{template}]" => "true", page: 1, per_page: 1).first | |
end | |
# If this is master and we're running a pull request merge commit and | |
# the merged branch has a built packer image and nothing in packer | |
# has changed on master since this branch started then we can use the | |
# already-built image. | |
# | |
# Useful when the pull request image has already been tested and | |
# we're just merging to promote that image into production. | |
if !previous_build and | |
branch == "master" and | |
%r{Merge pull request #(?:\d+) from (?:[^/]+)/(?<previous_branch>.+)} =~ capture!("git", "show", commit, "--format=format:%s").chomp and | |
system("git", "diff", "--quiet", "#{capture!("git", "merge-base", "HEAD^1", "HEAD^2").chomp}...#{commit}^", "packer") | |
previous_build = $buildkit.pipeline_builds(organization, pipeline, branch: previous_branch, "meta_data[packer:build:#{template}]" => template, page: 1, per_page: 1).first | |
end | |
# Otherwise maybe there's a recent master build which we can use as a base for comparison | |
if !previous_build | |
previous_build = $buildkit.pipeline_builds(organization, pipeline, branch: "master", "meta_data[packer:build:#{template}]" => "true", page: 1, per_page: 1).first | |
end | |
# If we found a previous build then see if there have been any changes | |
if previous_build | |
# Make sure we have the commit we want to diff against | |
unless system "git", "cat-file", "-e", "#{previous_build.commit}^{commit}" | |
system! "git", "fetch", "origin", previous_build.commit | |
end | |
# Has this template been changed since then? | |
# | |
# XXX: This only considers the template file, not the scripts or | |
# any files for copying like services, etc. You must bump the | |
# template content to trigger an automatic packer build. | |
# | |
if not system("git", "diff", "--quiet", "--diff-filter", "ACMR", "#{previous_build.commit}...#{commit}", "--", "packer/#{template}.json") | |
puts "#{template} has been built on #{previous_build.branch} at #{previous_build.commit} in #{link_to(previous_build.web_url, "build #{previous_build.number}")} but packer template has changed, building." | |
templates << template | |
else | |
puts "#{template} has been built on #{previous_build.branch} at #{previous_build.commit} in #{link_to(previous_build.web_url, "build #{previous_build.number}")}." | |
end | |
else | |
puts "#{template} has never been built, building." | |
# We couldn't find a single build of this template! Definitely build it. | |
templates << template | |
end | |
end | |
end | |
templates.each do |template| | |
puts "+++ :thinking_face: Building #{template}" | |
system! "packer", "build", "packer/#{template}.json" | |
meta_data_set "packer:build:#{template}", "true" | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment