<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>err &amp;err - taskcluster</title><link href="https://www.erranderr.com/blog/" rel="alternate"></link><link href="https://www.erranderr.com/blog/feeds/taskcluster.atom.xml" rel="self"></link><id>https://www.erranderr.com/blog/</id><updated>2016-05-02T00:00:00-04:00</updated><entry><title>Not Testing a Firefox Build (Generic Tasks in TaskCluster)</title><link href="https://www.erranderr.com/blog/taskcluster-generic-tasks.html" rel="alternate"></link><published>2016-05-02T00:00:00-04:00</published><updated>2016-05-02T00:00:00-04:00</updated><author><name>Maja Frydrychowicz</name></author><id>tag:www.erranderr.com,2016-05-02:/blog/taskcluster-generic-tasks.html</id><summary type="html">&lt;p&gt;I take advantage of generic tasks to run a mozharness script in a gecko source&amp;nbsp;checkout.&lt;/p&gt;</summary><content type="html">&lt;p&gt;A few months ago I wrote about my &lt;a href="https://www.erranderr.com/blog/taskcluster-learning.html"&gt;tentative setup&lt;/a&gt; of a TaskCluster task that was neither a build nor a test. Since then, gps has implemented &lt;a href="https://groups.google.com/forum/#!searchin/mozilla.dev.platform/generic$20task/mozilla.dev.platform/bNYp2HDyeqU/tg4mnGHEAwAJ"&gt;&amp;#8220;generic&amp;#8221; in-tree tasks&lt;/a&gt; so I &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1227367#c116"&gt;adapted my initial work&lt;/a&gt; to take advantage of&amp;nbsp;that.&lt;/p&gt;
&lt;h1&gt;Triggered by file&amp;nbsp;changes&lt;/h1&gt;
&lt;p&gt;All along I wanted to run some in-tree tests without having them wait around for a Firefox build or any other dependencies they don&amp;#8217;t need. So I originally implemented this task as a &lt;a href="https://www.erranderr.com/blog/taskcluster-learning.html#scheduling_summary"&gt;&amp;#8220;build&amp;#8221;&lt;/a&gt; so that it would get scheduled for every incoming changeset in Mozilla&amp;#8217;s&amp;nbsp;repositories. &lt;/p&gt;
&lt;p&gt;But forget &amp;#8220;builds&amp;#8221;, forget &amp;#8220;tests&amp;#8221; &amp;#8212; now there&amp;#8217;s a third category of tasks that we&amp;#8217;ll call &amp;#8220;generic&amp;#8221; and it&amp;#8217;s exactly what I&amp;nbsp;need. &lt;/p&gt;
&lt;p&gt;In &lt;a href="https://hg.mozilla.org/mozilla-central/diff/e4ea9261d5bb/testing/taskcluster/tasks/branches/base_jobs.yml"&gt;base_jobs.yml&lt;/a&gt; I say, &amp;#8220;hey, here&amp;#8217;s a new task called &lt;code&gt;marionette-harness&lt;/code&gt; &amp;#8212; run it whenever there&amp;#8217;s a change under (branch)/testing/marionette/harness&amp;#8221;. Of course, I can also just trigger the task with try syntax like &lt;code&gt;try: -p linux64_tc -j marionette-harness -u none -t none&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When the task is triggered, a chain of events&amp;nbsp;follows: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;marionette-harness&lt;/code&gt; is defined by &lt;a href="https://hg.mozilla.org/mozilla-central/file/e4ea9261d5bb/testing/taskcluster/tasks/tests/harness_marionette.yml"&gt;harness_marionette.yml&lt;/a&gt;, which depends on &lt;a href="https://hg.mozilla.org/mozilla-central/file/e4ea9261d5bb/testing/taskcluster/tasks/harness_test.yml"&gt;harness_test.yml&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hg.mozilla.org/mozilla-central/file/e4ea9261d5bb/testing/taskcluster/tasks/harness_test.yml"&gt;harness_test.yml&lt;/a&gt; says to run &lt;a href="https://hg.mozilla.org/mozilla-central/diff/e4ea9261d5bb/testing/docker/desktop-build/bin/build.sh"&gt;build.sh&lt;/a&gt; with the appropriate mozilla branch and&amp;nbsp;revision.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hg.mozilla.org/mozilla-central/file/e4ea9261d5bb/testing/taskcluster/tasks/tests/harness_marionette.yml"&gt;harness_marionette.yml&lt;/a&gt; sets more environment variables and parameters for build.sh to use (&lt;code&gt;JOB_SCRIPT&lt;/code&gt;, &lt;code&gt;MOZHARNESS_SCRIPT&lt;/code&gt;,&amp;nbsp;etc.)&lt;/li&gt;
&lt;li&gt;So build.sh checks out the source tree and executes &lt;a href="https://hg.mozilla.org/mozilla-central/diff/e4ea9261d5bb/testing/taskcluster/scripts/tester/harness-test-linux.sh"&gt;harness-test-linux.sh&lt;/a&gt; (&lt;code&gt;JOB_SCRIPT&lt;/code&gt;)&amp;#8230;&lt;/li&gt;
&lt;li&gt;&amp;#8230;which in turn executes &lt;a href="https://hg.mozilla.org/mozilla-central/file/1e0b4e27bd51/testing/mozharness/scripts/marionette_harness_tests.py"&gt;marionette_harness_tests.py&lt;/a&gt; (&lt;code&gt;MOZHARNESS_SCRIPT&lt;/code&gt;) with the parameters passed on by&amp;nbsp;build.sh&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;For Tasks that Make Sense in a gecko Source&amp;nbsp;Checkout&lt;/h1&gt;
&lt;p&gt;As you can see, I made the &lt;code&gt;build.sh&lt;/code&gt; script in the &lt;code&gt;desktop-build&lt;/code&gt; docker image execute an arbitrary in-tree &lt;code&gt;JOB_SCRIPT&lt;/code&gt;, and I created &lt;code&gt;harness-test-linux.sh&lt;/code&gt; to run mozharness within a gecko source&amp;nbsp;checkout. &lt;/p&gt;
&lt;h2&gt;Why not the desktop-test&amp;nbsp;image?&lt;/h2&gt;
&lt;p&gt;But we can also run arbitrary mozharness scripts thanks to the configuration in the desktop-test docker image! Yes, and all of that configuration is geared toward testing a Firefox binary, which implies downloading tools that my task either doesn&amp;#8217;t need or already has access to in the source tree. Now we have a lighter-weight option for executing tests that don&amp;#8217;t exercise&amp;nbsp;Firefox.&lt;/p&gt;
&lt;h2&gt;Why not&amp;nbsp;mach?&lt;/h2&gt;
&lt;p&gt;In my lazy work-in-progress, I had originally executed the Marionette harness tests via a simple call to mach, yet now I have this crazy chain of shell scripts that leads all the way mozharness. The mach command didn&amp;#8217;t disappear &amp;#8212; you can run Marionette harness tests with &lt;code&gt;./mach python-test ...&lt;/code&gt;. However, mozharness provides clearer control of Python dependencies, appropriate handling of return codes to report test results to Treeherder, and I can write a job-specific script and&amp;nbsp;configuration.&lt;/p&gt;</content><category term="mozilla"></category><category term="foss"></category><category term="ci"></category><category term="automation"></category><category term="taskcluster"></category></entry><entry><title>First Experiment with TaskCluster</title><link href="https://www.erranderr.com/blog/taskcluster-learning.html" rel="alternate"></link><published>2016-02-09T00:00:00-05:00</published><updated>2016-02-16T00:00:00-05:00</updated><author><name>Maja Frydrychowicz</name></author><id>tag:www.erranderr.com,2016-02-09:/blog/taskcluster-learning.html</id><summary type="html">&lt;p&gt;Adding a new task to TaskCluster continuous integration&amp;nbsp;system.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://docs.taskcluster.net/"&gt;TaskCluster&lt;/a&gt; is a new-ish continuous integration system made at Mozilla. It manages the scheduling and execution of tasks based on a graph of their dependencies. It&amp;#8217;s a general &lt;span class="caps"&gt;CI&lt;/span&gt; tool, and could be used for any kind of job, not just Mozilla&amp;nbsp;things. &lt;/p&gt;
&lt;p&gt;However, the example I describe here refers to a Mozilla-centric use case of TaskCluster&lt;sup id="fnref-1"&gt;&lt;a class="footnote-ref" href="#fn-1"&gt;1&lt;/a&gt;&lt;/sup&gt;: tasks are run per check-in on the branches of Mozilla&amp;#8217;s Mercurial repository and then results are posted to &lt;a href="https://github.com/mozilla/treeherder"&gt;Treeherder&lt;/a&gt;. For now, the tasks can be configured to run in Docker images (Linux), but other platforms are in the works&lt;sup id="fnref-2"&gt;&lt;a class="footnote-ref" href="#fn-2"&gt;2&lt;/a&gt;&lt;/sup&gt;. &lt;/p&gt;
&lt;p&gt;So, I want to schedule a task! I need to add a new task to the task graph that&amp;#8217;s created for each revision submitted to hg.mozilla.org. (This is part of my work on deploying a suite of &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1227367"&gt;tests for the Marionette Python test runner&lt;/a&gt;, i.e. testing the test harness&amp;nbsp;itself.) &lt;/p&gt;
&lt;p&gt;The rest of this post describes what I learned while making &lt;a href="https://hg.mozilla.org/try/rev/6b7479c4aa30"&gt;this work-in-progress&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;There are builds and there are&amp;nbsp;tests&lt;/h1&gt;
&lt;p&gt;mozilla-taskcluster operates based on the info under &lt;a href="https://dxr.mozilla.org/mozilla-central/source/testing/taskcluster/tasks"&gt;&lt;code&gt;testing/taskcluster/tasks&lt;/code&gt;&lt;/a&gt; in Mozilla&amp;#8217;s source tree, where there are yaml files that describe tasks. Specific tasks can inherit common configuration options from base yaml&amp;nbsp;files. &lt;/p&gt;
&lt;p&gt;The yaml files are organized into two main categories of tasks: builds and tests. This is just a convention in mozilla-taskcluster about how to group task configurations; &lt;span class="caps"&gt;TC&lt;/span&gt; itself doesn&amp;#8217;t actually know or care whether a task is a build or a&amp;nbsp;test.&lt;/p&gt;
&lt;p&gt;The task I&amp;#8217;m creating doesn&amp;#8217;t quite fit into either category: it runs harness tests that just exercise the Python runner code in &lt;a href="https://marionette-client.readthedocs.org"&gt;marionette_client&lt;/a&gt;, so I only need a source checkout, not a Firefox build. I&amp;#8217;d like these tests to run quickly without having to wait around for a build. Another example of such a task is the recently-created &lt;a href="https://hg.mozilla.org/mozilla-central/rev/4b34c9d1a31a"&gt;ESLint task&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Scheduling a&amp;nbsp;task&lt;/h1&gt;
&lt;p&gt;Just adding a yaml file that describes your new task under &lt;code&gt;testing/taskcluster/tasks&lt;/code&gt; isn&amp;#8217;t enough to get it scheduled: you must also add it to the list of tasks in &lt;a href="https://dxr.mozilla.org/mozilla-central/source/testing/taskcluster/tasks/branches/base_jobs.yml"&gt;&lt;code&gt;base_jobs.yml&lt;/code&gt;&lt;/a&gt;, and define an identifier for your task in &lt;a href="https://dxr.mozilla.org/mozilla-central/source/testing/taskcluster/tasks/branches/base_job_flags.yml"&gt;&lt;code&gt;base_job_flags.yml&lt;/code&gt;&lt;/a&gt;. This identifier is used in &lt;code&gt;base_jobs.yml&lt;/code&gt;, and also by people who want to run your task when pushing to &lt;a href="https://wiki.mozilla.org/ReleaseEngineering/TryServer"&gt;try&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;How does scheduling work? First a &lt;a href="https://docs.taskcluster.net/introduction/getting-started/#decision-tasks-and-task-graphs"&gt;decision task&lt;/a&gt; generates a &lt;em&gt;task graph&lt;/em&gt;, which describes all the tasks and their relationships. More precisely, it looks at &lt;code&gt;base_jobs.yml&lt;/code&gt; and other yaml files in &lt;code&gt;testing/taskcluster/tasks&lt;/code&gt; and spits out a json artifact, &lt;code&gt;graph.json&lt;/code&gt;&lt;sup id="fnref-3"&gt;&lt;a class="footnote-ref" href="#fn-3"&gt;3&lt;/a&gt;&lt;/sup&gt;. Then, &lt;code&gt;graph.json&lt;/code&gt; gets sent to &lt;span class="caps"&gt;TC&lt;/span&gt;&amp;#8217;s &lt;a href="https://docs.taskcluster.net/queue/api-docs/#createTask"&gt;&lt;code&gt;createTask&lt;/code&gt;&lt;/a&gt; endpoint, which takes care of the actual&amp;nbsp;scheduling.  &lt;/p&gt;
&lt;p&gt;In the excerpt below, you can see a task definition with a &lt;code&gt;requires&lt;/code&gt; field and you can recognize a lot of fields that are in common with the &amp;#8216;task&amp;#8217; section of the yaml files under &lt;code&gt;testing/taskcluster/tasks/&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="s2"&gt;&amp;quot;tasks&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;&amp;quot;requires&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="c1"&gt;// id of a build task that this task depends on&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;fZ42HVdDQ-KFFycr9PxptA&amp;quot;&lt;/span&gt;  
      &lt;span class="p"&gt;],&lt;/span&gt; 
      &lt;span class="s2"&gt;&amp;quot;task&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;taskId&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;c2VD_eCgQyeUDVOjsmQZSg&amp;quot;&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;extra&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;&amp;quot;treeherder&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="s2"&gt;&amp;quot;groupName&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Reftest&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
              &lt;span class="s2"&gt;&amp;quot;groupSymbol&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;tc-R&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
          &lt;span class="p"&gt;},&lt;/span&gt; 
        &lt;span class="p"&gt;},&lt;/span&gt; 
        &lt;span class="s2"&gt;&amp;quot;metadata&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;&amp;quot;description&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Reftest test run 1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
          &lt;span class="s2"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;[TC] Reftest&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="c1"&gt;//...&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;For now at least, a major assumption in the task-graph creation process seems to be that &lt;em&gt;test&lt;/em&gt; tasks can depend on &lt;em&gt;build&lt;/em&gt; tasks and &lt;em&gt;build&lt;/em&gt; tasks don&amp;#8217;t really&lt;sup id="fnref-4"&gt;&lt;a class="footnote-ref" href="#fn-4"&gt;4&lt;/a&gt;&lt;/sup&gt; depend on anything. So: &lt;a name="scheduling_summary"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If you want your tasks to run for every push to a Mozilla hg branch, add it to the list of &lt;strong&gt;builds&lt;/strong&gt; in &lt;code&gt;base_jobs.yml&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;If you want your task to run after certain build tasks succeed, add it to the list of &lt;strong&gt;tests&lt;/strong&gt; in &lt;code&gt;base_jobs.yml&lt;/code&gt; and specify which build tasks it depends&amp;nbsp;on.&lt;/li&gt;
