Slide 1

Slide 1 text

Development workflow

Slide 2

Slide 2 text

$developer Matthieu Moquet MattKetmo The quality guy Yoann Brault Opium84

Slide 3

Slide 3 text

What is BlaBlaCar ?

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

…and more than 200 white-label websites.

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

Benefits Less CO2 Social++ Less traffic Low cost

Slide 8

Slide 8 text

3 000 000 members A large community

Slide 9

Slide 9 text

8 countries § France § Spain § Italy § UK § Poland § Portugal § Netherlands § Benelux

Slide 10

Slide 10 text

50 millions 25 millions January 2008 January 2013 Growth Page views.

Slide 11

Slide 11 text

Infrastructure ü 2  physical  fronts   ü 1  MySQL  master  +  4  slaves  SSD   ü 1  private  cloud  (KVM  +  Open  vSwitch)   o  Redis   o  Memcache   o  RabbitMQ/workers   ü 1  cluster  ElasEcSearch  

Slide 12

Slide 12 text

Why migrate to Symfony?

Slide 13

Slide 13 text

…quand je dois corriger un bug dans du code "historique" Source: http://lesjoiesducode.tumblr.com

Slide 14

Slide 14 text

Why migrate to Symfony2 ? §  « Separation of concerns » §  Services isolation (Bundles/Components) §  Unit & functional tests §  Scalability/maintainability o Modern Framework PHP 5.3+ o Active community o SensioLabs expertise

Slide 15

Slide 15 text

How to migrate to Symfony?

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

Migration Strategy 2 applications with same database

Slide 18

Slide 18 text

OLD   NEW   Progressive Migration

Slide 19

Slide 19 text

Behind the scene…

Slide 20

Slide 20 text

Development Workflow

Slide 21

Slide 21 text

A day at BlaBlaCar… •  Up to 15 deployments per days •  Default environment is localhost •  Common development server •  Fast reaction time

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

Workflow git Branching  model:   ü  dev ü  preprod ü  master   §  Cherry-­‐pick  to  deploy   §  Branch  for  long  features  

Slide 24

Slide 24 text

Workflow git : the bad parts •  Discontinuous workflow à May cause inconsistencies •  It complicates long features •  Intermediate branches are boring

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

Git Flow Consistent workflow, but not adapted to our needs

Slide 27

Slide 27 text

GitHub Flow « We typically deploy dozens of times per day and ship new features regularly » — Brian Doll http://scottchacon.com/2011/08/31/github-flow.html

Slide 28

Slide 28 text

Tools (before) Issue tracker Repository manager Pull Request Code Review Continuous Integration Trac gitolite (Internal) pmsipilot/Crew Jenkins

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

Tools (now) Issue tracker Repository manager Pull Request Code Review Continuous Integration Jira Stash Stash Stash Bamboo

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

Internal organization ü Product team conceives features and creates Jira tickets ü Tickets are distributed to developers each week ü Developers resolve those tickets (captain obvious) ü Product team validates the implementation ü Q/A team checks everything works ü Minidevs are for Friday

Slide 34

Slide 34 text

ü How does the product team validate the changes? ü How does the Q/A team check everything works as expected? GitHub Flow, That’s cool, but…

Slide 35

Slide 35 text

Prototypes

Slide 36

Slide 36 text

Prototypes GOAL Make available any branch on our development servers HOW? – API REST Symfony2 – Javascript client – PHP Workers

Slide 37

Slide 37 text

How Prototypes works? $ git checkout -b hipster-feature # commit code... $ git push origin hipster-feature

Slide 38

Slide 38 text

No content

Slide 39

Slide 39 text

Environments $debug !$debug DEV PROD

Slide 40

Slide 40 text

Loads of time saved ü Easy access to dev or prod database ü Product & Q/A team can test a branch directly with « real » data ü We can debug production with the Symfony WDT (Web Debug Toolbar)

Slide 41

Slide 41 text

Summary Code à Test à Review à Deploy à Validate à Merge

Slide 42

Slide 42 text

…quand j’ai une idée de feature Source: http://lesjoiesducode.tumblr.com

Slide 43

Slide 43 text

Translations

Slide 44

Slide 44 text

Translations workflow RULE #1 o Translations must be editable at any moment o Developers are not required to update translations à  Save translations in database

Slide 45

Slide 45 text

Translations workflow RULE #2 •  Do NOT "SELECT * From translations" for each HTTP request •  Keep translations app cache in each frontal server à  Only keep token in Redis

Slide 46

Slide 46 text

Translations workflow HTTP   Request   TranslaEon   Service   isFresh()   false   SELECT translations   Update   app/cache   $lastModified >= $redis->get('last_modif') ? true : false;  

Slide 47

Slide 47 text

Translations workflow ü  Once  the  feature  is  finished,  the  branch  is  waiEng  for   the  product  &  Q/A  team  validaEon   ü  Meanwhile,  internaEonal  team  translates  all  the  new   strings     ü  Before  merging  to  master,  the  new  strings  have  already   been  translated   ü  At  any  moment  they  can  be  updated,  even  aVer  a   deployment  

Slide 48

Slide 48 text

ü  FULLTEXT search tool ü  Debug mode How to find the right translations keys?

Slide 49

Slide 49 text

Translator DebugMode // AcmeBundle/Translator.php class Translator extends BaseTranslator { protected $debugMode; public function trans($id, $parameters, $domain = 'messages', $locale = null) { if ($this->debugMode) { return $id; } return parent::trans($id, $parameters, $domain, $locale); } } // AcmeBundle/DebugListener.php public function onKernelRequest(GetResponseEvent $e) { $request = $e->getRequest(); if (/* put your own logic here */) { $this->translator->setDebug(true); } }

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

Emailing

Slide 52

Slide 52 text

