When we first launched our Google App Engine Deployer we had separate build steps for “Deploy Python Application to Google App Engine” and “Deploy Java Application to Google App Engine” on top of that you had the option for deploying your application to CloudBees’ RUN@cloud service with the “Deploy to CloudBees” build step.
When we started integrating the deployer for Cloud Foundry I had a vision that we’d eventually end up with a mess of “Deploy application to XYZ” build steps replicating code all the way along.
I don’t like a mess.
So we refactored the CloudBees Deployer plugin, as of version 4.0 of the CloudBees Deployer Plugin its build steps are now just called “Deploy applications”. There is an API for various deploy engines to plugin into and allow deployment within the CloudBees Deployer Plugin framework. The framework provides the correct hooks that are needed in each different use case to allow each deploy engine to resolve its deployable applications correctly:
Build steps in the main build can only resolve applications from the build workspace (as artifacts have not been archived until after all build steps complete)
Publishers can resolve applications from the build workspace and from the archived artifacts.
Build steps in a build promotion can resolve applications from the archived artifacts of the build that is being promoted.
The Deploy Now functionality can only resolve applications from the archived artifacts and cannot resolve exploded directory artifacts for that reason.
These are just some of the complexities that you have to learn when implementing a proper application deployment framework within Jenkins. It does not make sense to re-invent the wheel every time you want to write an application deployer. With the new framework in the CloudBees Deployer Plugin a deploy engine provider need only concern itself with three things:
A class that describes the target of deployment (i.e. where is the application going to). All targets have a source for the application file/directory to deploy
A class that describes the host of the target(s) (i.e. who are we deploying as, and which hosting service is the target on)
A class that can take a host and a list of targets and will deploy the sourced applications to the host.
From the descriptors of these three classes the framework is able to:
Infer which hosting services are available in each context (e.g. when used: in a Build step; in a Publisher; in a Build step in a Promotion process; or in Deploy Now)
Infer which application sources are appropriate for targets of a host depending on the context.
For example in a Maven Project type build, when using the “Deploy applications’ publisher, the CloudBees RUN@cloud engine deploys files, so the Maven artifact selector is appropriate for RUN@cloud targets. On the other hand Google App Engine deploys exploded directories, so the Maven artifact selector is not appropriate for App Engine targets.
So the take-home from all of the above is that we did a lot of work to make writing deploy engines easier. Our intention is to push the core of our framework back to OSS, but there is still some untangling to do before we can do that and our priority is ensuring that we don’t break things for our customers. In other words if we rushed the untangling we would break existing users of the CloudBees Deployer Plugin, and we don’t want to do that.
So what are the changes that a user will see?
Well the first most obvious change is the Deploy Now icon. It used to be
Now it is
The changes signify that it is no longer just about deploying “.war” files, because, well firstly you can deploy lots of different application types to CloudBees RUN@cloud, but also the other deploy engines need not be restricted to “.war”. Secondly we removed the CloudBees logo because it is no longer just about deploying to CloudBees.
The second change is that all your “Deploy to Cloud
Bees” build steps will be automatically converted to “Deploy applications” build steps with a “CloudBees RUN@cloud” hosting service. This is part of our commitment to not breaking things for our existing users. Other than that there should be no change in functionality.
Our DEV@cloud users though can start turning on the enhanced functionality. If they visit our Google App Engine console or our Cloud Foundry console they can enable their DEV@cloud instance for deploying to these other hosting services, and if your app will run on all three services, well you can deploy to all three:
I think that is pretty nifty. Here’s what the deployment configuration for the above build job looks like:
Where this really starts to come into its own is when you start using the build promotion plugin, you can set up a build promotion process that does the deployment for you, e.g.
Build promotion processes are great for two reasons:
- I get traceability of who performed the promotion and which builds were promoted
If a deployment fails or has a bug, I can re-execute a previous promotion to roll back production into a known working state without having to wait for a full build or try and figure out what commit to revert.
The “Deploy Now” functionality, from my point of view, is ideal for developers in two situations:
You want to just quickly try your application on a different PaaS.
You need to verify a bug, use “Deploy Now” to deploy the application into your own instance and verify the bug without touching production.
Anyway, this post has turned into something a bit longer than I intended when I started writing it, but hopefully you found it worth the read!
Stephen Connolly has over 20 years experience in software development. He is involved in a number of open source projects, including Jenkins. Stephen was one of the first non-Sun committers to the Jenkins project and developed the weather icons. Stephen lives in Dublin, Ireland - where the weather icons are particularly useful. Follow Stephen on Twitter and on his blog.