Automate your Sculpin publishing
After Sculpin proved himself to be a team player, I wondered if we could make him do one more thing — together with Travis CI, take care of our deployments.
Static sites, like ours, are very easy to deploy. Just type in:
rsync -rv /local/sculpin/output_prod email@example.com:/srv/www
and presto! Deployed!
That is simple enough, but it should be even simpler! Since Sculpin is heavy user of Symfony Console, it is only logical that deployment should be in realm of:
and presto! Deployed!
But it is still not simple enough. You have to juggle public keys on deployment server. If someone adds a new PR, you have to merge it, pull changes, generate and publish whole site, making it impossible if you are for example on mobile phone.
First, you need to prepare Sculpin. Assuming that you are currently using Sculpin installed globally (in /usr/local/bin or something else in $PATH) first thing that you need is to switch it to local installation through Composer. Rename your sculpin.json to composer.json and add the following packages.
After installation, you will be using /vendor/bin/sculpin instead of sculpin.
Next up, prepare your project for Travis CI by adding .travis.yml file:
You have to run composer install before everything else — that is why we put it in “install part” of .travis.yml file. We also have to provide some sort of testing mechanism. Usually, people use phpunit, but as our static site does not have any unit test we will rely on sculpin generate to exit with 0 (zero) if everything is OK and that should signal Travis that build should be green.
At this point, everything should work. By everything I mean — add a new commit, push it to repo, Travis CI picks it up and builds it. If not, double check everything, especially if Build pushes option is turned on in settings.
Now comes the tricky part, making Travis CI to upload generated files to our server. We added a simple publish Command, nothing fancy just a wrapper around rsync that will pick up server name and directory from configuration or PHP environment. To use it, you will need to generate and add SSH keys to production server as this will allow connecting without any interaction (no password inputs, etc.). Generate a new SSH key (avoid using your own ☺) and make sure you do not set a passpharse as that causes deployment to hang waiting for user input. SSH key generation is done with ssh-keygen.
You will end up with two files: travis_id_rsa and travis_id_rsa.pub. Add travis_id_rsa.pub to .ssh/authorized_keys on production server under user you use to access it. That was straightforward part. Next, we will base64 encode travis_id_rsa.
Then we need to encrypt travis_id_rsa_base64 and put it into .travis.yml. We are using travis client so install it if you haven’t already.
You should end up with your .travis.yml file filled with encrypted SSH key at the end. It should look like this (you need to format and add env/global part yourself).
We will use this information to recreate private key inside each Travis CI build. If you look closely at your build log, you will notice that it now contains a lot of id_rsa_XX vars.
Now we have to reverse the process, paste all those values together, decode them and put them in .ssh/id_rsa. Add following code into your before_script part of .travis.yml file.
Last two lines are needed to avoid any kind of waiting for user input that will hang the build. Usually, OS likes to ask for passphrase if id_rsa is readable by anyone other than owner. Also, by adding “StrictHostKeyChecking no” you avoid being prompted for confirming the authenticity of the host that you are connecting to.
Commit all that, push it and presto! Watch how your website is automatically deployed! If not, I probably made a typo or skipped a step — please let me know so I can update.
Now, we just need to setup some sort of staging server where anyone that submitted a PR could see what they did, even without local Sculpin installation… but that is another story.