一千萬個為什麽

搜索

將Python腳本集成到Bash腳本中的問題Git預接收鉤子



我們在bash shell腳本中有一個預接收鉤子腳本,它以預定義的格式強制提交具有正確票號的消息。我們還有一個單獨的python腳本,可以在預接收鉤子bash腳本中調用,以調用PMD靜態分析開發人員推送到目標遠程分支的分支中的源代碼。

在此之前,我們一直使用pre-receive bash腳本來驗證我們的開發過程與我們的Gitlab服務器問題票據有關。

我最近試圖在bash腳本中調用python腳本,以便在調用PMD暴露不符合標準的源代碼之前完成我們的售票和裏程碑驗證。這沒有按照這個順序工作,所以我決定調用python腳本在ticket驗證之前運行PMD。這也導致只有python腳本獨自運行而不調用bash腳本代碼的其余部分。

我會感謝任何幫助。請先找到預先接收的bash腳本的源代碼,當我嘗試調用python/PMD時。請指出我如何在驗票後最後打電話給python。

#!/bin/bash
#
# pre-receive hook for Commit Check
#
COMPANY_EMAIL="mycorp.org"

readonly PROGNAME=$(basename $0)
readonly PROGDIR=$(readlink -m $(dirname $0))
IS_MERGE=0

check_single_commit()
{
  COMMIT_CHECK_STATUS=1
    echo "Repo >> $REPOSITORY_BASENAME"

    if [[ "$COMMIT_MESSAGE" == "Merge branch"* ]] || [[ "$COMMIT_MESSAGE" == "WIP MI"* ]]; then
      COMMIT_CHECK_STATUS=0
      IS_MERGE=1
    else
    workFlowResult=`java -jar -Dspring.config.location=/home/gitlab/gitlab_custom_hooks/application.properties /home/gitlab/gitlab_custom_hooks/gitlab-tool.jar -prercv "$COMMIT_AUTHOR" "$COMMIT_MESSAGE" "$REPOSITORY_BASENAME"`
    echo "COMMIT_AUTHOR=$COMMIT_AUTHOR, COMMIT_MESSAGE=$COMMIT_MESSAGE, REPOSITORY_BASE=$REPOSITORY_BASENAME"

      echo " >>>>>>>>>>>>>>>>> $workFlowResult >>>>>>>>>>>>>>>>>" >&2
    if [[ "$workFlowResult" == *"PRE_RECEIVE_OK"* ]]; then
      echo " >>>>>>>>>>>>>>>>> $workFlowResult >>>>>>>>>>>>>>>>>" >&2
      COMMIT_CHECK_STATUS=0
    fi

    fi
}

check_all_commits()
{
  REVISIONS=$(git rev-list $OLD_REVISION..$NEW_REVISION)
  IFS='\n' read -ra LIST_OF_REVISIONS <<< "$REVISIONS"
if [ $(git rev-parse --is-bare-repository) = true ]
then
    REPOSITORY_BASENAME=$(basename "$PWD")
else
    REPOSITORY_BASENAME=$(basename $(readlink -nf "$PWD"/..))
fi
    echo REPOSITORY_BASENAME is $REPOSITORY_BASENAME
    REPOSITORY_BASENAME=$(basename "$PWD")
    REPOSITORY_BASENAME=${REPOSITORY_BASENAME%.git}

  for rid in "${!LIST_OF_REVISIONS[@]}"; do
    REVISION=${LIST_OF_REVISIONS[rid]}
    COMMIT_MESSAGE=$(git cat-file commit $REVISION | sed '1,/^$/d')
    COMMIT_AUTHOR=$(git cat-file commit $REVISION | grep committer | sed 's/^.* \([^@ ]\[email protected][^ ]\+\) \?.*$/\1/' | sed 's/<//' | sed 's/>//' | sed 's/@$COMPANY_EMAIL//')
    check_single_commit

    if [ "$COMMIT_CHECK_STATUS" != "0" ]; then
      echo "Commit validation failed for commit $REVISION" >&2
      exit 1
    fi

  done
}



echo "Checking the coding style, coding standards and look out for potential issues"

if python /home/gitlab/gitlab_custom_hooks/pmd-policy.py; then
   echo "PMD_CHECK_OK"
   PMD_CHECK_STATUS=0

  # Get custom commit message format
    while read OLD_REVISION NEW_REVISION REFNAME ; do
        check_all_commits
    done



    exit 0

else

  echo "PMD_CHECK_FAILED: Review your Code and fix the issues"
  exit 1

fi

以下是調用PMD最後一次提交給Gitlab服務器分支的python腳本的代碼。

#!/usr/bin/env python

import subprocess
import sys
import tempfile
import shutil
import os
import errno


pmd = '/home/gitlab/gitlab_custom_hooks/pmd-bin-5.5.4/bin/run.sh'

# implementing check_output for python < 2.7
if not hasattr(subprocess, 'check_output'):
    def check_output(*popenargs, **kwargs):
        if 'stdout' in kwargs:
            raise ValueError('stdout argument not allowed, it will be overridden.')
        process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
        output, unused_err = process.communicate()
        retcode = process.poll()
        if retcode:
            cmd = kwargs.get("args")
            if cmd is None:
                cmd = popenargs[0]
            er = subprocess.CalledProcessError(retcode, cmd)
            er.output = output
            raise er
        return output
    subprocess.check_output = check_output


# helper for calling executables
def call(*args, **kwargs):
    return subprocess.check_output(*args, **kwargs).strip()


# helper for calling git
def call_git(cmd, *args, **kwargs):
    return call(['git'] + cmd, *args, **kwargs)


# get all new commits from stdin
def get_commits():
    commits = {}
    for line in sys.stdin:
        old, new, ref = line.strip().split(' ')
        if old == '0000000000000000000000000000000000000000':
            old = '4b825dc642cb6eb9a060e54bf8d69288fbee4904'

        if ref not in commits:
            commits[ref] = []
        commits[ref].append({
            'old': old,
            'new': new,
            'files': get_changed_files(old, new)
            })

    return commits


# get a list of changed files between to commits
def get_changed_files(old, new):
    return call_git(['diff', '--name-only', old, new]).split('\n')


# get filemode, object type (blob,tree,commit), hash for the given file at the
# given commit
def get_change_type(commit, filename):
    return call_git(['ls-tree', commit, filename]).split('\t')[0].split(' ')


commits = get_commits()

# use the latest file commit only
print "Cleaning up file list..."

files = {}
count = 0
for ref, data in commits.iteritems():
    files[ref] = {}
    for commit in data:
        for filename in commit['files']:
            if not filename.lower().endswith('.java'): continue
            files[ref][filename] = get_change_type(commit['new'], filename)
    count += len(files[ref])

print "%d Files to check in %d branches" % (count, len(files))

# create temporary dir and save a copy of the new files
tempdir = tempfile.mkdtemp('git_hook')
for ref, files in files.iteritems():
    for filename, data in files.iteritems():
        dname = os.path.dirname(filename)
        bname = os.path.basename(filename)
        try:
            os.makedirs(os.path.join(tempdir, dname))
        except OSError, exc:
            if exc.errno == errno.EEXIST:  # directory exists already
                pass
            else:
                raise

        with open(os.path.join(tempdir, dname, bname), 'w') as fp:
            fp.write(call_git(['cat-file', data[1], data[2]]))

try:
    # call checkstyle and/or pmd and print output
    print call([pmd, 'pmd', '-d', tempdir, '-f', 'text', '-R', 'rulesets/java/basic.xml,rulesets/java/unusedcode.xml,rulesets/java/imports.xml,rulesets/java/strings.xml,rulesets/java/braces.xml,rulesets/java/clone.xml,rulesets/java/design.xml,rulesets/java/clone.xml,rulesets/java/finalizers.xml,rulesets/java/junit.xml,rulesets/java/migrating.xml,rulesets/java/optimizations.xml,rulesets/java/strictexception.xml,rulesets/java/sunsecure.xml,rulesets/java/typeresolution.xml'])
    print "SUCCESS"
    sys.exit(0)
except subprocess.CalledProcessError, ex:
    print ex.output  # print checkstyle and/or pmd messages
    exit(1)
finally:
    # remove temporary directory
    shutil.rmtree(tempdir)

轉載註明原文: 將Python腳本集成到Bash腳本中的問題Git預接收鉤子

一共有 0 個回答: