pythontrac

How to use a script to generate a Trac Milestone complete with a description?


The description is the body of a milestone, and I'd like to generate milestones that include descriptions in an automated process.

Trac doesn't behave well if you directly update the tables in its database, so even though I can see the milestones there, I would avoid taking that approach.

Using the trac-admin command line utility documented at https://trac.edgewall.org/wiki/0.11/TracAdmin almost does the trick, as it allows milestones to be created, but it stops short of being able to specify a description for a milestone.

The MilestoneModule and RoadmapModule classes here: https://het.as.utexas.edu/HET/Software/trac/api/trac_ticket_roadmap.html look promising but MilestoneModule and RoadmapModule don't seem to offer the ability to create and list milestones.

So there must be some mostly undocumented class or method for doing this. What is it?


Solution

  • Add milestones using the MilestoneCache object, like this script does (or just use the script, which is what I do either from the command line or from Python3 via subprocess.run, since Trac currently runs on Python2 and not 3)

    #!/usr/bin/python2
    
    from trac.env import open_environment
    from trac.ticket import Milestone
    from trac.ticket.model import MilestoneCache
    from trac.core import TracError
    import sys, json;
    
    if len(sys.argv)!=2:
      print '''
      Usage: python2 createMilestone.py2 dir
    
      e.g.   python2 createMilestone.py2 ~/trac M3 <<END
             { "name": "M3",
               "due": "2021-01-01 04:00:00+00:00",
               "completed": "2021-12-31 23:59:59+00:00",
               "description": "" }
             END
      '''
      exit(3)
    
    try:
      data = json.load(sys.stdin)
    except:
      sys.stderr.write("Bad input data")
      exit(2)
    
    try:
      mc=MilestoneCache(open_environment(sys.argv[1]))
      mc.factory((data['name'],data['due'],data['completed'],data['description'])).insert()  
    except:
      sys.stderr.write("Can't update "+sys.argv[1]+"\n")
      exit(1)
    

    The script takes JSON with all the fields of the milestone as input. It's the same technique I use for creating tickets when writing Python3, since Trac is a Python2 program.

    Conversely, if you want to list milestones, you can use this similar script, and you can pipe a milestone listed as jSON from one Trac site to another.

    Sometimes I teach courses where I prepare a Trac site for each student, and I dump milestones through this script below and pipe it through the script above to propagate it into student Trac sites.

    #!/usr/bin/python2
    
    from trac.env import open_environment
    from trac.ticket import Milestone
    from trac.ticket.model import MilestoneCache
    from trac.core import TracError
    import sys, json;
    
    if len(sys.argv)!=3:
      print '''
      Usage: python2 getMilestone dir milestone
    
      e.g.   python2 getMilestone ~/trac M3
      '''
      exit(3)
    
    try:
      name,due,completed,description = MilestoneCache(open_environment(sys.argv[1])).milestones[sys.argv[2]]
      print json.dumps({
        "name":name,
        "due":str(due) if due else None,
        "completed":str(completed) if completed else None,
        "description":description
      },indent=2)
    except KeyError:
      pass
    except TracError:
      sys.stderr.write("Can't open "+sys.argv[1]+"\n")
      exit(1)