diff options
Diffstat (limited to 'git')
| -rwxr-xr-x | git/parent.py | 96 | ||||
| -rwxr-xr-x | git/parent.rb | 45 | ||||
| -rwxr-xr-x | git/yaml_validation.py | 68 | ||||
| -rwxr-xr-x | git/yaml_validation.rb | 72 | 
4 files changed, 164 insertions, 117 deletions
diff --git a/git/parent.py b/git/parent.py new file mode 100755 index 000000000..154a02350 --- /dev/null +++ b/git/parent.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python +''' +  Script to determine if this commit has also +  been merged through the stage branch +''' +# +#  Usage: +#    parent_check.py <branch> <commit_id> +# +# +import sys +import subprocess + +def run_cli_cmd(cmd, in_stdout=None, in_stderr=None): +    '''Run a command and return its output''' +    if not in_stderr: +        proc = subprocess.Popen(cmd, bufsize=-1, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=False) +    else: +        proc = subprocess.check_output(cmd, bufsize=-1, stdout=in_stdout, stderr=in_stderr, shell=False) +    stdout, stderr = proc.communicate() +    if proc.returncode != 0: +        return {"rc": proc.returncode, "error": stderr} +    else: +        return {"rc": proc.returncode, "result": stdout} + +def main(): +    '''Check to ensure that the commit that is currently +       being submitted is also in the stage branch. + +       if it is, succeed +       else, fail +    ''' +    branch = 'prod' + +    if sys.argv[1] != branch: +        sys.exit(0) + +    # git co stg +    results = run_cli_cmd(['/usr/bin/git', 'checkout', 'stg']) + +    # git pull latest +    results = run_cli_cmd(['/usr/bin/git', 'pull']) + +    # setup on the <prod> branch in git +    results = run_cli_cmd(['/usr/bin/git', 'checkout', 'prod']) + +    results = run_cli_cmd(['/usr/bin/git', 'pull']) +    # merge the passed in commit into my current <branch> + +    commit_id = sys.argv[2] +    results = run_cli_cmd(['/usr/bin/git', 'merge', commit_id]) + +    # get the differences from stg and <branch> +    results = run_cli_cmd(['/usr/bin/git', 'rev-list', '--left-right', 'stg...prod']) + +    # exit here with error code if the result coming back is an error +    if results['rc'] != 0: +        print results['error'] +        sys.exit(results['rc']) + +    count = 0 +    # Each 'result' is a commit +    # Walk through each commit and see if it is in stg +    for commit in results['result'].split('\n'): + +        # continue if it is already in stg +        if not commit or commit.startswith('<'): +            continue + +        # remove the first char '>' +        commit = commit[1:] + +        # check if any remote branches contain $commit +        results = run_cli_cmd(['/usr/bin/git', 'branch', '-q', '-r', '--contains', commit], in_stderr=None) + +        # if this comes back empty, nothing contains it, we can skip it as +        # we have probably created the merge commit here locally +        if results['rc'] == 0 and len(results['result']) == 0: +            continue + +        # The results generally contain origin/pr/246/merge and origin/pr/246/head +        # this is the pull request which would contain the commit in question. +        # +        # If the results do not contain origin/stg then stage does not contain +        # the commit in question.  Therefore we need to alert! +        if 'origin/stg' not in results['result']: +            print "\nFAILED: (These commits are not in stage.)\n" +            print "\t%s" % commit +            count += 1 + +    # Exit with count of commits in #{branch} but not stg +    sys.exit(count) + +if __name__ == '__main__': +    main() + diff --git a/git/parent.rb b/git/parent.rb deleted file mode 100755 index 2acb127c4..000000000 --- a/git/parent.rb +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env ruby -# -# -# - -if __FILE__ == $0 -  # If we aren't on master we don't need to parent check -  branch = 'prod' -  exit(0) if ARGV[0] !~ /#{branch}/ -  commit_id = ARGV[1] -  %x[/usr/bin/git checkout #{branch}] -  %x[/usr/bin/git merge #{commit_id}] - -  count = 0 -  #lines = %x[/usr/bin/git rev-list --left-right stg...master].split("\n") -  lines = %x[/usr/bin/git rev-list --left-right remotes/origin/stg...#{branch}].split("\n") -  lines.each do |commit| -    # next if they are in stage -    next if commit =~ /^</ -    # remove the first char '>' -    commit = commit[1..-1] -    # check if any remote branches contain $commit -    results = %x[/usr/bin/git branch -q -r --contains #{commit} 2>/dev/null ] -    # if this comes back empty, nothing contains it, we can skip it as -    # we have probably created the merge commit here locally -    next if results.empty? - -    # The results generally contain origin/pr/246/merge and origin/pr/246/head -    # this is the pull request which would contain the commit in question. -    # -    # If the results do not contain origin/stg then stage does not contain -    # the commit in question.  Therefore we need to alert! -    unless results =~ /origin\/stg/ -      puts "\nFAILED: (These commits are not in stage.)\n" -      puts "\t#{commit}" -      count += 1 -    end -  end - -  # Exit with count of commits in #{branch} but not stg -  exit(count) -end - -__END__ - diff --git a/git/yaml_validation.py b/git/yaml_validation.py new file mode 100755 index 000000000..2b5c8ed49 --- /dev/null +++ b/git/yaml_validation.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# +#  python yaml validator for a git commit +# +''' +python yaml validator for a git commit +''' +import shutil +import sys +import os +import tempfile +import subprocess +import yaml + +def get_changes(oldrev, newrev, tempdir): +    '''Get a list of git changes from oldrev to newrev''' +    proc = subprocess.Popen(['/usr/bin/git', 'diff', '--name-only', oldrev, +                             newrev, '--diff-filter=ACM'], stdout=subprocess.PIPE) +    stdout, _ = proc.communicate() +    files = stdout.split('\n') + +    # No file changes +    if not files: +        return [] + +    cmd = '/usr/bin/git archive %s %s | /bin/tar x -C %s' % (newrev, " ".join(files), tempdir) +    proc = subprocess.Popen(cmd, shell=True) +    _, _ = proc.communicate() + +    rfiles = [] +    for dirpath, _, fnames in os.walk(tempdir): +        for fname in fnames: +            rfiles.append(os.path.join(dirpath, fname)) + +    return rfiles + +def main(): +    ''' +    Perform yaml validation +    ''' +    results = [] +    try: +        tmpdir = tempfile.mkdtemp(prefix='jenkins-git-') +        old, new, _ = sys.argv[1:] + +        for file_mod in get_changes(old, new, tmpdir): + +            print "+++++++ Received: %s" % file_mod + +            if not file_mod.endswith('.yml') and not file_mod.endswith('.yaml') and not os.path.islink(file_mod): +                continue + +            try: +                yaml.load(open(file_mod)) +                results.append(True) + +            except yaml.scanner.ScannerError as yerr: +                print yerr +                results.append(False) +    finally: +        shutil.rmtree(tmpdir) + +    if not all(results): +        sys.exit(1) + +if __name__ == "__main__": +    main() + diff --git a/git/yaml_validation.rb b/git/yaml_validation.rb deleted file mode 100755 index f5ded7a78..000000000 --- a/git/yaml_validation.rb +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env ruby -# -# -# -require 'yaml' -require 'tmpdir' - -class YamlValidate -  def self.yaml_file?(filename) -    return filename.end_with?('.yaml') || filename.end_with?('.yml') -  end - -  def self.short_yaml_ext?(filename) -    return filename.end_with?(".yml") -  end - -  def self.valid_yaml?(filename) -    YAML::load_file(filename) - -    return true -  end -end - -class GitCommit -  attr_accessor :oldrev, :newrev, :refname, :tmp -  def initialize(oldrev, newrev, refname) -    @oldrev = oldrev -    @newrev = newrev -    @refname = refname -    @tmp = Dir.mktmpdir(@newrev) -  end - -  def get_file_changes() -    files = %x[/usr/bin/git diff --name-only #{@oldrev} #{@newrev} --diff-filter=ACM].split("\n") - -    # if files is empty we will get a full checkout.  This happens on -    # a git rm file.  If there are no changes then we need to skip the archive -    return [] if files.empty? - -    # We only want to take the files that changed.  Archive will do that when passed -    # the filenames.  It will export these to a tmp dir -    system("/usr/bin/git archive #{@newrev} #{files.join(" ")} | tar x -C #{@tmp}") -    return Dir.glob("#{@tmp}/**/*").delete_if { |file| File.directory?(file) } -  end -end - -if __FILE__ == $0 -  while data = STDIN.gets -    oldrev, newrev, refname = data.split -    gc = GitCommit.new(oldrev, newrev, refname) - -    results = [] -    gc.get_file_changes().each do |file| -      begin -        puts "++++++ Received:  #{file}" - -        #raise "Yaml file extensions must be .yaml not .yml" if YamlValidate.short_yaml_ext? file - -        # skip readme, other files, etc -        next unless YamlValidate.yaml_file?(file) - -        results << YamlValidate.valid_yaml?(file) -      rescue Exception => ex -        puts "\n#{ex.message}\n\n" -        results << false -      end -    end - -    #puts "RESULTS\n#{results.inspect}\n" -    exit 1 if results.include?(false) -  end -end  | 
