├── check_yaml_syntax ├── README.md ├── JENKINS.md ├── check_yaml.rb └── check_yaml_syntax.sh ├── check_puppet_syntax ├── README.md ├── check_puppet_syntax_helper.sh ├── check_puppet_erb_helper.sh ├── JENKINS.md ├── managed_script_check_puppet_syntax.sh └── check_puppet_syntax.sh ├── common ├── functions.sh └── git.sh ├── check_puppet_style ├── managed_script_check_style.sh └── check_puppet_style.sh ├── doc_puppet_generate └── doc_puppet_generate.sh ├── README.md ├── check_git_release ├── check_git_release_test.sh └── check_git_release.sh └── package_puppet_tree_fpm └── package_puppet_tree_fpm.sh /check_yaml_syntax/README.md: -------------------------------------------------------------------------------- 1 | This script is for checking hiera yaml files. It checks not only 2 | if the file is valid yaml, it must also contain a hash. Hiera only 3 | works with hashes so this is a pretty safe check. 4 | -------------------------------------------------------------------------------- /check_puppet_syntax/README.md: -------------------------------------------------------------------------------- 1 | # NOTES 2 | 3 | Currently we are not using --ignoreimport when running `puppet parser validate`. 4 | This results in some errors being printed twice. This will remain this way until 5 | https://projects.puppetlabs.com/issues/9670 is resolved. 6 | -------------------------------------------------------------------------------- /check_puppet_syntax/check_puppet_syntax_helper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | f="$1"; 4 | if [ ! -f "$f" ]; then 5 | echo "File does not exist: '$f'" 1>&2 6 | exit 1; 7 | fi 8 | 9 | if [ "${PUPPET_STOREDCONFIGS-0}" == "1" ]; then 10 | PUPPET_OPTS="${PUPPET_OPTS} --storeconfigs" 11 | fi; 12 | 13 | $PUPPET_BIN parser validate $PUPPET_OPTS --color false --render-as s $f 2>&1 | while read line; do 14 | echo "PUPPET_SYNTAX:$f: $line"; 15 | done; 16 | exit ${PIPESTATUS[0]} 17 | -------------------------------------------------------------------------------- /check_puppet_syntax/check_puppet_erb_helper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | f="$1"; 4 | if [ ! -f "$f" ]; then 5 | echo "File does not exist: '$f'" 1>&2 6 | exit 1; 7 | fi 8 | 9 | $ERB_BIN -P -x -S 0 -T '-' $f | $RUBY_BIN -c 2>&1 | while read line; do 10 | if echo "$line" | grep -q 'Syntax OK'; then 11 | echo "$f: $(tput setaf 2; tput bold)$line$( tput sgr0)"; 12 | else 13 | echo "$f: $(tput setaf 1; tput bold)$line$( tput sgr0)"; 14 | fi 15 | done; 16 | exit ${PIPESTATUS[1]} 17 | -------------------------------------------------------------------------------- /common/functions.sh: -------------------------------------------------------------------------------- 1 | #============================================================================== 2 | # ,---.,---.,-.-.,-.-.,---.,---. 3 | # | | || | || | || || | 4 | # `---'`---'` ' '` ' '`---'` ' 5 | ## 6 | 7 | err() { 8 | echo "$0: ERROR: $*" 1>&2 9 | } 10 | 11 | warn() { 12 | echo "$0: WARN: $*" 1>&2 13 | } 14 | 15 | info() { 16 | echo "$0: INFO: $*"; 17 | } 18 | 19 | debug() { 20 | if [ "${SCRIPTDEBUG}" ]; then 21 | echo "$0: DEBUG: $*" 1>&2; 22 | fi; 23 | } 24 | 25 | 26 | 27 | ## check_for_bash 28 | # Returns '0' if the script is running under bash 29 | # Returns '1' if it doesn't. 30 | function check_for_bash() { 31 | pid=$$; 32 | if [[ -f "/proc/${pid}/cmdline" ]]; then 33 | if [[ -z $( cat "/proc/${pid}/cmdline" | sed "s|$0||g" | grep "bash" ) ]]; then 34 | return 1; 35 | else 36 | return 0; 37 | fi; 38 | fi; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /check_yaml_syntax/JENKINS.md: -------------------------------------------------------------------------------- 1 | # Warnings Plugin 2 | 3 | You can use the following regex and groovy for the warnings plugin. Since 4 | We are adding a prefix to the output to parse it more effectivly in case you 5 | do syntax checks and other checks which produce similar output in one job. 6 | 7 | You can obviously choose the name for the parser and the trend graph. 8 | 9 | __Regular Expression:__ 10 | ``` 11 | ^YAML_SYNTAX:([^:]*):(ERROR):([0-9]+):(.*)$ 12 | ``` 13 | 14 | __Mapping Script:__ 15 | 16 | ```groovy 17 | import hudson.plugins.warnings.parser.Warning 18 | import hudson.plugins.analysis.util.model.Priority 19 | 20 | String fileName = matcher.group(1) 21 | String lineNumber = matcher.group(3) 22 | String category = matcher.group(2) 23 | String message = matcher.group(4) 24 | Priority prio = Priority.HIGH 25 | 26 | return new Warning(fileName, Integer.parseInt(lineNumber), "YAML Syntax", category, message, prio); 27 | ``` 28 | 29 | 30 | -------------------------------------------------------------------------------- /check_yaml_syntax/check_yaml.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'yaml' 3 | 4 | status=0 5 | 6 | def check_file(filename) 7 | status=0 8 | begin 9 | r = YAML.load_file(filename) 10 | rescue Errno::ENOENT => ex 11 | $stderr.print "YAML_SYNTAX:#{filename}:ERROR:0:File does not exist!\n" 12 | status=1 13 | rescue Psych::SyntaxError => ex 14 | $stderr.print "YAML_SYNTAX:#{filename}:ERROR:#{ex.line}:#{ex.problem}\n" 15 | status=1 16 | rescue Exception => ex 17 | $stderr.print "YAML_SYNTAX:#{filename}:ERROR:0:Unknown error: #{ex.message}\n" 18 | else 19 | ## Print OK? 20 | end 21 | unless status == 1 or r.is_a?(Hash) 22 | $stderr.print "YAML_SYNTAX:#{filename}:ERROR:0:YAML file does not contain a hash\n" 23 | status=1 24 | end 25 | status 26 | end 27 | 28 | ARGV.each do |file| 29 | if File.directory?(file) 30 | $stdout.print "YAML_SYNTAX:#{file}:INFO:Is a directory. Scanning for *.yaml\n" 31 | Dir.glob("#{file}/**/*.yaml").each do |f| 32 | s = check_file(f) 33 | status = s unless s == 0 34 | 35 | end 36 | else 37 | s = check_file(file) 38 | status = s unless s == 0 39 | end 40 | end 41 | 42 | exit status 43 | -------------------------------------------------------------------------------- /check_puppet_syntax/JENKINS.md: -------------------------------------------------------------------------------- 1 | # Warnings Plugin 2 | 3 | You can use the following regex and groovy for the warnings plugin. Since 4 | We are adding a prefix to the output to parse it more effectivly in case you 5 | do syntax checks and other checks which produce similar output in one job. 6 | 7 | You can obviously choose the name for the parser and the trend graph. 8 | 9 | __Regular Expression:__ 10 | ``` 11 | ^PUPPET_SYNTAX[^:]*:(.*):.*(warning|err|Error):\s*(.*)$ 12 | ``` 13 | 14 | __Mapping Script:__ 15 | 16 | ```groovy 17 | import hudson.plugins.warnings.parser.Warning 18 | import hudson.plugins.analysis.util.model.Priority 19 | 20 | String fileName = matcher.group(1) 21 | String lineNumber = "0" 22 | String category = matcher.group(2) 23 | String message = matcher.group(3) 24 | Priority prio = Priority.NORMAL 25 | 26 | if (message =~ /puppet help parser validate/ ) { 27 | return false 28 | } 29 | 30 | if (category == "err" || category == "Error") { 31 | prio = Priority.HIGH 32 | category = "error" 33 | } 34 | // Catch line numbers at the end of the file:100 35 | def m = message =~ /:(\d+)$/ 36 | if (m.size() >0 ) { lineNumber = m[0][1] } 37 | 38 | // Catch line numbers 'on line 100' or 'at line 100' 39 | m = message =~ /^.*(on|at) line (\d+).*$/ 40 | if (m.size() > 0) { lineNumber = m[0][2] } 41 | 42 | return new Warning(fileName, Integer.parseInt(lineNumber), "Puppet Syntax", category, message, prio); 43 | ``` 44 | 45 | 46 | -------------------------------------------------------------------------------- /check_puppet_syntax/managed_script_check_puppet_syntax.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Runs a syntax check on the modified files of a puppet tree only 4 | # Variables to be set: PUPPET_SYNTAX_THREADS, PUPPET_BIN, ERB_BIN, RUBY_BIN 5 | # 6 | # scripts_job_name: Name of the jenkins job which is used to pull this repo into your jenkins environment 7 | 8 | [ -n $GIT_PREVIOUS_COMMIT ] || GIT_PREVIOUS_COMMIT='HEAD^' 9 | 10 | [ "$EXTRA_PATH" ] && export PATH="$EXTRA_PATH:$PATH"; 11 | scripts_job_name="scripts/puppet" 12 | 13 | # Catch the modified .pp manifests, puts them in an array and use that array to peform the puppet-syntax checks 14 | declare -a files 15 | 16 | for FILE in $(git diff --name-only --diff-filter=ACMRTUXB ${GIT_PREVIOUS_COMMIT} | grep ".pp$"); 17 | do 18 | files=("${files[@]}" $FILE) 19 | done 20 | 21 | if [ ${#files[@]} -eq 0 ];then 22 | echo "No modified manifests to check" 23 | else 24 | for i in ${files[@]}; 25 | do 26 | echo "Syntax check on manifest $i:"; 27 | bash -e /var/lib/jenkins/$scripts_job_name/check_puppet_syntax/check_puppet_syntax.sh $i || manifests_failed=1 28 | done 29 | fi 30 | 31 | # Catch the modified modules, puts them in an array and use that array to peform the puppet-style checks 32 | declare -a modules 33 | 34 | for MODULE in $(git diff --name-only --diff-filter=ACMRTUXB ${GIT_PREVIOUS_COMMIT} | grep "^modules/"); 35 | do 36 | modules=("${modules[@]}" $MODULE) 37 | done 38 | 39 | if [ ${#modules[@]} -eq 0 ];then 40 | echo "No modified modules to check" 41 | else 42 | for i in ${modules[@]}; 43 | do 44 | echo "Syntax check on module $i:"; 45 | bash -e /var/lib/jenkins/$scripts_job_name/check_puppet_syntax/check_puppet_syntax.sh $i || module_failed=1 46 | done 47 | fi 48 | 49 | 50 | failed=0 51 | if [ "$manifests_failed" == "1" ]; then 52 | echo "Syntax check on manifests dir failed"; 53 | failed=1; 54 | fi 55 | if [ "$module_failed" == "1" ]; then 56 | echo "Syntax check on modules failed"; 57 | failed=1; 58 | fi; 59 | 60 | [ "$failed" == "0" ] || exit 1; 61 | -------------------------------------------------------------------------------- /check_puppet_style/managed_script_check_style.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Script wich catches the modified files from the latest commit in a git repository and 4 | # runs a puppet-lint check on them 5 | # 6 | # Variables to be set: 7 | # 8 | # PUPPET_SUBDIR 9 | # 10 | # PUPPET_LINT_THREADS, PUPPET_LINT_SKIP_TESTS, PUPPET_LINT_SKIP_EXAMPLES, 11 | # PUPPET_LINT_BIN, PUPPET_LINT_FAILS_WARNING, PUPPET_LINT_FAILS_ERROR 12 | 13 | GIT_PREVIOUS_COMMIT="${GIT_PREVIOUS_COMMIT-HEAD^}" 14 | 15 | [ "$EXTRA_PATH" ] && export PATH="$EXTRA_PATH:$PATH"; 16 | 17 | printenv | sort 18 | 19 | manifests_exclude="${1-autoloader_layout}" 20 | module_exclude="${2}" 21 | style_script="$(cd $(dirname "$0"); pwd)/../check_puppet_style/check_puppet_style.sh" 22 | 23 | # Catch the modified .pp manifests, puts them in an array and use that array to peform the puppet-style checks 24 | declare -a files 25 | 26 | for FILE in $(git diff --name-only --diff-filter=ACMRTUXB ${GIT_PREVIOUS_COMMIT} | grep ".pp$"); 27 | do 28 | files=("${files[@]}" $FILE) 29 | done 30 | 31 | if [ ${#files[@]} -eq 0 ];then 32 | echo "No modified manifests to check" 33 | else 34 | for i in ${files[@]}; 35 | do 36 | echo "Stylecheck on manifest $i:"; 37 | bash -e "${style_script}" -x "${manifests_exclude}" $i || manifests_failed=1 38 | done 39 | fi 40 | 41 | # Catch the modified modules, puts them in an array and use that array to peform the puppet-style checks 42 | declare -a modules 43 | 44 | for MODULE in $(git diff --name-only --diff-filter=ACMRTUXB ${GIT_PREVIOUS_COMMIT} | grep "^modules/"); 45 | do 46 | modules=("${modules[@]}" $MODULE) 47 | done 48 | 49 | if [ ${#modules[@]} -eq 0 ];then 50 | echo "No modified modules to check" 51 | else 52 | for i in ${modules[@]}; 53 | do 54 | echo "Stylecheck on module $i:"; 55 | bash -e "${style_script}" -x "${module_exclude}" $i || module_failed=1 56 | done 57 | fi 58 | 59 | failed=0 60 | if [ "$manifests_failed" == "1" ]; then 61 | echo "Style check on manifests dir failed"; 62 | failed=1; 63 | fi 64 | if [ "$module_failed" == "1" ]; then 65 | echo "Style check on modules failed"; 66 | failed=1; 67 | fi; 68 | 69 | [ "$failed" == "0" ] || exit 1; 70 | -------------------------------------------------------------------------------- /check_yaml_syntax/check_yaml_syntax.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #========================================================== 4 | # ,---- | o 5 | # |__. . .,---.,---.|--- .,---.,---.,---. 6 | # | | || || | || || |`---. 7 | # ` `---'` '`---'`---'``---'` '`---' 8 | # 9 | 10 | syserr() { 11 | echo "[$0] ERROR: $*" 1>&2 12 | exit 1; 13 | } 14 | 15 | test_bin() { 16 | local desc=$1; 17 | local bin=$2; 18 | which ${bin} >/dev/null 2>&1 || syserr "${desc} executable (${bin}) not found on path"; 19 | [ -x $( which $bin ) ] || syserr "${desc} executable (${bin}) does not exist or is not executable"; 20 | } 21 | 22 | _help() { 23 | cat < [...] 25 | Checks syntax of yaml files. 26 | 27 | OPTIONS: 28 | -t, --max-threads NUMBER The max number of simultaneous threads to use. 29 | You can also specify YAML_SYNTAX_THREADS as an env 30 | variable. Defaults to 5. 31 | -r, --ruby-bin Path to ruby executable. You can also specify 32 | RUBY_BIN as an environment variable. 33 | Defaults to 'ruby'. 34 | -h, --help Display this message and exit. 35 | 36 | The argument(s) should be a file or directories containing yaml files. 37 | Folders are checked recursively. 38 | 39 | EOHELP 40 | exit 0; 41 | } 42 | 43 | ## getopts parsing 44 | if `getopt -T >/dev/null 2>&1` ; [ $? = 4 ] ; then 45 | true; # Enhanced getopt. 46 | else 47 | syserr "You are using an old getopt version $(getopt -V)"; 48 | fi; 49 | 50 | 51 | TEMP=`getopt -o -t:r:h -l max-threads:,ruby-bin:,help -n "$0" -- "$@"`; 52 | 53 | if [[ $? != 0 ]]; then 54 | syserr "Error parsing arguments"; 55 | fi; 56 | 57 | while [ $# -gt 0 ]; do 58 | case "$1" in 59 | -t|--max-threads) YAML_SYNTAX_THREADS="$2"; shift;; 60 | -r|--ruby-bin) RUBY_BIN="$2"; shift;; 61 | -h|--help) _help;; 62 | -*) syserr "Command option '$1' not recognized";; 63 | --) shift; break;; 64 | *) break;; 65 | esac 66 | shift; 67 | done; 68 | 69 | YAML_SYNTAX_THREADS="${YAML_SYNTAX_THREADS-5}"; 70 | RUBY_BIN="${RUBY_BIN-ruby}"; 71 | 72 | ## No arguments 73 | if [ ${#*} == 0 ]; then 74 | _help 75 | fi; 76 | 77 | echo "${YAML_SYNTAX_THREADS}" | grep -q '^[0-9]\+$' || syserr "max threads should be a number"; 78 | 79 | test_bin 'ruby' "${RUBY_BIN}" 80 | 81 | _YAML_HELPER="$( cd $(dirname "$0"); pwd)/check_yaml.rb"; 82 | test_bin 'check_yaml' "${_YAML_HELPER}"; 83 | 84 | #========================================================== 85 | # | o | 86 | # | ,---.,---..,---.,---.| 87 | # | | || ||| ,---|| 88 | # `---'`---'`---|``---'`---^`---' 89 | # 90 | 91 | find $* -iname '*.yaml' | xargs --no-run-if-empty -t -n1 -P${YAML_SYNTAX_THREADS} -I file \ 92 | sh -c "$RUBY_BIN $_YAML_HELPER file" 2>&1 || yaml_error="1"; 93 | 94 | if [ "$yaml_error" == 1 ]; then 95 | echo "YAML Syntax error detected."; 96 | exit 1; 97 | fi; 98 | -------------------------------------------------------------------------------- /common/git.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #========================================================== 3 | # ,---- | o 4 | # |__. . .,---.,---.|--- .,---.,---.,---. 5 | # | | || || | || || |`---. 6 | # ` `---'` '`---'`---'``---'` '`---' 7 | 8 | ## System error, exits the script and outputs to stderr 9 | # USAGE: syserr 10 | syserr() { 11 | echo "[git_check] ERROR: $*" 1>&2 12 | exit 1; 13 | } 14 | 15 | ## Returns the real git dir (if any). If its a submodule, parse the .git file. 16 | # USAGE: get_git_dir 17 | get_git_dir() { 18 | local path=${1-.}; 19 | local git_path="${path}/.git"; 20 | local real_dir; 21 | 22 | # its a file. maybe from a submodule? 23 | if [ -f $git_path ]; then 24 | # check for gitdir: blah 25 | if `cat $git_path | grep -q 'gitdir\: .\+'`; then 26 | real_dir=`cat $git_path | grep -o 'gitdir\: .*' | sed -e 's@gitdir: @@'`; 27 | if [ -d $real_dir ]; then 28 | git_path=$real_dir; 29 | fi; 30 | else 31 | return 1; 32 | fi 33 | fi; 34 | [ -d $git_path ] || return 1; 35 | echo $git_path; 36 | } 37 | 38 | 39 | ## Returns the current commit hash of a git repo. 40 | # USAGE: get_current_commit [git_dir] 41 | get_current_commit() { 42 | local work_tree="${1-.}"; 43 | local git_dir="${2-`get_git_dir $work_tree`}" || return 1; 44 | git --git-dir=$git_dir --work-tree=$work_tree \ 45 | rev-parse HEAD 2>/dev/null|| return 1; 46 | } 47 | 48 | git_check_dirty() { 49 | local work_tree="${1-.}"; 50 | local git_dir="${2-`get_git_dir $work_tree`}" || return 1; 51 | [ -z "$( git --git-dir=$git_dir --work-tree=$work_tree status --porcelain )" ] || \ 52 | return 1; 53 | } 54 | 55 | ## Returns the tag of the commit of a certain git repository. 56 | ## This function will return 1 if no tag has been set or no repo is found. 57 | # USAGE: get_tag [commit] [git_dir] 58 | get_tag() { 59 | local work_tree="${1-.}"; 60 | local commit="${2-`get_current_commit $work_tree`}" || return 1; 61 | local git_dir="${3-`get_git_dir $work_tree`}" || return 1; 62 | git --git-dir=$git_dir --work-tree=$work_tree \ 63 | describe --tags --exact-match $commit 2>/dev/null || return 1; 64 | } 65 | 66 | get_branch() { 67 | local work_tree="${1-.}" 68 | local commit="${2-`get_current_commit $work_tree`}" || return 1; 69 | local git_dir="${3-`get_git_dir $work_tree`}" || return 1; 70 | git --git-dir=$git_dir --work-tree=$work_tree \ 71 | name-rev --name-only $commit 2>/dev/null || return 1; 72 | } 73 | 74 | get_all_branches() { 75 | local work_tree="${1-.}" 76 | local commit="${2-`get_current_commit $work_tree`}" || return 1; 77 | local git_dir="${3-`get_git_dir $work_tree`}" || return 1; 78 | git --git-dir=$git_dir --work-tree=$work_tree \ 79 | branch -a --contains $commit 2>/dev/null || return 1; 80 | } 81 | 82 | get_branch_best_match() { 83 | local work_tree="${1-.}" 84 | local commit="${2-`get_current_commit $work_tree`}" || return 1; 85 | local git_dir="${3-`get_git_dir $work_tree`}" || return 1; 86 | local _branches=`get_all_branches $work_tree $commit $git_dir` || return 1; 87 | if `echo "$_branches" | grep -q '^\*[ ]*[a-z]\+'`; then 88 | echo "$_branches" | grep -o '^\*.*$' | sed 's@^\*\s*@@' 89 | return 0; 90 | elif `echo "$_branches" | grep -q 'HEAD'`; then 91 | echo "$_branches" | grep 'HEAD' | sed 's@.*\/\([a-zA-Z0-9_-]\+\)$@\1@' 92 | return 0; 93 | else 94 | echo "$_branches" | grep -v '^*' | sed 's@.*\/\([a-zA-Z0-9_-]\+\)$@\1@' | uniq | head -n1 95 | return 0; 96 | fi; 97 | return 1; 98 | } 99 | # vim: set filetype=sh : 100 | -------------------------------------------------------------------------------- /doc_puppet_generate/doc_puppet_generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #========================================================== 4 | # ,---- | o 5 | # |__. . .,---.,---.|--- .,---.,---.,---. 6 | # | | || || | || || |`---. 7 | # ` `---'` '`---'`---'``---'` '`---' 8 | # 9 | 10 | syserr() { 11 | echo "$0: ERROR: $*" 1>&2 12 | exit 1; 13 | } 14 | 15 | _help() { 16 | cat < 18 | 19 | -o, --output-dir DIR Directory to put the files in. Defaults to 20 | doc/ in the current directory. 21 | -f, --force Force output even if the output directory 22 | already exists. 23 | -n, --no-postprocess Postprocessing will use some sed magic 24 | to fix paths and filenames in the docs 25 | so that documentation seems to be based 26 | on the /etc/puppet structure in stead of 27 | the working directory of your module. 28 | With this flag, you disable this behaviour. 29 | -w, --workspace PATH This is the part that gets stripped off 30 | during the postprocessing. It defaults 31 | to the current directory you are running 32 | this script from. You can also change this 33 | by setting the WORKSPACE environment variable. 34 | -s, --single Indicate that the workspace contains a single 35 | puppet module. If not, we will assume its a 36 | directory where each subfolder contains a puppet 37 | module. 38 | -h, --help Show this message and exit. 39 | 40 | EOHELP 41 | exit 0; 42 | } 43 | 44 | #========================================================== 45 | # | | 46 | # ,---.,---.|--- ,---.,---.|--- ,---. 47 | # | ||---'| | || || `---. 48 | # `---|`---'`---'`---'|---'`---'`---' 49 | # `---' | 50 | 51 | ## getopts parsing 52 | if `getopt -T >/dev/null 2>&1` ; [ $? = 4 ] ; then 53 | true; # Enhanced getopt. 54 | else 55 | syserr "You are using an old getopt version $(getopt -V)"; 56 | fi; 57 | 58 | 59 | TEMP=`getopt -o -o:nw:hfs \ 60 | -l output-dir:,no-postprocess,workspace:,help,force,single -n "$@" -- "$@"`; 61 | 62 | if [[ $? != 0 ]]; then 63 | syserr "Error parsing arguments"; 64 | fi; 65 | 66 | while [ $# -gt 0 ]; do 67 | case "$1" in 68 | -o|--output-dir) DOC_OUTPUT="$2"; shift;; 69 | -n|--no-postprocess) NO_POST=1;; 70 | -w|--workspace) WORKSPACE="$2"; shift;; 71 | -f|--force) FORCE=1;; 72 | -h|--help) _help;; 73 | -*) syserr "Command option '$1' not recognized";; 74 | --) shift; break;; 75 | *) break;; 76 | esac; 77 | shift; 78 | done; 79 | 80 | DOC_OUTPUT="${DOC_OUTPUT-./doc}" 81 | NO_POST="${NO_POST}"; 82 | WORKSPACE="${WORKSPACE-.}"; 83 | FORCE="${FORCE}" 84 | 85 | ## expand workspace 86 | WORKSPACE="`readlink -f ${WORKSPACE}`" 87 | 88 | echo "WORKSPACE: $WORKSPACE" 89 | exit 0; 90 | [[ -d $DOC_OUTPUT && ! "$FORCE" ]] && \ 91 | syserr "Output directory '$DOC_OUTPUT' already exists. use --force to force" 92 | [ -d $DOC_OUTPUT ] || mkdir -p $DOC_OUTPUT 93 | 94 | # | o | 95 | # | ,---.,---..,---.,---.| 96 | # | | || ||| ,---|| 97 | # `---'`---'`---|``---'`---^`---' 98 | # `---' 99 | 100 | ## setup the environment 101 | 102 | ## Generate docs 103 | puppet doc --mode rdoc --manifestdir manifests/ --modulepath ./modules/ --outputdir doc 104 | 105 | ## Fix docs to how I want them bitches 106 | ##! [ -d ${WORKSPACE}/doc/files/puppet ] && mkdir -v ${WORKSPACE}/doc/files/puppet; 107 | 108 | if [ -d ${WORKSPACE}/doc/files/${WORKSPACE}/modules ]; then 109 | mv -v "${WORKSPACE}/doc/files/${WORKSPACE}/modules" "${WORKSPACE}/doc/files/modules" 110 | fi; 111 | echo "WORKSPACE: '${WORKSPACE}'" 112 | grep -l -R ${WORKSPACE} * | while read fname; do sed -i "s@${WORKSPACE}/@/@g" $fname; done; 113 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | This repo contains various scripts that get used throughout our Jenkins setup. 4 | 5 | # Usage 6 | 7 | A recommended way of using these scripts could be to setup a separate Jenkins 8 | job that pull in this repository. You can easily set a global variable JENKINS_SCRIPTS 9 | pointing to that workspace and use ${JENKINS_SCRIPTS} throughout your setup. 10 | 11 | Another option is to include the scripts as managed scripts and add the arguments. See the README or 12 | script itself to find out what arguments are available. 13 | 14 | # Jenkins 15 | 16 | Below follows a quick overview on how these scripts are used on our Jenkins 17 | instance. You can either use the script directly or used it through the config 18 | file provider plugin (see below). Both should be pretty straightforward. 19 | We use parameters extensively. 20 | 21 | ## Used plugins 22 | 23 | The following plugins (and their dependencies) are used for setting up the jobs. 24 | 25 | * [Downstream Build View Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Downstream+buildview+plugin): 26 | Optional plugin to display your build pipelines. 27 | * [Config File Provider Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Config+File+Provider+Plugin): 28 | Manage your often used scripts in a centralized fashion. 29 | * [Warnings Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Warnings+Plugin): 30 | This plugin generates the trend report for compiler warnings in the console 31 | log or in log files. The warnings plugin has support for puppet-lint. 32 | * [Parameterized Trigger Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Parameterized+Trigger+Plugins): 33 | Triggers parametrized builds on other jobs. 34 | * [GIT Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Git+Plugin): 35 | This plugin integrates GIT with Jenkins. 36 | * [GIT Parameter Plugin](https://github.com/lukanus/git-parameter): 37 | Adds ability to choose from git repository revisions or tags. 38 | 39 | ## Pipelines 40 | 41 | We use 2 almost similar pipelines. One for release branch and one for development 42 | branches. The packaging system uses this information to build 2 kind of packages. 43 | In short: The release branch needs a tag. The tag will be used as the environment. 44 | For development branches. the development name is used as the environment. If a tag 45 | is set on such a branch, we will append it to the environment name. 46 | 47 | ### 1. Release Pipeline [puppet-tree-release] 48 | 49 | Holds ALL the parameters that can influence a build. We use this as a single entry point 50 | for our pipeline. You really don't want to start any build except the entry build. 51 | 52 | This has a couple of advantages. It will catch problems with your VCS. GIT in our case. 53 | If you git submodules, somebody will forget to push the submodule before the parent tree 54 | and your job will get stuck in a fail loop. We would not want these kind of hiccups to 55 | mess up the build trend for various more important checks. 56 | 57 | This job will trigger the next one if everything goes fine. 58 | 59 | ### 2. Syntax Checks [puppet-tree-release-syntax] 60 | 61 | Do syntax checks on as much code as possible. Currently, we have ruby templates and 62 | puppet manifests covered. 63 | 64 | ### 0. Add your fantastic spec test script here! 65 | 66 | ### 3. Style Checks [puppet-tree-release-style] 67 | 68 | The tagging check would be a lot faster to do here, but it might be interesting to already 69 | get a picture of the errors on the master branch. :) 70 | 71 | ### 4. GIT Tagging check [puppet-tree-release-tagging] 72 | 73 | Check if a tag is set. We need to enforce this because otherwise people push stuff into 74 | production like savages. We need to get rid of that mentality. If you broke something, 75 | create a hotfix with proper tagging etc etc. 76 | 77 | ### 5. Packaging [puppet-tree-release-packaging] 78 | Package it. We use fpm to produce RPMs. Easily adjustable to produce debs or ... 79 | 80 | ### 6. Deploy it [puppet-tree-release-deploy] 81 | Either push it to a pulp repo, or scp it to some site or ... 82 | 83 | 84 | # TODO: 85 | 86 | What we still need is 87 | 88 | * A job for documentation. I have some stuff somewhere. 89 | * A job for spec tests. Preferably, also a Jenkins warnings parser addition to parse the output. 90 | * While we are talking about Jenkins warnings parser: We need to support having modules in different 91 | structures than just /modules/ALLTHESTUFF. 92 | 93 | -------------------------------------------------------------------------------- /check_puppet_syntax/check_puppet_syntax.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #========================================================== 4 | # ,---- | o 5 | # |__. . .,---.,---.|--- .,---.,---.,---. 6 | # | | || || | || || |`---. 7 | # ` `---'` '`---'`---'``---'` '`---' 8 | # 9 | 10 | syserr() { 11 | echo "[$0] ERROR: $*" 1>&2 12 | exit 1; 13 | } 14 | 15 | 16 | _help() { 17 | cat < [...] 19 | Checks syntax of all puppet files. 20 | 21 | OPTIONS: 22 | -t, --max-threads NUMBER The max number of simultaneous threads to use. 23 | You can also specify PUPPET_SYNTAX_THREADS as an env 24 | variable. Defaults to 5. 25 | -s, --storedconfigs Enable storedconfigs while checking. 26 | -p, --puppet-bin Path to puppet executable to use. You can also 27 | set PUPPET_BIN as an environment variable. 28 | Defaults to 'puppet'. 29 | -e, --erb-bin Path to erb executable. You can also specify ERB_BIN 30 | as an environment variable. Defaults to 'erb'. 31 | -r, --ruby-bin Path to ruby executable. You can also specify 32 | RUBY_BIN as an environment variable. 33 | Defaults to 'ruby'. 34 | -h, --help Display this message and exit. 35 | 36 | The argument(s) should be a file or directories containing puppet manifests 37 | and/or ruby templates. Folders are search recursivly for files. 38 | 39 | EOHELP 40 | exit 0; 41 | } 42 | 43 | 44 | 45 | ## getopts parsing 46 | if `getopt -T >/dev/null 2>&1` ; [ $? = 4 ] ; then 47 | true; # Enhanced getopt. 48 | else 49 | syserr "You are using an old getopt version $(getopt -V)"; 50 | fi; 51 | 52 | TEMP=`getopt -o -t:p:e:r:sh -l max-threads:,puppet-bin:,erb-bin:,ruby-bin:,storedconfigs,help -n "$0" -- "$@"`; 53 | 54 | if [[ $? != 0 ]]; then 55 | syserr "Error parsing arguments"; 56 | fi; 57 | 58 | while [ $# -gt 0 ]; do 59 | case "$1" in 60 | -t|--max-threads) PUPPET_SYNTAX_THREADS="$2"; shift;; 61 | -p|--puppet-bin) PUPPET_BIN="$2"; shift;; 62 | -e|--erb-bin) ERB_BIN="$2"; shift;; 63 | -r|--ruby-bin) RUBY_BIN="$2"; shift;; 64 | -h|--help) _help;; 65 | -s|--storedconfigs) PUPPET_STOREDCONFIGS="1";; 66 | -*) syserr "Command option '$1' not recognized";; 67 | --) shift; break;; 68 | *) break;; 69 | esac 70 | shift; 71 | done; 72 | 73 | PUPPET_STOREDCONFIGS="${PUPPET_STOREDCONFIGS-0}"; 74 | PUPPET_SYNTAX_THREADS="${PUPPET_SYNTAX_THREADS-5}"; 75 | PUPPET_BIN="${PUPPET_BIN-puppet}"; 76 | ERB_BIN="${ERB_BIN-erb}"; 77 | RUBY_BIN="${RUBY_BIN-ruby}"; 78 | 79 | 80 | ## No arguments 81 | if [ ${#*} == 0 ]; then 82 | _help 83 | fi; 84 | 85 | echo "${PUPPET_SYNTAX_THREADS}" | grep -q '^[0-9]\+$' || syserr "max threads should be a number"; 86 | 87 | test_bin() { 88 | local desc=$1; 89 | local bin=$2; 90 | which ${bin} >/dev/null 2>&1 || syserr "${desc} executable (${bin}) not found on path"; 91 | [ -x $( which $bin ) ] || syserr "${desc} executable (${bin}) does not exist or is not executable"; 92 | } 93 | test_bin 'puppet' "${PUPPET_BIN}" 94 | test_bin 'erb' "${ERB_BIN}" 95 | test_bin 'ruby' "${RUBY_BIN}" 96 | 97 | 98 | _ERB_HELPER="$(cd $(dirname "$0"); pwd)/check_puppet_erb_helper.sh"; 99 | test_bin 'erb_helper_script' "${_ERB_HELPER}"; 100 | 101 | _PUPPET_HELPER="$(cd $(dirname "$0"); pwd)/check_puppet_syntax_helper.sh"; 102 | test_bin 'puppet_helper_script' "${_PUPPET_HELPER}"; 103 | 104 | #========================================================== 105 | # | o | 106 | # | ,---.,---..,---.,---.| 107 | # | | || ||| ,---|| 108 | # `---'`---'`---|``---'`---^`---' 109 | # `---' 110 | 111 | echo "Checking puppet syntax (Using $PUPPET_SYNTAX_THREADS threads)" 112 | find $* -iname '*.pp' | xargs --no-run-if-empty -t -n1 -P${PUPPET_SYNTAX_THREADS} -I file \ 113 | sh -c "PUPPET_BIN='${PUPPET_BIN}' PUPPET_STOREDCONFIGS='${PUPPET_STOREDCONFIGS}' $_PUPPET_HELPER file" || puppet_error="1"; 114 | 115 | echo "Puppet error: $puppet_error"; 116 | 117 | echo "Checking ruby template syntax (Using $PUPPET_SYNTAX_THREADS threads)" 118 | find $* -iname '*.erb' | xargs --no-run-if-empty -t -n1 -P${PUPPET_SYNTAX_THREADS} -I file \ 119 | sh -c "RUBY_BIN='${RUBY_BIN}' ERB_BIN='${ERB_BIN}' $_ERB_HELPER file" || ruby_error="1"; 120 | 121 | if [ "$puppet_error" == 1 ]; then 122 | echo "Puppet syntax error detected."; 123 | failed=1; 124 | fi; 125 | 126 | if [ "$ruby_error" == "1" ]; then 127 | echo "Ruby template syntax error detected."; 128 | failed=1; 129 | fi; 130 | 131 | if [ "$failed" == "1" ]; then 132 | echo FAILED 133 | exit 1; 134 | fi; 135 | -------------------------------------------------------------------------------- /check_git_release/check_git_release_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | green=$( tput setaf 2 ); 4 | bgreen=$( tput setaf 2; tput bold ); 5 | red=$( tput setaf 1 ); 6 | bred=$( tput setaf 1; tput bold ); 7 | reset=$( tput sgr0 ); 8 | 9 | ok() { 10 | local test="$1"; 11 | pos=$(( $(tput cols) - `echo "$test" | wc -c` - 8 )); 12 | if [ $pos -gt 5 ]; then 13 | echo "${test} $(tput cuf $pos )[${bgreen}PASSED${reset}]"; 14 | else 15 | echo "${test} [${bgreen}PASSED${reset}]"; 16 | fi; 17 | } 18 | nok() { 19 | local test="$1"; 20 | local err="${2-no reason provided}"; 21 | local msg="$test [$err]"; 22 | pos=$(( $(tput cols) - `echo "$msg" | wc -c` - 8 )); 23 | if [ $pos -gt 5 ]; then 24 | echo "${msg} $(tput cuf $pos )[${bred}FAILED${reset}]"; 25 | else 26 | echo "${msg} [${bred}FAILED${reset}]"; 27 | fi; 28 | } 29 | 30 | create_repo() { 31 | local d=$1; 32 | rm -rf $d; 33 | mkdir -p $d; 34 | (cd $d; git init 1>/dev/null; touch README; git add README 1>/dev/null; git commit -m 'Initial commit' 1>/dev/null); 35 | } 36 | 37 | create_file() { 38 | local d=$1; 39 | local f=$2; 40 | local m="${3}"; 41 | local c="${4}" 42 | (cd $d; echo "$c" > $f; git add $f 1>/dev/null; git commit -m "$m" 1>/dev/null); 43 | } 44 | 45 | tag() { 46 | local d=$1; 47 | local t=$2; 48 | (cd $d; git tag $t 1>/dev/null); 49 | } 50 | 51 | add_submod() { 52 | local d=$1; 53 | local s=../$2; 54 | (cd $d; git submodule add $s $2 1>/dev/null; git commit -m "Added subrepo $2" 1>/dev/null); 55 | } 56 | 57 | 58 | 59 | test_should_be() { 60 | local test="$1"; 61 | local command="$2"; 62 | local regex="$3"; 63 | echo $command 64 | if [ "$4" ]; then 65 | eval "$command 2>&1" >/dev/null; 66 | exit=$? 67 | if [ $exit != $4 ]; then 68 | nok "$test" "wrong exit status. expected $4, got $exit"; return 1; 69 | fi; 70 | fi; 71 | 72 | if eval "$command 2>&1" | grep -qz --color=always "$regex"; then 73 | ok "$test"; 74 | else 75 | nok "$test" "output '$regex' does not match"; return 1; 76 | fi; 77 | } 78 | 79 | echo "Preparing test environment" 80 | 81 | echo "+ creating test_subrepo_tag" 82 | create_repo test_subrepo_tag 83 | create_file test_subrepo_tag VERSION "Version bump to 0.1" "Version 0.1"; 84 | tag test_subrepo_tag "0_1" 85 | 86 | echo "+ create test_subrepo_notag" 87 | create_repo test_subrepo_notag 88 | 89 | echo "+ create test_subrepo_dirty" 90 | create_repo test_subrepo_dirty 91 | tag test_subrepo_dirty "0_1" 92 | touch test_subrepo_dirty/dirty 93 | 94 | echo "+ creating test_repo"; 95 | create_repo test_repo 96 | create_file test_repo VERSION "Version bump to 0.1" "Version 0.1" 97 | echo "++ adding subrepo test_subrepo_notag"; 98 | add_submod test_repo test_subrepo_notag 99 | echo "++ adding subrepo test_subrepo_dirty"; 100 | add_submod test_repo test_subrepo_dirty 101 | echo "++ adding subrepo test_subrepo_tag"; 102 | add_submod test_repo test_subrepo_tag 103 | tag test_repo "0_1" 104 | 105 | echo "+ creating test_repo_dots" 106 | create_repo test_repo_dots 107 | create_file test_repo_dots VERSION "Version bump to 0.1" "Version 0.1"; 108 | tag test_repo_dots "0.1" 109 | 110 | echo '# o | |' 111 | echo '# ,---.. .,---.,---..,---.,---. |--- ,---.,---.|--- ,---.'; 112 | echo "# | | || || ||| || | | |---'\`---.| \`---."; 113 | echo "# \` \`---'\` '\` '\`\` '\`---| \`---'\`---'\`---'\`---'\`---'" 114 | echo "# \`---'" 115 | 116 | 117 | #./check_git_release.sh test_repo 2>&1 >/dev/null 118 | #exit_should_be "single repository, no tag set" 1 $? 119 | 120 | 121 | 122 | test_should_be "single repository, no tag set [no args]" \ 123 | "./check_git_release.sh test_subrepo_notag" \ 124 | "GIT_CHECK:ERROR:MAIN:SYS:could not find any tag on path" 125 | 126 | x="$?" 127 | 128 | test_should_be "single repository, tag set [no args]" \ 129 | "./check_git_release.sh test_subrepo_tag" \ 130 | "GIT_CHECK:INFO:MAIN:TAG=" 131 | e=$? 132 | 133 | [ "$x" == "0" ] && x="$e" 134 | 135 | test_should_be "single repository, bogus tag set [no args]" \ 136 | "./check_git_release.sh test_repo_dots" \ 137 | "GIT_CHECK:ERROR:MAIN:SYS:tag contains invalid" 1 138 | e=$? 139 | 140 | [ "$x" == "0" ] && x="$e" 141 | 142 | test_should_be "single repository, bogus tag set [--tag-check false]" \ 143 | "./check_git_release.sh --tag-check false test_repo_dots" \ 144 | "GIT_CHECK:INFO:MAIN:TAG=" 0 145 | e=$? 146 | 147 | [ "$x" == "0" ] && x="$e" 148 | 149 | test_should_be "single_repository, dirty [no args]" \ 150 | "./check_git_release.sh test_subrepo_dirty" \ 151 | "GIT_CHECK:ERROR:MAIN:SYS:the git tree seems to be dirty" 1 152 | e=$? 153 | 154 | [ "$x" == "0" ] && x="$e" 155 | 156 | test_should_be "single_repository, dirty [--dirty-tree-error 0]" \ 157 | "./check_git_release.sh --dirty-tree-error 0 test_subrepo_dirty " \ 158 | "GIT_CHECK:WARN:MAIN:SYS:the git tree seems to be dirty" 0 159 | e=$? 160 | 161 | [ "$x" == "0" ] && x="$e" 162 | 163 | test_should_be "repo with submodules, tag set [no args]" \ 164 | "./check_git_release.sh test_repo" \ 165 | "GIT_CHECK:INFO:MAIN:TAG=" 0 166 | e=$? 167 | 168 | [ "$x" == "0" ] && x="$e" 169 | 170 | test_should_be "repo with submodules, tag set [--submods-tag-error 1]" \ 171 | "./check_git_release.sh --submods-tag-error 1 test_repo" \ 172 | "GIT_CHECK:INFO:MAIN:TAG=" 1 173 | e=$? 174 | 175 | [ "$x" == "0" ] && x="$e" 176 | 177 | touch test_repo/test_subrepo_dirty/dirty 178 | test_should_be "repo with submodules, dirty submodule [no args]" \ 179 | "./check_git_release.sh test_repo" \ 180 | "GIT_CHECK:ERROR:MAIN:SYS:the git tree seems to be dirty.*GIT_CHECK:ERROR:SUBMODULE:test_subrepo_dirty:SYS:the git submodule tree seems to be dirty" 1 181 | e=$? 182 | 183 | [ "$x" == "0" ] && x="$e" 184 | 185 | test_should_be "repo with submodules, dirty submodule [--dirty-tree-error 0]" \ 186 | "./check_git_release.sh --dirty-tree-error 0 test_repo" \ 187 | "GIT_CHECK:WARN:MAIN:SYS:the git tree seems to be dirty.*GIT_CHECK:WARN:SUBMODULE:test_subrepo_dirty:SYS:the git submodule tree seems to be dirty" 0 188 | e=$? 189 | 190 | [ "$x" == "0" ] && x="$e" 191 | 192 | if [ $x == "1" ]; then 193 | echo "ERRORS found. Skipping cleanup" 194 | else 195 | echo "Cleaning up" 196 | rm -rf test_repo* test_subrepo* 197 | fi; 198 | exit $x; 199 | -------------------------------------------------------------------------------- /check_puppet_style/check_puppet_style.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #========================================================== 4 | # ,---- | o 5 | # |__. . .,---.,---.|--- .,---.,---.,---. 6 | # | | || || | || || |`---. 7 | # ` `---'` '`---'`---'``---'` '`---' 8 | # 9 | 10 | syserr() { 11 | echo "$0: ERROR: $*" 1>&2 12 | exit 1; 13 | } 14 | 15 | _help() { 16 | cat < [...] 18 | Checks your puppet manifests with puppet-lint. 19 | 20 | OPTIONS: 21 | -t, --max-threads NUMBER The maximum number of simultaneous threads to 22 | use. You can also specify PUPPET_LINT_THREADS as an 23 | environment variable. Defaults to 5. 24 | -p, --puppet-lint-bin PATH Path to puppet-lint executable. Can also be 25 | specified as an env variable PUPPET_LINT_BIN. 26 | Defaults to 'puppet-lint'. 27 | -l, --log-format Override the log format. The default log format 28 | has been setup to use with the jenkins 29 | warnings-plugin (puppet-lint). 30 | -s, --skip-tests Skips the tests directory in puppet modules. 31 | You can also specify PUPPET_LINT_SKIP_TESTS as an 32 | non empty environment variable. 33 | -e, --skip-examples Skips the examples directory in puppet modules. 34 | You can also specify PUPPET_LINT_SKIP_EXAMPLES as an 35 | non empty environment variable. 36 | -c, --skip-custom Custom pattern to skip. This is added with ! -iwholename 37 | to the find command we are building. You can specify 38 | this option multiple times if needed. 39 | -f, --fail-on-error By default, this script always exits with an 40 | exit status of 0. If this is enabled, we will 41 | exit with a status of 1 if any errors are 42 | detected by puppet lint. You can also specify 43 | a non empty environment variable PUPPET_LINT_FAILS_ERROR. 44 | -w, --fail-on-warning Exit with a status of 1 if a warning is 45 | detected by puppet lint. This implies 46 | fail-on-error too. You can also specify a non 47 | empty environment variable FAIL_ON_WARN. 48 | -x, --exclude-checks A comma seperated list of puppet lint checks to 49 | exclude. You can check puppet-lint --help for all 50 | available tests. 51 | Example: '-x ensure_first_param,80chars,...' 52 | -h, --help Display this message and exit. 53 | 54 | The argument(s) should be a file or directories containing puppet manifests. 55 | Folders are search recursivly for files. 56 | 57 | EOHELP 58 | exit 0; 59 | } 60 | 61 | 62 | 63 | #========================================================== 64 | # | | 65 | # ,---.,---.|--- ,---.,---.|--- ,---. 66 | # | ||---'| | || || `---. 67 | # `---|`---'`---'`---'|---'`---'`---' 68 | # `---' | 69 | 70 | 71 | ## getopts parsing 72 | if `getopt -T >/dev/null 2>&1` ; [ $? = 4 ] ; then 73 | true; # Enhanced getopt. 74 | else 75 | syserr "You are using an old getopt version $(getopt -V)"; 76 | fi; 77 | 78 | 79 | TEMP=`getopt -o -p:sec:t:hl:fwx: \ 80 | -l puppet-lint-bin:skip-tests,skip-examples,skip-custom:,max-threads,help,log-format,fail-on-error,fail-on-warning,exclude-checks -n "$0" -- "$@";` 81 | 82 | if [[ $? != 0 ]]; then 83 | syserr "Error parsing arguments"; 84 | fi; 85 | 86 | 87 | while [ $# -gt 0 ]; do 88 | case "$1" in 89 | -t|--max-threads) echo "$2" | grep -q '^[0-9]\+$' || \ 90 | syserr "max-threads should be a number"; 91 | PUPPET_LINT_THREADS="$2"; shift;; 92 | -p|--puppet-lint-bin) [ -f $2 ] || \ 93 | syserr "puppet-lint-bin: file does not exist."; 94 | PUPPET_LINT_BIN="$2"; shift;; 95 | -l|--log-format) PUPPET_LINT_LOG_FORMAT="$2"; shift;; 96 | -s|--skip-tests) PUPPET_LINT_SKIP_TESTS="1";; 97 | -e|--skip-examples) PUPPET_LINT_SKIP_EXAMPLES="1";; 98 | -c|--skip-custom) PUPPET_LINT_SKIP_CUSTOM="${PUPPET_LINT_SKIP_CUSTOM}|$2"; shift;; 99 | -f|--fail-on-error) PUPPET_LINT_FAILS_ERROR="1";; 100 | -w|--fail-on-warning) PUPPET_LINT_FAILS_WARNING="1";; 101 | -x|--exclude-checks) PUPPET_LINT_EXCLUDE_CHECKS="$2"; shift;; 102 | -h|--help) _help;; 103 | -*) syserr "Command option '$1' not recognized";; 104 | --) shift; break;; 105 | *) break;; 106 | esac; 107 | shift; 108 | done; 109 | 110 | if [ $# == 0 ]; then 111 | _help; 112 | fi 113 | 114 | PUPPET_LINT_THREADS="${PUPPET_LINT_THREADS-5}"; 115 | PUPPET_LINT_BIN="${PUPPET_LINT_BIN-puppet-lint}"; 116 | 117 | PUPPET_LINT_SKIP_TESTS="${PUPPET_LINT_SKIP_TESTS}"; 118 | PUPPET_LINT_SKIP_EXAMPLES="${PUPPET_LINT_SKIP_EXAMPLES}"; 119 | PUPPET_LINT_SKIP_CUSTOM="${PUPPET_LINT_SKIP_CUSTOM}"; 120 | 121 | PUPPET_LINT_LOG_FORMAT="${PUPPET_LINT_LOG_FORMAT}" 122 | [ ! "${PUPPET_LINT_LOG_FORMAT}" ] && PUPPET_LINT_LOG_FORMAT="%{path}:%{linenumber}:%{check}:%{KIND}:%{message}" 123 | 124 | PUPPET_LINT_FAILS_WARNING="${PUPPET_LINT_FAILS_WARNING}"; 125 | PUPPET_LINT_FAILS_ERROR="${PUPPET_LINT_FAILS_ERROR-${PUPPET_LINT_FAILS_WARNING}}"; 126 | 127 | PUPPET_LINT_EXCLUDE_CHECKS="${PUPPET_LINT_EXCLUDE_CHECKS}"; 128 | 129 | ## Accept 1, true, yes as boolean values. anything else is false really. 130 | [[ "${PUPPET_LINT_SKIP_TESTS}" == "true" || "${PUPPET_LINT_SKIP_TESTS}" == "yes" ]] && PUPPET_LINT_SKIP_TESTS="1"; 131 | [[ "${PUPPET_LINT_SKIP_EXAMPLES}" == "true" || "${PUPPET_LINT_SKIP_EXAMPLES}" == "yes" ]] && PUPPET_LINT_SKIP_EXAMPLES="1"; 132 | [[ "${PUPPET_LINT_FAILS_WARNING}" == "true" || "${PUPPET_LINT_FAILS_WARNING}" == "yes" ]] && PUPPET_LINT_FAILS_WARNING="1"; 133 | [[ "${PUPPET_LINT_FAILS_ERROR}" == "true" || "${PUPPET_LINT_FAILS_ERROR}" == "yes" ]] && PUPPET_LINT_FAILS_ERROR="1"; 134 | 135 | 136 | ## TEST SETTINGS/ARGUMENTS ## 137 | echo "${PUPPET_LINT_THREADS}" | grep -q '^[0-9]\+$' || syserr "max threads should be a number"; 138 | 139 | test_bin() { 140 | local desc=$1; 141 | local bin=$2; 142 | which ${bin} 2>&1 >/dev/null || syserr "${desc} executable (${bin}) not found on path"; 143 | [ -x $( which $bin ) ] || syserr "${desc} executable (${bin}) does not exist or is not executable"; 144 | } 145 | 146 | test_bin 'puppet-lint' "${PUPPET_LINT_BIN}" 147 | 148 | echo "Checking puppet style (Using $PUPPET_LINT_THREADS threads):" 149 | _find="find $* -iname '*.pp'" 150 | if [ "$PUPPET_LINT_SKIP_TESTS" == "1" ]; then 151 | _find="${_find} ! -iwholename '*/tests/*'" 152 | fi; 153 | if [ "$PUPPET_LINT_SKIP_EXAMPLES" == "1" ]; then 154 | _find="${_find} ! -iwholename '*/examples/*'" 155 | fi; 156 | if [ "$PUPPET_LINT_SKIP_CUSTOM" ]; then 157 | set -f 158 | for custom in $( echo "${PUPPET_LINT_SKIP_CUSTOM}" | tr '|' "\n"); do 159 | [ "$custom" ] && _find="${_find} ! -iwholename '${custom}'" 160 | done; 161 | set +f 162 | fi; 163 | 164 | 165 | warning_count=0 166 | error_count=0 167 | 168 | _puppet_lint="${PUPPET_LINT_BIN} --log-format '${PUPPET_LINT_LOG_FORMAT}'" 169 | if [ "$PUPPET_LINT_EXCLUDE_CHECKS" ]; then 170 | for check in $( echo "$PUPPET_LINT_EXCLUDE_CHECKS" | tr ',' "\n") ; do 171 | _puppet_lint="${_puppet_lint} --no-${check}-check"; 172 | done 173 | fi; 174 | 175 | eval $_find | xargs --no-run-if-empty -n1 -P${PUPPET_LINT_THREADS} \ 176 | $_puppet_lint --log-format "${PUPPET_LINT_LOG_FORMAT}" | ( 177 | while read line; do 178 | echo $line | grep -q ':WARNING:' && let "warning_count++" 179 | echo $line | grep -q ':ERROR:' && let "error_count++" 180 | echo $line 181 | done 182 | echo "Puppet lint finished"; 183 | echo "- Error count: ${error_count}"; 184 | echo "- Warn count: ${warning_count}"; 185 | if [[ "$PUPPET_LINT_FAILS_ERROR" == "1" && $error_count -gt 0 ]]; then 186 | echo "=> PUPPET_LINT_FAILS_ERROR enabled and error_count above 0"; 187 | exit 1; 188 | fi; 189 | if [[ "$PUPPET_LINT_FAILS_WARNING" == "1" && $warning_count -gt 0 ]]; then 190 | echo "=> PUPPET_LINT_FAILS_WARNING enabled and warning_count above 0"; 191 | exit 1; 192 | fi; 193 | exit 0; 194 | ) || exit $? 195 | 196 | -------------------------------------------------------------------------------- /check_git_release/check_git_release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This script should be used in a release branch. 4 | # It checks if a (git) tag has been set on the current branch. This should be 5 | # the master branch. 6 | # 7 | # If there are any submodules defined, these will also be checked but throw 8 | # warnings by default. There are some arguments available to change this 9 | # behaviour. See below. 10 | # 11 | 12 | #========================================================== 13 | # ,---- | o 14 | # |__. . .,---.,---.|--- .,---.,---.,---. 15 | # | | || || | || || |`---. 16 | # ` `---'` '`---'`---'``---'` '`---' 17 | 18 | ## External scripts 19 | #source $(cd $(dirname "$0")/../common/; pwd)/functions.sh || \ 20 | # syserr "Failed to load required common/functions.sh library."; 21 | if ! source $(cd $(dirname "$0"); pwd)/../common/git.sh; then 22 | echo "Failed to load required common/git.sh library." 1>&2 23 | exit 1 24 | fi; 25 | 26 | ## Keep track of the number of errors we encounter. 27 | declare -i errors=0; 28 | ## A error has been found. Expose for parsing! 29 | # USAGE: err 30 | err() { 31 | errors=1; 32 | echo "GIT_CHECK:ERROR:$*" 1>&2 33 | } 34 | 35 | ## Output a warning line for git_check 36 | # USAGE: warn 37 | warn() { 38 | echo "GIT_CHECK:WARN:$*" 1>&2 39 | } 40 | 41 | ## Output a info line for git_check. 42 | # USAGE: info 43 | info() { 44 | echo "GIT_CHECK:INFO:$*"; 45 | } 46 | 47 | ## A submodule warning/error. Depends on $submodules_throws_error. 48 | # USAGE: sub 49 | sub() { 50 | if [ "$CHECK_GIT_SUBERROR" == "1" ]; then 51 | err $*; 52 | else 53 | warn $* 54 | fi; 55 | } 56 | 57 | 58 | ## Debug function. Only ouputs stuff if SCRIPTDEBUG is set to something/anything. 59 | # USAGE: debug 60 | debug() { 61 | if [ "$SCRIPTDEBUG" ]; then 62 | echo "[debug] $*" 1>&2; 63 | fi; 64 | } 65 | 66 | _help() { 67 | cat < 69 | Check if a tag has been set on the repository and/or his submodules. 70 | 71 | OPTIONS: 72 | -e, --dirty-tree-error 1|0 If enabled, a dirty tree will throw an error. 73 | If a submodule is dirty, the main tree is 74 | also dirty so this will automaticly fail. 75 | You can also change this setting by setting 76 | an environment variable called CHECK_GIT_DIRTY. 77 | Defaults to enabled (1). 78 | -m, --check-submodules 1|0 Enable or disable checking of submodules. 79 | You can also change this setting by setting 80 | an environment variable called CHECK_GIT_SUBMODULES. 81 | Defaults to enabled (1). 82 | -t, --submods-tag-error 1|0 If a submodule has no tag set, throw an error 83 | or just warn. You can also change this setting by 84 | setting an environment variable called 85 | CHECK_GIT_SUBERROR. 86 | Defaults to warning only (0). 87 | -c, --tag-check 1|0 Check for unwanted characters in the tag. You can 88 | also change this setting by using CHECK_GIT_TAG. 89 | Defaults to true (1). 90 | that was set. This is required if the tag will 91 | be the actual version of your package. 92 | -d, --debug Enable debugging of the script. 93 | Debugging is also enabled when a SCRIPTDEBUG 94 | environment variable has been set with a 95 | non-empty value. 96 | -h, --help Show this message and exit. 97 | 98 | The argument should be the path to a git repository. This can also be a 99 | specific submodule. It no path is provided, we default to the current dir. 100 | 101 | EOHELP 102 | exit 0; 103 | } 104 | 105 | 106 | ## getopts parsing 107 | if `getopt -T >/dev/null 2>&1` ; [ $? = 4 ] ; then 108 | true; # Enhanced getopt. 109 | else 110 | syserr "You are using an old getopt version $(getopt -V)"; 111 | fi; 112 | 113 | TEMP=`getopt -o -e:m:t:dhc: \ 114 | --long dirty-tree-error:,check-submodules:,submods-tag-error:,debug,help,tag-check: \ 115 | -n "$0" -- "$@"`; 116 | 117 | if [[ $? != 0 ]]; then 118 | syserr "Error parsing arguments" 119 | fi; 120 | 121 | while [ $# -gt 0 ]; do 122 | case "$1" in 123 | -e|--dirty-tree-error) CHECK_GIT_DIRTY="$2"; shift;; 124 | -m|--check-submodules) CHECK_GIT_SUBMODULES="$2"; shift;; 125 | -t|--submods-tag-error) CHECK_GIT_SUBERROR="$2"; shift;; 126 | -c|--tag-check) CHECK_GIT_TAG="$2"; shift;; 127 | -h|--help) _help;; 128 | -d|--debug) SCRIPTDEBUG=1;; 129 | -*) syserr "Command option not recognized";; 130 | --) shift; break;; 131 | *) break;; 132 | esac 133 | shift; 134 | done; 135 | 136 | #========================================================== 137 | # ,---.,---.,---.,---. 138 | # ,---|| | |`---. 139 | # `---^` `---|`---' 140 | # `---' 141 | 142 | # Git repository to check 143 | repo_path="${1-.}" 144 | # Check submodules 145 | CHECK_GIT_TAG=${CHECK_GIT_TAG-1} 146 | CHECK_GIT_SUBMODULES="${CHECK_GIT_SUBMODULES-1}"; 147 | CHECK_GIT_SUBERROR="${CHECK_GIT_SUBERROR-0}"; 148 | CHECK_GIT_DIRTY="${CHECK_GIT_DIRTY-1}"; 149 | 150 | [[ "${CHECK_GIT_SUBMODULES}" == "true" || "${CHECK_GIT_SUBMODULES}" == "yes" ]] && CHECK_GIT_SUBMODULES="1"; 151 | [[ "${CHECK_GIT_SUBERROR}" == "true" || "${CHECK_GIT_SUBERROR}" == "yes" ]] && CHECK_GIT_SUBERROR="1"; 152 | [[ "${CHECK_GIT_DIRTY}" == "true" || "${CHECK_GIT_DIRTY}" == "yes" ]] && CHECK_GIT_DIRTY="1"; 153 | [[ "${CHECK_GIT_TAG}" == "true" || "${CHECK_GIT_TAG}" == "yes" ]] && CHECK_GIT_TAG="1"; 154 | 155 | #========================================================== 156 | # | | 157 | # |--- ,---.,---.|--- ,---. 158 | # | |---'`---.| `---. 159 | # `---'`---'`---'`---'`---' 160 | # 161 | 162 | debug "repo_path = '$repo_path'"; 163 | ## Is it even a directory that exists? 164 | [ -d $repo_path ] || syserr "path '$repo_path' does not exist"; 165 | 166 | ## Is this a git repo? and if it is, what is the git dir? 167 | git_dir=`get_git_dir $repo_path` || \ 168 | syserr "path '$repo_path' does not seem to be a git repository"; 169 | debug "git_dir = '$git_dir'"; 170 | 171 | ## Get the commit hash were are on. 172 | commit=`get_current_commit $repo_path $git_dir` || \ 173 | syserr "could not get current commit on path '$repo_path'"; 174 | debug "current commit = '$commit'"; 175 | 176 | #========================================================== 177 | # | o | 178 | # | ,---.,---..,---.,---.| 179 | # | | || ||| ,---|| 180 | # `---'`---'`---|``---'`---^`---' 181 | # `---' 182 | # 183 | 184 | if ! git_check_dirty $repo_path $git_dir; then 185 | if [ "$CHECK_GIT_DIRTY" == "1" ]; then 186 | err "MAIN:SYS:the git tree seems to be dirty" 187 | else 188 | warn "MAIN:SYS:the git tree seems to be dirty" 189 | fi; 190 | fi; 191 | 192 | tag=`get_tag $repo_path $commit $git_dir` || \ 193 | err "MAIN:SYS:could not find any tag on path '$repo_path'"; 194 | debug "tag = '$tag'"; 195 | 196 | [ "$tag" ] || tag="unknown"; 197 | info "MAIN:TAG=${tag-unknown}"; 198 | 199 | if [[ "$CHECK_GIT_TAG" == "1" ]]; then 200 | echo $tag | grep -q '^[a-zA-Z0-9_]\+$' || err "MAIN:SYS:tag contains invalid characters: '${tag}' (allowed: alphanumeric and underscore)"; 201 | fi; 202 | 203 | if [[ "$CHECK_GIT_SUBMODULES" == "1" && -f $repo_path/.gitmodules ]]; then 204 | SUBMODULES=$( cd $repo_path; git submodule status | \ 205 | sed -e 's@^\s*\([a-z0-9]\+\)\s*\([^ ]\+\).*@\1 \2@'; 206 | ); 207 | 208 | while read submod_commit submod_dir; do 209 | submod_path="${repo_path}/${submod_dir}"; 210 | submod_git_dir=`get_git_dir "${submod_path}"` || \ 211 | sub "SUBMODULE:could not detect git repository in '${submod_path}'"; 212 | 213 | if ! git_check_dirty $submod_path $submod_git_dir; then 214 | debug "[submodule] is dirty" 215 | if [ "$CHECK_GIT_DIRTY" == "1" ]; then 216 | err "SUBMODULE:${submod_dir}:SYS:the git submodule tree seems to be dirty" 217 | else 218 | warn "SUBMODULE:${submod_dir}:SYS:the git submodule tree seems to be dirty"; 219 | fi; 220 | fi; 221 | submod_tag=`get_tag $submod_path $submod_commit $submod_git_dir` || \ 222 | sub "SUBMODULE:${submod_dir}:SYS:could not find any tag for submodule ${submod_dir}"; 223 | debug "[submodule] errors = '$errors'"; 224 | debug "[submodule] submod_tag = '$submod_tag'"; 225 | 226 | [ "$submod_tag" ] && \ 227 | info "SUBMODULE:${submod_dir}:TAG=$submod_tag"; 228 | done <<< "$SUBMODULES" 229 | fi; 230 | 231 | 232 | debug "errors = '$errors'"; 233 | [ $errors == 0 ] || exit 1; 234 | -------------------------------------------------------------------------------- /package_puppet_tree_fpm/package_puppet_tree_fpm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | VERSION="0.2" 4 | 5 | #========================================================== 6 | # ,---- | o 7 | # |__. . .,---.,---.|--- .,---.,---.,---. 8 | # | | || || | || || |`---. 9 | # ` `---'` '`---'`---'``---'` '`---' 10 | # 11 | 12 | if ! source $(cd $(dirname "$0"); pwd)/../common/functions.sh; then 13 | echo "Failed to load required common/functions.sh library." 1>&2 14 | exit 1; 15 | fi; 16 | 17 | if ! source $(cd $(dirname "$0"); pwd)/../common/git.sh; then 18 | echo "Failed to load required common/git.sh library." 1>&2 19 | exit 1 20 | fi; 21 | 22 | _environment_variables=( 23 | PPKG_GENERAL=-------------------------------- 24 | PPKG_ENVIRONMENT='Set the environment name.' 25 | PPKG_VERSION='Set the package version.' 26 | PPKG_ITERATION='Set the package iteration.' 27 | PPKG_TYPE='Package type to produce.' 28 | PPKG_NAME_PREFIX='This will be added in front of the default name: -puppet-tree-' 29 | PPKG_NAME_BASE='The base of the package name. This is prefixed by the name prefix and the environment is appended.' 30 | PPKG_TARGET='target directory to package'. 31 | PPKG_GIT_ROOT='if you only build a subdir from your repository, set this to the repo root.' 32 | PPKG_META_INFO=-------------------------------- 33 | PPKG_VENDOR='The vendor providing the package' 34 | PPKG_DESCRIPTION='Description of the package' 35 | PPKG_CATEGORY='Category to use for package' 36 | PPKG_MAINTAINER='maintainer of the package.' 37 | PPKG_URL='url of the package' 38 | PPKG_SYS=-------------------------------- 39 | PPKG_DEPENDENCIES='comma seperated list of dependencies' 40 | PPKG_CONFIGS='comma seperated list of files to mark as configuration. we will prepend the PREFIX to relative files' 41 | PPKG_EXCLUDES='files to exclude from the package.' 42 | PPKG_PROVIDES='comma seperated list of provides' 43 | PPKG_FPM_OPTIONS='directly pass through options to fpm' 44 | PPKG_INTERNALS=-------------------------------- 45 | PPKG_MAP_ENVIRONMENTS='A list of branch name to environment mappings. Must be =. Seperate multiple values with spaces. This does not work for the GIT_RELEASE_BRANCH since that relies on the GIT_TAG for the environment name.' 46 | PPKG_GIT_RELEASE_BRANCH='name of the branch which contains releases' 47 | PPKG_NO_RELEASE='set this to something if this is NOT a release. This resolves some issues where a tag is in multiple branches' 48 | PPKG_GIT_FORCE_BRANCH='force to only build this branch. fails if the current commit is not on that branch' 49 | PPKG_DEFAULT_VERSION='override the default version (which is 1.0)' 50 | PPKG_PREFIX_BASE="Default prefix base." 51 | PPKG_PREFIX='override the prefix (not recommended).' 52 | PPKG_NAME='override the package name (not recommended).' 53 | 54 | ) 55 | _max_env_len="20" 56 | _help_environment_var() { 57 | local key 58 | local value 59 | local env 60 | local strlen 61 | 62 | for env in "${_environment_variables[@]}"; do 63 | key="${env%%=*}"; 64 | value="${env##*=}"; 65 | strlen=$(( $_max_env_len - `echo $key | wc -c` )) 66 | if [ "${value}" == "--------------------------------" ]; then 67 | echo ""; 68 | continue; 69 | fi; 70 | printf " %s='' %${strlen}s# %s\n" "$key" " " "$value"; 71 | done 72 | } 73 | 74 | 75 | _help() { 76 | cat < [...] 78 | Packages a puppet tree as an environment. 79 | 80 | DESCRIPTION: 81 | This script has been written to package a puppet tree to use as an split 82 | off environment. In short, the directory provided as an argument should 83 | be the root of your puppet tree. It will be installed in a folder with the 84 | following format: 85 | 86 | /etc/puppet/environments/ 87 | 88 | The environment name will be build with the following logic in mind: 89 | * Is this a git repository? If not, you should provide the environment name 90 | yourself. 91 | * We're NOT on the master branch? If not, we will use the branch name as 92 | the environment name. If a tag is set on the branch, we will append it 93 | to the environment name (ex: -). The version 94 | will be the one provided or the default version '1.0'. 95 | * On the master branch? 96 | * A git tag has been set? Well, you should really do this. 97 | We'll warn about this and set the environment name to master. 98 | * You have a git tag, this will be the environment name. The version 99 | will be the version provided or the default version '1.0'. 100 | 101 | Package iteration? If you do not provide the number, this will be either 0 102 | or if the BUILD_NUMBER environment variable is set, we will use that instead. 103 | BUILD_NUMBER is an environment variable that is automatically set by Jenkins. 104 | 105 | PPKG-SETTINGS FILE 106 | 107 | If you have a file called .ppkg-settings in the folder to package, 108 | it will be sourced before processing begins. You can use this file to specify 109 | environment variables for this build. This file will be excluded from 110 | packaging. Note that anything here will override any setting you provide (except the 111 | target folder to package). You can work arround this by using (for example): 112 | PPKG_NAME="${PPKG_NAME-myname}". 113 | 114 | OPTIONS: 115 | 116 | -e, --environment Overrides the name of the environment to use. 117 | You can set this to 'GIT_BRANCH' to use the git 118 | branch (if available) as the environment name. 119 | This will alter the default behaviour by NOT 120 | appending (or using) the git tag. 121 | Works well together with 'GIT_TAG' as version 122 | number. To also use this for your release branch, 123 | change PPKG_GIT_RELEASE_BRANCH to sth that would 124 | not be used. 125 | ex: '_this_release_uses_alternative_naming_'. 126 | -v, --version Specify the package version. Defaults to 1.0. 127 | You can set this to 'GIT_TAG' if you prefer 128 | to use that as the default version number instead 129 | of 1.0. 130 | -i, --iteration The iteration number to use. 131 | -t, --type Package type to build. Defaults to rpm. 132 | -h, --help Display this message and exit. 133 | 134 | 135 | ARGUMENT: 136 | Path of the puppet tree to package. This has no default. If you want to 137 | package the current working directory, you have to explictly set it to '.' 138 | 139 | ENVIRONMENT VARIABLES: 140 | You can alter the behaviour a lot more by using the following environment 141 | variables before calling the script. These include the possibility to 142 | override values you would otherwise set using the options. 143 | EOHELP 144 | _help_environment_var 145 | exit 1; 146 | } 147 | 148 | 149 | _build_deps_cmd() { 150 | _build_array_cmd "${PPKG_DEPENDENCIES}" "--depends" 151 | } 152 | 153 | _build_excludes_cmd() { 154 | set -f 155 | _build_array_cmd "${PPKG_EXCLUDES}" "--exclude" 156 | set +f 157 | } 158 | 159 | _build_configs_cmd() { 160 | _build_array_cmd "${PPKG_CONFIGS}" "--config-files" 161 | } 162 | _build_provides_cmd() { 163 | _build_array_cmd "${PPKG_PROVIDES}" "--provides" 164 | } 165 | 166 | _build_array_cmd() { 167 | local cmd 168 | local item 169 | local arr="${1// /…}" 170 | local opt="$2" 171 | for item in $( echo "${arr}" | tr ',' "\n" ); do 172 | cmd="${cmd} ${opt} '${item//…/ }'"; 173 | done; 174 | echo "$cmd"; 175 | } 176 | 177 | _map_branch_to_environment() { 178 | local branch=$1 179 | for map in $PPKG_MAP_ENVIRONMENTS; do 180 | if echo $map | grep -q "^${branch}="; then 181 | echo "${map##${branch}=}" 182 | debug "ROUND REMAP: branch '${branch}' -> '${map##${branch}=}'" 183 | return 0; 184 | fi 185 | done; 186 | echo $branch 187 | return 0; 188 | } 189 | 190 | ## getopts parsing 191 | if `getopt -T >/dev/null 2>&1` ; [ $? = 4 ] ; then 192 | true; # Enhanced getopt. 193 | else 194 | err "You are using an old getopt version $(getopt -V)"; 195 | exit 1; 196 | fi; 197 | 198 | 199 | TEMP=`getopt -o -e:v:i:t:h \ 200 | -l environment:,version:,iteration:,type:,help -n "$0" -- "$@"`; 201 | 202 | if [[ $? != 0 ]]; then 203 | err "Error parsing arguments"; 204 | exit 1; 205 | fi; 206 | 207 | while [ $# -gt 0 ]; do 208 | case "$1" in 209 | -e|--environment) PPKG_ENVIRONMENT="$2"; shift;; 210 | -v|--version) PPKG_VERSION="$2"; shift;; 211 | -i|--iteration) PPKG_ITERATION="$2"; shift;; 212 | -t|--type) PPKG_TYPE="$2"; shift;; 213 | -h|--help) _help;; 214 | -*) err "Command option '$1' not recognized"; exit 1;; 215 | --) shift; break;; 216 | *) break;; 217 | esac; 218 | shift; 219 | done; 220 | 221 | 222 | ## No arguments 223 | if [[ ${#*} == 0 && ! "${PPKG_TARGET}" ]]; then 224 | echo "ERROR: No arguments provided. You should specify the folder to package or set the PPKG_TARGET environment variable"; 225 | echo "" 226 | _help; 227 | fi; 228 | 229 | ##---- TARGET FOLDER -----## 230 | PPKG_TARGET="${PPKG_TARGET-${1}}"; 231 | if [ ! -d "$PPKG_TARGET" ]; then 232 | err "TARGET is not a folder (${PPKG_TARGET})!" 233 | exit 1; 234 | fi; 235 | 236 | [ -f "${PPKG_TARGET}/.ppkg-settings" ] && \ 237 | source "${PPKG_TARGET}/.ppkg-settings" 238 | 239 | if [ "$PPKG_MIN_VERSION" ]; then 240 | if [ $PPKG_MIN_VERSION == $VERSION ]; then 241 | debug "Required version is current version."; 242 | else 243 | _vspec=$( echo -e $PPKG_MIN_VERSION"\n"$VERSION | sort -t'.' -g | tail -n 1) 244 | if [ "$_vspec" == "${PPKG_MIN_VERSION}" ]; then 245 | err "You requested a minimum script version '${PPKG_MIN_VERSION}' but current version is '${VERSION}'." 246 | exit 1; 247 | else 248 | debug "Required version is newer."; 249 | fi; 250 | fi; 251 | 252 | fi; 253 | 254 | if echo "$PPKG_NO_RELEASE" | grep -q "false\|0\|no"; then 255 | PPKG_NO_RELEASE="" 256 | fi; 257 | 258 | debug "PPKG_TARGET: '${PPKG_TARGET}'"; 259 | 260 | PPKG_DEFAULT_VERSION="${PPKG_DEFAULT_VERSION-1.0}" 261 | 262 | ##----- GIT RELATED SETTINGS -----## 263 | PPKG_GIT_RELEASE_BRANCH="${PPKG_GIT_RELEASE_BRANCH-master}"; 264 | debug "PPKG_GIT_RELEASE_BRANCH: '${PPKG_GIT_RELEASE_BRANCH}'"; 265 | 266 | # The git root (work-tree) defaults to the provided target directory 267 | PPKG_GIT_ROOT="${PPKG_GIT_ROOT-${PPKG_TARGET}}"; 268 | debug "PPKG_GIT_ROOT: '${PPKG_GIT_ROOT}'"; 269 | 270 | _GIT_DIR=$( get_git_dir $PPKG_GIT_ROOT ) || warn "could not find the git dir" 271 | debug "_GIT_DIR: '${_GIT_DIR}'" 272 | 273 | if [ "$_GIT_DIR" ]; then 274 | _GIT_TAG=`get_tag $PPKG_GIT_ROOT` || warn "could not find a git tag" 275 | 276 | ## Expanded branch logic. We ran into a problem when we are in a 277 | # detached state and the commit was in several branches. 278 | 279 | 280 | _GIT_BRANCHES=`get_all_branches $PPKG_GIT_ROOT | grep "remotes/*" | grep -o '[^/]\+$'`; 281 | debug "_GIT_BRANCHES (raw): '${_GIT_BRANCHES}'"; 282 | # we are forcing the use of this branch. Can we? 283 | if [ "$PPKG_GIT_FORCE_BRANCH" ]; then 284 | debug "Enforcing git branch: '${PPKG_GIT_FORCE_BRANCH}'"; 285 | if echo "${_GIT_BRANCHES}" | grep -q "${PPKG_GIT_FORCE_BRANCH}"; then 286 | _GIT_BRANCHES="${PPKG_GIT_FORCE_BRANCH}"; 287 | else 288 | err "Forcing the use of branch '${PPKG_GIT_FORCE_BRANCH}' but this branch does not have the current commit." 289 | exit 1; 290 | fi 291 | else 292 | # Are we enforcing NO_RELEASE or there is no tag? get rid of the release branch and recheck the branch list. 293 | if [[ "${PPKG_NO_RELEASE}" || ! "${_GIT_TAG}" ]]; then 294 | _GIT_BRANCHES=`echo "${_GIT_BRANCHES}" | grep -v "${PPKG_GIT_RELEASE_BRANCH}"` 295 | debug "PPKG_NO_RELEASE set ('${NO_RELEASE}') or no GIT TAG found: removed the git release branch ('${PPKG_GIT_RELEASE_BRANCH}')"; 296 | fi; 297 | # Are we NOT enforcing NO_RELEASE? Is there a tag on the release branch? if yes, use it, if not, remove it. 298 | if [[ "${_GIT_TAG}" && $(echo "${_GIT_BRANCHES}" | grep -q "${PPKG_GIT_RELEASE_BRANCH}" ) ]]; then 299 | _GIT_BRANCHES="${PPKG_GIT_RELEASE_BRANCH}"; 300 | debug "Tag found on the release branch ('${PPKG_GIT_RELEASE_BRANCH}')"; 301 | fi 302 | # Are there multiple something elses? Pick one and warn about it. 303 | fi; 304 | 305 | debug "_GIT_BRANCHES: '${_GIT_BRANCHES}'"; 306 | if [ `echo "${_GIT_BRANCHES}" | wc -l` == 1 ]; then 307 | # there is only one branch, use that! 308 | _GIT_BRANCH="${_GIT_BRANCHES}"; 309 | else 310 | warn "Multiple branches contain this commit! Defaulting to the first one"; 311 | _GIT_BRANCH="`echo "${_GIT_BRANCHES}" | head -n1`"; 312 | fi; 313 | fi; 314 | debug "_GIT_TAG: '${_GIT_TAG}'"; 315 | debug "_GIT_BRANCH: '${_GIT_BRANCH}'"; 316 | 317 | ##----- PACKAGE ENVIRONMENT -----## 318 | # environment has been specified. 319 | if [[ "${PPKG_ENVIRONMENT}" && "${PPKG_ENVIRONMENT}" != "GIT_BRANCH" ]]; then 320 | debug "Environment has been specified" 321 | # do we have a branch? 322 | elif [ "${_GIT_BRANCH}" ]; then 323 | # is it the release branch? 324 | if [ "${PPKG_MAP_ENVIRONMENTS}" ]; then 325 | PPKG_ENVIRONMENT=`_map_branch_to_environment $_GIT_BRANCH`; 326 | elif [ "${_GIT_BRANCH}" == "${PPKG_GIT_RELEASE_BRANCH}" ]; then 327 | # do we have a git tag? 328 | if [ "${_GIT_TAG}" ]; then 329 | # use it 330 | PPKG_ENVIRONMENT="${_GIT_TAG}"; 331 | else 332 | # warn there is no tag and use the branch name. 333 | warn "We are on the release branch but no tag has been set!" 334 | PPKG_ENVIRONMENT="${_GIT_BRANCH}"; 335 | fi 336 | else 337 | if [[ "${GIT_TAG}" && "${PPKG_ENVIRONMENT}" != "GIT_BRANCH" ]]; then 338 | PPKG_ENVIRONMENT="${_GIT_BRANCH}-${_GIT_TAG}" 339 | else 340 | PPKG_ENVIRONMENT="${_GIT_BRANCH}"; 341 | fi 342 | fi 343 | else 344 | # errrr dno what to do now! 345 | PPKG_ENVIRONMENT=""; 346 | err "No git branch detected. You should provide the environment name using the options or the PPKG_ENVIRONMENT variable" 347 | exit 1; 348 | fi 349 | debug "PPKG_ENVIRONMENT: '${PPKG_ENVIRONMENT}'"; 350 | 351 | ##----- PACKAGE PREFIX -----## 352 | PPKG_PREFIX_BASE="${PPKG_PREFIX_BASE-/etc/puppet/environments}"; 353 | debug "PPKG_PREFIX_BASE: '${PPKG_PREFIX_BASE}'"; 354 | 355 | PPKG_PREFIX="${PPKG_PREFIX-${PPKG_PREFIX_BASE}/${PPKG_ENVIRONMENT}}"; 356 | debug "PPKG_PREFIX: '${PPKG_PREFIX}'"; 357 | 358 | ##----- PACKAGE NAME -----## 359 | PPKG_NAME_PREFIX="${PPKG_NAME_PREFIX}" 360 | debug "PPKG_NAME_PREFIX: '${PPKG_NAME_PREFIX}'"; 361 | 362 | PPKG_NAME_BASE="${PPKG_NAME_BASE-puppet-tree}" 363 | debug "PPKG_NAME_BASE: '${PPKG_NAME_BASE}'" 364 | 365 | if [[ ! "${PPKG_NAME}" && "${PPKG_NAME_PREFIX}" ]]; then 366 | PPKG_NAME="${PPKG_NAME_PREFIX}-${PPKG_NAME_BASE}-${PPKG_ENVIRONMENT}"; 367 | fi 368 | PPKG_NAME="${PPKG_NAME-${PPKG_NAME_BASE}-${PPKG_ENVIRONMENT}}"; 369 | debug "PPKG_NAME: '${PPKG_NAME}'"; 370 | 371 | ##----- PACKAGE VERSION -----## 372 | if [ "${PPKG_VERSION}" == "GIT_TAG" ]; then 373 | PPKG_VERSION="${PPKG_DEFAULT_VERSION}" 374 | if [ "${_GIT_TAG}" ]; then 375 | PPKG_VERSION="${_GIT_TAG}"; 376 | else 377 | warn "requested to use the git tag as version but could not find a tag. falling back to default." 378 | fi; 379 | fi; 380 | PPKG_VERSION="${PPKG_VERSION-${PPKG_DEFAULT_VERSION}}"; 381 | debug "PPKG_VERSION: '${PPKG_VERSION}'"; 382 | 383 | ##----- PACKAGE ITERATION -----## 384 | #use jenkins stuff if available for the default value. 385 | _PPKG_DEFAULT_ITERATION="${BUILD_NUMBER-0}" 386 | PPKG_ITERATION="${PPKG_ITERATION-${_PPKG_DEFAULT_ITERATION}}"; 387 | debug "PPKG_ITERATION: '${PPKG_ITERATION}'"; 388 | 389 | ##----- PACKAGE TYPE -----## 390 | PPKG_TYPE="${PPKG_TYPE-rpm}"; 391 | debug "PPKG_TYPE: '${PPKG_TYPE}'"; 392 | 393 | ##----- GENERAL PACKAGE STUFFS -----## 394 | PPKG_VENDOR="${PPKG_VENDOR}"; 395 | PPKG_DESCRIPTION="${PPKG_DESCRIPTION}"; 396 | PPKG_CATEGORY="${PPKG_CATEGORY}"; 397 | PPKG_MAINTAINER="${PPKG_MAINTAINER}"; 398 | PPKG_URL="${PPKG_URL}"; 399 | PPKG_FPM_OPTIONS="${PPKG_FPM_OPTIONS}"; 400 | 401 | ##----- DEPENDENCIES -----## 402 | PPKG_DEPENDENCIES="${PPKG_DEPENDENCIES-puppet}"; #handled 403 | PPKG_CONFIGS="${PPKG_CONFIGS}"; 404 | PPKG_EXCLUDES="${PPKG_EXCLUDES-**/.git*}"; 405 | PPKG_PROVIDES="${PPKG_PROVIDES}"; 406 | 407 | 408 | #========================================================== 409 | # | o | 410 | # | ,---.,---..,---.,---.| 411 | # | | || ||| ,---|| 412 | # `---'`---'`---|``---'`---^`---' 413 | # `---' 414 | 415 | 416 | ## Building the command line for fpm. 417 | 418 | _ppkg_cmd="fpm -t ${PPKG_TYPE} -s dir -a all -n ${PPKG_NAME}"; 419 | _ppkg_cmd="$_ppkg_cmd -v ${PPKG_VERSION} --epoch=1 --iteration ${PPKG_ITERATION}"; 420 | [ "${PPKG_DESCRIPTION}" ] && \ 421 | _ppkg_cmd="$_ppkg_cmd --description '${PPKG_DESCRIPTION}'"; 422 | [ "${PPKG_URL}" ] && _ppkg_cmd="$_ppkg_cmd --url '${PPKG_URL}'"; 423 | [ "${PPKG_CATEGORY}" ] && _ppkg_cmd="$_ppkg_cmd --category '${PPKG_CATEGORY}'"; 424 | [ "${PPKG_VENDOR}" ] && _ppkg_cmd="$_ppkg_cmd --vendor '${PPKG_VENDOR}'"; 425 | [ "${PPKG_MAINTAINER}" ] && _ppkg_cmd="$_ppkg_cmd -m '${PPKG_MAINTAINER}'"; 426 | 427 | _ppkg_cmd="$_ppkg_cmd --prefix ${PPKG_PREFIX}"; 428 | _ppkg_cmd="$_ppkg_cmd `_build_deps_cmd`"; 429 | _ppkg_cmd="$_ppkg_cmd `_build_configs_cmd`"; 430 | _ppkg_cmd="$_ppkg_cmd `_build_excludes_cmd`"; 431 | [ -f "${PPKG_TARGET}/.ppkg-settings" ] && _ppkg_cmd="$_ppkg_cmd -x '.ppkg-settings'"; 432 | _ppkg_cmd="$_ppkg_cmd `_build_provides_cmd`"; 433 | _ppkg_cmd="$_ppkg_cmd ${PPKG_FPM_OPTIONS}"; 434 | _ppkg_cmd="$_ppkg_cmd -C ${PPKG_TARGET} ."; 435 | 436 | debug "PPKG_CMD: $_ppkg_cmd"; 437 | 438 | [ "${SCRIPTDEBUG}" ] && exit 0; 439 | 440 | eval $_ppkg_cmd; 441 | 442 | --------------------------------------------------------------------------------