Perforce Triggers in Python (Pt 1)
Perforce is a wily beast. A lot of companies use it, but I feel few outside of the IT department really have to deal with it much. As I work myself deeper and deeper into the damp hole that is asset validation, I have really been writing a lot of python to deal with certain issues; but always scripts that work from the outside.
Perforce has a system that allows you to write scripts that are run, server side, when any number of events are triggered. You can use many scripting languages, but I will only touch on Python.
Test Environment
To follow along here, you should set up a test environment. Perforce is freely downloadable, and free to use with 2 users. Of course you are going to need python, and p4python. So get your server running and add two users, a user and an administrator.
Your First Trigger
Let’s create the simplest python script. It will be a submit trigger that says ‘Hello World’ then passes or fails. If it passes, the item will be checked in to perforce, if it fails, it will not. exiting while returning a ‘1’ is considered a fail, ‘0’ a pass.
print 'Hello World!' print 'No checkin for you!' sys.exit(1) |
Ok, so save this file as hello_trigger.py. Now go to a command line and enter ‘p4 triggers’ this will open a text document, edit that document to point to your trigger, like so (but point to the location of your script on disk):
Triggers: hello_trigger change-submit //depot/... "python X:/projects/2010/p4/hello_trigger.py" |
Close/save the trigger TMP file, you should see ‘Triggers saved.’ echo’d at the prompt. Now, when we try to submit a file to the depot, we will get this:
So: awesome, you just DENIED your first check-in!
Connecting to Perforce from Inside a Trigger
So we are now denying check-ins, but let’s try to do some other things, let’s connect to perforce from inside a trigger.
from P4 import P4, P4Exception p4 = P4() try: #use whatever your admin l/p was #this isn't the safest, but it works at this beginner level p4.user = "admin" p4.password = "admin" p4.port = "1666" p4.connect() info = p4.run("info") print info sys.exit(1) #this will return any errors except P4Exception: for e in p4.errors: print e sys.exit(1) |
So now when you try to submit a file to depot you will get this:
Passing Info to the Trigger
Now we are running triggers, accepting or denying checkins, but we really don’t know much about them. Let’s try to get enough info to where we could make a decision about whether or not we want the file to pass validation. Let’s make another python trigger, trigger_test.py, and let’s query something from the perforce server in the submit trigger. To do this we need to edit our trigger file like so:
Triggers: test change-submit //depot/... "python X:/projects/2010/p4/test_trigger.py %user% %changelist%" |
This will pass the user and changelist number into the python script as an arg, the same way dragging/dropping passed args to python in my previous example. So let’s set that up, save the script from before as ‘test_trigger.py’ as shown above, and add the following:
import sys from P4 import P4, P4Exception p4 = P4() describe = [] try: p4.user = "admin" p4.password = "admin" p4.port = "1666" p4.connect() except P4Exception: for e in p4.errors: print e sys.exit(1) print str(sys.argv) describe = p4.run('describe',sys.argv[2]) print str(describe) p4.disconnect() sys.exit(1) |
So, as you can see, it has returned the user and changelist number:
However, for this changelist to be useful, we query p4, asking the server to describe the changelist. This returns a lot of information about the changelist.
Where to Go From here
The few simple things shown here really give you the tools to do many more things. Here are some examples of triggers that can be created with the know-how above:
- Deny check-ins of a certain filetype (like deny compiled source files/assets)
- Deny check-ins whose hash digest matches an existing file on the server
- Deny/allow a certain type of file check-in from a user in a certain group
- Email a lead any time a file in a certain folder is updated
Did you find this helpful? What creative triggers have you written?
Thanks for this post.
I been thinking of doing a trigger that would deny submit of say an “exported” file type, without the presence of a matching “source” file.
Missing source files seem to be somewhat of an issue for us (especially with outsourcers in some departments) and this is currently batteled with a number of very persistent prompts to add/edit/check into perforce littered throughout our “source” applications.
Comment by Sune — 2012/06/15 @ 10:00 PM
Thanks for your post. It’s very useful for me especially the key point -> “p4 triggers” command. I cannot find it on p4 manual. Thank you. ^^”
Comment by Pajace — 2013/04/02 @ 8:44 AM
This was super helpful. Thanks for Posting!
I was unable to get perforce to recognize a local path for my script however, i was forced to put a depot relative path.
Also took me some digging to realize I needed to grab the p4python executable to get this to fully work properly. Here is the link for anyone else that ran across the same thing:
http://www.perforce.com/perforce/doc.current/manuals/p4script/03_python.html
Comment by Adam — 2015/03/23 @ 11:31 PM