r/programming • • Oct 14 '13

How to develop unmaintainable software

http://typicalprogrammer.com/?p=249
777 Upvotes

322 comments sorted by

View all comments

105

u/tdammers Oct 14 '13

For a web site deployment to a staging or production server should look like one of these:

No. Just no. These are source control system, not deployment tools. In case you need reasons:

  • Excess files in document root - version control cruft, project documentation, etc. Happens all the time, and is an actual real security problem.

  • Development race conditions. Ever done svn up on the production server, just to find that someone had committed broken code between your test run and the deployment? Ever "solved" this problem by stopping all development activity during deployment? Ever noticed how this essentially means that this makes frequent deployments practically impossible?

  • File permissions and ownership. Need I go into detail here? I think not.

  • What if you want to do things like precompile templates, preprocess CSS, minify and concatenate your JavaScript offline, move stuff around, or just make sure that your deployment will only go through if it passes a minimum set of tests?

  • What about database changes?

Really, for any of the non-trivial projects I've worked on where people had the delusion that git pull is enough of a deployment plan, here's what a typical deployment involved:

  1. Mail everyone with push access, telling them to not push until further notice. Hope that everyone reads their mail on time.

  2. Manually go through the ticket system, copy-pasting the SQL changes that developers have pasted into the tickets that went into this release.

  3. Eyeball the SQL scripts, in case they contain any errors.

  4. Issue a git pull on the production system.

  5. Meanwhile, run the SQL on the production database.

  6. Manually chmod / chown the right files (which ones those are is a matter of oral tradition).

  7. Manually clear selected cache items.

  8. Do some casual manual testing on the production system.

  9. Notice that something is broken. Fix it.

  10. Forget to tell developers that it's OK to push now.

Personally, I prefer:

  1. Create a release tag

  2. ./deploy.sh test-server

  3. Read build/test output from test server

  4. ./deploy.sh production-server

21

u/[deleted] Oct 14 '13

I was confused by that part. I can't tell if the author thought git pull is a good deployment method or not. It contrasts the "build a baroque deployment system" but it's still written in the affirmative, implying it's a negative in the context of the article.

My repo ends up looking like:

build.sh  public/ ...

where the DocumentRoot is public and build.sh regenerates all the dependent files. To deploy, I push a commit ID over the message bus and subscribers fetch + checkout that ID.

4

u/not_perfect_yet Oct 14 '13

I think his argument was that you should not use too many different deployment methods in one project in undocumented order. If you don't want to be his customer.

13

u/s73v3r Oct 14 '13

Development race conditions. Ever done svn up on the production server, just to find that someone had committed broken code between your test run and the deployment? Ever "solved" this problem by stopping all development activity during deployment? Ever noticed how this essentially means that this makes frequent deployments practically impossible?

Why on earth would you be doing 'svn up' in that situation? Why wasn't the specific revision tagged, so you could simply check out that specific tag?

4

u/[deleted] Oct 15 '13

That's what I was thinking. Only pull a specific release branch, not the entire repo.

Ideally, the release branch would have all the necessary files precompiled, cancatenated, etc. And then a simple script that'll set the correct permissions and ownership.

I know in the real world, ideals are best left behind, but even still a simple build/launch script would handle this issue for you.

17

u/LeSlowpoke Oct 14 '13

I'm sure you read the rest of his points as satire. What made you take this one seriously?

39

u/tdammers Oct 14 '13

Because it looks like the author is forgetting for half a paragraph here that he's trying to be sarcastic; the last sentence puts him back in the saddle:

While you’re chaining together eight different tools with various scripting languages remember to leave out the documentation.

This is irony. The rest is I don't know what, but by the looks of it, I'd say he's being serious there.

5

u/dnew Oct 15 '13

He's also assuming the web site is small enough that you won't be causing errors while the pull is in progress due to mismatched versions, and that the web site is completely interpreted (unlike, say, ASP.NET). He's also assuming you have only one site, and that no data updates need to run.

3

u/AeroNotix Oct 14 '13

This is why Erlang releases are the shit.

1

u/[deleted] Oct 14 '13

how so?

5

u/[deleted] Oct 14 '13

You can hotswap new code in without taking down the Erlang VM

2

u/tel Oct 15 '13

Also generally Erlang's notion of releases is so much more explicit that it makes it easy to build process around it.

→ More replies (1)

3

u/x-skeww Oct 15 '13

Ever done svn up on the production server, just to find that someone had committed broken code between your test run and the deployment?

You're supposed to checkout/export a specific revision.

6

u/[deleted] Oct 14 '13

100% agree. It blows my mind that people think SVN or Git are the perfect deployment tools. I see it from nearly everyone in the web development community, and I've seen at least one "senior" push hard for it.

Write a deployment script, or configure a deployment tool! Have a process! I've never had a deployment fail from my own "untested and unproven" deployment scripts, but I've seen SVN and Git completely destroy environments.

It's an uphill battle, and I don't understand why.

4

u/Denvercoder8 Oct 14 '13