&lt;li&gt;Other than the above, I don&amp;#8217;t see any way to specify a dependency between task A and task B in &lt;code&gt;testing/taskcluster/tasks&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, I added &lt;code&gt;marionette-harness&lt;/code&gt; under &lt;code&gt;builds&lt;/code&gt;. Recall, my task isn&amp;#8217;t a build task, but it doesn&amp;#8217;t depend on a build, so it&amp;#8217;s not a test, so I&amp;#8217;ll treat it like a&amp;nbsp;build.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;# in base_job_flags.yml&lt;/span&gt;
&lt;span class="l l-Scalar l-Scalar-Plain"&gt;builds&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;marionette-harness&lt;/span&gt;

&lt;span class="c1"&gt;# in base_jobs.yml&lt;/span&gt;
&lt;span class="l l-Scalar l-Scalar-Plain"&gt;builds&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="l l-Scalar l-Scalar-Plain"&gt;marionette-harness&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt;
    &lt;span class="l l-Scalar l-Scalar-Plain"&gt;platforms&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt;
      &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;Linux64&lt;/span&gt;
    &lt;span class="l l-Scalar l-Scalar-Plain"&gt;types&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt;
      &lt;span class="l l-Scalar l-Scalar-Plain"&gt;opt&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt;
        &lt;span class="l l-Scalar l-Scalar-Plain"&gt;task&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt; &lt;span class="l l-Scalar l-Scalar-Plain"&gt;tasks/tests/harness_marionette.yml&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This will allow me to trigger my task with the following try syntax: &lt;code&gt;try: -b o -p marionette-harness&lt;/code&gt;.&amp;nbsp;Cool.&lt;/p&gt;
