Our final examination is going to be my prefered method, which, ironically, I don’t actually use… yet. That is, the operating system specific method. Because I’m using CentoOS that means using RPM and yum for me. I don’t always deploy my applications, but when I do, I prefer yum. OK, that sounded funnier in my head.

The reason I like this method is because it blurs the line between the application and the operating system. Consider for a moment a goal that needs more than one person to be achieved. Can the goal be achieved without the two of them working closely together? Yes, but it will be less likely than if they know what each other is doing and how it is going to affect progress to the goal. The application and the operating system cannot be thought of as two separate entities. Also, most developers know squat about how to administer on operating system. There’s nothing wrong with that, but it’s mostly true. Yes, they may know about things like symbolic links and that log files exist but my experience has shown that a lot of developers, especially if they are not directly building onto the features of an OS, are not in-depth experts about the OS. Some developers are, but they are not the majority.

Do you need to update an operating system? Yes. Do you need to update an application? Yes. Do your administrators need to do both? Yes. (Developers shouldn’t have access to systems that could run away, frightened that a developer might look at them) So why not use what is already there that your admins already know.

rpm.spec

This file is the basis for the whole thing. They can be relatively complex when you’re dealing with compiled files, but with PHP it can actually be relatively simple. So let’s take a look at what one of these looks like.

The first three are just some constant definitions. All 3 of them are required for rpmbuild (the package builder). They don’t have to be defined there, but the values do need to be in that header section. Name and version are self-explanatory. Revision is simply a number that you are supposed to increment when you create a new package for the same release number. What you see in that header section is about the minimum that you require, with the exception of the Requires. That’s not required. That’s optional. But here’s the good thing about using Requires. It does not separate the application from the environment. So when you install the application, you are also installing the environment. Kinda a neat idea.

%description is required. Nuff sed.

After that we have a series of macros that need are going to be run. That’s what the %build, %install, etc. all are is macros. And order is sometimes important, especially with the %files macro. %build is empty because we’re not building anything.

%files lists the locations of all the files that you want to include in the package. Directories will be included recursively, though you can specify individual files as well. You can also exclude files by setting up an %exclude list.

%install is where we script how it is that we want the deployment box to create the installation. What that means is that we set up the application’s structure as we want it to be on the production systems. I am installing my application in /var/www/application. So what I do is first remove that directory and then export the version that I had tagged during my testing process.

Then what I want to do is automatically take the resulting RPM file and place it in a yum repository so I can deploy it to my production machines. Why do it during %clean? Because %clean is run after the RPM is written. So while I’m technically not doing an actual clean I am able to hook in there and copy the built RPM file from its build location to the yum repository. After that I run createrepo to yumify it.

There are also several hooks that can be set up that can be run pre and post installation, or unintallation. So what I do in mine is, for the macro %post, restart Apache to make sure that my opcode cache is cleared.

Building the RPM file

To create the RPM file I run the following command (I have version 0.0.3 tagged as my most current one).