wiki:ReleaseManagement

Release Management

Four Principles of Low-Risk Software Releases

Release Management for the Haiti Portal

Note: As of January 2012, BZR/Launchpad info for eden is deprecated. Please visit the GitHub page. Thanks.

This example can be updated/adapted for future instances.

We have 3 running instances:

The Bug Tracker should have different views to distinguish between bugs being reported against each version

  • ToDo customise the 'Report Bugs' footer URL to link directly to a new ticket against that version?

We have several Code branches:

Release Process

Overall responsible Person: Fran (currently)

  1. Where generic, new code is merged 1st into Trunk by Fran
  2. Code is then merged into the Haiti branch by Fran
    • RMS is currently Haiti-specific so is merged directly to Haiti branch
  3. Code is pulled from the Haiti branch to Dev by Fran
    • Data is 1st synced from Prod:
      /root/automysqlbackup.sh
      scp /backups/daily/haitiprod/haitiprod_2010-01-27_01h24m.Wednesday.sql.gz flavour@haiti-dev.sahanafoundation.org:.
      
      gunzip haitiprod_2010-01-27_01h24m.Wednesday.sql.gz
      sed 's/haitiprod/haitidev/g' haitiprod_2010-01-27_01h24m.Wednesday.sql > haitidev_import.sql
      vim /etc/crontab
      #0-59/1 * * * * www-data cd /home/haiti/web2py/ && python web2py.py -C -D 1 >> /tmp/cron.output 2>&1
      ln -sf /etc/apache2/sites-available/dev-maintain /etc/apache2/sites-enabled/dev
      /etc/init.d/apache2 force-reload
      mysql
      drop DATABASE haitidev;
      create DATABASE haitidev;
      \q
      mysql < haitidev_import.sql
      vim /home/haiti/dev/models/00_db.py
      migrate=True
      ln -sf /etc/apache2/sites-available/dev /etc/apache2/sites-enabled/dev
      /etc/init.d/apache2 force-reload
      vim /etc/crontab
      0-59/1 * * * * www-data cd /home/haiti/web2py/ && python web2py.py -C -D 1 >> /tmp/cron.output 2>&1
      vim /home/haiti/dev/models/00_db.py
      migrate=False
      
    • A 1st draft of a data migration plan is made
  4. Code is pulled from the Haiti branch to UAT by lifeeth or chamindra
    • Testers to be informed before this via the group: tbc
    • Data is 1st synced from Prod
    • A more detailed data migration plan is made
  5. Code is pulled from the Haiti branch to Prod by Fran (Volunteers welcomed to take over!)
    • Sign-off for this to come from the group: tbc
    • A careful data migration plan is made
  • Backup
    • Disable system crontab & put Website into Maintenance Mode
      vim /etc/crontab
      #0-59/1 * * * * www-data cd /home/haiti/web2py/ && python web2py.py -C -D 1 >> /tmp/cron.output 2>&1
      vim /home/haiti/prod/models/00_db.py
       migrate=True
      rm /etc/apache2/sites-enabled/prod-ssl
      /etc/init.d/apache2 force-reload
      /home/haiti/update-prod
      /home/haiti/shell-prod
      db.export_to_csv_file(open('db.csv','wb'))
      Ctrl+D
      
  • DataMigration
    • cd /home/haiti/web2py ; python web2py.py -S prod -M -N
      Ctrl+D
      
  • Restore Website & Cron
    ln -s /etc/apache2/sites-available/prod-ssl /etc/apache2/sites-enabled
    /etc/init.d/apache2 force-reload
    vim /home/haiti/prod/models/00_db.py
     migrate=False
    vim /etc/crontab
    0-59/1 * * * * www-data cd /home/haiti/web2py/ && python web2py.py -C -D 1 >> /tmp/cron.output 2>&1
    
    

Technical Details

Production

  • haiti.sahanapy.org VM: 212.23.5.4
  • /home/haiti/web2py/applications/prod
  • /etc/apache2/sites-enabled/prod
  • Sqlite MySQL
  • Web2Py r1544
  • Sahana Haiti r547
  • Customisations:
    • models/00_db.py
      #migrate = True
      migrate = False
      
      #exec('from applications.%s.modules.sahana import *' % request.application)
      # Faster for Production (where app-name won't change):
      from applications.prod.modules.sahana import *
      
      #exec('from applications.%s.modules.s3.s3validators import *' % request.application)
      # Faster for Production (where app-name won't change):
      from applications.prod.modules.validators import *
      
    • models/00_settings.py
      • auth.settings.registration_requires_verification = True
      • auth.settings.registration_requires_approval = True
    • models/01_modules.py
      s3.menu_modules.append([T('Home'), False, URL(c='default', f='open_module', vars=dict(id=1))])
      if auth.has_membership(1):
          s3.menu_modules.append([T('Admin'), False, URL(c='default', f='open_module', vars=dict(id=2))])
      s3.menu_modules.append([T('Mapping'), False, URL(c='default', f='open_module', vars=dict(id=3))])
      module_id = db(db.s3_module.name == 'or').select()[0].id
      s3.menu_modules.append([T('Organizations'), False, URL(c='default', f='open_module', vars=dict(id=module_id))])
      s3.menu_modules.append([T('People'), False, URL(c='default', f='open_module', vars=dict(id=4))])
      #dvi_group = db(db[auth.settings.table_group_name] == 'DVI').select()[0].id
      #if auth.has_membership(dvi_group):
      #module_id = db(db.s3_module.name == 'dvi').select()[0].id
      #s3.menu_modules.append([T('Victim Identification'), False, URL(c='default', f='open_module', vars=dict(id=module_id))])
      module_id = db(db.s3_module.name == 'rms').select()[0].id
      s3.menu_modules.append([T('Requests'), False, URL(c='default', f='open_module', vars=dict(id=module_id))])
      
    • cron/crontab
      */5   *       *       *       *       root *applications/prod/cron/rms_entry2record.py
      */5   *       *       *       *       root *applications/prod/cron/rms_tweet2request.py
      
    • views/layout.html
      <script type="text/javascript">
      var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
      document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
      </script>
      <script type="text/javascript">
      try {
      var pageTracker = _gat._getTracker("UA-12510226-2");
      pageTracker._setDomainName(".sahanafoundation.org");
      pageTracker._trackPageview();
      } catch(err) {}</script>
      
    • views/ext.html
      <!-- For Sites Hosted on the Public Internet, using Cachefly CDN's version of ExtJS may provide better performance
      <script type="text/javascript" src="/{{=request.application}}/static/scripts/ext/ext-all.js"></script>
       -->
      <script type="text/javascript" src="http://extjs.cachefly.net/ext-3.0.3/ext-all.js"></script>
      
    • views/sahana_scripts_min.html
      <!-- For Sites Hosted on the Public Internet, using Google's version of jQuery will provide better performance
      <script src="/{{=request.application}}/static/scripts/web2py/jquery-1.3.2.min.js" type="text/javascript"></script>
      -->
      <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
      
    • views/gis/index.html
            #LI(
            #  SPAN(A(T('Bulk Uploader'),
            #    _href=URL(c='gis', f='bulk_upload')),_style="font-weight:bold;"),
            # P(T('Allows authorized users to upload multiple features into the situation map.')),
            #    _style="margin-top:1em;"),
      
  • http://haiti-test.sahanafoundation.org/test/gis/apikey/update/1
    • ABQIAAAAgB-1pyZu7pKAZrMGv3nksRR1-chREdZE62d-MGawPNPOGidOJBQQCwHsElsSGbD5VMpNj7DBMNxjTg

UAT

  • logistics.sahanapy.org VM: 212.23.5.5
  • /home/haiti/web2py-test/applications/test
  • /etc/apache2/sites-enabled/haiti-test
  • MySQL hopefully
  • Web2Py r1544
  • Sahana Haiti r547
  • Customisations:
    • models/00_db.py
      • migrate = False
      • db = DAL('mysql://haititest:password@localhost/haititest', pool_size=10)
    • models/00_settings.py
    • cron/crontab
      */5   *       *       *       *       root *applications/test/cron/rms_entry2record.py
      */5   *       *       *       *       root *applications/test/cron/rms_tweet2request.py
      
    • views/ext.html
      <!-- For Sites Hosted on the Public Internet, using Cachefly CDN's version of ExtJS may provide better performance
      <script type="text/javascript" src="/{{=request.application}}/static/scripts/ext/ext-all.js"></script>
       -->
      <script type="text/javascript" src="http://extjs.cachefly.net/ext-3.0.3/ext-all.js"></script>
      
    • views/sahana_scripts_min.html
      <!-- For Sites Hosted on the Public Internet, using Google's version of jQuery will provide better performance
      <script src="/{{=request.application}}/static/scripts/web2py/jquery-1.3.2.min.js" type="text/javascript"></script>
      -->
      <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
      
    • views/gis/index.html
            #LI(
            #  SPAN(A(T('Bulk Uploader'),
            #    _href=URL(c='gis', f='bulk_upload')),_style="font-weight:bold;"),
            # P(T('Allows authorized users to upload multiple features into the situation map.')),
            #    _style="margin-top:1em;"),
      
    • http://haiti-test.sahanafoundation.org/test/gis/apikey/update/1
      • ABQIAAAAgB-1pyZu7pKAZrMGv3nksRR1-chREdZE62d-MGawPNPOGidOJBQQCwHsElsSGbD5VMpNj7DBMNxjTg

Dev

  • logistics.sahanapy.org VM: 212.23.5.5
  • /home/haiti/web2py/applications/dev
  • /etc/apache2/sites-available/dev
  • /etc/apache2/sites-available/dev-maintain
  • /etc/apache2/sites-enabled/dev
  • MySQL
  • Web2Py r1544
  • Sahana Haiti r547
    cd /home/haiti/web2py/applications
    bzr branch lp:s3/haiti-quake-2010 dev
    cd dev
    chown www-data:www-data -R cache
    chown www-data:www-data -R databases
    chown www-data:www-data -R errors
    chown www-data:www-data -R sessions
    chown www-data:www-data -R static/img/markers
    chown www-data:www-data -R static/scripts
    chown www-data:www-data -R static/styles
    chown www-data:www-data -R uploads
    
  • Customisations:
    • models/00_db.py
      • migrate = False (after 1st run)
      • db = DAL('mysql://haitidev:password@localhost/haitidev', pool_size=10)
    • models/01_modules.py
      s3.menu_modules.append([T('Home'), False, URL(c='default', f='open_module', vars=dict(id=1))])
      if auth.has_membership(1):
          s3.menu_modules.append([T('Admin'), False, URL(c='default', f='open_module', vars=dict(id=2))])
      s3.menu_modules.append([T('Mapping'), False, URL(c='default', f='open_module', vars=dict(id=3))])
      module_id = db(db.s3_module.name == 'or').select()[0].id
      s3.menu_modules.append([T('Organizations'), False, URL(c='default', f='open_module', vars=dict(id=module_id))])
      module_id = db(db.s3_module.name == 'hms').select()[0].id
      s3.menu_modules.append([T('Hospitals'), False, URL(c='default', f='open_module', vars=dict(id=module_id))])
      s3.menu_modules.append([T('People'), False, URL(c='default', f='open_module', vars=dict(id=4))])
      #dvi_group = db(db[auth.settings.table_group_name] == 'DVI').select()[0].id
      #if auth.has_membership(dvi_group):
      module_id = db(db.s3_module.name == 'dvi').select()[0].id
      s3.menu_modules.append([T('Victims'), False, URL(c='default', f='open_module', vars=dict(id=module_id))])
      module_id = db(db.s3_module.name == 'rms').select()[0].id
      s3.menu_modules.append([T('Requests'), False, URL(c='default', f='open_module', vars=dict(id=module_id))])
      module_id = db(db.s3_module.name == 'vol').select()[0].id
      s3.menu_modules.append([T('Volunteers'), False, URL(c='default', f='open_module', vars=dict(id=module_id))])
      
    • models/00_settings.py
    • cron/crontab
      sed '/sahana/ s/sahana/dev/g' /home/haiti/dev/cron/crontab > /tmp/crontab
      mv /tmp/crontab /home/haiti/dev/cron/crontab
      
      vim cron/crontab
      */5   *       *       *       *       root *applications/dev/cron/rms_sms2record.py
      */5   *       *       *       *       root *applications/dev/cron/rms_tweet2request.py
      */5    *       *       *       *       root *applications/dev/cron/import_job_do_processing.py
      */5    *       *       *       *       root *applications/dev/cron/import_job_do_import.py
      
    • views/ext.html
      <!-- For Sites Hosted on the Public Internet, using Cachefly CDN's version of ExtJS may provide better performance
      <script type="text/javascript" src="/{{=request.application}}/static/scripts/ext/ext-all.js"></script>
       -->
      <script type="text/javascript" src="http://extjs.cachefly.net/ext-3.0.3/ext-all.js"></script>
      
    • views/sahana_scripts_min.html
      <!-- For Sites Hosted on the Public Internet, using Google's version of jQuery will provide better performance
      <script src="/{{=request.application}}/static/scripts/web2py/jquery-1.3.2.min.js" type="text/javascript"></script>
      -->
      <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
      
  • http://haiti-dev.sahanafoundation.org/dev/gis/apikey/update/1
    • ABQIAAAAgB-1pyZu7pKAZrMGv3nksRR1-chREdZE62d-MGawPNPOGidOJBQQCwHsElsSGbD5VMpNj7DBMNxjTg
  • static/robots.txt
    sed '/prod/ s/prod/dev/g' /home/haiti/dev/static/robots.txt > /tmp/robots.txt
    mv /tmp/robots.txt /home/haiti/dev/static/robots.txt
    

Note that UAT & Dev have different Web2Py instances so that:

  • We can trial different Web2Py versions on Dev
  • Crontab can be separately enabled/disabled

Note that all names/paths include the words 'dev'/'test'/'prod' to minimise chances of confusion as to which site is being altered


Haiti

Last modified 12 years ago Last modified on 11/27/12 11:03:08
Note: See TracWiki for help on using the wiki.