So what I’ve typically seen done is: prod, uat, and dev use separate Chef environments. Jenkins/Bamboo/whatever CI tool you use takes git checkins and uploads the new cookbook versions to the server using Berkshelf. Each non-dev environment then has a set of cookbook pins so they are not impacted by new cookbooks being uploaded. Dev runs without pins and just relies on the dependency solver in Chef to get the most up to date cookbook versions that will play together. Once changes are tested in dev, then the pins are updated in UAT, and then promoted to production during your scheduled maintenance/patching/update/release cycle. Since roles and databags are not versioned, if those are a potential issue, swap out environments for organizations and operate that way instead.
If there are enough people working on Chef code and the risk of testing related changes is too high to impact the development environment, what I’ve done before is create a second organization. That organization is hooked up to your CI system through a separate branch (say “develop” versus “master”), and pushes updates to that organization (unless you skip that whole step and just have the devs upload directly to the test organization), where you have a set of test nodes to work with. On the other hand, if you’re doing strong enough testing locally with Vagrant / Test-Kitchen, a dedicated test organization may not be needed. (At the time it was faster to spin up a new VMWare VM than it was to launch a local VM and Docker didn’t work on Macs well with the boot2docker kludge… things are definitely different now and local development and testing is a lot easier to implement.)
Moxie Cloud Services (MCS)