Skip to content
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

Proxy Jenkins build status to GitHub #35

Merged
merged 8 commits into from
May 11, 2016
Merged

Proxy Jenkins build status to GitHub #35

merged 8 commits into from
May 11, 2016

Conversation

phillipj
Copy link
Member

This is work in progress atm, PR exists for public scrutiny and to show I've started working on it.

Any thoughts are much appreciated!

Refs #5

@Fishrock123
Copy link
Contributor

Is this page the only official docs on it? https://wiki.jenkins-ci.org/display/JENKINS/Remote+access+API

cc @jbergstroem

@phillipj
Copy link
Member Author

phillipj commented May 2, 2016

Made some improvements to this today. My biggest question atm is how we should trigger Jenkins polling in the first place?

I've thought of two different approaches so far:

  1. Does Jenkins have support for notifying the bot with a HTTP request? If so that could be a pretty clean approach.
  2. Listen for PR comments matching "CI: https://ci.nodejs.org/job/node-test-pull-request/X".

Any other thoughts?

/cc @Fishrock123 @jbergstroem

@Fishrock123
Copy link
Contributor

All of my existing ideas have been around suggestion 1. -- by far the most reliable.

@jbergstroem
Copy link
Member

@phillipj we could implement it [pinging the bot] as a build step. The problem here is security; the receiving end can't use much else than ip/hostname matching for security. If that's acceptable it would likely be the best path forward.

As for methodology; I'd like to suggest the following:

  1. (based on option one) accept the incoming request
  2. inspect what subjobs are being spawned
  3. post a 'pending' request for all subjobs to the PR
  4. wait for subjobs to complete
  5. add a completion task at each job which posts info to bot (again, if trust can be established)
  6. parse info and notify github. I'd really like to see something like:
  7. if test passes, something basic (ci/linux: all tests passed)
  8. if we get flakey/skips, use pass again but mention flakey/skips (ci/linux: tests passed (5 flakey, 5 skips))
  9. if we get fails, post as failure with num fail tests (ci/linux: 2 failed tests)

Also, once we close in on this I reckon we should split linter from the test-pr job and start calling it separately from the gh bot on pretty much every commit, as well as create a set of slaves that does the same for commit message validation.

@Fishrock123
Copy link
Contributor

Fishrock123 commented May 3, 2016

The problem here is security; the receiving end can't use much else than ip/hostname matching for security.

Can it be over https? Github and the like just send a secret to verify, or the hash of a secret. Would that be possible?

That being said ip/hostname matching probably isn't too bad?

I like the methodology suggestions. @jbergstroem how difficult would it be to make those subjobs so we can start trying this?

@jbergstroem
Copy link
Member

@Fishrock123 the problem isn't so much man in the middle, but the fact that we can't store credentials at jenkins since a PR could potentially just do echo $FOO. I actually implemented posting progress to github as part of the jenkins jobs but abandoned due to security issues. More info about findings over here nodejs/build#236.

@Fishrock123 by subjobs i was referring to the fact that node-test-pr invokes node-test-commit which in turn invokes node-test-linux and so on. So what we'd do is likely send a request from each (if POST_STATUS_TO_PR is set at top level) at start and completion.

@phillipj
Copy link
Member Author

phillipj commented May 4, 2016

@jbergstroem no problem going for ip/host matching for incoming HTTP requests.

To ensure we're on the same page here: if the bot gets HTTP requests upon subjob start and completion, it will not perform any Jenkins polling at all, but will work more like a proxy for updating github PR (commit) status? ..if so that sounds very good 👍

It would be very helpful if we could get our hands on some example payloads those subjob requests from Jenkins include.

@Fishrock123
Copy link
Contributor

if the bot gets HTTP requests upon subjob start and completion, it will not perform any Jenkins polling at all, but will work more like a proxy for updating github PR (commit) status?

@phillipj correct.

It would be very helpful if we could get our hands on some example payloads those subjob requests from Jenkins include.

Yes. this. :D

@jbergstroem
Copy link
Member

Example payloads: I can craft them whatever way we want -- will essentially just pass stuff through curl.

@phillipj
Copy link
Member Author

phillipj commented May 5, 2016

@jbergstroem we should come a long way with:

  • build parameters
  • subjob name
  • subjob URL
  • commit sha
  • build result (upon completion)

The structure of the payload isn't important, as long as it's JSON. Is it doable?

@Fishrock123
Copy link
Contributor

What do we need build params for?

@Fishrock123
Copy link
Contributor

Imo, we'll need:

  • name
  • url
  • commit sha
  • status

@phillipj
Copy link
Member Author

phillipj commented May 5, 2016

What do we need build params for?

@Fishrock123 the POST_STATUS_TO_PR option. Should we simply ignore it and report 'em all?

@Fishrock123
Copy link
Contributor

Fishrock123 commented May 5, 2016

@phillipj I presume that would determine if the bot gets contacted at all or not?

@phillipj
Copy link
Member Author

phillipj commented May 5, 2016

@Fishrock123 ahh that makes sense. Agreed we could do wo/build params then.

@jbergstroem
Copy link
Member

More a summary of yours, but yeah; this is what I'm thinking:

on start:
  • the jenkins job will check if POST_STATUS_TO_PR is set or bail
  • curl to $url/$start_endpoint with a pretty low timeout since this is sync, with:
    • job name (we can map job name to something more user friendly at the gihub bot, for instance: node-test-linux -> test/linux)
    • url to job
    • commit sha
    • designated slave
on completion:
  • the jenkins job will check if POST_STATUS_TO_PR is set or bail
  • curl to $url/$stop_endpoint
    • job name
    • url to job
    • commit sha
    • designated slave
    • build results (this will be different between some jobs; for instance linter or commit-message-validator):
      • passed/flaky/fail
      • total tests/flaky/failed
      • time spent

We should poll jobs occasionally slave might go away during job. Not very likely but it happens. Also, we sometimes have ci-related failures. Reporting them as a "ci fail" would be a nice ui improvement.

@phillipj
Copy link
Member Author

phillipj commented May 6, 2016

@jbergstroem @Fishrock123 just did some adjustments based on what we've been discussing here.

I did some assumptions on the structure and made three fixtures:

You can see the result of POSTing those payloads in TestOrgPleaseIgnore/node#13

What's missing from @jbergstroem last comment is use of designated slave and different kinds of build results. It also doesn't use two different endpoints for start / completion, I did see the need for that so far.

..and it would have been nice to get this covered by tests.