Rendering emails GOAL •  Display any email without having to perform the associated actions •  See the rendering with different locales or with DebugMode à  Let’s make an interface for that…

Slide 53

Slide 53 text

Email Renderer Interface interface EmailRendererInterface { /** * @return string */ public function getTemplate(); /** * @return Form */ public function getForm(); } public function renderAction(Request $request) { $renderer = // ... $form = $renderer->getForm(); if ('POST' === $request->getMethod() && $form->bind($request)->isValid()) { return $this->render($renderer->getTemplate(), $form->getData()) } return $this->render('EmailRenderer:index.html.twig'); }

Slide 54

Slide 54 text

No content

Slide 55

Slide 55 text

No content

Slide 56

Slide 56 text

Front-end development

Slide 57

Slide 57 text

Front-end development GOAL •  Allow front-end developers to easily create Twig templates •  Do not interfere with existing templates {{ form_widget(form) }} class AcmeExtension extends \Twig_Extension { public function getFilters() { return array( 'price' => new \Twig_Filter_Method( $this, 'priceFilter'), ); } }

Slide 58

Slide 58 text

Front-end development SOLUTION •  Create a dedicated folder for front-end templates •  List those templates in development environment only # AcmeDevBundle/Resources/views Design "## index.html.twig $## templates "## demo % $## example.html.twig "## profile % "## annonces.html.twig % "## dashboard.html.twig % "## vehicles.html.twig % $## verifications.html.twig "## registration % "## phone-fill.html.twig % $## register.html.twig "## search % "## empty.html.twig % "## no-result.html.twig % $## search.html.twig "## static % "## apps.html.twig % "## howto.html.twig % $## trust.html.twig $## widget $## widget.html.twig

Slide 59

Slide 59 text

Front-end development class DesignController { public function indexAction() { $files = Finder::create()->files()->in($this->templateDirectory); return $this->render('AcmeCoreBundle:Design:index.html.twig', array( 'files' => $files )); } public function showAction(Request $request, $template) { $filename = $this->templateDirectory.'/'.$template; if (!file_exists($filename)) { throw $this->createNotFoundException(); } return $this->render( 'AcmeCoreBundle:Design:templates/'.$template, $request->query->all(); // convert parameters from the request ); } }

Slide 60

Slide 60 text

No content

Slide 61

Slide 61 text

No content

Slide 62

Slide 62 text

No content

Slide 63

Slide 63 text

Tests

Slide 64

Slide 64 text

Continuous Integration

Slide 65

Slide 65 text

Yoann Brault Opium84 Meet Yoann, not a developer The quality guy

Slide 66

Slide 66 text

Quality Assurance 6 years experience in web and mobile application testing

Slide 67

Slide 67 text

My role in the BlaBlaCar team The product and marketing teams write specifications Developers implement them The Q/A. verifies that the specifications are respected

Slide 68

Slide 68 text

Problematic of Q.A. Ensure that the entire site works on all browsers, for all languages ​​ and avoid regression

Slide 69

Slide 69 text

The adopted solution Automation for the Scenario execution on production environment on available prototypes

Slide 70

Slide 70 text

An example for the search functionnality on the BlaBlacar website First we define the function to be tested Then we define the scenario

Slide 71

Slide 71 text

Paris Reims We have what is expected Submit the form An example for the search functionnality on the BlaBlacar website

Slide 72

Slide 72 text

We have what was expected An example for the search functionnality on the BlaBlacar website

Slide 73

Slide 73 text

Here, the result of the executed scenario An example for the search functionnality on the BlaBlacar website

Slide 74

Slide 74 text

Here is the result of the tests. Those are launched two to three times a day. Below the 34 scenarios were all successful Below, 1 failed scenario, resulting in 7 ignored steps. An example for the search functionnality on the BlaBlacar website

Slide 75

Slide 75 text

Screenshots are always usefull to better understand why the test failed An example for the search functionnality on the BlaBlacar website

Slide 76

Slide 76 text

List of current automatic tests I can register a new account I can't use an email already in use I can create a new alert I can check the lowest/max price I can add preference I can post a new trip I can check the ladies only option and check if the trip is available for men I create a new roundtrip I Can check the sharing options and change them I can access the alerts tab I Can signup with a FB account on Landing Pages 3 I can verify a phone number I can perform a classic search I can perform a search only with departure city I can perform a search only with arrival city I can connect with Facebook, […] I check for private message notification […] I can delete a trip I can add a car to my profile I can remove a car from my profile I Can signup with a FB account on Landing Pages 1 I can add a bio to my profile I can check if the photo notification is available I can create a trip with stepover I can post a new trip, make a return and duplicate the trip I can sign up in with a FB account I can search each subtrip from a trip with stepover I can access to the post trip page from the homepage I can request a new password I can erase an account I Can signup with a FB account on Landing Pages 4 I can perform a search from the homepage I can check some short urlAcces to the backoffice to verify that the short link page is ok ...

Slide 77

Slide 77 text

Future of automatic tests We have developed a tool to make things easier and faster

Slide 78

Slide 78 text

Deployments

Slide 79

Slide 79 text

…quand je fais une mise en prod Source: http://lesjoiesducode.tumblr.com

Slide 80

Slide 80 text

How to MEP? $ ./mep.sh

Slide 81

Slide 81 text

How to MEP? Yo dude! it’s time to deploy [RSYNC] Gimme the code

Slide 82

Slide 82 text

Monitoring

Slide 83

Slide 83 text

More details on our tech blog http://tech.covoiturage.fr

Slide 84

Slide 84 text

What is YOUR development workflow?

Slide 85

Slide 85 text

Thank you! Slides available at http://moquet.net/talks/symfony-live-2013 We’re  hiring!   Leave feedbacks @MattKetmo