3 Trigger Purposes
This section presents several representative purposes for writing triggers. Providing a complete survey of trigger purposes would be impossible. This paper attempts to
stimulate thought on the range of possibilities by showing canonical or interesting applications of each trigger type. Code for several of the examples will be presented at
the conference, but are not included in the paper for brevity.
3.1 Ensure related files are submitted together
Since submit triggers have been available longer than the other trigger types, their use has been explored more fully. One of the canonical uses is to ensure that related files are submitted together rather than being allowed to track at different rates. The key enabler is that the relationship between the files predictably or observably exists
and that it can be easily discerned by patterns in the file naming or location. The naming requirement stems from the submit trigger’s inability to examine the content of files. Two common uses for this are
• To ensure that the implementation file is updated whenever the header file is modified in a language like C++. Every time a .h, .hxx or .hpp file is modified, its
corresponding .c, .cpp, .cxx, .CC, .c++ file is also in the changelist.
• To ensure that test harnesses are updated whenever their corresponding source code is modified. In Java with JUnit, a class named MyClass.java should have a
test case named MyClassTestCase.java. The test case class will generally be in a different directory tree to keep it separate from the production code, but the
location and naming should be predictable, and the presence of the file is most likely required.
3.2 Verify all header files have company copyright banner
Some purposes require inspection of the files being submitted, which is accomplished with a content trigger. A common use for content triggers checks header files to ensure that company copyright information has been included and preserved in the file. This is particularly important when the headers are being distributed as part of an API for a product. In a language like Java, headers usually take the form of interface classes, leading to a file pattern for the trigger of “//…/I*.java”. This may catch more than just interface classes, leading to an additional use for the content inspection to check whether the class is truly an interface or just a class whose name starts with “I.” In a language like C/C++, headers may have multiple extensions. This may be to distinguish between C and C++ files or to distinguish between header files for different platform compiler conventions. Directory locations may also be used to identify the relevant files. In any case, application of the technique from section 2.4 applies the same action to each of the different file patterns.
3.3 Reject submissions with zero-content deltas
Another application of content triggers would be to reject changelists with empty deltas. This functionality was requested on the perforce-user mailing list in February 20052. The ability of a content trigger to inspect the contents and reject the submission is ideal for this situation.
3.4 Run continuous integration build after each Submission
A canonical example of a commit trigger initiates a build based on a submission. Since the build would be too time-consuming to complete during trigger execution, the techniques from section 2.7 would be used to initiate the build. Starting the processing immediately could easily run into race conditions, so signaling the
processing would be a better option. A review daemon implementation should be considered at that point, since it provides the signaling mechanism and the
implementation will also use scheduled polling.
3.5 Integrate changes on a branch forward
A common need in a shrink-wrap style release scheme is to propagate fixes to a release codeline forward to later releases or back to main. Ignoring issues of process approval, this kind of integration is generally highly automatable. Conflicts generally only occur when there have been significant overhauls to the affected section of code. Since integration is also typically a very fast operation, this purpose can be fulfilled during the submission. The brevity of the operation, along with the sanctity of release branches and the locality of the change, minimizes the possibility of a race condition. Failures due to conflicts would provide notification to a branch owner for manual resolution. Safer automatic resolve options could be used for greater confidence in the result. Naturally, a follow-on build and test cycle should be signaled, suggesting that this trigger should be declared prior to the build trigger.
3.6 Configurable number of binary revisions
This novel and daring example of a commit trigger helps to maintain disk space by extending the concept behind the +S type modifier to an arbitrary number of revisions. The details of this example are discussed extensively in [Baum2005].
3.7 Add company-specific content to change form
In the absence of the hopefully upcoming fully customizable forms3 many installations have adopted the convention of putting well-known tags in the changelist Description field. Until out triggers became available in 2004.2, this had to be done manually when filling in the form, leaving it up to the attention to detail of the submittor. Out form triggers allow this policy to be proactively implemented by inserting the required information when the form is initially created. A typical example of this usage puts a ReviewedBy field in the description to be filled in by the developer to indicate who reviewed the code being submitted.
3.8 Enforce jobs status life cycle
An example of an “in” form trigger presented in [Bowles2005] enforces defect tracking state transition in jobs fixed by a changelist.
3.9 Enforce finer grained authorization
The prime example of a “save” form trigger is shown in [Perforce2004.2] on page 98. This trigger provides or denies authorization to modify client forms to particular groups. It compares the group of the person submitting the form to a list of groups authorized to modify client specs and rejects the modification when not allowed. This type of finer grained authorization can operate on any type of form and could also take into account
• User name: similar to group
• View contents: Disallow modification if views contain particular paths• Form name: Disallow modifications to branches or labels that contain certain
naming components, such as “rel”• Option changes: Disallow use of particular options, such as “compress” or“normdir”
• Combinations: For example, only administrators are allowed to turn on compression on clients that do not involve already compressed binary content.
3.10 Protect template specs from deletion
The new “delete” form trigger added in 2005.1 also allows finer grained access control. An immediately apparent use is to protect crucial specs from deletion, just as you would protect them from modification in section 3.9. Prime examples of the types of forms you would want to protect are
• Release or test marker labels
• Release branch specs
• Special build client specs