The whole idea of Puppet is to put your machine configuration scripts in a versioned repository. This is good because I've found that a syntax error on a manifest not even used by the current machine will stop the puppet updates from running. One error anywhere kills the whole thing everywhere. So, being able to back out of a change is good.
We can go one better however and keep people from checking in files that aren't syntactically correct using the pre-commit hook in SVN. If you don't use SVN, your repository probably has something similar.
I followed these instructions for the hook and these instructions for installing it.
I ran into a problem however. The pre-commit script wasn't reporting an error condition correctly. I'm not sure what was wrong. Running the puppet command on the command line and then checking $? gave a "1", but inside the script it wasn't working that way. So, I punted and wrote the error output to a file and checked whether or not the file existed and then just cat'd that out to standard err. Messy, but it worked and I need to go home. Here's the file as modified by me:
#!/bin/bash # SVN pre-commit hook to check Puppet syntax for .pp files PATH="/usr/bin:/bin" REPOS="$1" TXN="$2" tmpfile=`mktemp` errfile=`mktemp` export HOME=/ SVNLOOK=/usr/bin/svnlook $SVNLOOK changed -t "$TXN" "$REPOS" | awk '{print $2}' \\ | grep '\\.pp$' | while read line do $SVNLOOK cat -t "$TXN" "$REPOS" "$line" > $tmpfile if [ $? -ne 0 ] then echo "Warning: Failed to checkout $line" >&2 fi /usr/bin/puppet --color=false --confdir=/tmp \\ --vardir=/tmp --parseonly --ignoreimport $tmpfile \\ >$errfile 2>/dev/null if [ -s $errfile ] then echo "Puppet syntax error in $line." >&2 cat $errfile >&2 exit 2 fi done res=$? rm -f $tmpfile rm -f $errfile if [ $res -ne 0 ] then exit $res fi
Note: you may need to combine lines separated by "\\\\" into a single line.
This works great. Syntax errors are caught before they make it into the repository. I'm still looking for a good way to thoroughly test puppet scripts before they get into the production servers. If you have any best practices in that area, I'd love to hear about them.