1How Tos 2======= 3 4All of this equipment is here to help you get your work done more efficiently. 5However, learning how task-graphs are generated is probably not the work you 6are interested in doing. This section should help you accomplish some of the 7more common changes to the task graph with minimal fuss. 8 9.. important:: 10 11 If you cannot accomplish what you need with the information provided here, 12 please consider whether you can achieve your goal in a different way. 13 Perhaps something simpler would cost a bit more in compute time, but save 14 the much more expensive resource of developers' mental bandwidth. 15 Task-graph generation is already complex enough! 16 17 If you want to proceed, you may need to delve into the implementation of 18 task-graph generation. The documentation and code are designed to help, as 19 are the authors - ``hg blame`` may help track down helpful people. 20 21 As you write your new transform or add a new kind, please consider the next 22 developer. Where possible, make your change data-driven and general, so 23 that others can make a much smaller change. Document the semantics of what 24 you are changing clearly, especially if it involves modifying a transform 25 schema. And if you are adding complexity temporarily while making a 26 gradual transition, please open a new bug to remind yourself to remove the 27 complexity when the transition is complete. 28 29Hacking Task Graphs 30------------------- 31 32The recommended process for changing task graphs is this: 33 341. Run one of the ``mach taskgraph`` subcommands (see :doc:`mach`) to 35 generate a baseline against which to measure your changes. 36 37 .. code-block:: none 38 39 ./mach taskgraph tasks --json > old-tasks.json 40 412. Make your modifications under ``taskcluster/``. 42 433. Run the same ``mach taskgraph`` command, sending the output to a new file, 44 and use ``diff`` to compare the old and new files. Make sure your changes 45 have the desired effect and no undesirable side-effects. A plain unified 46 diff should be useful for most changes, but in some cases it may be helpful 47 to post-process the JSON to strip distracting changes. 48 494. When you are satisfied with the changes, push them to try to ensure that the 50 modified tasks work as expected. 51 52Hacking Actions 53............... 54 55If you are working on an action task and wish to test it out locally, use the 56``./mach taskgraph test-action-callback`` command: 57 58 .. code-block:: none 59 60 ./mach taskgraph test-action-callback \ 61 --task-id I4gu9KDmSZWu3KHx6ba6tw --task-group-id sMO4ybV9Qb2tmcI1sDHClQ \ 62 --input input.yml hello_world_action 63 64This invocation will run the hello world callback with the given inputs and 65print any created tasks to stdout, rather than actually creating them. 66 67Common Changes 68-------------- 69 70Changing Test Characteristics 71............................. 72 73First, find the test description. This will be in 74``taskcluster/ci/*/tests.yml``, for the appropriate kind (consult 75:doc:`kinds`). You will find a YAML stanza for each test suite, and each 76stanza defines the test's characteristics. For example, the ``chunks`` 77property gives the number of chunks to run. This can be specified as a simple 78integer if all platforms have the same chunk count, or it can be keyed by test 79platform. For example: 80 81.. code-block:: yaml 82 83 chunks: 84 by-test-platform: 85 linux64/debug: 10 86 default: 8 87 88The full set of available properties is in 89``taskcluster/taskgraph/transforms/tests.py``. Some other 90commonly-modified properties are ``max-run-time`` (useful if tests are being 91killed for exceeding maxRunTime) and ``treeherder-symbol``. 92 93.. note:: 94 95 Android tests are also chunked at the mozharness level, so you will need to 96 modify the relevant mozharness config, as well. 97 98Adding a Test Suite 99................... 100 101To add a new test suite, you will need to know the proper mozharness invocation 102for that suite, and which kind it fits into (consult :doc:`kinds`). 103 104Add a new stanza to ``taskcluster/ci/<kind>/tests.yml``, copying from the other 105stanzas in that file. The meanings should be clear, but authoritative 106documentation is in 107``taskcluster/taskgraph/transforms/tests.py`` should you need 108it. The stanza name is the name by which the test will be referenced in try 109syntax. 110 111Add your new test to a test set in ``test-sets.yml`` in the same directory. If 112the test should only run on a limited set of platforms, you may need to define 113a new test set and reference that from the appropriate platforms in 114``test-platforms.yml``. If you do so, include some helpful comments in 115``test-sets.yml`` for the next person. 116 117Greening Up a New Test 118...................... 119 120When a test is not yet reliably green, configuration for that test should not 121be landed on integration branches. Of course, you can control where the 122configuration is landed! For many cases, it is easiest to green up a test in 123try: push the configuration to run the test to try along with your work to fix 124the remaining test failures. 125 126When working with a group, check out a "twig" repository to share among your 127group, and land the test configuration in that repository. Once the test is 128green, merge to an integration branch and the test will begin running there as 129well. 130 131Adding a New Task 132................. 133 134If you are adding a new task that is not a test suite, there are a number of 135options. A few questions to consider: 136 137 * Is this a new build platform or variant that will produce an artifact to 138 be run through the usual test suites? 139 140 * Does this task depend on other tasks? Do other tasks depend on it? 141 142 * Is this one of a few related tasks, or will you need to generate a large 143 set of tasks using some programmatic means (for example, chunking)? 144 145 * How is the task actually executed? Mozharness? Mach? 146 147 * What kind of environment does the task require? 148 149Armed with that information, you can choose among a few options for 150implementing this new task. Try to choose the simplest solution that will 151satisfy your near-term needs. Since this is all implemented in-tree, it 152is not difficult to refactor later when you need more generality. 153 154Existing Kind 155````````````` 156 157The simplest option is to add your task to an existing kind. This is most 158practical when the task "makes sense" as part of that kind -- for example, if 159your task is building an installer for a new platform using mozharness scripts 160similar to the existing build tasks, it makes most sense to add your task to 161the ``build`` kind. If you need some additional functionality in the kind, 162it's OK to modify the implementation as necessary, as long as the modification 163is complete and useful to the next developer to come along. 164 165Tasks in the ``build`` kind generate Firefox installers, and the ``test`` kind 166will add a full set of Firefox tests for each ``build`` task. 167 168New Kind 169```````` 170 171The next option to consider is adding a new kind. A distinct kind gives you 172some isolation from other task types, which can be nice if you are adding an 173experimental kind of task. 174 175Kinds can range in complexity. The simplest sort of kind uses the transform 176loader to read a list of jobs from the ``jobs`` key, and applies the standard 177``job`` and ``task`` transforms: 178 179.. code-block:: yaml 180 181 implementation: taskgraph.task.transform:TransformTask 182 transforms: 183 - taskgraph.transforms.job:transforms 184 - taskgraph.transforms.task:transforms 185 jobs: 186 - ..your job description here.. 187 188Job descriptions are defined and documented in 189``taskcluster/taskgraph/transforms/job/__init__.py``. 190 191Custom Kind Loader 192`````````````````` 193 194If your task depends on other tasks, then the decision of which tasks to create 195may require some code. For example, the ``test`` kind iterates over 196the builds in the graph, generating a full set of test tasks for each one. This specific 197post-build behavior is implemented as a loader defined in ``taskcluster/taskgraph/loader/test.py``. 198 199A custom loader is useful when the set of tasks you want to create is not 200static but based on something else (such as the available builds) or when the 201dependency relationships for your tasks are complex. 202 203Custom Transforms 204````````````````` 205 206Most loaders apply a series of ":doc:`transforms <transforms>`" that start with 207an initial human-friendly description of a task and end with a task definition 208suitable for insertion into a Taskcluster queue. 209 210Custom transforms can be useful to apply defaults, simplifying the YAML files 211in your kind. They can also apply business logic that is more easily expressed 212in code than in YAML. 213 214Transforms need not be one-to-one: a transform can produce zero or more outputs 215for each input. For example, the test transforms perform chunking by producing 216an output for each chunk of a given input. 217 218Ideally those transforms will produce job descriptions, so you can use the 219existing ``job`` and ``task`` transforms: 220 221.. code-block:: yaml 222 223 transforms: 224 - taskgraph.transforms.my_stuff:transforms 225 - taskgraph.transforms.job:transforms 226 - taskgraph.transforms.task:transforms 227 228Try to keep transforms simple, single-purpose and well-documented! 229 230Custom Run-Using 231```````````````` 232 233If the way your task is executed is unique (so, not a mach command or 234mozharness invocation), you can add a new implementation of the job 235description's "run" section. Before you do this, consider that it might be a 236better investment to modify your task to support invocation via mozharness or 237mach, instead. If this is not possible, then adding a new file in 238``taskcluster/taskgraph/transforms/jobs`` with a structure similar to its peers 239will make the new run-using option available for job descriptions. 240 241Something Else? 242............... 243 244If you make another change not described here that turns out to be simple or 245common, please include an update to this file in your patch. 246 247 248