&lt;h1&gt;Make your task do&amp;nbsp;stuff&lt;/h1&gt;
&lt;p&gt;Now I have to add some stuff to &lt;code&gt;tasks/tests/harness_marionette.yml&lt;/code&gt;. Many of my choices here are based on the work done for the &lt;a href="https://hg.mozilla.org/mozilla-central/rev/4b34c9d1a31a"&gt;ESLint task&lt;/a&gt;. I created a base task called &lt;code&gt;harness_test.yml&lt;/code&gt; by mostly copying bits and pieces from the basic build task, &lt;code&gt;build.yml&lt;/code&gt; and making a few small changes. The actual task, &lt;code&gt;harness_marionette.yml&lt;/code&gt; inherits from &lt;code&gt;harness_test.yml&lt;/code&gt; and defines specifics like Treeherder symbols and the command to&amp;nbsp;run.&lt;/p&gt;
&lt;h2&gt;The&amp;nbsp;command&lt;/h2&gt;
&lt;p&gt;The heart of the task is in &lt;code&gt;task.payload.command&lt;/code&gt;. You could chain a bunch of shell commands together directly in this field of the yaml file, but it&amp;#8217;s better not to. Instead, it&amp;#8217;s common to call a TaskCluster-friendly shell script that&amp;#8217;s available in your task&amp;#8217;s environment. For example, the &lt;a href="https://dxr.mozilla.org/mozilla-central/source/testing/docker/desktop-test"&gt;&lt;code&gt;desktop-test&lt;/code&gt;&lt;/a&gt; docker image has a script called &lt;code&gt;test.sh&lt;/code&gt; through which you can call the &lt;a href="https://wiki.mozilla.org/ReleaseEngineering/Mozharness"&gt;mozharness&lt;/a&gt; script for your tests. There&amp;#8217;s a similar &lt;code&gt;build.sh&lt;/code&gt; script on &lt;code&gt;desktop-build&lt;/code&gt;. Both of these scripts depend on environment variables set elsewhere in your task definition, or in the Docker image used by your task. The environment might also provide utilities like &lt;a href="https://tc-vcs.readthedocs.org/en/latest/"&gt;tc-vcs&lt;/a&gt;, which is used for checking out source&amp;nbsp;code.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;# in harness_marionette.yml&lt;/span&gt;
&lt;span class="l l-Scalar l-Scalar-Plain"&gt;payload&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt;
  &lt;span class="l l-Scalar l-Scalar-Plain"&gt;command&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt;
    &lt;span class="l l-Scalar l-Scalar-Plain"&gt;+ bash&lt;/span&gt;
    &lt;span class="l l-Scalar l-Scalar-Plain"&gt;+ -cx&lt;/span&gt;
    &lt;span class="l l-Scalar l-Scalar-Plain"&gt;+ &amp;gt;&lt;/span&gt;
        &lt;span class="l l-Scalar l-Scalar-Plain"&gt;tc-vcs checkout ./gecko {{base_repository}} {{head_repository}} {{head_rev}} {{head_ref}} &amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="l l-Scalar l-Scalar-Plain"&gt;cd gecko &amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="l l-Scalar l-Scalar-Plain"&gt;./mach marionette-harness-test&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;My task&amp;#8217;s &lt;code&gt;payload.command&lt;/code&gt; should be moved into a custom shell script, but for now it just chains together the source checkout and a call to &lt;a href="https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/mach"&gt;mach&lt;/a&gt;. It&amp;#8217;s not terrible of me to use mach in this case because I expect my task to work in a build environment, but most tests would likely call&amp;nbsp;mozharness.&lt;/p&gt;
