trying continuous delivery - pyconjp 2012
TRANSCRIPT
Trying'Con*nuous'Delivery�
Toru Furukawa!@torufurukawa!
Keep service running before and after releasing�
Change,'Change,'Change�
Ship it as soon as it is ready�
Con*nuous'delivery�
#"Update"the"site"every"5"minutes"*/5"*"*"*"*"cd"/www/example.com"\"""""""""&&"git"pull"\"""""""""&&"service"apache"restart"
h5ps://speakerdeck.com/u/zeeg/p/prac*cing>con*nuous>deployment>disqus>pycon>2012�
Business value�
5 Problems�
1. Manual operation is expensive and unpredictable�
Prefer'scripts'over'opera*ons�
$"make"env".............."build"dev"environment"unittest"........."run"unit"tests"acceptancetest"..."run"acceptance"tests"inspect".........."inspect"codes"deploy"..........."deploy"to"App"Engine"�
Automate'acceptance'tests�
Have'Jenkins'run'tests�
Push!
Acceptance test!Unit tests�Write codes
Unit tests!
Notify!
Pull!
Deploy!
2. Requirements will never be fixed�
Design product to ship incrementally�
Schema change�
class"User(Model):"""name"="StringProperty()"""birthday"=\"""""DateProperty()"
class"User(Model):"""name"="StringProperty()"""birthday"=\"""""StringProperty()"""email"=\"""""StringProperty()"
Add'new'property�
1. Add property with required=False!2. Deploy!3. Add app code to read and write new
property!4. Update index!5. Deploy!�
Change property�
1. “Add” property with required=False!2. Deploy!3. Add app code to access old and new
model!4. Update index!5. Deploy!6. Fill new property (if necessary)!7. Remove old property!
class"User(Model):"""name"="StringProperty()"""birthday"="DateProperty()"
class"User(Model):"""name"="StringProperty()"""date_birthday"=\"""""DateProperty(name='birthday')"""str_birthday"=\"""""StringProperty(name='str_birthday’)"
class"User(Model):"""name"="StringProperty()"""date_birthday"="…"""str_birthday"="…""""def"get_birthday(self):"""""return"self.date_birthday""""def"set_birthday(self,"val):"""""self.date_birthday"="val""""birthday"="property(get_birthday,"""""""""""""""""""""""set_birthday)"
class"User(Model):"""name"="StringProperty()"""date_birthday"="…"""str_birthday"="…""""def"get_birthday(self):"""""if"self.date_birthday:"""""""return"self.date_birthday.strftime(…)"""""else:"""""""return"self.str_birthday"
class"User(Model):"""name"="db.StringProperty()"""date_birthday"="…"""str_birthday"="…""""def"get_birthday(self):"…""""def"set_birthday(self,"val):"""""if"isinstance(val,"datetime.date):"""""""val"="val.strftime(…)"""""""self.date_birthday"="None"""""self.str_birthday"="val"
class"User(Model):"""name"="db.StringProperty()"""date_birthday"="…"""str_birthday"="…""""def"get_birthday(self):"…""""def"set_birthday(self,"val):"…""""birthday"="property(get_birthday,"""""""""""""""""""""""set_birthday)"
3. Building and changing environment is expensive�
Google App Engine lets us focus on app�
Make dev and production environments almost identical�
app.yaml�
Local dev server�
$ dev_appserver.py src�
Dev Server�$ appcfg.py update src�
$ appcfg.py update –A myproduction src�Production
Server�
Have multiple versions deployed to switch code quickly�
$"appcfg.py"–V"v11"update"src"..."(v11.myapp.appspot.com)"$"appcfg.py"–V"v11"set_default_version"src"..."(myapp.appspot.com)""
4. We still have problems�
Hg-flow for hotfix branches�
develop�
master�
feature�
release� hotfix�
Deploy� Deploy�
Rollback by changing default version�
$"appcfg.py"–V"v11"update"src"..."(v11.myapp.appspot.com)"$"appcfg.py"–V"v11"set_default_version"src""$"appcfg.py"–V"v10"set_default_version"src"
5. It does not happen overnight�
Start with what makes sense to you�
Allocate time for improvement�
TODOs�• Review!• Faster feedback!• Automate capacity tests!• Manage libraries!• Test client side app�
Things got better and are getting even better�
Share OUR experiences�
@torufurukawa!http://about.me/torufurukawa!
http://facebook.com/toru.furukawa!