92
Always ship trunk Managing change in complex websites Paul Hammond

Always ship trunk

  • Upload
    dodieu

  • View
    239

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Always ship trunk

Always ship trunkManaging change in complex websites

Paul Hammond

Page 2: Always ship trunk
Page 3: Always ship trunk

Revision Control

Page 4: Always ship trunk

version 1version 2version 3version 4

Page 5: Always ship trunk
Page 6: Always ship trunk

If youʼre not using any revision control system leave now and start using one

Page 7: Always ship trunk

But...

Page 8: Always ship trunk

Coordinating many people working on many things

at the same time is still hard

Page 9: Always ship trunk

“Just use branching”

Page 10: Always ship trunk

...which means merging

Page 11: Always ship trunk

“Branching causes problems in Subversion because Subversion doesnʼt store enough information to make merging work. In Mercurial, merging is painless and easy, and so branching is commonplace and harmless.”

—Joel Spolsky, http://hginit.com/00.html

Page 12: Always ship trunk

“Git will allow you to have multiple local branches ... the creation, merging and deletion of those lines of development take seconds ... Git makes this process incredibly easy and it changes the way most developers work when they learn it”

— Scott Chacon, http://whygitisbetterthanx.com/

Page 13: Always ship trunk

Distributed branching & merging is awesome

Page 14: Always ship trunk

But...

Page 15: Always ship trunk
Page 16: Always ship trunk

“What the !#*$ is going on?”“What the !#*$ just went wrong?”

“What the !#*$ is running on www34?”

Page 17: Always ship trunk

All existing revision control systems were built by people who build installed software

Page 18: Always ship trunk

1. Installed software2. Open source installed software3. Web applications & Software as a Service

Three kinds of software:

Page 19: Always ship trunk

Web apps are not like installed apps

Page 20: Always ship trunk

“In the online world, a software product drives a service to which users have access. There is, most often, a single copy of the actual software product in use. There is one consumer of the software: you. The users are consumers of the service built atop the software.”

– Theo Schlossnagehttp://omniti.com/seeds/online-application-

deployment-reducing-risk

Page 21: Always ship trunk

Does your team admin every computer your software is installed on?

Page 22: Always ship trunk

Each new release happens exactly once

Page 23: Always ship trunk

Once an upgrade has happened, the old code will never be run again

Page 24: Always ship trunk

1.0 1.1 1.2

1.0.1

1.1.1

1.0.2

Page 25: Always ship trunk

r2301 r2302 r2306

Page 26: Always ship trunk

Well, kind of...

Page 27: Always ship trunk

Upgrades are not deployed to all servers simultaneously

Page 28: Always ship trunk

Staging/QA environments

Page 29: Always ship trunk

Beta environments

Page 30: Always ship trunk

Upgrades are not deployed to all users simultaneously

Page 31: Always ship trunk

A/B testing

Page 32: Always ship trunk

Public betas

Page 33: Always ship trunk
Page 34: Always ship trunk

Configuration managementApplication code

Page 35: Always ship trunk

Installed library dependenciesWeb service dependencies

Page 36: Always ship trunk

Coordinating many people working on many things

and running them all at the same timeis hard

Page 37: Always ship trunk
Page 38: Always ship trunk

But nobody knows you just deployed(unless you tell them)

Page 39: Always ship trunk

Idea one: separate feature launches from infrastructure launches

Page 40: Always ship trunk

You can deploy the code for a feature long before you launch it

and nobody will know

Page 41: Always ship trunk

You can completely rewrite your infrastructure and keep the UI the sameand nobody will know

Page 42: Always ship trunk

Idea two: run multiple versions of your code at once

Page 43: Always ship trunk

You can repeatedly switch between two backend systems and keep the UI the same

and nobody will know

Page 44: Always ship trunk

You can deploy a non-user facing change to only a small percentage of servers

and nobody will know

Page 45: Always ship trunk

You can offer different user interfacesto different users

and nobody will know

Page 46: Always ship trunk

Need a revision control system that allows us to manage multiple parallel versions of the code and

switch between them at runtime

Page 47: Always ship trunk

Branches?

Page 48: Always ship trunk

Branches donʼt help you switch between versions at runtime

Page 49: Always ship trunk

Branches donʼt help you managedependency changes that need to happen

on all versions at once

Page 50: Always ship trunk

Need a revision control system that allows us to manage multiple parallel versions of the code

and switch between them at runtime

Page 51: Always ship trunk

Need a revision control system that allows us to manage multiple parallel versions of the code

and switch between them at runtime

Page 52: Always ship trunk

Need a revision control system that allows us to manage multiple parallel versions of the code

and switch between them at runtime

Page 53: Always ship trunk

Manage the different versions within your application

Page 54: Always ship trunk

Branch in code

Page 55: Always ship trunk

if ($cfg['use_snowflake_ticket_server']) {

# new hotness $ticket = snowflake_ticket();

} else {

# old and boring $ticket = db_generate_ticket();

}

Page 56: Always ship trunk

# hardcoded to not run$cfg['use_snowflake_ticket_server'] = false;

Page 57: Always ship trunk

# only in certain environmentsif ($cfg['environment'] == 'dev') { $cfg['use_snowflake_ticket_server'] = true;} else { $cfg['use_snowflake_ticket_server'] = false;}

Page 58: Always ship trunk

# only for a percentage of usersif (($user->id % 100) < 3) { $cfg['use_snowflake_ticket_server'] = true;} else { $cfg['use_snowflake_ticket_server'] = false;}

Page 59: Always ship trunk

# only for a percentage of requests$rand = rand(0,99);if ($rand < 3) { $cfg['use_snowflake_ticket_server'] = true;} else { $cfg['use_snowflake_ticket_server'] = false;}

Page 60: Always ship trunk

# only for a percentage of requestsif ($cfg['environment'] == 'dev') { $cfg['use_snowflake_percentage'] = 100;} else { $cfg['use_snowflake_percentage'] = 2;}

$rand = rand(0,99);if ($rand < $cfg['use_snowflake_percentage']) { $cfg['use_snowflake_ticket_server'] = true;} else { $cfg['use_snowflake_ticket_server'] = false;}

Page 61: Always ship trunk

# done testing, let’s launch$cfg['use_snowflake_ticket_server'] = true;

Page 62: Always ship trunk

# uh oh...$cfg['use_snowflake_ticket_server'] = false;

Page 63: Always ship trunk

# ok, it works again$cfg['use_snowflake_ticket_server'] = true;

Page 64: Always ship trunk

Feature testing on production servers

Page 65: Always ship trunk

# team testing$team = array(41,287,5806,5930);if (in_array($user->id, $team)) { $cfg['use_new_context_widget'] = true;} else { $cfg['use_new_context_widget'] = false;}

Page 66: Always ship trunk

# private staff alpha testingif ($user->is_admin()) { $cfg['use_new_context_widget'] = true;} else { $cfg['use_new_context_widget'] = false;}

Page 67: Always ship trunk

# opt-in private staff alpha testing$has_cookie = isset($_COOKIE['new_context']);if ($user->is_admin() && $has_cookie) { $cfg['use_new_context_widget'] = true;} else { $cfg['use_new_context_widget'] = false;}

Page 69: Always ship trunk

# opt-in public betasif ($user->has_pref('new_context')) { $cfg['use_new_context_widget'] = true;} else { $cfg['use_new_context_widget'] = false;}

Page 70: Always ship trunk

# opt-in public betas via groupsif ($user->in_group('new_context')) { $cfg['use_new_context_widget'] = true;} else { $cfg['use_new_context_widget'] = false;}

Page 71: Always ship trunk

# user tagging (ala dopplr)if ($user->has_tag('context_widget')) { $cfg['use_new_context_widget'] = true;} else { $cfg['use_new_context_widget'] = false;}

Page 72: Always ship trunk

Flexibility

Page 73: Always ship trunk

# dark launches can be ramped upif ($cfg['front_page_dark_launch']) { # notice we're not keeping the data get_some_really_complex_data()}

Page 74: Always ship trunk

1. Development on user facing features2. Development on infrastructure3. Kill-switches

Three types of feature flags:

Page 75: Always ship trunk

# killswitchif ($cfg['disable_login']) { error('Sorry, login is unavailable'); exit;}

Page 76: Always ship trunk

Usually need multiple flags at onceduring development and testing

Page 77: Always ship trunk

# for development$cfg['disable_search_tests_all'] = false;$cfg['disable_search_ui_beta_test'] = false;$cfg['disable_search_darklaunch'] = false;

# for post launch$cfg['disable_search'] = false;

Page 78: Always ship trunk

Complexity

Page 79: Always ship trunk

Separate operational controls from development flags

Page 80: Always ship trunk

Be disciplined about removing unused feature flags

Page 81: Always ship trunk

Always deploy trunk to every server on every deploy

and manage versions through config

Page 82: Always ship trunk

# integrate with configuration managementif (in_array('beta', $node['roles']) { # …} else { # …}

# or generate the application config file # from configuration management system…

Page 83: Always ship trunk
Page 84: Always ship trunk

“I canʼt tell you how many Subversion users have told me the following story: “We tried to branch our code, and that worked fine. But when it came time to merge back, it was a complete nightmare and we had to practically reapply every change by hand, and we swore never again and we developed a new way of developing software using if statements instead of branches.

“Sometimes theyʼre even kind of proud of this new, single-trunk invention of theirs. As if itʼs a virtue to work around the fact that your version control tool is not doing what itʼs meant to do.”

—Joel Spolsky, http://www.joelonsoftware.com/items/2010/03/17.html

Page 85: Always ship trunk

Distributed branching & merging is awesome

Page 86: Always ship trunk

Use branches for early development

Branches merged into trunk

Use flags for rollout of almost-finished code

Page 87: Always ship trunk

“I canʼt tell you how many Subversion users have told me the following story: “We tried to branch our code, and that worked fine. But when it came time to merge back, it was a complete nightmare and we had to practically reapply every change by hand, and we swore never again and we developed a new way of developing software using if statements instead of branches.

“Sometimes theyʼre even kind of proud of this new, single-trunk invention of theirs. As if itʼs a virtue to work around the fact that your version control tool is not doing what itʼs meant to do.”

—Joel Spolsky, http://www.joelonsoftware.com/items/2010/03/17.html

Page 88: Always ship trunk

“I canʼt tell you how many Subversion users have told me the following story: “We tried to branch our code, and that worked fine. But when it came time to merge back, it was a complete nightmare and we had to practically reapply every change by hand, and we swore never again and we developed a new way of developing software using if statements instead of branches.

“Sometimes theyʼre even kind of proud of this new, single-trunk invention of theirs. As if itʼs a virtue to work around the fact that your version control tool is not doing what itʼs meant to do.”

—Joel Spolsky, http://www.joelonsoftware.com/items/2010/03/17.html

Page 89: Always ship trunk

All existing revision control systems were built by people who build installed software

Page 90: Always ship trunk

Web apps are not like installed apps

Page 91: Always ship trunk

What would a revision control system built for supporting deployed web applications be like?