#!/usr/bin/env ruby require 'yaml' require 'fileutils' require 'pp' CONFIG_DIR = '~/.sf' CONFIG_FILE = '~/.sf/credentials.yaml' GLOBAL_CONFIG_FILE = '~/.sf/salesforce.yaml' SANDBOX_CONFIG_FILE = '~/.sf/salesforce.sbox' FileUtils.mkdir File.expand_path CONFIG_DIR if not Dir.exists? File.expand_path CONFIG_DIR config = {} [CONFIG_FILE,GLOBAL_CONFIG_FILE].each do |file| file = File.expand_path file if File.exists? file config_content = YAML::load(File.open(file).read) config.merge! config_content if config_content else FileUtils.touch file end end begin sandbox = File.open(File.expand_path(SANDBOX_CONFIG_FILE)).read rescue sandbox = nil end require 'salesforcedeploytool' program :version, SalesforceDeployTool::VERSION program :description, 'A cli tool to help manage and deploy salesforce sandboxes with git' command :init do |c| c.syntax = 'sf init [options]' c.summary = 'Initialize salesforce sandbox from git' c.description = "Clone the #{config[:git_repo]} to #{config[:git_dir]}" c.example 'usage', 'sf init' c.option "--sandbox NAME", "-s NAME", "use 'prod' to deploy production or sandbox name" c.action do |args, options| # Parameter validation: options.sandbox = options.s if options.s if options.sandbox.nil? and sandbox.nil? puts "error: please specify sandbox using --sandbox or sf sandbox" exit 1 end config[:sandbox] = options.sandbox || sandbox # Initialize sfdt = SalesforceDeployTool::App.new config # Clone sfdt.clone end end command :pull do |c| c.syntax = 'sf pull' c.summary = 'Pull code from the sandbox' c.description = "Pull code from sandbox and update #{config[:git_dir]}" c.example 'usage:', 'sf pull' c.option "--append", "Pull code appending it to the local repository" c.option "--debug", "Verbose output" c.option "--sandbox NAME", "-s NAME", "use 'prod' to deploy production or sandbox name" c.action do |args, options| # Parameter validation: if options.sandbox.nil? and sandbox.nil? puts "error: please specify the sandbox to pull from using --sandbox" exit 1 end config[:sandbox] = options.sandbox || sandbox config[:debug] = options.debug.nil? ? false : true # Initialize sfdt = SalesforceDeployTool::App.new config # Clean all files from repo sfdt.clean_git_dir unless options.append # Pull the changes sfdt.pull "INFO: Pulling changes from #{config[:sandbox]} " end end command :push do |c| c.syntax = 'sf push [options]' c.summary = 'Push code into a sandbox' c.description = '' c.example 'description', "Push the code that is located into #{config[:git_dir]} into the active sandbox" c.option "--sandbox NAME", "-s NAME", "use 'prod' to deploy production or sandbox name" c.option "--debug", "Verbose output" c.option "--test", "-T", "Deploy and test" c.option "--exclude LIST", "-x LIST", "a CSV list of metadata to exclude when creating destructiveChange.xml" c.option "--append", "Disable destructive change and do an append deploy" c.action do |args, options| # short flag for test, so that not conflicts with trace options.test = true if options.T options.exclude = options.x if options.x options.sandbox = options.s if options.s # Parameter validation: if options.sandbox.nil? and sandbox.nil? puts "error: please specify the sandbox to pull from using --sandbox" exit 1 end config[:sandbox] = options.sandbox || sandbox config[:debug] = options.debug.nil? ? false : true config[:test] = options.test.nil? ? false : true # Initialize sfdt = SalesforceDeployTool::App.new config if ! options.append # Pull changes from sandbox to temporary directory: config_tmp = config.clone config_tmp[:git_dir] = config_tmp[:tmp_dir] FileUtils.rm_rf config_tmp[:git_dir] if File.exists? config_tmp[:git_dir] sfdt_tmp = SalesforceDeployTool::App.new config_tmp sfdt_tmp.clone sfdt_tmp.clean_git_dir sfdt_tmp.pull "INFO: Pulling changes from #{config[:sandbox]} to temporary directory #{config[:tmp_dir]} to generate destructiveChanges.xml " # Create destructiveChanges.xml puts "INFO: Creating destructive changes xml" dc_gen = Dcgen::App.new dc_gen.master = File.join(config[:git_dir],'src') dc_gen.destination = File.join(config[:tmp_dir],'src') dc_gen.output = File.join(config[:git_dir],'src','destructiveChanges.xml') dc_gen.exclude = options.exclude.split(',') unless options.exclude.nil? # Capture stdout when running generate_destructive_Changes, TODO: fix dcgen stringio = StringIO.new stdout_tmp = $stdout $stdout = stringio unless options.debug dc_gen.generate_destructive_changes $stdout = stdout_tmp end # Finally push: sfdt.push end end command :sandbox do |c| c.syntax = 'sf sandbox SANDBOX_NAME' c.summary = 'Set sandbox to work on, this can be overriden by --sandbox ' c.description = 'Set the sandbox to work with pull and push. If no parameter defined, it will print the current sandbox selected.' c.action do |args, options| if args.size > 1 puts "error: Wrong number of arguments" end if args.size == 0 if ! sandbox.nil? puts "sandbox: " + sandbox exit 0 else puts "WARN: Sandbox has not been set yet" exit 1 end end File.open(File.expand_path(SANDBOX_CONFIG_FILE),'w').write args.first end end command :config do |c| c.syntax = 'sf config' c.summary = 'Go through the configuration wizard to config your environment' c.action do |args, options| if args.size != 0 puts "error: Wrong number of arguments" end config_new = {} config_new[:username] = ask "Please enter your SalesForce production login user name" do |q| q.validate = /^\S+@\S+$/ end.to_s config_new[:password] = ask "Please enter your Salesforce production password" do |q| q.echo = "x" end.to_s git_name = ask "Please enter your Full name to be used as commit owner on GIT" do |q| q.validate = /^[a-zA-Z\s]+$/ end git_email = ask "Please enter your email to be used as commit email on GIT" do |q| q.validate = /^\S+@\S+$/ end %x[git config --global user.email "#{git_email}"] %x[git config --global user.name "#{git_name}"] config[:username] = config_new[:username] config[:password] = config_new[:password] File.open(File.expand_path(CONFIG_FILE),'w').write config_new.to_yaml end end default_command :help