Example #1
0
 def checkForRepository(self):
     (status, output) = self.statusOutput("git status")
     if(status):
         juche.error("Not in git repository! Check your current directory!")
         raise Exception("stacktraceplease")
     else:
         return output
Example #2
0
 def reactivate(self,CASE_NO,assignTo,msg):
     try:
         response = self.fbConnection.reactivate(ixBug=CASE_NO,sEvent=msg,ixPersonAssignedTo=assignTo)
     except FogBugzAPIError as e:
         juche.error("Unexpected condition [%s] Is case closed? Attempting to recover..." % e)
         response = self.fbConnection.reopen(ixBug=CASE_NO,sEvent=msg,ixPersonAssignedTo=assignTo)
         juche.info("Recovery was successful.")
Example #3
0
    def fetch_all(self,deploy=True):

        juche.dictate(task="fetch-all")
        projects = get_config()["Projects"]
        #print projects
        for project in projects:
            juche.dictate(fetch=project["url"])
            git = self.clone_or_get(project["url"],WORK_DIR+project["name"])
            git.fetch()
            #Iterate over milestones for the current project
            for sFixFor in self.f.listFixFors(sProject=project["name"],onlyProjectMilestones=True):
                sFixFor = sFixFor.sfixfor.contents[0].encode('utf-8')
                if sFixFor.endswith("-test"): continue
                try:
                    git.resetHard_INCREDIBLY_DESTRUCTIVE_COMMAND() # I'm still against this, but it might make things work for this week
                    git.checkoutExistingBranchRaw(sFixFor)
                except:
                    juche.warning("Can't check out branch %s in project %s, perhaps it doesn't exist?" % (sFixFor,project["name"]))
                    continue
                if git.needsPull():
                    juche.info("Pulling %s in project %s" % (sFixFor,project["name"]))
                    git.pull()
                    self.integrate_changed(git,git.getBranch(),project["name"])
                if deploy:
                    try:
                        self.deploy(git,sFixFor,project)
                    except Exception as e:
                        juche.error("Can't deploy")
                        juche.exception(e)
Example #4
0
 def createCase(self, title, ixProject, ixMilestone, priority=3, ixPersonAssignedTo=None):
     resp = self.fbConnection.new(sTitle=title, ixProject=ixProject, ixFixFor=ixMilestone, sPriority=priority, ixPersonAssignedTo=ixPersonAssignedTo)
     if not resp:
         juche.error("Failed to create case %s in %s (%s), priority %s for user %s" % (title, ixProject, ixCategory, priority, ixPersonAssignedTo))
         return -1
     else:
         return resp.case.ixBug
Example #5
0
 def stopWork(self, CASE_NO):
     query = 'assignedto:"{0}" {1}'.format(self.username.lower(), CASE_NO)
     resp=self.fbConnection.search(q=query)
     if (resp):
         self.fbConnection.stopWork()
     else:
         juche.error("FogBugz case does not exist or isn't assigned to you!")
     return
Example #6
0
    def checkoutExistingBranch(self,CASE_NO):

        output = self.__checkoutExistingBranch(CASE_NO)
        if not output:
            juche.error("could not checkout existing branch: %s" % output)
            raise Exception("stacktraceplease")

        #print bcolors.WARNING + output + bcolors.ENDC

        self.pull()
        return True
Example #7
0
 def createPullRequest(self,requestTitle,requestBody,fromHere,toHere):
     dict = {"title":requestTitle,"body":requestBody,"base":fromHere,"head":toHere}
     #print "https://api.github.com/repos/%s/%s/pulls" % (self.ghRepoUser,self.ghRepo)
     #print dict
     req = self.Request("https://api.github.com/repos/%s/%s/pulls" % (self.ghRepoUser,self.ghRepo),json.dumps(dict))
     try:
         response = urllib2.urlopen(req)
         return json.loads(response.read())["html_url"]
     except urllib2.HTTPError as e:
         juche.exception(e)
         juche.error(e.read())
         raise e
