We recently experienced a deployment issue where it turned out that the version objects were not in sync in one of the environments.
We have a large database group and different teams have different responsibilities and ownerships – I might code on schema X, Y, Z but I also will have dependancies on objects owned by other groups. This is the same no matter what technology – java libraries having different versions and what not.
My aim is to have something be in a webpage or a database table or something that I can see that for object A I have version X installed in Production, X + 1 in UAT and QA, and X + 2 installed in DEV.
How do other folks handle this? How do you pick up version changes? Do you rely on SCM? Build numbers? Hash value of the source code?
I’m interested in managing version consistency across technologies – java to db for instance.
6
From what I see, you are referring to configuration management, however, if there are different parts to your system and you want to put them in version control to keep them consistent, the best I can think of is:
A) To maintain a file (in XML, JSON or whatever serialization format you like) where you describe what version of each thing you need for each component.
{
"JAVA": ">1.7.0_05",
"MYSQL": ">=5.0.28",
...
}
Have each component import this file into constants and assert their values against the environment they are running on, there are ways to get this information from wherever your application is deployed. If they don’t match the desired values (or value ranges even), throw a warning.
B) If you have different components and you use something like Mercurial for version control, then you could use something like the subrepository feature, where your top/manager repository essentially does configuration management, this is, the top repository will keep track what versions of each component are being used across in a given moment in time. Picture this:
project_x #250 <- top repository at changeset 250
|--component_a #1232 <-component a at changeset 1232
|--component_b #23 <- component b at changeset 23
|--component_c #32 <- component c at changeset 32
And then with component_a‘s new version (say 1233) you need a new version of component_c, but not component_b, so you update component_a and component_c and commit project_x to a new version that records those changes
project_x #251 <- top repository at changeset 251, recording 1233 and 33 for a and c
|--component_a #1233 <-component a now at at changeset 1233
|--component_b #23 <- component b at changeset 23
|--component_c #33 <- component c now at changeset 33
Keep in mind that it might not be the best idea to store java or mysql itself in version control, but as mentioned earlier, this would be effective configuration management for project-independent components.
If you want to keep track of Java, MySQL, etc, “A)” provides a good mechanism to assert that configuration.
The “project_x” repo can have a development branch and a production branch where it tracks different component configurations.
In summary
Have a manifest to which you can code against and assert your configuration, and for your project independant components you can use Mercurial subrepos (or git submodules) to keep track of the version configuration among them.
Quick Answer: The easiest way would be setting build-tags/value (application code, database schema version, dependencies, etc..) in your Database or app.configuration, and directly reading from there when application is starts.
Each build need to have a pre-generated label attached to the build.
- Example of Application version-ing from VS perspective – Versioning Controlled Build
- Example of build process for Python project – Your Version Control and Build Systems Don’t Scale
How configuration management differs from environment to environment, language to language. I can give a concrete example on how things are handled in deployments that I manage, where most of the software is written in python.
In the Python world, individual libraries are distributed as eggs, and list their dependcenies in the package metadata:
install_requires=[
'setuptools',
'PyRTF',
'pisa >= 3.0.29',
'reportlab >= 2.2',
'html5lib == 0.11.1',
'pyPdf == 1.12',
],
In the above example some package versions are left un-pinned, others specify a minimum, and the last two are pinned to exact versions only. The deployment tool then has the responsibility of picking versions where no exact versions have been specified to match the constraints set for this egg.
We use buildout to manage our deployments; it is a build system that uses python packages called recipes to construct software for us. It’s configuration files easily let you include other configuration files letting you delegate responsibilities and specify different configurations for different deployment scenarios with ease.
Within buildout, we generally pin the exact versions for a release in a versions list:
[buildout]
versions = versions
[versions]
setuptools = 0.6c11
PyRTF = 0.45
pisa = 3.0.33
# etc.
A development.cfg
configuration could override specific versions, clear the pins for others, or pull in a whole new set of versions by also including the configuration for a large framework version upgrade. We often use a staging.cfg
to roll out test configurations to the staging server so the customer can sign off on test plans before changes are rolled out to production.
It helps tremendously here that large frameworks such as Plone publish version lists for the python packages that make up the framework; this let’s you upgrade your application to use a new release of the framework, or just upgrade individual packages using a local override.
Finally, how we discover new package releases also depends on whom releases the packages; the Python Package index (PyPI) publishes an RSS feed of new packages, various projects have their own news channels, and for internal updates we use similar mechanisms.
It is important for us to keep our buildouts repeatable and predictable however, so we only upgrade packages when we actually need the changes in the newer versions and have tested the upgrade; but thanks to buildout configurations, setting up a CI server such as Jenkins for various setups (production, staging, project milestone, etc) is very easy. As long as your test suite has good test coverage, you could even automate pulling in new versions of packages from other teams within your organisation.
I used to use a wiki page to keep track of such things, but no one kept it up. The only way to make this work is to have the page run some code to figure out the answers for itself. I started with some php code a coworker wrote, so I continued with PHP. But just about any language you can run in a server can work.
The easiest thing would be to have a admin page in your application that lists all the information and then have a summary page (in a different app) that generates a line per installation. The summary page gets all the information from the admin pages of your installations. The only thing you have to update on the summary page is the urls to the installations.
1