Any code library requires proper documentation. Our own CloudObjects PHP SDK (which, among other things, wraps the Object API) is no exception. Without a properly automated process, however, documentation quickly becomes stale and no longer remains in sync with the actual implementation. I’d like to show you the process which we set up to automatically generate and publish documentation for the SDK as this might be useful for anyone releasing a PHP SDK or library.

phpDoc and Sami

The first tool in the chain is Sami, a documentation generator created by the folks behind the Symfony framework and also used for the API documentation of the framework itself. Sami extracts PHPDoc annotations from within the source code comments and builds static HTML pages out of them. PHPDoc annotations look something like this:

<?php /* ... */ /** * The ObjectRetriever provides access to objects on CloudObjects. */ class ObjectRetriever { /* ... */ /** * Get an object description from CloudObjects. * * @param IRI $coid COID of the object * @return Node|null */ public function getObject ( IRI $coid ) { /* ... */ } /* ... */ }

The goal of our process was that these annotations are the only thing that developers have to worry about. All steps from here to a deployed public website shall be automated. And the annotations are almost enough for Sami. The only additional required configuration for Sami was a tiny sami-config.php file which, in our case, looks like this:

<?php use Sami\Sami ; return new Sami ( './CloudObjects' , [ 'title' => 'CloudObjects PHP SDK' ]);

Of course we could do more customization but at the moment this is enough to get basic SDK API docs built.

The build process is part of our makefile :

.PHONY : all all : vendor build composer.lock : composer.json # Updating Dependencies with Composer composer update -o vendor : composer.lock # Installing Dependencies with Composer composer install -o sami.phar : # Get a copy of sami wget http://get.sensiolabs.org/sami.phar build : sami.phar # Building documentation with sami.phar php sami.phar update sami-config.php --force

As you can see we have included local installation of Sami as part of the process to ensure that the tool is available. Sami is distributed as a single-file PHAR (PHP archive). The update command parses the code based on the configuration and then renders the data into the build folder by default.

Continuous Integration (CI)

Every developer could trigger the documentation generator locally by typing make but we wanted this to run on a build server. As the SDK is on GitHub and open source it can easily be set up with the free hosted version of Travis CI. Travis is triggered on every commit through webhooks, clones the source and runs the steps defined in a special configuration file called .travis.yml . Here’s how ours looks:

language : php php : - ' 5.6' - ' 7.0' - hhvm - nightly before_script : make script : vendor/bin/phpunit --testsuite=OfflineTests

This file informs Travis that we’re building a PHP project. Running the build with different versions is not required for the documentation generator but as you can see we also have a PHPUnit testsuite running to make sure the SDK is properly unit-tested and works everywhere. As we had already integrated the documentation generator into our makefile there’s nothing Sami-specific in the Travis configuration file, just calling make is enough.

Continuous Delivery (CD)

Now the docs are being built but they are swept off again when Travis cleans up the environment. Obviously we need to save them somewhere to get them published. We’ve decided to deploy them to Surge, a very simple static hosting provider which also has a free plan. Travis even has Surge integrated as a deployment option so no custom deployment script is necessary. We just needed to add a deploy section to .travis.yml :

deploy : provider : surge skip_cleanup : true project : ./build/ domain : php-sdk-docs.cloudobjects.io on : php : ' 7.0'

As you can see from this, the contents of the build directory are deployed to php-sdk-docs.cloudobjects.io. Click the link, it works :) And it’s always up-to-date with the latest build!

For the first deployment the domain was set up using the surge command line tool locally. To tell Travis how to authenticate with Surge the credentials had to be added as environment variables in the Travis settings so that no credentials end up in the repository. As you’ve seen in the previous section the build process runs on multiple different versions of PHP. The deploy section is only triggered on one version because the generated docs do not differ so uploading them once is enough.

One limitation of Surge’s free plan is that there’s no SSL for custom domains. This can easily be overcome by running the site behind Cloudflare.

Future Enhancements

Right now the docs always stay in sync with the master of the project. Sami actually supports building docs for different versions, e.g. branches and release tags, so this is something we want to look into later, so that making a release on GitHub will also set up a static version of the docs for that version.

Final Remarks

Developers should always automate as much as possible when it comes to their build and documentation process. Thanks to powerful cloud-based services this is quite simple and often free for open source or smaller projects. I hope this article gave you some inspiration.