You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@yetus.apache.org by aw...@apache.org on 2017/12/10 00:15:12 UTC

yetus git commit: YETUS-288. move precommit-admin from Hadoop

Repository: yetus
Updated Branches:
  refs/heads/master ef2b90a80 -> 34b1ff77c


YETUS-288. move precommit-admin from Hadoop

This is a copy of the jenkinsPrecommitAdmin.py written by
Brock Noland <br...@apache.org> as series of commits in the
svn://svn.apache.org/repos/asf/hadoop/nightly source tree.

The commits correspond with HADOOP-9765, HADOOP-10199, and
HADOOP-10200.

Signed-off-by: Brock Nelson <br...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/yetus/repo
Commit: http://git-wip-us.apache.org/repos/asf/yetus/commit/34b1ff77
Tree: http://git-wip-us.apache.org/repos/asf/yetus/tree/34b1ff77
Diff: http://git-wip-us.apache.org/repos/asf/yetus/diff/34b1ff77

Branch: refs/heads/master
Commit: 34b1ff77cf13389ca21c41a2ecc9f335e6da7aea
Parents: ef2b90a
Author: Allen Wittenauer <aw...@apache.org>
Authored: Fri Dec 8 11:13:24 2017 -0800
Committer: Allen Wittenauer <aw...@apache.org>
Committed: Sat Dec 9 16:14:39 2017 -0800

----------------------------------------------------------------------
 precommit/jenkins/jenkins-admin.py | 143 ++++++++++++++++++++++++++++++++
 1 file changed, 143 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/yetus/blob/34b1ff77/precommit/jenkins/jenkins-admin.py
----------------------------------------------------------------------
diff --git a/precommit/jenkins/jenkins-admin.py b/precommit/jenkins/jenkins-admin.py
new file mode 100755
index 0000000..0fe34b0
--- /dev/null
+++ b/precommit/jenkins/jenkins-admin.py
@@ -0,0 +1,143 @@
+#!/usr/bin/env python
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Script uses a JIRA search filter to submit test Jenkins
+# jobs for patch avilable issues. For more information see:
+#  http://wiki.apache.org/general/PreCommitBuilds
+#  https://builds.apache.org/job/PreCommit-Admin/
+
+from optparse import OptionParser
+from tempfile import NamedTemporaryFile
+from xml.etree import ElementTree
+import os, re, sys, urllib2
+
+# max number of entries to keep in the patch_tested.txt file
+MAX_HISTORY = 5000
+
+def httpGet(resource, ignoreError=False):
+  if ignoreError:
+    try:
+      return urllib2.urlopen(resource).read()
+    except urllib2.URLError, e:
+      print "ERROR retrieving resource %s: %s" % (resource, e)
+      return ""
+  return urllib2.urlopen(resource).read()
+
+
+# returns a map of (project, issue) => attachment id
+def parseJiraData(fileName):
+  tree = ElementTree.parse(fileName)
+  root = tree.getroot()
+  jiraPattern = re.compile('([A-Z]+)\-([0-9]+)')
+  result = {}
+  for item in root.findall("./channel/item"):
+    key = item.find('key')
+    if key == None: continue
+    issue = key.text
+    matcher = jiraPattern.match(issue)
+    if not matcher: continue
+    issue = matcher.group(1), matcher.group(2)
+    attachmentIds = []
+    for attachment in item.findall('./attachments/attachment'):
+      attachmentId = attachment.get('id')
+      try:
+        attachmentIds.append(int(attachmentId))
+      except ValueError:
+        pass
+    if len(attachmentIds) > 0:
+      attachmentIds.sort()
+      result[issue] = attachmentIds[-1]
+  return result
+
+if __name__ == '__main__':
+  parser = OptionParser()
+  parser.add_option("--jenkins-url", dest="jenkinsUrl",
+                    help="Jenkins base URL", metavar="URL")
+  parser.add_option("--jenkins-token", dest="jenkinsToken",
+                    help="Jenkins Token", metavar="TOKEN")
+  parser.add_option("--jira-filter", dest="jiraFilter",
+                    help="JIRA filter URL", metavar="URL")
+  parser.add_option("--jenkins-url-override", dest="jenkinsUrlOverrides", action="append",
+                    help="Project specific Jenkins base URL", metavar="PROJECT=URL")
+  parser.add_option("--live", dest="live", action="store_true",
+                    help="Submit Job to jenkins")
+  (options, args) = parser.parse_args()
+  if not options.jiraFilter:
+    parser.error("JIRA Filter is a required argument")
+  if not options.jenkinsUrl:
+    parser.error("Jenkins URL is a required argument")
+  if options.live and not options.jenkinsToken:
+    parser.error("Jenkins Token is required when in live mode")
+  jenkinsUrlOverrides = {}
+  if options.jenkinsUrlOverrides:
+    for override in options.jenkinsUrlOverrides:
+      if "=" not in override:
+        parser.error("Invalid Jenkins Url Override: " + override)
+      (project, url) = override.split("=", 1)
+      jenkinsUrlOverrides[project.upper()] = url
+  tempFile = NamedTemporaryFile(delete=False)
+  try:
+    jobLogHistory = httpGet(options.jenkinsUrl + \
+      "/job/PreCommit-Admin/lastSuccessfulBuild/artifact/patch_tested.txt", True)
+    # if we don't have a successful build available try the last build
+    if not jobLogHistory:
+      jobLogHistory = httpGet(options.jenkinsUrl + \
+        "/job/PreCommit-Admin/lastCompletedBuild/artifact/patch_tested.txt")
+    jobLogHistory = jobLogHistory.strip().split("\n")
+    if "TESTED ISSUES" not in jobLogHistory[0]:
+      print "Downloaded patch_tested.txt control file may be corrupted. Failing."
+      sys.exit(1)
+    jobLog = open('patch_tested.txt', 'w+')
+    if len(jobLogHistory)  > MAX_HISTORY:
+      jobLogHistory = [ jobLogHistory[0] ] + jobLogHistory[len(jobLogHistory) - MAX_HISTORY:]
+    for jobHistoryRecord in jobLogHistory:
+      jobLog.write(jobHistoryRecord + "\n")
+    jobLog.flush()
+    rssData = httpGet(options.jiraFilter)
+    tempFile.write(rssData)
+    tempFile.flush()
+    for key, attachment in parseJiraData(tempFile.name).items():
+      (project, issue) = key
+      if jenkinsUrlOverrides.has_key(project):
+        url = jenkinsUrlOverrides[project]
+      else:
+        url = options.jenkinsUrl
+      jenkinsUrlTemplate = url + "/job/PreCommit-{project}-Build/buildWithParameters" + \
+        "?token={token}&ISSUE_NUM={issue}&ATTACHMENT_ID={attachment}"
+      urlArgs = {'token': options.jenkinsToken, 'project': project, 'issue': issue, 'attachment': attachment }
+      jenkinsUrl = jenkinsUrlTemplate.format(**urlArgs)
+      # submit job
+      jobName = "%s-%s,%s" % (project, issue, attachment)
+      if jobName not in jobLogHistory:
+        print jobName + " has not been processed, submitting"
+        jobLog.write(jobName + "\n")
+        jobLog.flush()
+        if options.live:
+          httpGet(jenkinsUrl, True)
+        else:
+          print "GET " + jenkinsUrl
+      else:
+        print jobName + " has been processed, ignoring"
+    jobLog.close()
+  finally:
+    if options.live:
+      os.remove(tempFile.name)
+    else:
+      print "JIRA Data is located: " + tempFile.name