-
Notifications
You must be signed in to change notification settings - Fork 166
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
A novel approach to trimming Jenkins nodes by Node.js version #1153
Comments
Also cc @gibfahn, this is a similar problem to the one we're attempting to solve internally in IBM with pipelines. |
Having more logic hidden inside of jenkins (and duplicacated) is a minus for me, but I do like that it would avoid having to run the job at and it will be more obvious when we get it wrong (as we'll see a shaded entry as opposed to a green due to pre-mature exist). Is there any way to pull the script that does the filtering from the repo as opposed to having to configure in jenkins itself ? |
This is great work @rvagg, this is a massive improvement over what was there before. First, we actually have 3 strategies for doing different things in Jenkins. The 2 mentioned above, but there is also a One way to think of this is that (ignoring pipelines for now) we have 2 ways of structuring jobs in Jenkins:
The approach mentioned here with the plugin allows to have the same mechanism for both types, which is great. Until now we had About having the logic hidden in Jenkins is something that we can and should improve, but it's no worse than it is today (have a look at the combination filter for |
Do you have a link to your plugin? Would be interesting to see how much extra you have to add to make it a Jenkins plugin. Long-term I think using a Jenkins pipeline is a better way to go if it's not more difficult, simply because it's less clicking around in the UI. I have a pipeline script somewhere that takes an array of labels to run on and runs a job on each, it would be simple enough to hook this groovy function up to something like that. I had a play with implementing Either way it's not an issue, they're both groovy scripting languages, so there's no reason we shouldn't start with a Jenkins plugin and then move the script into a pipeline if it makes sense. |
re pipelines .. I remain unconvinced, although I feel like a laggard with everyone saying that they are the way of the future with Jenkins. I still find them opaque and not user-friendly compared to what we have. I was hoping that the folks working on pipelines within our CI would be building a case for them as a solid replacement that will improve our lives as administrators while also hopefully improving the insight for users. Perhaps that case is coming? Anyway, @mhdawson re your point about hiding even more stuff in Jenkins, this is a real problem. So with that in mind, since we're dealing with a full Groovy sandbox I've replaced the entire script with this: def scriptUrl = 'https://raw.githubusercontent.com/nodejs/build/rvagg/VersionSelectorScript.groovy/jenkins/scripts/VersionSelectorScript.groovy'
def code = new URL(scriptUrl).getText()
println "Got matrix selection script from ${scriptUrl}:"
println "-------------------------------------------------------------------"
println code
println "-------------------------------------------------------------------"
evaluate(code)
return [ result, true ] and have put the script in our repo in the jenkins/script directory (on a branch for now): https://github.com/nodejs/build/blob/rvagg/VersionSelectorScript.groovy/jenkins/scripts/VersionSelectorScript.groovy That works nicely! Regarding the plugin, I was holding off putting code up for it in case this idea got shot down quickly. If I set up a new repo under my own GitHub profile then we have to jump through hoops to get it transferred into the org so I wanted to jump straight to setting up a project in the nodejs org. I'll do that now so you can review it. |
for your consideration: https://github.com/nodejs/node-version-jenkins-plugin |
Having it in a script in the build repo and pulling it/running from their is a great improvement ! Sounds though that you already have a plug in that will do the same thing as well. Either option seems good as we won't have to duplicate the logic across each job. |
I pushed an update to node-version-jenkins-plugin that fixes it so it works on ci.nodejs.org and can run remotely on the jenkins-workspace (and other) machines, it's simpler in ci-release so I didn't catch that bug. It's now installed in ci.nodejs.org and I'm moving this discussion to #1217 because I've started implementing it (doesn't mean that we have to embrace it fully, we could roll it back, but I quite like it!) |
For discussion, although I have a working implementing of the approach I'm detailing below on ci-release atm.
We have 2 different strategies for doing different things in Jenkins according to Node.js version:
NODE_MAJOR_VERSION
via some Bash scriptery inside a parent job and bubbling it down via environment variables (via env.properties). You can see this in node-test-commit and then it's used in the 3 jobs that are used to compile and test for Windows (node-test-binary-windows, node-compile-windows, node-test-commit-windows-fanned) to select amongst Windows builders.Our rules are most strict on ci-release where it's critical we get the right builders for a release:
Node 10 is going to make it more complicated. I think for instance we're going to have to introduce new rules for ARMv6 & ARMv7 (and possibly new machines) because we're still using Wheezy, plus I think CentOS 7 might be our new target builder for Node 10+ and probably a new SmartOS too (this discussion is for a new issue).
There are drawbacks to both approaches we use:
NODE_MAJOR_VERSION
you need to run a parent job to inspect the source, or you have to manually enter it in the job (it's currently set as default10
and that needs to be incremented each time we make a major release but, for example, if you want to test Node 8 and you don't select it then you'd get the wrong compiler and you may not even know. We've also kept ci-release pretty simple and only have a single job, with no hierarchy, so we can't use this approach unless we want to start splitting it up (my preference is to KISS but it's getting hard).So, I did some experimenting this weekend with a new approach on ci-release that might scale across ci too, although I admit that it's still complicated but perhaps we have to put up with that.
Jenkins plugin to detect version
Yeah .. I went down that route. A very simple plugin that hooks into the Git plugin and performs some work upon checkout. You opt-in to the functionality with a tickbox on the Git setup for a job. If you opt-in, then it will look for src/node_version.h in the current workspace, if there it'll parse it for the 3 semver elements and then use them to insert two parameters into the current build:
NODEJS_VERSION
—the full version (minus any tags) andNODEJS_MAJOR_VERSION
—just the major number, which is what we'll make most use of.Once we have parameters we can start to use them in our matrix job filtering. I have this installed on ci-release to try it out and I've also installed the Matrix Groovy Execution Strategy Plugin which lets us enter more sophisticated Groovy scripts into the matrix combination filtering. I think the same thing could be achieved with the basic "Combination filter" option but I haven't had as much success and the box is just an input field rather than a textbox so it gets out of hand really quickly.
By filtering execution at this level, the builders themselves don't even get invoked if we don't need them to be (similar to approach 1 above, but self-contained within a job). Plus, our rules for what gets to run is all contained in a single script in a single language that's pretty easy to grok and edit (unlike approach 2 now which spans Bash and BAT and even in Bash we have maybe 3 different approaches to achieving the same thing).
Here's the Groovy script I have for iojs+release at the moment that does what the existing per-builder scripting does (I haven't removed that second layer of scripting but if this is correct then they'll never short-cut a build because it shouldn't be running).
When you build off Node master (10) you end up with this kind of thing:
(the lighter shaded icons indicate that they weren't invoked)
Now, one drawback of this approach is that it's done per-job. If we include this logic in ci.nodejs.org then a script would have to be introduced wherever we need to do filtering. That means the script only needs to focus on the builders involved in that job (linux only, windows only, etc.) but it also means the logic is spread out and will end up being duplicated because we have so many copied jobs. It may be possible to have the above script done in a single location but it would take another plugin, or modification of that Groovy Matrix plugin (and some knowledge about Jenkins plugins that I don't have atm) to make it happen and we'd also have to make sure that it properly accounts for all of the builder labels we have and that they are used consistently across the jobs that make use of this.
/cc @joaocgreis @mhdawson because you have both been involved in hacking together our current approaches.
The text was updated successfully, but these errors were encountered: