new moving parts, which is riskier. • Bigger means we spent more time working on it, meaning the time until delivery was longer. • Agile values trying lots of things, some of which are not going to work. • Agile values delivering things quickly. • Small & Frequent > Large & Infrequent
partial build process Automated tests with some coverage Deployment is still done manually Offers: Immediate feedback to merge issues Immediate feedback for test failures Testing contract is established Smaller, frequent low risk deployments minimum ~ several stories
is triggered to a ‘production like’ environment. Automated tests runs in that ‘production like’ environment. Features are immediately delivered back to stakeholders for feedback. Deployment is still done semi-manually. Offers: Faster feedback cycles. Time in transit for stories can drop. Minimizes risk of deployment errors or code that didn’t pass. CAN RELEASE RELIABLY AT ANY TIME minimum ~ one story
IS AUTOMATIC √ ON ACCEPTANCE √ ON TEST SUITE PASSING Offers: Deployment several times per hour. Smallest deployments, lowest risk. Potential User Fatigue. Feature Toggles. minimum ~ one line of code
everything works, every deploy Ability to release as frequently as appropriate Shorter time story life from request to deployment Better security: managed libraries get updates more frequently Easy for anyone to add test coverage / run tests No tacit knowledge needed by team members to develop or deploy No more ‘prod credential holders’ needed on the team
easier to maintain. Deploys become less and less scary. Professional development in executing best practices. Try new techniques on current projects. Possible to undo prior mistakes or the sins of others. Never have to write another autoloader. Never fix a bug more than once. (Regression tests are awesome.)
CI/CD were developed to service the needs of these business behaviors and roles. The Agile umbrella is not required for CI/CD. Besides, its much harder to change how an organization works. The software part is comparatively easy. Do that part.
to end solution takes a long time to build. Test suites take a long time to mature. Learning to write tests well is hard. Small projects can be converted in a day. Big projects may never completely convert.
has package.json JS build tool: • Bower, .bowerrc or bower.json, can also run composer • Grunt, gruntfile.coffee or gulpfile.js • Gulp, gulpfile.js or gulpfile.coffee Pick your favorite. Covered again in build tools.
entry points. Move external libraries/dependencies into composer and test. Unlink old copies and remove old “require/include” statements. Remove any symlinks. Remove PEAR dependencies.* Turn your shared libraries into composer packages. Composer legacy libraries into your apps. Update your old autoloaders to stop offering to load legacy libraries. Remove all contents of /vendor from VCS, append /vendor to .gitignore. Update CI config to run `composer install` before deployment, add auth token.
be managed by the JS manager. Update layouts to use the managed package versions. Split distribution files from site specific files. Delete all the crud. Add `node_modules` to .gitignore. Later in CI, use “npm-cache clean” and “npm-cache install npm”
use it when creating the tests. • Case sensitivity. Fixing class name => filename and path name => namespace conventions can be worked around. Required: • Maximum one file per class.* (need to verify) • Each class across a library must have a unique name. • Remove all the include*/require* statements.
• Front Controller Pattern: Single app entry point across the application, usually an index.php • The only require/include statement across the application is a single “require_once ‘vendor/autoload.php” if possible. Required:* • Use Relative Paths for any paths for File IO or Require statements. Ex: __DIR__ . ’/../autoload.php’, __FILE__ . ‘/../../error.log’ • Note a leading slash in the string after PHP special constants.
my app instantiates 2. PHP needs to create an object or use a method in some class 3. PHP begins to instantiate the class 4. PHP checks get_declared_classes() or its C equivalent 5. PHP checks spl_autoload_functions() for any registered autoloaders 6. PHP asks each autoloaders to service the request, in order of the autoloader stack 7. PHP is able to instantiate the class or throws a Fatal error
\Foo\Bar is in /src/Foo/Bar.php spl_autoload_register(function ($className) { if (strncmp($className, ‘Foo', 3) !== 0) { //DO NOT BE GREEDY return; //return early, return often } require_once(__DIR__.’/src/’.str_replace(“\\”, “/”, $className).’.php’; });
known ways to specify a namespace in composer. Excellent for consuming legacy libraries that are ‘broken’. Use it when: • Class are snowflakes instead of class name => file name pairs. • The code base has case sensitivity inconsistencies. • The app doesn’t follow front controller pattern. • Renaming would break other dependent applications. (MVCS example) • Too many source files to fix. • Cannot modify source class files.
able to modify & test the code being managed by composer as a dependency, but maintained by your team. Not recommended: You can modify files live in vendor, and push changes upstream. But composer cannot update libs when there are mods, and “require-dev” was not installed in /vendor, so testing is not possible. Recommended: (package swap) Move <lib> to <lib>2, symlink and tell IDE to ignore <lib>2. Add an ant target or shell script to swap the symlink and editable copy on demand.
all dependencies from local to CI • Check in `composer.phar` • Check in `composer.lock` • Add vendor to .gitignore • CI should always call ‘composer install’ • Deployment to prod does not run composer
API limit on github.com to retrieve just ZF2 libraries • Author user API limit is much higher • A ‘Personal Access Token’ allows composer to auth • Add a ‘personal access token’ for each CI project composer config github-oauth '{"github.com":"<token>"}'
Examples: • Building Angular, Ember, Grunt, Gulp, SASS, Compass • Launching VMs and services (apache, mysql, selenium) • Launching tests and running against different environments (target servers) • Reloading development datasets and schemas • Rsync/scp files to our production servers
ant maven make gradle The tool doesn’t matter that much. Whichever makes you most effective (kind of the whole point). Tool chains can be mix-and-match for V1, but don’t use too many. Too many scripts = spaghetti deployments and black magic.
and conditional logic are supported. Low barrier to entry, lots of documentation. A build.xml file is composed of targets. Settings can be put in a separate build.properties file. Targets can call other targets or targets in other build scripts. Targets can be executing on remote servers or local. Plays nice with CI servers.
-4, 22.3, true, 1, ….]; False: [null, false, 0, ...]; OS return code logic: Success: $? == 0; Failure: $? == anything but zero `$?` is the last return code A php script succeeded if the script calls exit(0); or exit(); A php script should fail with: exit(1); or exit(‘anything’); An uncaught exception will also a fail. The exception code will be the return code.
and commit) Runs the build scripts Build script calls dependency managers Build script calls test suites Evaluates return codes at each step Evaluates test result files (junit.xml) Radiates success or failure Deploys code to production Bold is minimum req for CI. The rest indicate CD.
and easy, integrates with Github, badges, $$$, good first party docs Jenkins/Hudson CI - self hosed WAR, open source, harder setup, messy UI, lots of stackoverflow docs. SaaS offerings available. Bamboo - self hosted or cloud, works with JIRA/BitBucket/ Hipchat. Good APIs Team City - self hosted. Jetbrains offering. Mentioned because we like PHPStorm Plenty of fish to choose from...
of a build. Different events should happen at different times. Each can have its own script or ant target. Common events: pre-deploy: checkout latest code, run dependency managers, compile assets, inject db credentials, and hostname deploy: copy the code to the production like target post-deploy: server specific stuff, kick apache, restart memcache Test suite launch happens after post-deploy. prod-post-deploy: happens only on prod, usually to inject prod credential
variables. PHPUnit ::setup() should read them and setup selenium grid connections and baseurl. Selenium… docker : hostnames, dbs, build numbers. Auth.json for composer
list of environments • Connected to VCS • Can accomplish per target machine: • rsync (and tag with the commit) • advancement of symlink pointers • revert (reset symlink pointers) • verify actions completed successfully • Optional: All team members can self-serve Check out AWS PHP SDK.
and fail. Stop upgrading. Replace. If your servers are pets, think about saying goodbye. Move away from setup and over to provisioning. Provision from an AMI, apply a saltstack profile, deploy code.
prod” problem. • Container per service. • Extremely fast to provision. • Lower footprint than our Vagrant mono-container. • Developers check in a container. • CI tests run against the container, not the code. • A container is ‘promoted’ to production, vs code ‘deploy’.
1 million free per month, $.20 per million requests • No servers or infrastructure to manage • Code has access to S3, RDS, dynamodb, Redshift • Can be triggered event or called by service aggregator • HTTP endpoints • Supports Node JS, Java 8, Python
several times per minute. Zero or Infinite fatigue risk. • B2B (to Business): interacts several times per month. Easily fatigued. • B2C (to Customer): interacts for one session per year. Zero fatigue risk. • B2D (to Department): interacts several times per day, high savvy. Variable fatigue risk.
plan to try again • Currently high Self Serve, 1 devops per 10 engineers • Devs are snowflakes. Some will never have devops needs, some will need stuff every day. • Hip chat bot for us
greenfield project • Add composer.phar to the project • Composer init, add phpunit as a dependency • Create two namespaces under /src & /test in composer.json • Write some tests and create a phpunit.xml in / • Install a build tool and target that invokes phpunit in /vendor, and outputs using TAP • Push the project to github as a public project https://help.github.com/articles/create-a-repo/ • Connect it to a commercial CI server (Travis CI) • Add a .travis.yml file http://docs.travis-ci.com/user/languages/php/ • Fix config until the build passes • Add a README.md with build passing badges • Compare with https://github.com/matt-land/test-samples if stuck