In Jenkins, can we delete build artifacts for older builds, but keep build details/logs? - jenkins

As is good practise, I've got Jenkins set up at work to automatically build everything for continuous integration, pulling files from our Git repositories. On our development branches, builds get kicked off automatically whenever anyone commits a change. When we want to do formal testing, we pull the build from Jenkins and use that; and when we want to sign off a change request, we quote the Jenkins build number where the change went in. So far, so good.
The problem we have is that builds are a significant size. For our SDK, we have to build across multiple platforms so that we can check it works on all of them. At maybe 50MB per build, this starts to mount up! Short term I can keep asking IT to give me more storage space, but longer term I'd like a more strategic solution
The obvious answer in Jenkins is to set up deletion rules, whether deleting after some time or after some number of builds. The problem then though is that if we delete that older development build, we lose the traceability of what we tested. I'm sure most engineers at one time or another have had to do a binary chop through older builds to find an obscure bug/regression which was only spotted some time later. For me, it is unacceptable to lose that history.
The important feature of build history though is not the binary build artifacts, but the build log recording what Git commits (or anything else; toolchain versions for example) went into each build. That's what lets us go back to investigate older builds and recreate them if required. The build log is relatively small (and highly compressible, being a text file). We do still need to keep build artifacts for recent builds though, so that testers can use them. So I'm thinking a better alternative would be to preserve the build log in Jenkins for all builds, but to have Jenkins automatically delete build artifacts after some time.
Does anyone know of a way in Jenkins (perhaps a plugin?) which would let us automatically delete/archive build artifacts from older builds, but still keep the build details and log for those builds? I'm happy to do a Jenkins upgrade if necessary to get this feature. And of course this needs to be only for selected development build jobs - all release build jobs need their build artifacts to be preserved forever, as do any builds which have the "keep forever" button ticked.
If it's absolutely necessary, I could set up a separate cron job to do this on the Jenkins file area. That's a nasty hack though, and I suspect it's likely to cause some issues with Jenkins, so I'd rather not do something that brute-force if there's a better alternative.

I think you need this option in your jenkinsfile
buildDiscarder(logRotator(artifactNumToKeepStr: '10'))
artifactNumToKeepStr: This number of builds have their artifacts kept.

Related

How can a Jenkins Ivy Project be converted to a Freestyle Project?