@@ -0,0 +1,12 @@
{
"fullDisplayName": "node-test-commit-arm #3087",
"result": "FAILURE",

This comment was marked as off-topic.

@phillipj
Copy link
Member Author

phillipj commented May 7, 2016

Thanks for reviewing so quick guys!

Mind explaining the rational behind this?

@Fishrock123 it's the same structure as the Jenkins json/api uses. If we're not tied to that structure/format and can do adhoc, I'm more than happy to keep it simpler.

@phillipj
Copy link
Member Author

phillipj commented May 7, 2016

As just mentioned ^ if we're able to use whatever structure/format we want, just ignore the fixtures added here.

@jbergstroem would you be able to post an example of what these curl jobs could provide the bot with?

@jbergstroem
Copy link
Member

@phillipj jenkins basically has the same information available as what you can get from the api; so I'll just build a query similar to what we expect. I will build different queries based on fail/success/etc.

@Fishrock123
Copy link
Contributor

Fishrock123 commented May 8, 2016

@jbergstroem How about making it curl an object like this, and we'll go from there?

{
  "info": "something about node-test-commit-linux",
  "status": "FAILURE",
  "commit": "shasum",
  "url": "https://ci.nodejs.org/job/node-test-commit-linux/3176/"
}

@jbergstroem
Copy link
Member

@Fishrock123 sounds good. in addition to that, we should probably add identifier (linux, linter, etc) and test results. I'll look at my old stuff.

@jbergstroem
Copy link
Member

How about something like:

$ curl \
  --connect-timeout 5 \
  -X POST \
  -H "Content-Type: application/json" \
  -d "{ \
    \"identifier\": \"linter\", \
    \"status\": \"pending\", \
    \"url\": \"${BUILD_URL}\", \
    \"commit\": \"$(git rev-parse HEAD)\", \
    \"message\": \"checking for errors\" \
  }" \
  https://deepthought.nodejs.org/endpoint/

..and with payload:

curl \
  --connect-timeout 5 \
  -X POST \
  -H "Content-Type: application/json" \
  -d "{ \
    \"identifier\": \"test/linux\", \
    \"status\": \"failure\", \
    \"url\": \"${BUILD_URL}\", \
    \"commit\": \"$(git rev-parse HEAD)\", \
    \"message\": \"tests failed\",
    \"data\": { \
      \"total\": \"12345\", \
      \"pass\": \"12340\", \
      \"fail\": \"3\", \
      \"skip\": \"2\" \
    } \
  }" \
  https://deepthought.nodejs.org/endpoint/

The rationale behind abstracting data is that we could store it and start generating insights over time. I see something similar as part of the other data we collect from github by receiving all the events (briefly mentioned in #4). It's also easier working with the data -- one test failed (5 skipped, 2 flakey) vs 2 tests failed .. than through bash.

@phillipj
Copy link
Member Author

phillipj commented May 9, 2016

@jbergstroem LGTM, I'll update the fixtures tonight. I suggest we leave data out of the picture initially to get this out asap, and add it later in a separate PR which also stores that data somehow.

@phillipj phillipj changed the title WIP: polling Jenkins for build status WIP: proxy Jenkins build status to GitHub May 9, 2016
@jbergstroem
Copy link
Member

@phillipj that means I'll be formatting the failures from bash then?

@phillipj
Copy link
Member Author

phillipj commented May 9, 2016

@jbergstroem hm... you would prefer the status description (the text displayed to the right of the status) to be a combination of curl's message and a human readable format of data?

@Fishrock123
Copy link
Contributor

Fishrock123 commented May 9, 2016

@jbergstroem I think you can include the data but we will worry about processing that after we have the initial things up and running?

@phillipj
Copy link
Member Author

phillipj commented May 9, 2016

Just updated the fixtures, and deleted lots of code which ended up giving a lot of flexibility from the curl side of things. It's now very much a proxy to update GH statuses, forwarding whatever it gets as input, rather than trying to do smart transformations.

PTAL and shout if I've missed something from your comments.

image
TestOrgPleaseIgnore/node#14

@jbergstroem
Copy link
Member

@Fishrock123 yeah I agree. So, where do I post for now? Also, I'm kind of interested in finding a way of queueing/delegating all the curl requests so they return instantly -- anyone got any ideas?

@phillipj
Copy link
Member Author

phillipj commented May 10, 2016

@Fishrock123 nope, that's for the github repo hooks (used to trigger Travis polling). I'll send the URL to @jbergstroem on IRC as the location of the bot shouldn't be public atm since we don't have a ip/hostname match or other security measures in place.

@phillipj
Copy link
Member Author

@Fishrock123 @jbergstroem soooo, I just pushed a commit loading the gun so to speak ^.

ATM the bot gets curl updates from node-test-linter in production, but doesn't do anything since these changes hasn't been merged yet. Are we ready to merge & deploy this as is, or do we need more things before rolling forward?

@phillipj phillipj changed the title WIP: proxy Jenkins build status to GitHub Proxy Jenkins build status to GitHub May 10, 2016
@Fishrock123
Copy link
Contributor

I've made a test PR at nodejs/node#6674 -- forgot to make this on the repot itself though. LMK if it should open a new one from a node repo branch so you can push to it.

@phillipj
Copy link
Member Author

..and now it even has tests ensuring github is requested with the expected payload as well 🎆

@phillipj
Copy link
Member Author

@jbergstroem fyi I'm holding this 'til you respond. I could potentially deploy this specific branch instead of merging it to master, if you'd rather do a couple of test runs before we going full throttle ;)

@jbergstroem
Copy link
Member

I've now implemented check for POST_STATUS_FOR_PR. I'll default that to off for now and start adding status updates to more jobs.

@phillipj phillipj merged commit 39f2c49 into master May 11, 2016
@phillipj phillipj deleted the pull-jenkins branch May 11, 2016 05:41
@phillipj
Copy link
Member Author

This is now live in production 💥

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants