Your SlideShare is downloading. ×
0
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Building and Deploying PHP apps with Phing
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Building and Deploying PHP apps with Phing

2,426

Published on

Slides of the talk that I gave during PHP Johannesburg 2014 …

Slides of the talk that I gave during PHP Johannesburg 2014

https://joind.in/talk/view/10411

Manually creating builds and running deployments can be scary, tedious, error-prone, boring, stressful (check all that apply). What you need is a tool that helps automate the necessary steps to build, test, package and deploy your app.

During this talk you will be introduced to the workings of Phing, it's rich set of out-of-the-box tasks and easy extensibility. Step by step, you will learn how to write a comprehensive deployment script. A number of demonstrations will cover testing, packaging, database migration, continuous integration, multi-server deployments and other real-world use cases.

Published in: Software, Technology
0 Comments
9 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,426
On Slideshare
0
From Embeds
0
Number of Embeds
10
Actions
Shares
0
Downloads
38
Comments
0
Likes
9
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Building and deploying PHP apps with >< >< Michiel Rook PHP Johannesburg April 2014
  • 2. About me • Freelance PHP & Java contractor / consultant • PHP since '99 • Phing project lead • Dutch Web Alliance • http://www.linkedin.com/in/michieltcs • @michieltcs
  • 3. This talk • Why a build tool • What is Phing • Usage • Various examples • Deployments • Extending Phing
  • 4. Why a build tool?
  • 5. This is PHP!?
  • 6. Repetitive tasks • Version control • Database changes • Testing • Minifying • Packaging • Uploading • Deploying • Configuring
  • 7. Good programmers are lazy
  • 8. Good programmers automate repeatable things
  • 9. Automate! • Easier handover • Improves quality • Reduces errors • Saves time • Consolidate scripts, reduce technical debt
  • 10. What is Phing?
  • 11. Phing is AWESOME
  • 12. What is Phing? • “PHing Is Not GNU make; it's a PHP project build system or build tool based on Apache Ant.” • XML build files • Mostly cross-platform • Integrates various popular (PHP) tools • Lots. Of. Tasks.
  • 13. "Phing is good glue"
  • 14. The basics
  • 15. Installing Phing • PEAR installation $ pear channel-discover pear.phing.info $ pear install [--alldeps] phing/phing • Optionally, install the documentation package $ pear install phing/phingdocs • Composer • Phar package
  • 16. Build file • XML • Contains standard elements • Task: performs a specific function (copy, git commit, etc.) • Target: collection of tasks, can optionally depend on other targets • Project: root node, contains multiple targets
  • 17. Example build file <project name="Example" default="world"> <echo>Hi!</echo> <target name="hello"> <echo>Hello</echo> </target> <target name="world" depends="hello"> <echo>World!</echo> </target> </project>
  • 18. Example build file $ phing [-f build.xml] Buildfile: /home/michiel/phing/build.xml [echo] Hi! Example > hello: [echo] Hello Example > world: [echo] World! BUILD FINISHED
  • 19. Properties • Simple key-value pairs • ${attribute} • Replaced by actual value
  • 20. Properties <project name="Example" default="default"> <target name="default"> <property file="build.properties" /> <property name="foo" value="bar" /> <echo>${foo}</echo> </target> </project>
  • 21. Properties $ phing Buildfile: /home/michiel/phing/build.xml Example > default: [echo] bar BUILD FINISHED
  • 22. Fileset • Denotes a group of files • Include or exclude files based on patterns • References: define once, use many
  • 23. Fileset <copy todir="build"> <fileset dir="./application"> <include name="**/*.php" /> <exclude name="**/*Test.php" /> </fileset> </copy> <fileset dir="./application" includes="**"/> <fileset dir="./application" includes="**" id="files"/> <fileset refid="files"/>
  • 24. Fileset • Selectors allow fine-grained matching on certain attributes • contains, date, file name & size, ... <fileset dir="${dist}"> <and> <filename name="**"/> <date datetime="01/01/2011" when="before"/> </and> </fileset>
  • 25. Conditions • Nested elements that evaluate to booleans • Used in "condition", "if" and "waitfor" tasks
  • 26. Conditions <if> <equals arg1="${foo}" arg2="bar" /> <then> <echo message="The value of property foo is bar" /> </then> <else> <echo message="The value of property foo is not bar" /> </else> </if>
  • 27. Conditions <if> <available file="composer.json" /> <then> <exec checkreturn="true" command="composer install" passthru="true" logoutput="true" dir="build" /> </then> </if>
  • 28. Examples
  • 29. Examples • Version control • Unit testing • Packaging • Deployment • Database migration • Continuous integration
  • 30. Version control • Git • SVN • CVS
  • 31. Version control <svnexport repositoryurl="svn://localhost/project/trunk/" todir="/home/michiel/dev"/> <svnlastrevision repositoryurl="svn://localhost/project/trunk/" propertyname="lastrev"/> <echo>Last revision: ${lastrev}</echo>
  • 32. Version control <gitcommit repository="/home/michiel/dev/phing" message="Update documentation" allFiles="true"/> <gitpush repository="/home/michiel/dev/phing" refspec="master" tags="true" />
  • 33. PHPUnit • Built-in support for most configuration options • Gathers code coverage information • Various output formats / reports • PHPUnit 4.x support soon!
  • 34. PHPUnit • Stop the build when a test fails <phpunit haltonfailure="true" haltonerror="true" bootstrap="my_bootstrap.php" printsummary="true"> <batchtest> <fileset dir="src"> <include name="**/*Test.php"/> </fileset> </batchtest> </phpunit> Buildfile: /home/michiel/phpunit/build.xml Demo > test: [phpunit] Total tests run: 1, Failures: 1, Errors: 0, Incomplete: 0, Skipped: 0, Time elapsed: 0.00591 s Execution of target "test" failed for the following reason: /home/michiel/phpunit/build.xml:3:44: Test FAILURE (testSayHello in class HelloWorldTest): Failed asserting that two strings are equal.
  • 35. PHPUnit example • Determine which files to include in the coverage report <coverage-setup database="reports/coverage.db"> <fileset dir="src"> <include name="**/*.php"/> <exclude name="**/*Test.php"/> </fileset> </coverage-setup> • Gather code coverage and other data during the test run <phpunit codecoverage="true"> <formatter type="xml" todir="reports"/> <batchtest> <fileset dir="src"> <include name="**/*Test.php"/> </fileset> </batchtest> </phpunit>
  • 36. PHPUnit example • Generate some reports <phpunitreport infile="reports/testsuites.xml" format="frames" todir="reports/tests"/> <coverage-report outfile="reports/coverage.xml"> <report todir="reports/coverage" title="Demo"/> </coverage-report>
  • 37. Documentation • Phing currently integrates with popular documentation tools • phpDocumentor (2) • ApiGen • Also supports r(e)ST (reStructuredText) <phpdoc2 title="Phing API Documentation" output="docs"> <fileset dir="../../classes"> <include name="**/*.php"/> </fileset> </phpdoc2>
  • 38. phpDocumentor
  • 39. Packaging • Create bundles or packages • tar • zip • phar • PEAR
  • 40. Tar / zip <tar compression="gzip" destFile="package.tgz" basedir="build"/> <zip destfile="htmlfiles.zip"> <fileset dir="."> <include name="**/*.html"/> </fileset> </zip>
  • 41. Phar packages <pharpackage compression="gzip" destfile="test.phar" stub="stub.php" basedir="."> <fileset dir="hello"> <include name="**/**" /> </fileset> <metadata> <element name="version" value="1.0" /> <element name="authors"> <element name="John Doe"> <element name="e-mail" value="john@example.com" /> </element> </element> </metadata> </pharpackage>
  • 42. SSH <ssh username="john" password="smith" host="webserver" command="ls" /> <scp username="john" password="smith" host="webserver" todir="/www/htdocs/project/"> <fileset dir="test"> <include name="*.html"/> </fileset> </scp>
  • 43. Jenkins
  • 44. Jenkins
  • 45. Jenkins
  • 46. Putting it all together
  • 47. Build & deploy script Objectives: • Perform syntax check • Run tests • Create package • Deploy via SSH • To selectable target / environment • Update database • Roll back
  • 48. Syntax checks & tests <phplint haltonfailure="true"> <fileset dir="."> <include name="src/**" /> </fileset> </phplint> <phpunit haltonfailure="true"> <batchtest> <fileset dir="."> <include name="src/**/*Test.php" /> </fileset> </batchtest> </phpunit>
  • 49. Packaging <tstamp> <format property="build.timestamp" pattern="%Y%m%d%H%M%S"/> </tstamp> <property name="build.release" value="${project.name}-${build.timestamp}" /> <property name="package.name" value="${build.release}.tar.gz" /> <tar destfile="artifacts/${package.name}" basedir="${build.dir.project}" />
  • 50. Multiple targets • Several deployment targets: testing, staging, production, ... • One property file per target • Select based on input ssh.host=127.0.0.1 ssh.username=phing ssh.key.private=development-ssh ssh.key.public=development-ssh.pub deploy.location=/home/phing/apps
  • 51. Multiple targets <input propertyname="deploy.target" validArgs="testing,staging,production"> Enter target name </input> <property file="${deploy.target}.properties"/>
  • 52. Uploading <ssh host="${ssh.host}" username="${ssh.username}" privkeyfile="${ssh.key.private}" pubkeyfile="${ssh.key.public}" command="mkdir -p ${deploy.location.project}/${build.release}" failonerror="true" /> <echo>Copying package</echo> <scp host="${ssh.host}" port="${ssh.port}" username="${ssh.username}" privkeyfile="${ssh.key.private}" pubkeyfile="${ssh.key.public}" todir="${deploy.location.project}/${build.release}" file="${package.name.full}" />
  • 53. Uploading <echo>Extracting package</echo> <ssh ... command="cd ${deploy.location.project}/${build.release}; tar xzf ${package.name}" failonerror="true" />
  • 54. Symbolic links • All releases stored in separate directories • Symlink "current" to latest release • Allows for easy (code) rollbacks <echo>Creating symbolic link</echo> <ssh ... command="cd ${deploy.location.project}; if [ -h "current" ]; then rm -f previous; mv current previous; fi; ln -s ${build.release} current" />
  • 55. Database migration • Set of delta SQL files (1-create-post.sql) • Tracks current version of your db in changelog table • Generates do and undo SQL files CREATE TABLE changelog ( change_number BIGINT NOT NULL, delta_set VARCHAR(10) NOT NULL, start_dt TIMESTAMP NOT NULL, complete_dt TIMESTAMP NULL, applied_by VARCHAR(100) NOT NULL, description VARCHAR(500) NOT NULL )
  • 56. Database migration • Delta scripts with do (up) & undo (down) parts --// CREATE TABLE `post` ( `title` VARCHAR(255), `time_created` DATETIME, `content` MEDIUMTEXT ); --//@UNDO DROP TABLE `post`; --//
  • 57. Database migration <dbdeploy url="sqlite:test.db" dir="deltas" outputfile="deploy.sql" undooutputfile="undo.sql"/> <pdosqlexec src="deploy.sql" url="sqlite:test.db"/> [dbdeploy] Getting applied changed numbers from DB: mysql:host=localhost;dbname=demo [dbdeploy] Current db revision: 0 [dbdeploy] Checkall: [pdosqlexec] Executing file: /home/michiel/dbdeploy/deploy.sql [pdosqlexec] 3 of 3 SQL statements executed successfully
  • 58. Database migration -- Fragment begins: 1 -- INSERT INTO changelog (change_number, delta_set, start_dt, applied_by, description) VALUES (1, 'Main', NOW(), 'dbdeploy', '1-create_initial_schema.sql'); --// CREATE TABLE `post` ( `title` VARCHAR(255), `time_created` DATETIME, `content` MEDIUMTEXT ); UPDATE changelog SET complete_dt = NOW() WHERE change_number = 1 AND delta_set = 'Main'; -- Fragment ends: 1 --
  • 59. Database migration -- Fragment begins: 1 -- DROP TABLE `post`; --// DELETE FROM changelog WHERE change_number = 1 AND delta_set = 'Main'; -- Fragment ends: 1 --
  • 60. Restart services <ssh ... command="sudo service apache2 reload" failonerror="true" />
  • 61. Rolling back <trycatch> <try> <ssh ... command="cd ${deploy.location.project}; rm -f current; mv -f previous current" failonerror="true" /> <echo>Rollback complete</echo> </try> <catch> <echo>No previous version deployed!</echo> </catch> </trycatch>
  • 62. Extending Phing
  • 63. Writing your own task • Extend from Task • Contains main() method and optionally init() • Setter method for each attribute in the build file
  • 64. Our new task should • Accept filesets • Count number of lines in each file • Fail the build if a file with zero lines is found
  • 65. Our new task <?php require_once 'phing/Task.php'; class CountLinesTask extends Task { public function main() { $foundEmpty = false; if ($foundEmpty) { throw new BuildException("One or more files have zero lines"); } } }
  • 66. Injecting file sets private $_filesets = array(); /** * Creator for _filesets * * @return FileSet */ public function createFileset() { $num = array_push($this->_filesets, new FileSet()); return $this->_filesets[$num-1]; }
  • 67. Injecting file sets foreach ($this->_filesets as $fileset) { $files = $fileset->getDirectoryScanner($this->project) ->getIncludedFiles(); $dir = $fileset->getDir($this->project)->getAbsolutePath(); foreach ($files as $file) { $path = realpath($dir . DIRECTORY_SEPARATOR . $file); $lines = count(file($path)); $this->log($path . ": " . $lines . " line(s)"); if ($lines == 0) { $foundEmpty = true; } } }
  • 68. Using the task <project name="Count Lines" default="count"> <target name="count"> <taskdef name="countlines" classpath="/home/michiel/tasks" classname="CountLinesTask" /> <countlines> <fileset dir="."> <include name="**/*.txt" /> </fileset> </countlines> </target> </project>
  • 69. Using the task Buildfile: /home/michiel/examples/count.xml Count Lines > count: [countlines] /home/michiel/examples/empty.txt: 0 line(s) [countlines] /home/michiel/examples/lines.txt: 3 line(s) Execution of target "count" failed for the following reason: /home/michiel/examples/count.xml:7:20: One or more files have zero lines BUILD FAILED /home/michiel/examples/count.xml:7:20: One or more files have zero lines Total time: 0.0454 seconds
  • 70. Alternative: Ad Hoc <target name="main"> <adhoc-task name="foo"><![CDATA[ class FooTask extends Task { private $bar; public function setBar($bar) { $this->bar = $bar; } public function main() { $this->log("In main(): " . $this->bar); } } ]]></adhoc-task> <foo bar="TEST"/> </target>
  • 71. Where to go from here • Tool versions • Performance • Documentation • PHP 5.3/5.4/5.5 • IDE support • CI integration
  • 72. Questions? Example code at https://github.com/mrook/phing-examples Please leave feedback at https://joind.in/10411 Contact us on: http://www.phing.info #phing (freenode) @phingofficial Thank you!

×