&lt;h1&gt;Configuring the task&amp;#8217;s&amp;nbsp;environment&lt;/h1&gt;
&lt;p&gt;Where should the task run? What resources should it have access to? This was probably the hardest piece for me to figure&amp;nbsp;out.&lt;/p&gt;
&lt;h2&gt;docker-worker&lt;/h2&gt;
&lt;p&gt;My task will run in a docker image using a &lt;a href="https://docs.taskcluster.net/workers/docker-worker/"&gt;docker-worker&lt;/a&gt;&lt;sup id="fnref-5"&gt;&lt;a class="footnote-ref" href="#fn-5"&gt;5&lt;/a&gt;&lt;/sup&gt;. The image, called &lt;code&gt;desktop-build&lt;/code&gt;, is defined in-tree under &lt;a href="https://dxr.mozilla.org/mozilla-central/source/testing/docker/desktop-build"&gt;&lt;code&gt;testing/docker&lt;/code&gt;&lt;/a&gt;. There are many other images defined there, but I only considered &lt;code&gt;desktop-build&lt;/code&gt; versus &lt;code&gt;desktop-test&lt;/code&gt;. I opted for &lt;code&gt;desktop-build&lt;/code&gt; because &lt;code&gt;desktop-test&lt;/code&gt; seems to contain mozharness-related stuff that I don&amp;#8217;t need for&amp;nbsp;now.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;# harness_test.yml&lt;/span&gt;
&lt;span class="l l-Scalar l-Scalar-Plain"&gt;image&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt;
   &lt;span class="l l-Scalar l-Scalar-Plain"&gt;type&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;task-image&amp;#39;&lt;/span&gt;
   &lt;span class="l l-Scalar l-Scalar-Plain"&gt;path&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;public/image.tar&amp;#39;&lt;/span&gt;
   &lt;span class="l l-Scalar l-Scalar-Plain"&gt;taskId&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;{{#task_id_for_image}}desktop-build{{/task_id_for_image}}&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The image is stored as an artifact of another &lt;span class="caps"&gt;TC&lt;/span&gt; task, which makes it a &amp;#8216;task-image&amp;#8217;. Which artifact? The default is &lt;code&gt;public/image.tar&lt;/code&gt;. Which task do I find the image in? The magic incantation &lt;code&gt;'{{#task_id_for_image}}desktop-build{{/task_id_for_image}}'&lt;/code&gt; somehow&lt;sup id="fnref-6"&gt;&lt;a class="footnote-ref" href="#fn-6"&gt;6&lt;/a&gt;&lt;/sup&gt; obtains the correct &lt;span class="caps"&gt;ID&lt;/span&gt;, and if I look at a particular run of my task, the above snippet does indeed get populated with an actual &lt;code&gt;taskId&lt;/code&gt;. &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;image&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;&amp;quot;path&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;public/image.tar&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// Mystery task that makes a desktop-build image for us. Thanks, mystery task!&lt;/span&gt;
  &lt;span class="s2"&gt;&amp;quot;taskId&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;aqt_YdmkTvugYB5b-OvvJw&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="s2"&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;task-image&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Snooping around in the handy &lt;a href="https://tools.taskcluster.net/task-inspector/"&gt;Task Inspector&lt;/a&gt;, I found that the magical mystery task is defined in &lt;a href="https://dxr.mozilla.org/mozilla-central/source/testing/taskcluster/tasks/image.yml"&gt;image.yml&lt;/a&gt; and runs &lt;a href="https://dxr.mozilla.org/mozilla-central/source/testing/docker/image_builder/bin/build_image.sh"&gt;&lt;code&gt;build_image.sh&lt;/code&gt;&lt;/a&gt;. Fun. It&amp;#8217;s also quite convenient to &lt;a href="https://docs.taskcluster.net/presentations/TC-102/#/images-00"&gt;define and test your own custom image&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Other details that I mostly&amp;nbsp;ignored&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;# in harness_test.yml&lt;/span&gt;
&lt;span class="l l-Scalar l-Scalar-Plain"&gt;scopes&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Nearly all of our build tasks use tc-vcs&lt;/span&gt;
  &lt;span class="p p-Indicator"&gt;-&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;docker-worker:cache:level-{{level}}-{{project}}-tc-vcs&amp;#39;&lt;/span&gt;
&lt;span class="l l-Scalar l-Scalar-Plain"&gt;cache&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt;
   &lt;span class="c1"&gt;# The taskcluster-vcs tooling stores the large clone caches in this&lt;/span&gt;
   &lt;span class="c1"&gt;# directory and will reuse them for new requests this saves about 20s~&lt;/span&gt;
   &lt;span class="c1"&gt;# and is the most generic cache possible.&lt;/span&gt;
   &lt;span class="l l-Scalar l-Scalar-Plain"&gt;level-{{level}}-{{project}}-tc-vcs&lt;/span&gt;&lt;span class="p p-Indicator"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;/home/worker/.tc-vcs&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Routes&lt;/em&gt; allow your task to be looked up in the task index. This isn&amp;#8217;t necessary in my case so I just omitted routes&amp;nbsp;altogether.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Scopes&lt;/em&gt; are permissions for your tasks, and I just copied the scope that is used for checking out source&amp;nbsp;code.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;workerType&lt;/em&gt; is a configuration for managing the workers that run tasks. To me, this was a choice between &lt;code&gt;b2gtest&lt;/code&gt; and &lt;code&gt;b2gbuild&lt;/code&gt;, which aren&amp;#8217;t specific to b2g anyway. &lt;code&gt;b2gtest&lt;/code&gt; is more lightweight, I hear, which suits my harness-test task&amp;nbsp;fine.&lt;/li&gt;
&lt;li&gt;I had to include a few dummy values under &lt;code&gt;extra&lt;/code&gt; in &lt;code&gt;harness_test.yml&lt;/code&gt;, like &lt;code&gt;build_name&lt;/code&gt;, just because they are expected in &lt;em&gt;build&lt;/em&gt; tasks. I don&amp;#8217;t use these values for anything, but my task fails to run if I don&amp;#8217;t include&amp;nbsp;them.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Yay for trial and&amp;nbsp;error&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;If you have syntax errors in your yaml, the Decision task will fail. If this happens during a try push, look under Job Details &amp;gt; Inspect Task to fine useful error&amp;nbsp;messages.&lt;/li&gt;
&lt;li&gt;Iterating on your task is pretty easy. Aside from pushing to try, you can &lt;a href="https://docs.taskcluster.net/presentations/TC-101/#/run-locally-environment"&gt;run tasks locally using vagrant&lt;/a&gt; and you can build a task graph locally as well with &lt;code&gt;mach taskcluster-graph&lt;/code&gt;. &lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Resources&lt;/h1&gt;
&lt;p&gt;Blog posts from other TaskCluster users at&amp;nbsp;Mozilla:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ehsanakhgari.org/blog/2015-09-29/my-experience-adding-new-build-type-taskcluster"&gt;https://ehsanakhgari.org/blog/2015-09-29/my-experience-adding-new-build-type-taskcluster&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://elvis314.wordpress.com/2015/11/09/adventures-in-task-cluster-running-tests-locally/"&gt;https://elvis314.wordpress.com/2015/11/09/adventures-in-task-cluster-running-tests-locally/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://elvis314.wordpress.com/2015/11/11/adventures-in-task-cluster-running-a-custom-docker-image/"&gt;https://elvis314.wordpress.com/2015/11/11/adventures-in-task-cluster-running-a-custom-docker-image/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is lots of great documentation at &lt;a href="https://docs.taskcluster.net"&gt;docs.taskcluster.net&lt;/a&gt;, but these sections were especially useful to&amp;nbsp;me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.taskcluster.net/queue/api-docs/#createTask"&gt;createTask &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.taskcluster.net/workers/"&gt;Workers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Acknowledgements&lt;/h1&gt;
&lt;p&gt;Thanks to &lt;a href="http://code.v.igoro.us/"&gt;dustin&lt;/a&gt;, pmoore and others for corrections and&amp;nbsp;feedback.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn-1"&gt;
&lt;p&gt;This is accomplished in part thanks to &lt;a href="http://blog.gregarndt.com/taskcluster/2015/08/05/demystifying-in-tree-scheduling/"&gt;mozilla-taskcluster&lt;/a&gt;, a service that links Mozilla&amp;#8217;s hg repo to TaskCluster and creates each decision task. More at &lt;a href="https://docs.taskcluster.net/introduction/getting-started/#taskcluster-at-mozilla"&gt;TaskCluster at Mozilla&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn-2"&gt;
&lt;p&gt;Run tasks on any platform thanks to &lt;a href="https://docs.taskcluster.net/workers/generic-worker/"&gt;generic worker&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref-2" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn-3"&gt;
&lt;p&gt;To look at a &lt;code&gt;graph.json&lt;/code&gt; artifact, go to &lt;a href="https://treeherder.mozilla.org/"&gt;Treeherder&lt;/a&gt;, click a green &amp;#8216;D&amp;#8217; job, then Job details &amp;gt; Inspect Task, where you should find a list of artifacts.&amp;#160;&lt;a class="footnote-backref" href="#fnref-3" title="Jump back to footnote 3 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn-4"&gt;
&lt;p&gt;It&amp;#8217;s not &lt;em&gt;really&lt;/em&gt; true that build tasks don&amp;#8217;t depend on anything. Any task that uses a task-image depends on the task that creates the image. I&amp;#8217;m sorry for saying &amp;#8216;task&amp;#8217; five times in every sentence, by the way.&amp;#160;&lt;a class="footnote-backref" href="#fnref-4" title="Jump back to footnote 4 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn-5"&gt;
&lt;p&gt;&amp;#8230;as opposed to a &lt;a href="https://docs.taskcluster.net/workers/generic-worker/"&gt;generic worker&lt;/a&gt;.&amp;#160;&lt;a class="footnote-backref" href="#fnref-5" title="Jump back to footnote 5 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn-6"&gt;
&lt;p&gt;&lt;code&gt;{{#task_id_for_image}}&lt;/code&gt; is an example of a predefined variable that we can use in our &lt;span class="caps"&gt;TC&lt;/span&gt; yaml files. Where do they come from? How do they get populated? I don&amp;#8217;t know.&amp;#160;&lt;a class="footnote-backref" href="#fnref-6" title="Jump back to footnote 6 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><category term="mozilla"></category><category term="foss"></category><category term="ci"></category><category term="taskcluster"></category></entry></feed>