After a recent update (both Jenkins and Plug-ins) my Ivy Project settings can no longer be changed due to incompatible layouts (table to div change in a minor version update, from Jenkins 2.263 to 2.264). This broke every plugin that was involved in configuring projects, but went unnoticed for two months because our project settings haven't needed to change in quite a while, and the builds were still working fine in the meantime.
For reference, my build process is based on:
Ant for the build
Ivy for dependency resolution
Artifactory as a dependency repository
Subversion as a code repository (with Jenkins commit triggers)
Junit with Cobertura, Jmeter
FindBugs, CheckStyle, CLOC
Projects are based on Java and JavaDoc
I tried reverting to the earlier version of Jenkins, but this affected nearly every plugin, and I wasn't able to successfully revert to the plugin version combination from prior to the breaking update. After failing to revert the updates, I decided instead to plow forward in updating all of our 68 projects to accommodate the new plugin versions.
Unfortunately, I can't save any configuration changes to Ivy Projects. After trial and error, I've found that I can re-produce my builds using Freestyle Projects. However, Jenkins doesn't seem to offer any way to convert projects from one type to another. If I were to create new projects from scratch to replace my existing projects (all 68, including their dependencies and specific plugin settings), I would lose all of my previous build histories, including the build numbers (which carry over to our deployments) and our project metrics (which we use for performance evaluation). So, I don't want to lose all of that information.
How can I manually change an Ivy Project to a Freestyle Project?
I found a partial solution, but it doesn't seem to work for all projects.
Stop the Jenkins webapp (important).
For each Ivy Project that you want to convert to a Freestyle Project, rename the root element of jobs/[project]/config.xml from <hudson.ivy.IvyModuleSet plugin="ivy#2.1"> to <project> (don't forget to also change the closing tag at the end of the document from </hudson.ivy.IvyModuleSet> to </project>.
Restart Jenkins.
For most projects, I am then able to change the project configuration and save (importantly, Ant/Ivy-Artifactory Integration in a Freestyle Project is a feature-matched substitute for an Ivy Project).
However, three other projects still show up as Ivy Projects after changing the root element tag. What these projects had in common was that they all use the Performance Plugin. In order to finish converting these to Freestyle, I needed to additionally:
Disable the Performance Plugin
Restart Jenkins
Edit/Save the configuration for those projects as above.
Side effects and special considerations:
All of my build timestamps (prior to the change) are now listed as Dec 31, 1969 7:00 PM EDT, with a most recent build time as 50 yr. New build timestamps are correct. This likely was the result of no longer depending on the CloudBees plugin for build pipelines, which mapped build timestamps to build versions to avoid an old regression bug.
Every project immediately changed to red (Failed) on the dashboard, even though no builds had been attempted after the update, and the previous status was blue (Success) or yellow (Unstable). I suspect this is related to the above issue. After the next attempted build, whether successful or not, the status accurately reflects the build status.
No ability to use the Performance Plugin.
Several projects now show up as both an Upstream and Downstream Project, causing endless build cycles. There were three cases of this involving different combinations of projects, and in those cases, one or both projects needed to be removed from the build triggers. I suspect it had been this way for a while but for some reason the endless cycles only happen after the update.
I suddenly have a lot of "Unreadable Data" across all of my Jenkins projects. Unfortunately, discarding it is an all-or-nothing process (can't pick a single project to test). I backed up my jobs directory and clicked Discard, and to my surprise everything still works.
It looks like I'm back in business. My build numbers have been preserved, and the only noticeable side effect is the 50 year old builds. If I encounter any other issues resulting from these changes, I will update this answer.

Is there a standard way to delete successful vnext builds (PR) just after their completion?

The most aggressive build retention policy one can set for pull request builds is described in "Clean up pull request builds"
a policy that keeps a minimum of 0 builds
Still, it means that successful PR builds (with artifacts no one will ever need) will be deleted only after the next automatic retention cleanup - usually the next day, but in reality it results in nearly two days worth of no longer needed builds.
In our particular case it seems to be desirable to find a way to clean successful PR builds ASAP due to their frequency and artifact's sheer size that may periodically strain our not yet fully organized infrastructure dedicated to PR handling (it will be significantly improved, but not as soon as we'd like to, and those successful PR builds would still remain no less of a dead weight).
And as far as I see the only way to do it would be to delete builds manually.
While it is not too difficult to implement, I'd still like to check whether there is a simpler standard way to delete successful PR builds automatically.
P.S.: There is one particularity in our heavily customized build process - we have multiple dependent artifacts. Like create A, use it to build B, create C to test B... So trying not to Publish artifacts on overall successful build with custom condition like it is suggested below is not exactly feasible.
Let's look at the problem from a different perspective: The problem isn't that builds are retained, the problem is that your PR builds are publishing artifacts.
You can make the Publish Artifacts steps conditional so that they don't run during PRs. Something like and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) will make the task only run if it's not a PR.

Jenkins Promoted build

I don't understand what Promoted build really is and how it works. Can someone please explain to me like to a 10 years old kid. If you can provide some sample examples would help me a lot.
Thanks
In a typical software developing organization with CI system, there are 10's or 100's of continuous builds daily. Only one of those builds (usually the latest stable) is selected and "promoted" to be a Release Candidate (RC), which goes to the next quality gate - usually the QA department. Then, they select one of those RC's (others are dropped) and again, "promote" it to the next level - either to staging environment, validation etc. Then, finally... one of these builds is again "promoted" to be an official release.
Why is that important?
Visibility: You would want to distinguish many "regular", continuous builds from few, selected "RC" builds.
Retention: If you commit often (which is the best practice), you will likely get lot of daily builds, and would like to implement a retention policy (e.g. only keep last 100 builds or only builds from the last 7 days). You will then want to make sure promoted builds (RCs) are locked against retention. This is mostly important if you deploy binaries to customers, and may need the exact binary to reproduce an escaping bug in the future (though you still have the source code in the repository, I've seen cases where escaping bugs relate to the build process rather than the source code - due to rapid changes to the build process, or time-of-build sensitive data like digital signatures).
Permissions: you may want to prevent access to builds with "half baked" features from non-developers.
Binary Repositories: you may want to publish only meaningful builds to an external binary repository.
Builds in Jenkins can be "promoted" either manually or automatically, using plugins like Promoted Builds Plugin. You can also create your entire "promotion" workflow using pipeline scripts. Here's an example:
a "Continuous" job that polls SCM and builds on every change. It has a retention policy to keep only the last 50 builds. Access is restricted only to developers;
a "Release Candidates" job that copies artifacts from a manually selected build (using parameters). Access is allowed to QA testers;
a "Releases" jobs that copies artifacts from a manually selected RC. Access is allowed to the entire organization. Binaries are released to external/public repository.
I hope this answers your question :-)

When should I "Release" my builds?

We just started using Visual Studio Release Management for one of our projects, and we're already having some problems with how we are doing things.
For now, we've created a single release stage, which is responsible for deploying our build artifacts to a dedicated virtual machine for testing. We intend to use this machine to run our integration tests later on.
Right now, we have a gated checkin build process: each checkin fires all the unit tests and we configured the release trigger to happen on this build also. At first, it seemed plausible that, after each checkin, the project was deployed and the integration tests were executed. We noticed that all released builds were polluting the console on Release Management, and that all builds were being marked as "Retain Indefinitely" and our drop folder location was growing fast (after seeing that, it makes sense that the tool automatically does this, since one could promote any build to another stage and the artifacts need to be persisted).
The question then is: what are we doing wrong? I've been thinking about this and it really does not make any sense to "release" every checkin. We should probably be starting this release process when a sprint ends, a point that can be considered a "release candidate".
If we do that though, how and when would we run our automated integration tests? I mean, a deployment process is required for running those in our case, and if we try to use other means to achieve that (like the LabTemplate build process) we will end up duplicating deployment code.
What is the best approach here?
It's tough to say without being inside your organization and looking at how you do things, but I'll take a stab.
First, I generally avoid gated checkin builds unless there's a frequent problem with broken builds. If broken builds aren't a pain point, don't use gated checkin. Why? Simple: If your build/test process takes 10 minutes to run, that's 10 minutes that I have to wait to know whether I can keep working, or if I'm going to get my changes kicked back out at me. It discourages small, frequent checkins and encourages giant, contextless checkins.
It's also 10 minutes that Developer B has to wait to grab Developer A's latest changes. If Developer B needs that checkin to keep working, that's wasted time. Trust your CI process to catch a broken build and your developers to take responsibility and fix them on the rare occasions when they occur.
It's more appropriate (depending on your branching strategy) to do a gated checkin against your trunk, and then CI builds against your dev/feature branches. Of course, that opens up the whole "how do I build once/deploy many when I have multiple branches?" can of worms. :)
If your integration tests are slow and require a deployment to succeed, they're probably not good candidates to run as part of CI. Have a CI/gated checkin build that just:
Builds
Runs fast unit tests
Runs high-priority, non-deployment-based integration tests
Then, have a second build (either scheduled, or rolling) that actually deploys and runs the whole test suite. You can schedule it according to your tastes -- I usually go with one at noon (or whatever passes for "lunch break" among the team), and one at midnight. That way you get a tested build from the morning's work, and one from the afternoon's work.
Using the Release Default Template, you can target your scheduled builds to just go as far as your "dev" (/test/integration/whatever you call it) stage. When you're ready to actually release a build, you can kick off a new release using that specific build that targets Production and let it go through all your stages normally.
Don't get tripped up on the 'Release' word. In MS Release Management (RM), creating a Release does not necessarily mean you will have this code delivered to your customers / not even that it has the quality to move out of dev. It only means you are putting a version of the code on your Release Path. This version/release can stop right in the first stage and that is ok.
Let's say you have a Release Path consisting of Dev, QA, Prod. In the course of a month, you may end up releasing 100 times in Dev, but only 5 times in QA and once in Prod.
You should drive to get each check-in deployed and integration tested. If tests takes a long time, only do the minimal during (gated or not) check-in (for example, unit tests + deployment), and the rest in your second stage of Release Path (which should be automatically triggered after first stage completes). It does not matter if second stage takes a long time. As a dev, check-in, once build completes successfully (and first stage), expect the rest to go smoothly and continue on your next task. (Note that only result of the first stage impacts your TFS build).
Most of the time, deployment and rest will run fine and so there won't be any impact to dev. Every now and then, you will have a failure in first stage, now the dev will interrupt his new work and get a resolution asap.
As for the issue that every build is kept indefinitely, for the time being, that is a side effect of RM. Current customers need to do the clean up manually (or script it). In the coming releases, a new retention policy for releases/builds will be put in place to improve this. This has not been worked on yet, but the intention would be to, for example, instruct RM to keep all releases that went to Prod, keep only the last 5 that went to QA and keep only the last 2 that went to Dev.
This is not a simple question, so also the answer must be articulated.
First of all, you will never keep all of your builds; the older a build, the less interesting to anyone; a build that doesn't get deployed in production is overtaken by builds that reaches that stage.
A team must agree on the criteria that makes a build interesting to keep around and how long to keep it. Define a policy for builds shipped to production or customers: how long do you support them? Until the next release, until the following one, for five years? Potentially shippable builds, still not in your customers' hands, are superseded by newer, so you can use a numeric or a temporal criteria (TFS implements only the first, as the second is more error-prone). Often you have more than one shippable build, when you want a safety net option and being able select from a pool which deliver (the one with more manageable bugs).
The TFS "Retain Indefinitely" should be used when you cannot automate the previous criteria, so you switch to a manually implemented policy. Indefinitely is not forever, means for an unknown time interval.

Jenkins: Starting a build without permanently recording the result

I'm trying to tweak some options in my jenkins configuration, which is causing many builds to fail. I'd prefer to not keep these failures around in the build history, since they're not technically failures of the repository. In the past, I've just deleted the build after looking at the log, but this is a little tedious.
Is there a way to start a build with an option to not record the result of the build permanently?
Perhaps there's a URL that can be used to trigger a debugging build, somethign like:
JENKINS_URL/job/JOBNAME/build?DEBUGGING
You can set the "discard old builds" option in your job to only keep 1 build. If you have older builds you want to keep, you can give them the "keep this build forever" property. If you have a large number of jobs to work with, you can use the Configuration Slicing plugin to modify the Max # of builds to keep.

Resources