Within the Chef ecosystem there is a utility called Cookstyle, this is a derivative of rubocop and provides static code analysis to Chef-Infra Cookbooks and other Ruby based chef tools. This is great and enables chef-infra customers to have cookbooks that are inline with chef's recommended best practices, reducing misconfiguration and ensuring a smoother upgrade process to newer versions of Chef-Infra.
Stylelia builds on cookstyle by removing the need to run cookstyle manually on repositories for newer releases of cookstyle. It does this by checking out a targetted repo and running cookstyle on it, if there are changes it then opens a pull request to the upstream repository on GitHub, leaving the developers to review and merge the changes. This removes the concerns in a CI pipeline of being out of date with the latest cookstyle recommendations and means that when people go to write new business value in cookbooks they only need to focus on the code they are writing and not if the existing cookbook is inline with Chef's cookstyle recommendations.
The real point here is to remove the toil of running cookstyle from the developers concerns. With a great test suite it could even be fully automated with reviews and merges so no human interaction would be required. Though these cookbook test suites and automated reviews are out of the scope of this solution.
How does it Automate for Good?
It removed the toil from having to keep a repo up to date with best practices manually, therefore enabling developers to spend more time on the features that customers/users desire. By using this tool we expect:
- Upgrades of Chef-Infra to be easier, as they are already in line with best practice
- Developers to write more tests so these types of changes can be merged in quicker thus promoting more stable applications
- A reduction in security related threats that cookstyle handles as these will be quickly picked up and resolved, such as: https://docs.chef.io/workstation/cookstyle/chef_modernize_chefgemnokogiri/ where users not longer need to maintain the versions of the nokogiri gem
- Improvements in Chef-Inspec code maintainability as cookstyle also supports inspec profiles.
How we built it
Language of choice was Golang due to it being a language which Jason wanted to learn more of as well as how it is easy to get up and running. While Stylelia is currently built for lambda it would be easy to have it run on any OS due to the choice of Golang
The Cache stores the current Default branch Commit Sha and the version of cookstyle used at that time. We explicitly check the default branch as not every branch is named
main. If there is a difference between the cache and the current state or the repository does not exist in the cache then cookstyle is run. If a difference is detected then a pull request is created. If a pull request already exists we rebase the branch and update the Pull Request text to be a true reflection of the changes.
Challenges we ran into
Re-running the same changes time and time again was a waste of computing resources, so we built a cache to help us handle this. We can check the cache for the tool version or for the current commit sha and then decide if we actually need to run anything. This helps us reduce our costs with AWS Lambda
Local running for development was challenging with lambda until we found the lambci/lambda images which allowed us to make iterations much faster locally
Accomplishments that we're proud of
- Full unit testing throughout the application to ensure it works as we expect
- Good commit messages to ensure end users understand what is going on
- Quick local development time
What we learned
- Learnt golang from having very little understanding of the language
- Expanded knowledge of Lambdas
- Wrote his first ever Cache solution in Redis
- Learnt about chef and the ecosystem having never used chef before
- Understands more about rubocop, cookstyle and ruby based static linting
What's next for Stylelia
- Expand Stylelia to run other static code tools like rubocop
- Change to using a GitHub App instead of personal token
- Currently everything is done within 1 lambda, we will be splitting this out so it can run at higher scale based on async queues
- Allow users to request/submit other tools they want it to run
- Start a business for static code analysis fixers