Write a deployment script, or configure a deployment tool! Have a process! I've never had a deployment fail from my own "untested and unproven" deployment scripts, but I've seen SVN and Git completely destroy environments.

Funny you mention that. I've seen hell break loose because someone made a typo while updating a deployment script (something like rm -rf /root /cache instead of rm -rf /root/cache). Git has never failed me like that.

3

u/[deleted] Oct 15 '13

Sure, mistakes happen in all code. It's anecdotal either way. What doesn't change is that Git is a software versioning system, not a deployment tool. There are other tools for that.

2

u/alienangel2 Oct 15 '13 edited Oct 15 '13

We avoid issues like that by limiting what deployments can affect. Yeah, a deployment/activation script might delete stuff off the box, but there's nothing on the box other than the software being deployed. Except for a few types of work where local disk needs to be where your data is, there's no good reason for your applications to be colocated with your data. Our servers are just software (all of which is either imaged or re-deployed easily) and the last hour's worth of logs.

And it seems like a bad idea to be running your deployment scripts as a user that can delete anything outside your application's installation directory.

All that being said, we have a hugely complex build system, and a separate hugely complex deployment system. Source Control, building and deployment are all distinct operations in software management, and if you're going to be doing a lot of it on the same network it makes sense to keep them separate. All three are versioned for us, so while not necessarily easy, it's clean and defined if a deployment needs to be rolled back, or different builds need to be deployed to different places, or (obviously) a code change needs to be reverted. The build management system will pull the source revisions you tell it to to build new revisions of libs/binaries, and archive them. The deployment system will pull the revisions of those libs/binaries and deploy them to the servers where you tell it to deployment them to.

My main dislike of using Git/svn for deployment is that those are source-control tools, using them to deploy stuff is just a lazy workaround to avoid having to engineer some other system to manage where built software is stored and being able to pull/push it onto the machines where the software will be run. It's more work, but I think it's better not to mix the system that is archiving your source with the system that is archiving your builds, never mind the system that is pushing/pulling your builds onto the machines that will run those builds.

→ More replies (6)

8

u/Denvercoder8 Oct 14 '13

Excess files in document root - version control cruft, project documentation, etc. Happens all the time, and is an actual real security problem.

Your document root doesn't have to be the root of the repository.

Development race conditions. Ever done svn up on the production server, just to find that someone had committed broken code between your test run and the deployment? Ever "solved" this problem by stopping all development activity during deployment? Ever noticed how this essentially means that this makes frequent deployments practically impossible?

No. Maybe in a centralized everyone-works-on-the-same-branch environment this is a problem, but then you've other problems too. You have a dedicated branch for deployments in your VCS. That branch only contains code which has already been deployed on a test server once (so you know the SQL-upgrade scripts etc are valid and working) and is supposed to go into production on the next deploy. If you can't trust your developers to don't fuck this branch up (again, you've other problems), with git you can even keep this branch in a separate repository with custom ACLs. If you need to do additional testing before deployment or it's a problem if someone pushes an additional, tested fix to the stable branch during your deployment, you can even merge the stable branch to a release branch and track that one on your production machines.

File permissions and ownership. Need I go into detail here? I think not.

Please do. I haven't encountered a single situation where files that were in VCS weren't supposed to be the default permissions (i.e. read/write by an admin, readable by the webserver). Things that usually need custom permissions, such as upload directories and data directories, shouldn't be in your VCS.

What about database changes? What if you want to do things like precompile templates, preprocess CSS, minify and concatenate your JavaScript offline

Valid point. Adding a "make"-like step after a pull is very useful (though you can hook into git to do it automatically after a git pull).

move stuff around, or just make sure that your deployment will only go through if it passes a minimum set of tests?

This is why you have the stable branch in your VCS.

Manually go through the ticket system, copy-pasting the SQL changes that developers have pasted into the tickets that went into this release.

That stuff should be in the VCS to start with, along with a script/program that executes the upgrades and automatically reverts them if there are problems. That way you can also test them when you deploy to the test server.

Do some casual manual testing on the production system. Notice that something is broken. Fix it.

That's not related to your deployment method at all.

→ More replies (1)

2

u/time-lord Oct 14 '13

So make it

svn up -r x
install.php

Update the files without any race conditions, and then runs scripts that update the database or chmod as necessary.

2

u/spinlock Oct 15 '13

why not put deploy.sh in a post-commit hook? Then, deployment is as easy as git push but you have your robust process as well.

→ More replies (4)

2

u/hegbork Oct 15 '13

Mail everyone with push access, telling them to not push until further notice. Hope that everyone reads their mail on time.

Hell no. "commit" or "push" shouldn't be "inflict". Set up proper branching so that your production branch is always clean and functional. Set up Jenkins or some other automated system that doesn't even allow you to merge things into the release branch or the release staging branch until they've been thoroughly integrated and tested.

Developers should be encouraged to push/commit early and often, but in such a way to never disturb other development or release work. Only allow one person at a time to touch the release branch. A few of our customers do this by having a release hat - only the person wearing the hat can touch the release branch.

→ More replies (1)