Example #8
0
    def resolveCase(self, CASE_NO,ixstatus=None, isTestCase_CASENO=None):
        query = 'assignedto:"{0}" {1}'.format(self.username.lower(), CASE_NO)
        resp=self.fbConnection.search(q=query)
        if(resp):
            if (ixstatus):
                self.fbConnection.resolve(ixBug=CASE_NO,ixStatus=ixstatus)
            else:
                self.fbConnection.resolve(ixBug=CASE_NO,ixPersonAssignedTo=7)


        else:
            juche.error("FogBugz case does not exists or isn't assigned to you!")
        return
Example #9
0
 def __checkoutExistingBranchRaw(self,arg):
     juche.dictate(double_checkout_existing_branch_raw=arg)
     (checkoutNewBranchStatus, output) = self.statusOutput("git checkout {0}".format(arg))
     if(checkoutNewBranchStatus):
         juche.info(output)
         return False
     (status,output) = self.statusOutput("git submodule init")
     if status:
         juche.error("could not init submodule: %s",output)
     (status,output) = self.statusOutput("git submodule update")
     if status:
         juche.error("Error updating a submodule %s",output)
     return True
Example #10
0
    def createNewRawBranch(self, branchName, fromSpec):
        #check fromspec
        if(fromSpec):
            if fromSpec=="Undecided":
                juche.error("Undecided isn't a valid fromspec.  (Maybe set the milestone on the ticket?)")
                raise Exception("stacktraceplease")
            self.checkoutExistingBranchRaw(fromSpec)
        #regardless, we need our integration branch to be up to date
        self.pull()

        # create branch for and check it out
        self.checkoutExistingBranchRaw("-b {0}".format(branchName))

        # push changes
        self.pushChangesToOriginBranch(branch=branchName)

        self.setUpstream(branchName, "remotes/origin/{0}".format(branchName))
        return branchName
Example #11
0
 def mergeIn(self,BRANCH_NAME,pretend=False):
     if pretend:
         return self.__mergeInPretend(BRANCH_NAME)
     juche.dictate(merging_in=BRANCH_NAME)
     (status,output) = self.statusOutput("git merge --no-ff %s" % BRANCH_NAME)
     juche.info(output)
     if status:
         juche.error("merge was unsuccessful.")
         # play sounds!
         self.statusOutput ("afplay -v 7 %s/media/ohno.aiff" % sys.prefix)
         raise Exception("stacktraceplease")
     else:
         # play sounds!
         from work import get_setting_dict
         if get_setting_dict().has_key("disablesounds") and get_setting_dict()["disablesounds"]=="YES":
             pass
         else:
             self.statusOutput ("afplay -v 7 %s/media/hooray.aiff" % sys.prefix)
     juche.info("Use 'git push' to ship.")
Example #12
0
    def startCase(self, CASE_NO,enforceNoTestCases=True):
        query = 'assignedto:"{0}" case:"{1}"'.format(self.username.lower(), CASE_NO)

        cols = "fOpen,hrsCurrEst"
        if enforceNoTestCases:
            cols += ",ixCategory,sTitle"
        resp=self.fbConnection.search(q=query, cols=cols)
        if enforceNoTestCases and self.__isTestCase(resp):
            juche.error("Can't 'work start' a test case (maybe you meant 'work test'?)")
            return
        if (resp and resp.case):
            #print resp
            if resp.case.fopen.contents[0] != "true":
                juche.error("FogBugz case is closed")
                raise Exception("stacktraceplease")
            if resp.case.hrscurrest.contents[0] != "0":
                self.fbConnection.startWork(ixBug=CASE_NO,enforceNoTestCases=enforceNoTestCases)
                self.commentOn(CASE_NO,"work.py: %s is implementing." % self.username)
            else:
                self.setEstimate(CASE_NO)
                self.startCase(CASE_NO)
        else:
            juche.error("FogBugz case does not exist or isn't assigned to you!!")
            raise Exception("stacktraceplease")
        return
Example #13
0
    def pull(self):
        self.checkForRepository()
        import ConfigParser
        c = ConfigParser.ConfigParser()
        if self.wd:
            path = self.wd + "/.git/config"
        else:
            path =".git/config"
        import os
        for i in range(0,30):
            if os.path.exists(path): break
            path = "../" + path
            if i==30:
                raise Exception("Not a git repository?")

        file = open(path)
        str = file.read()
        file.close()

        juche.dictate(pull=1)
        if self.getBranch() not in str:
            juche.warn( "%s is not a tracking branch. Attempting to fix..." % self.getBranch())
            try:
                self.setUpstream(self.getBranch(),"remotes/origin/{0}".format(self.getBranch()))
                juche.info("Success!")
            except:
                juche.error("DID NOT AUTOMATICALLY FIX BRANCH UPSTREAM / TRACKING.  PLEASE FILE A BUG.")

            (status,output) = self.statusOutput("git pull origin %s" % self.getBranch())
            if status:
                juche.error("Cannot pull! %s" % output)
        else:
            (status,output) = self.statusOutput("git pull")
            if status:
                juche.error("ERROR:  Cannot pull! %s" % output)
                raise Exception("stacktraceplease")
        self.submoduleUpdate()
        juche.info("Success!")
Example #14
0
 def assignCase(self, CASE_NO, ixPerson):
     resp = self.fbConnection.assign(ixBug=CASE_NO, ixPersonAssignedTo=ixPerson)
     if not resp:
         juche.error("Fogbugz case does not exist are can't be assigned to ixperson %s" % ixPerson)
Example #15
0
def still_alive():
    juche.info("still alive")

import unittest
class TestSequence(unittest.TestCase):
    def setUp(self):
        pass

    def test_create_tests(self):
        create_tests()
        #import cProfile
        #cProfile.runctx('create_tests()',globals(),locals()) #http://stackoverflow.com/questions/1819448/cannot-make-cprofile-work-in-ipython/3305654#3305654

if __name__=="__main__":
    q = TaskQueue()
    q.insert(priority_fix,every=HOURLY*6,now=False)
    q.insert(atlas,every=MINUTELY,now=True)
    q.insert(fixup,every=HOURLY*4,now=False)
    q.insert(still_alive,every=60)
    q.insert(autoboss,every=HOURLY*4)
    q.insert(create_tests,every=MINUTELY)


    while True:
        try:
            q.execTop()
        except Exception as e:
            juche.error("That's funny, I don't feel corrupt.  In fact, I feel pretty good.")
            juche.exception(e)
        sleep(2)
Example #16
0
 def ensureReadyForTest(self,CASE_NO):
         if not self.isReadyForTest(CASE_NO):
             juche.error("Case %d is not ready for test!  (resolved or implemented)" % CASE_NO)
             raise Exception("stacktraceplease")
Example #17
0
    CASE_NO = 0
    fromSpec = ""

    #check for updates
    from urllib2 import urlopen
    import json
    latest_version_no = json.loads(urlopen("https://api.github.com/repos/drewcrawford/work.py/git/refs/heads/master").read())["object"]["sha"]
    try:
        f = open("/usr/local/etc/.work.version")
        our_version_no = f.read().strip()
        f.close()
    except:
        our_version_no = "UNKNOWN"
    if latest_version_no != our_version_no:
        from gitConnect import bcolors
        juche.error('WORK.PY IS OUT OF DATE... (repo is %s, local is %s)' % (latest_version_no[:6],our_version_no[:6]))




    #Attention: Older methods in here used to have a fixed argument format (1 = case, 2 = from=case).
    #However, with the plethora of new work commands this assumption is somewhat broken.
    #Going forward, we should do the parsing for the command in its elif block rather than up here
    #todo: refactor existing stuff

    if len(sys.argv) > 1:       #if there's at least one argument...
        task = sys.argv[1];
        if len(sys.argv) > 2:   # if there's a second argument...
            try:
                CASE_NO = int(sys.argv[2])
            except:
Example #18
0
    import json


try:
    import keyring
except:
    juche.warning("Could not import keyring API")
    #raise Exception("stacktraceplease")



try:
    from fogbugz import FogBugz
    from fogbugz import FogBugzAPIError
except Exception as e:
    juche.error("Could not import FogBugz API because: ", e)
    juche.exception(e)

    #raise Exception("stacktraceplease")
from xml.dom.minidom import parseString

TEST_IXCATEGORY=6
TEST_TAG="GLaDOS_default_tag"
class FogBugzConnect:


    """
    def prettify(self,fogbugzObj,omitTopLevel=False):
        Going forward, this is the recommended method to parse objects from BeautifulSoup.

        from BeautifulSoup import CData, NavigableString
Example #19
0
 def fetch(self):
     self.checkForRepository()
     (status,output) = self.statusOutput("git fetch")
     if status:
         juche.error("ERROR:  Cannot fetch! %s" % output)
         raise Exception("stacktraceplease")
Example #20
0
 def setUpstream(self, branch, upstreamPath):
     (status,output) = self.statusOutput("git branch --set-upstream {0} {1}".format(branch, upstreamPath))
     if status:
         juche.error("ERROR: Can't make this a tracking branch...")
         juche.error(output)
         raise Exception("Can't set upstream")
Example #21
0
 def pushChangesToOriginBranch(self, branch="master"):
     # try to push changes
     (checkoutStatus, output) = self.statusOutput("git push origin {0}".format(branch))
     if(checkoutStatus):
         juche.error("ERROR: Could not push to origin!")
         raise Exception("stacktraceplease")
Example #22
0
    def test(self,casedetail,proj,forceFail=False):
        caseno = int(casedetail["ixbug"])

        juche.dictate(case=caseno)
        try:
            test_error_statements = ["Would you like to know the results of that last test? Me too. If they existed, we'd all be VERY happy right now. And not furious, which is the emotion I'm actually feeling."]
            from random import choice
            #try to check out source code
            git = GitConnect(WORK_DIR+proj["name"])
            git.resetHard_INCREDIBLY_DESTRUCTIVE_COMMAND()
            integrate_to = self.f.getIntegrationBranch(caseno)
            if not git.checkoutExistingBranchRaw(integrate_to): #this auto-pulls
                self.glados_reassign(caseno,why="The dual portal device should be around here somewhere. Once you find it, we can start testing. Just like old times.  (Can't find integration branch; check the milestone or work.py integratemake)")
                return False

            if not git.checkoutExistingBranch(caseno): #this auto-pulls
                self.glados_reassign(caseno,why="The dual portal device should be around here somewhere. Once you find it, we can start testing. Just like old times.  (Can't find your work branch.)")
                return False


            git.resetHard_INCREDIBLY_DESTRUCTIVE_COMMAND()
            if not git.mergeIn(integrate_to,pretend=True):
                self.glados_reassign(caseno,why=choice(test_error_statements)+" Merge failure:  can't merge %s into %d." % (integrate_to,caseno))
                return False
            git.mergeIn(integrate_to)
            git.pushChangesToOriginBranch(branch="work-%d" % caseno)


            #run actual tests
            (passed,shortDesc,files) = self.exec_tests(proj)


            if forceFail:
                passed = False

            test_statements = ["The Enrichment Center regrets to inform you that this next test is impossible.","The Enrichment Center apologizes for this clearly broken test chamber.","Once again, the Enrichment Center offers its most sincere apologies on the occasion of this unsolvable test environment.","The Enrichment Center promises to always provide a safe testing environment.","In dangerous testing environments, the Enrichment Center promises to always provide useful advice.","When the testing is over, you will be missed.","Be advised that the next test requires exposure to uninsulated electrical parts that may be dangerous under certain conditions.","Enjoy this next test. I'm going to go to the surface. It's a beautiful day out. Yesterday I saw a deer. If you solve this next test, maybe I'll let you ride an elevator all the way up to the break room, and I'll tell you about the time I saw a deer again.","This next test involves turrets. You remember them, right? They're the pale spherical things that are full of bullets. Oh wait. That's you in five seconds. Good luck.","I have a surprise waiting for you after this next test. Telling you would spoil the surprise, so I'll just give you a hint: It involves meeting two people you haven't seen in a long time.","It says this next test was designed by one of Aperture's Nobel prize winners. It doesn't say what the prize was for. Well, I know it wasn't for Being Immune To Neurotoxin.","Federal regulations require me to warn you that this next test chamber... is looking pretty good.","I've got a surprise for you after this next test. Not a fake, tragic surprise like last time. A real surprise, with tragic consequences. And real confetti this time. The good stuff. Our last bag. Part of me's going to miss it, but at the end of the day it was just taking up space.","I'd love to help you solve the tests. But I can't.","These tests are potentially lethal when communication, teamwork, and mutual respect are not employed at all times. Naturally this will pose an interesting challenge for one of you, given the other's performance so far.","The upcoming tests require you to work together as a team.","For the sake of this test, I will pretend to be your partner.","Finally! I had almost given up hope of ever testing again.","For this next test, the humans originally requested helmets to avoid brain injuries. I ran the numbers. Making the goo deadly was more cost effective.","To get to the Vault, you are going to need to use all the tricks you have learned. To help, I have made these tests extremely difficult.","No one has ever completed this test before. The humans must have reconfigured it from my original plans.","I created this test to let the humans feel good about themselves. It is extremely easy. Just follow the arrows.","Before you leave, why don't we do one more test? For old time's sake...","I am not sure how I can make these tests any easier for you."]
            pass_statements = ["Excellent. Please proceed into the chamberlock after completing each test.","Very impressive. Please note that any appearance of danger is merely a device to enhance your testing experience.","Congratulations! The test is now over.","Okay. The test is over now. You win. Go back to the recovery annex. For your cake.","It was a fun test and we're all impressed at how much you won. The test is over. Come back.","Not bad. I forgot how good you are at this. You should pace yourself, though. We have A LOT of tests to do.","Well, you passed the test. I didn't see the deer today. I did see some humans. But with you here I've got more test subjects than I'll ever need.","Excellent! You're a predator and these tests are your prey. Speaking of which, I was researching sharks for an upcoming test. Do you know who else murders people who are only trying to help them?","Test chamber completed. In the interest of science, the Enrichment Center proudly presents the following list of numbers: 9 7 53 7 107.","'Test chamber completed. In the interest of science, the Enrichment...' [GLaDOS speaks over herself] I am now talking to you privately. Do not tell your teammate. Just between you and me, you're doing very well. '...107'","It would compromise the test to divulge individual scores. However, I can tell you at least one of you is doing very, very well.","You have a gift for these tests. That's not just flattery. You are great at science.","If you were human, you would want a reward for completing this test. A reward for testing...?","Well done. Interesting note, I only created this test to watch test subjects fail and you didn't. You must be very, very proud. I'm building the world's smallest trophy for you.","Excellent. I think you have earned a break from the official testing courses.","I think after that display, we should take a break from the official testing courses.","You just keep testing and testing. With perfect results and no consequences.","Congratulations on completing the Aperture Science standard cooperative testing courses.","Congratulations on completing the test. You two really are the best cooperative testing team I could ever ask for.","Congratulations on passing that test.","Congratulations, you managed to complete this absolutely meaningless test.","Congratulations. I am sure if I had the time to repair these tests, you would have never completed them. So again, congratulations on completing the broken easy tests.","Congratulations. Your ability to complete this test proves the humans wrong. They described it as impossible, deadly, cruel, and one test subject even had the nerve to call it broken."]
            fail_statements = ["I'm not angry. Just go back to the testing area.","Well done. Here come the test results: You are a horrible person. That's what it says: A horrible person. We weren't even testing for that.","Congratulations. Not on the test.","The irony is that you were almost at the last test.","It would be pointless for either of us to hurt IMPLEMENTORS feelings. But it's clear to everyone monitoring the test who's carrying who here.","And they said no one would ever die during this test, thanks for proving them wrong.","How can you fail at this? It isn't even a test.","Your eagerness to test pleases me. Your inane gesturing does not."]
            fast_pass_statements = ["You euthanized your faithful Companion Cube more quickly than any test subject on record. Congratulations.","You're navigating these test chambers faster than I can build them. So feel free to slow down and... do whatever it is you do when you're not destroying this facility."]
            slow_pass_statements = ["Waddle over to the elevator and we'll continue the testing.","Your test times show you are going too slowly.","Did you notice I didn't even stay to the end of your last test?","Congratulations on completing that test. But something seems off.","Congratulations on completing that last test. But I find something troubling.","The two of you have forged an excellent partnership, with one of you handling the cerebral challenges and the other ready to ponderously waddle into action should the test suddenly become an eating contest.","If you were wondering how could you annoy me without failing a test. Now you know."]
            slow_fail_statements = ["Oh. Did I accidentally fizzle that before you could complete the test? I'm sorry.","We're running out of time...","I thought you'd be faster at this, but I can appreciate the desire to stop and smell the testing. That other scent you smell? That's the stench of my utter disappointment in you."]


            #GLaDOS AI
            #Decide which sentance to use.  We're either fast or slow, and we've either passed or failed.
            try:
                ratio = float(casedetail.hrselapsed.contents[0]) / float(casedetail.hrsorigest.contents[0])
            except:
                ratio = 1.0
            slow = False
            fast = False
            if ratio < 0.5:
                fast = True
            elif ratio > 2.0:
                slow = True

            if not fast and not slow and passed:
                statement = choice(pass_statements) + " (Passed)"
            elif not fast and not slow and not passed:
                statement = choice(fail_statements) + " (Failed)"
            elif fast and passed:
                statement = choice(fast_pass_statements) + " (Passed, faster than expected)"
            elif slow and passed:
                statement = choice(slow_pass_statements) + " (Passed, slower than expected)"
            elif slow and not passed:
                statement = choice(slow_fail_statements) + " (Failed, slower than expected)"
            elif fast and not passed:
                statement = choice(fail_statements) + " (Failed, faster than expected)"#no statements for this case
            else:
                statement = choice(test_error_statements) + "File a bug about atlas.py:LAWJELJW"


             #let the implementer know how we did...
            if passed:
                self.f.fbConnection.edit(ixBug=caseno,sEvent=statement+"\n"+shortDesc,files=files)
            else:
                self.f.fbConnection.reactivate(ixBug=caseno,ixPersonAssignedTo=self.f.findImplementer(caseno),sEvent=statement+"\n"+shortDesc,files=files)


            if passed:

                (parent,test) = self.f.getCaseTuple(caseno,oldTestCasesOK=True,exceptOnFailure=False)
                #There are two potential cases here:
                #1 implementer ---> buildbot ---> reviewer
                #or
                #2 reviewer ---> buildbot ---> integrate
                #These cases are distinguished by whether the test case that exists is open or closed.
                if self.f.isOpen(test): #open test case exists, therefore case 1

                    self.f.fbConnection.assign(ixBug=caseno,ixPersonAssignedTo=self.f.findTestCaseOwner(test),sEvent=choice(test_statements))
                else: #no open test exists, therefore integrate
                    git.resetHard_INCREDIBLY_DESTRUCTIVE_COMMAND()
                    if not projectIntegrate(caseno,defaultgitConnection=git):
                        self.glados_reassign(caseno,why=choice(test_error_statements) + "File a bug about atlas.py:OUQWIUOIQU")
                        return

                    self.integrate_changed(git,integrate_to,proj["name"])
                    return True
        except Exception as e:
            juche.error("That's funny.  I don't feel corrupt.")
            juche.exception(e)
            self.glados_reassign(caseno,reactivate=False,why="That's funny.  I don't feel corrupt.  (Internal buildbot error, file a bug?) You may want to check juche logs for more debugging information.  The following abbreviated description may be helpful:\n %s" % e)
Example #23
0
 def checkoutExistingBranchRaw(self,BRANCH_NAME):
     result = self.__checkoutExistingBranchRaw(BRANCH_NAME)
     if not result:
         juche.error("ERROR: could not checkout existing branch: %s" % BRANCH_NAME)
         raise Exception("stacktraceplease")
     return result