#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ==============================================================================
# Copyright and license info is available in the LICENSE file included with
# the Server Deployment Package (SDP), and also available online:
# https://swarm.workshop.perforce.com/projects/perforce-software-sdp/view/main/LICENSE
# ------------------------------------------------------------------------------
"""
NAME:
RequireJob.py
DESCRIPTION:
This is a trigger which allows admins to require a job to be linked with any submits.
It takes a config file of the format for CreateSwarmReview.yaml which controls
whether this trigger fires or not (in addition to trigger table entries).
It refers to field 'swarm_user' and allows that user, if specified, to bypass this trigger.
To install, add a line to your Perforce triggers table like the following:
require-job change-submit //... "python /p4/common/bin/triggers/RequireJob.py -c /p4/common/config/Workflow.yaml -p %serverport% -u perforce %change% "
or (if server is standard SDP and has appropriate environment defaults for P4PORT and P4USER):
require-job change-submit //... "python /p4/common/bin/triggers/RequireJob.py -c /p4/common/config/Workflow.yaml %change% "
You may need to provide the full path to python executable, or edit the path to the trigger.
Also, don't forget to make the file executable.
"""
# Python 2.7/3.3 compatibility.
from __future__ import print_function
import sys
import P4Triggers
import P4
import yaml
ERROR_MSG = """
Submit failed because this codeline requires a job to be linked to every changelist!
Please retry your submit/shelve after linking a job to it.
You may need to create a P4 job from the related Jira issue.
"""
class RequireJob(P4Triggers.P4Trigger):
"""See module doc string for details"""
def __init__(self, *args, **kwargs):
P4Triggers.P4Trigger.__init__(self, **kwargs)
self.parse_args(__doc__, args)
def add_parse_args(self, parser):
"""Specific args for this trigger - also calls super class to add common trigger args"""
parser.add_argument('-c', '--config-file', default=None,
help="Configuration file for trigger. Default: RequireJob.yaml")
parser.add_argument('change', help="Change to process - %%change%% argument from triggers entry.")
super(RequireJob, self).add_parse_args(parser)
def load_config(self, config_file=None):
if not config_file:
config_file = "/p4/common/config/CreateSwarmReview.yaml"
try:
with open(config_file, 'r') as f:
config = yaml.load(f)
return config
except:
return {}
def job_required(self, config, change):
"""Returns true if changelist needs a job according to config"""
if not 'projects' in config:
return False
map = P4.Map()
# Search all config projects and return as soon as we find one that we are in which
# has 'require_job' set to 'y'
for prj in config['projects']:
if not 'name' in prj or not 'depot_paths' in prj:
continue
if not 'require_job' in prj or not prj['require_job'] == 'y':
continue
for p in prj['depot_paths']:
map.insert(p)
for df in change.files:
if map.includes(df.depotFile):
return True
self.logger.debug("Ignoring change as no files in project paths")
return False
def run(self):
"""Runs trigger"""
try:
self.logger.debug("RequireJob trigger firing")
self.setupP4()
self.p4.connect()
change = self.getChange(self.options.change)
config = self.load_config(self.options.config_file)
if not self.job_required(config, change):
self.logger.debug("RequireJob: no job needed")
return 0
if 'swarm_user' in config and config['swarm_user'] == change.user:
self.logger.debug("RequireJob: swarm user - no job needed")
return 0
# Look for jobs attached to this changelist
fixes = self.p4.run_fixes("-c", self.options.change)
if not fixes or len(fixes) == 0:
self.logger.debug("RequireJob: no job found")
print(ERROR_MSG)
return 1
self.logger.debug("RequireJob: job found")
return 0
except Exception:
return self.reportException()
if __name__ == '__main__':
""" Main Program"""
trigger = RequireJob(*sys.argv[1:])
sys.exit(trigger.run())