There are a few ways to validate CloudFormation templates, but I mostly use
cfn-lint. I run it in my build pipelines, but I also like to run it locally just so I don’t have to wait for a build to find out if I did a typo. I work on a lot of templates, though, and it’s easy to forget. I still end up finding out about simple errors after builds fail. Good news! Git can remember to do it for me.
My goal is to keep bad code out of the git history, so I want commits to fail if there are linting errors. For that we need
#!/usr/bin/env bash find . -type f -name "*\.yaml" | xargs cfn-lint
It must be executable:
chmod u+x .git/hooks/pre-commit
I bodged together a repo with some bad templates in it so you can see the output:
. └── templates ├── app1 │ └── working.yaml └── app2 └── broken.yaml
There’s a deliberate syntax error in
broken.yaml. If I try to commit:
git commit -m "Test cfn-lint pre-commit hook." E0000 Template needs to be an object. ./templates/app2/broken.yaml:1:1
… and there’s no commit. My changes are still just staged:
git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: templates/app1/working.yaml new file: templates/app2/broken.yaml
A few notes:
- You can ignore hook errors with the
--no-verifyflag. I use this when I need to break down my work into iterations of partially-working commits, then I go back and squash them in an interactive rebase.
- These hooks are unique to your clone, they don’t automatically copy to others. That’s fine for my cases because this is just my personal development process; the build jobs are the real gateway.
cfn-lintdoesn’t automatically descend into subdirectories, which is why I do a
- This only works if the hook script exits non-zero when there are errors. My
xargspattern does, but there are lots of patterns that don’t. If you use a
for/do/doneloop, for example, you can end up masking the return codes and the hook won’t block commits. If you modify the pattern for searching, make sure you test the failure cases.
- I always use the
.yamlextension for my templates, and typically they’re the only YAML files in my repo. If your case is more complex than that, you’ll need to modify the pattern for searching.
Need more than just this article? I’m available to consult.
You might also want to check out these related articles: