require"concourse/version"require"yaml"require"tempfile"classConcourseincludeRake::DSL# these numbers/names align with public docker image namesRUBIES={mri: %w[2.3 2.4 2.5 2.6],# docker repository: "ruby"jruby: %w[9.1 9.2],# docker repository: "jruby"rbx: %w[latest],# docker repository: "rubinius/docker"windows: %w[2.3 2.4 2.5 2.6]# windows-ruby-dev-tools-release}DEFAULT_DIRECTORY="concourse"attr_reader:project_name,:pipeline_filename,:pipeline_erb_filename,:directory,:private_var_filedefself.validate_fly_targettask,task_argsunlesstask_args[:fly_target]raise"ERROR: must specify a fly target, like `rake #{task.name}[targetname]`"endreturntask_args[:fly_target]enddefself.url_forfly_targetmatching_line=`fly targets`.split("\n").grep(/^#{fly_target}/).firstraise"invalid fly target #{fly_target}"unlessmatching_linematching_line.split(/ +/)[1]enddefself.default_execute_argstaskargs=[]task["config"]["inputs"].eachdo|input|args<<"--input=#{input["name"]}=."endargs.join(" ")enddefself.production_rubiesRUBIES[:mri].reject{|r|r=~/rc/}enddefself.rc_rubiesRUBIES[:mri].select{|r|r=~/rc/}enddefinitializeproject_name,args={}@project_name=project_name@directory=args[:directory]||DEFAULT_DIRECTORY@pipeline_filename=File.join(@directory,"#{project_name}.final.yml")@pipeline_erb_filename=File.join(@directory,"#{project_name}.yml")@private_var_file=File.join(@directory,"private.yml")enddeferbifydocument_string,*argsERB.new(document_string,nil,"%-").result(binding)enddefrake_initFileUtils.mkdir_pFile.join(directory,"tasks")FileUtils.touchpipeline_erb_filenameFile.open".gitignore","a"do|f|f.putsprivate_var_filef.putspipeline_filenameendenddefcreate_tasks!unlessDir.exist?directorymkdir_pdirectoryendunlessFile.exist?pipeline_erb_filenamewarn"WARNING: concourse template #{pipeline_erb_filename.inspect} does not exist, run `rake concourse:init`"endCLOBBER.includepipeline_filenameifdefined?(CLOBBER)namespace:concoursedo## project commands#desc"bootstrap a concourse config"task:initdorake_initend## pipeline commands#desc"generate and validate the pipeline file for #{project_name}"task"generate"do|t|File.openpipeline_filename,"w"do|f|f.writeerbify(File.read(pipeline_erb_filename))endsh"fly validate-pipeline -c #{pipeline_filename}"enddesc"upload the pipeline file for #{project_name}"task"set",[:fly_target]=>["generate"]do|t,args|fly_target=Concourse.validate_fly_targett,argsoptions=["-p '#{project_name}'","-c '#{pipeline_filename}'",]ifFile.exist?private_var_fileputs"using #{private_var_file} to resolve template vars"options<<"-l '#{private_var_file}'"endsh"fly -t #{fly_target} set-pipeline #{options.join(" ")}"end%w[expose hide pause unpause destroy].eachdo|command|desc"#{command} the #{project_name} pipeline"task"#{command}",[:fly_target]do|t,args|fly_target=Concourse.validate_fly_targett,argssh"fly -t #{fly_target}#{command}-pipeline -p #{project_name}"endenddesc"remove generate pipeline file"task"clean"do|t|rm_fpipeline_filenameend## task commands#desc"list all the available tasks from the #{project_name} pipeline"task"tasks"=>"generate"dotasks=[]each_taskdo|job,task|tasks<<"#{job["name"]}/#{task["task"]}"endputs"Available Concourse tasks for #{project_name} are:"tasks.sort.each{|task|puts" * #{task}"}enddesc"fly execute the specified task"task"task",[:fly_target,:job_task,:fly_execute_args]=>"generate"do|t,args|fly_target=Concourse.validate_fly_targett,argsjob_task=args[:job_task]unlessjob_taskraise"ERROR: must specify a task name, like `rake #{t.name}[target,taskname]`"endconcourse_task=find_taskjob_taskraise"ERROR: could not find task `#{job_task}`"unlessconcourse_taskfly_execute_args=args[:fly_execute_args]||Concourse.default_execute_args(concourse_task)putsconcourse_task.to_yamlTempfile.create("concourse-task")do|f|f.writeconcourse_task["config"].to_yamlf.closeBundler.with_clean_envdosh"fly -t #{fly_target} execute #{fly_execute_args} -c #{f.path}"endendend## builds commands#desc"abort all running builds for this pipeline"task"abort-builds",[:fly_target]do|t,args|fly_target=Concourse.validate_fly_targett,args`fly -t #{fly_target} builds`.split("\n").eachdo|line|pipeline_job,build_id,status=*line.split(/\s+/)[1,3]nextunlessstatus=="started"sh"fly -t #{fly_target} abort-build -j #{pipeline_job} -b #{build_id}"endendendenddefeach_jobpipeline=YAML.load_file(pipeline_filename)pipeline["jobs"].eachdo|job|yieldjobendenddefeach_taskeach_jobdo|job|job["plan"].eachdo|task|yieldjob,taskiftask["task"]endendenddeffind_taskjob_taskjob_name,task_name=*job_task.split("/")each_taskdo|job,task|returntaskiftask["task"]==task_name&&job["name"]==job_nameendnilendend