<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="https://www.w3.org/2005/Atom">
  <channel>
    <title>Wander Lairson Costa</title>
    <description>Hackers gonna hack</description>
    <link>https://walac.github.io</link>
    <atom:link href="https://walac.github.iotaskcluster-feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Mon, 21 Sep 2026 22:53:51 +0000</pubDate>
    <lastBuildDate>Mon, 21 Sep 2026 22:53:51 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
        <item>
          <title>Running packet.net images in qemu</title>
          <description>&lt;p&gt;For the past months, I have been working on adding Taskcluster support
for &lt;a href=&quot;https://packet.com&quot;&gt;packet.net&lt;/a&gt; cloud provider. The reason for that
is to get faster Firefox for Android CI tests. Tests showed that jobs run
up to 4x faster on bare metal machines than EC2.&lt;/p&gt;

&lt;p&gt;I set up 25 machines to run a small subset of the production tasks, and so
far results are excellent. The problem is that those machines are up 24/7 and there
is no dynamic provisioning. If we need more machines, I have to manually change
the &lt;a href=&quot;https://www.terraform.io&quot;&gt;terraform&lt;/a&gt; script to scale it up. We need a smart
way to do that. We are going to build something similar to
&lt;a href=&quot;https://github.com/taskcluster/aws-provisioner&quot;&gt;aws-provisioner&lt;/a&gt;. However,
we need a custom &lt;strong&gt;packet.net&lt;/strong&gt; image to speed up instance startup.&lt;/p&gt;

&lt;p&gt;The problem is that if you can’t ssh into the machine, there is no way to get
access to it to see what’s wrong. In this post, I am going to show how you can
run a packet image locally with &lt;a href=&quot;https://www.qemu.org/&quot;&gt;qemu&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can find documentation about creating custom packet images
&lt;a href=&quot;https://support.packet.com/kb/articles/custom-images&quot;&gt;here&lt;/a&gt; and
&lt;a href=&quot;https://github.com/packethost/packet-images/blob/master/README.md&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s create a sample image for the post. After you clone the
&lt;a href=&quot;https://github.com/packethost/packet-images&quot;&gt;packet-images repo&lt;/a&gt;, run:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ./tools/build.sh -d ubuntu_14_04 -p t1.small.x86 -a x86_64 -b ubuntu_14_04-t1.small.x86-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This creates the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;image.tar.gz&lt;/code&gt; file, which is your packet image.
The goal of this post is not to guide you on creating your custom image; you can refer
to the documentation linked above for this. The goal here is, once you have your
image, how you can run it locally with &lt;a href=&quot;https://www.qemu.org/&quot;&gt;qemu&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The first step is to create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qemu&lt;/code&gt; disk to install the image into it:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ qemu-img create -f raw linux.img 10G
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This command creates a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raw&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qemu&lt;/code&gt; image. We now need to create a disk partition:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cfdisk linux.img
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Select &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dos&lt;/code&gt; for the partition table, create a single primary partition and
make it bootable. We now need to create a loop device to handle our image:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sudo losetup -Pf linux.img
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-f&lt;/code&gt; option looks for the first free loop device for attachment to the image file.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-P&lt;/code&gt; option instructs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;losetup&lt;/code&gt; to read the partition table and create a loop
device for each partition found; this avoids us having to play with disk
offsets. Now let’s find our loop device:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sudo losetup -l
NAME        SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE                                         DIO LOG-SEC
/dev/loop1          0      0         1  1 /var/lib/snapd/snaps/gnome-calculator_260.snap      0     512
/dev/loop8          0      0         1  1 /var/lib/snapd/snaps/gtk-common-themes_818.snap     0     512
/dev/loop6          0      0         1  1 /var/lib/snapd/snaps/core_5662.snap                 0     512
/dev/loop4          0      0         1  1 /var/lib/snapd/snaps/gtk-common-themes_701.snap     0     512
/dev/loop11         0      0         1  1 /var/lib/snapd/snaps/gnome-characters_139.snap      0     512
/dev/loop2          0      0         1  1 /var/lib/snapd/snaps/gnome-calculator_238.snap      0     512
/dev/loop0          0      0         1  1 /var/lib/snapd/snaps/gnome-logs_45.snap             0     512
/dev/loop9          0      0         1  1 /var/lib/snapd/snaps/core_6034.snap                 0     512
/dev/loop7          0      0         1  1 /var/lib/snapd/snaps/gnome-characters_124.snap      0     512
/dev/loop5          0      0         1  1 /var/lib/snapd/snaps/gnome-3-26-1604_70.snap        0     512
/dev/loop12         0      0         0  0 /home/walac/work/packet-images/linux.img            0     512
/dev/loop3          0      0         1  1 /var/lib/snapd/snaps/gnome-system-monitor_57.snap   0     512
/dev/loop10         0      0         1  1 /var/lib/snapd/snaps/gnome-3-26-1604_74.snap        0     512
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We see that our loop device is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/loop12&lt;/code&gt;. If we look in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev&lt;/code&gt; directory:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ls -l /dev/loop12*
brw-rw---- 1 root   7, 12 Dec 17 10:39 /dev/loop12
brw-rw---- 1 root 259,  0 Dec 17 10:39 /dev/loop12p1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We see that, thanks to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-P&lt;/code&gt; option, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;losetup&lt;/code&gt; created the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loop12p1&lt;/code&gt;
device for the partition we have. It is time to set up the filesystem:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sudo mkfs.ext4 -b 1024 /dev/loop12p1 
mke2fs 1.44.4 (18-Aug-2018)
Discarding device blocks: done                            
Creating filesystem with 10484716 1k blocks and 655360 inodes
Filesystem UUID: 2edfe9f2-7e90-4c35-80e2-bd2e49cad251
Superblock backups stored on blocks: 
        8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409, 663553, 
        1024001, 1990657, 2809857, 5120001, 5971969

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (65536 blocks): done
Writing superblocks and filesystem accounting information: done     
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ok, finally we can mount our device and extract the image to it:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ mkdir mnt
$ sudo mount /dev/loop12p1 mnt/
$ sudo tar -xzf image.tar.gz -C mnt/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The last step is to install the bootloader. As we are running an Ubuntu image,
we will use &lt;a href=&quot;https://www.gnu.org/software/grub/manual/grub/grub.html&quot;&gt;grub2&lt;/a&gt;
for that.&lt;/p&gt;

&lt;p&gt;Firstly we need to install grub in the boot sector:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sudo grub-install --boot-directory mnt/boot/ /dev/loop12
Installing for i386-pc platform.
Installation finished. No error reported.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Notice we point to the boot directory of our image. Next, we have to
generate the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grub.cfg&lt;/code&gt; file:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cd mnt/
$ for i in /proc /dev /sys; do sudo mount -B $i .$i; done
$ sudo chroot .
# cd /etc/grub.d/
# chmod -x 30_os-prober
# update-grub
Generating grub configuration file ...
Warning: Setting GRUB_TIMEOUT to a non-zero value when GRUB_HIDDEN_TIMEOUT is set is no longer supported.
Found linux image: /boot/vmlinuz-3.13.0-123-generic
Found initrd image: /boot/initrd.img-3.13.0-123-generic
done
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We &lt;em&gt;bind mount&lt;/em&gt; the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/proc&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/sys&lt;/code&gt; host mount points inside the Ubuntu image,
then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chroot&lt;/code&gt; into it. Next, to avoid grub creating entries for our host OSes, we disable the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;30_os-prober&lt;/code&gt; script.  Finally we run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update-grub&lt;/code&gt; and it creates the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/boot/grub/grub.cfg&lt;/code&gt; file.
Now the only thing left is cleanup:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# exit
$ for i in dev/ sys/ proc/; do sudo umount $i; done
$ cd ..
$ sudo umount mnt/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The commands are self-explanatory. Now let’s run our image:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sudo qemu-system-x86_64 -enable-kvm -hda /dev/loop12
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/qemu.png&quot; alt=&quot;qemu&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And that’s it, you now can run your packet image locally!&lt;/p&gt;
</description>
          <pubDate>Fri, 14 Dec 2018 00:00:00 +0000</pubDate>
          <link>https://walac.github.io/booting-packet-images-qemu/</link>
          <guid isPermaLink="true">https://walac.github.io/booting-packet-images-qemu/</guid>
          
          <category>qemu</category>
          
          <category>linux</category>
          
          <category>taskcluster</category>
          
          
          <category>linux</category>
          
        </item>
      
    
      
    
      
    
      
        <item>
          <title>The taskcluster-worker Mac OSX engine</title>
          <description>&lt;p&gt;In this quarter, I worked on implementing the
&lt;a href=&quot;https://blog.gregarndt.com/taskcluster/2016/03/24/birth-of-new-worker/&quot;&gt;taskcluster-worker&lt;/a&gt;
Mac OSX engine. Before talking about this specific implementation,
let me explain what a worker is and how taskcluster-worker differs from
&lt;a href=&quot;https://github.com/taskcluster/docker-worker&quot;&gt;docker-worker&lt;/a&gt;, the current
main worker in
&lt;a href=&quot;https://yourdomain.com/mozilla,%20ci/2014/03/04/taskcluster.html&quot;&gt;Taskcluster&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;the-role-of-a-taskcluster-worker&quot;&gt;The role of a Taskcluster worker&lt;/h1&gt;

&lt;p&gt;When a user submits a task graph to Taskcluster,
contrary to common sense (at least if you are used to how OS
schedulers usually work), these tasks are submitted to the scheduler first,
which is responsible for processing dependencies and enqueue them. In the
&lt;a href=&quot;https://docs.taskcluster.net/manual&quot;&gt;Taskcluster manual page&lt;/a&gt; there is a
clear picture illustrating this concept.&lt;/p&gt;

&lt;p&gt;The provisioner is responsible for looking at the queue and determining how
many pending tasks exist and, based on that, it launches worker instances to
run these tasks.&lt;/p&gt;

&lt;p&gt;Then comes the figure of the worker. The worker is responsible for actually
executing the task. It claims a task from the queue, runs it, uploads the
generated artifacts and submits the status of the finished task, using the
&lt;a href=&quot;https://docs.taskcluster.net/manual/apis&quot;&gt;Taskcluster APIs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-worker&lt;/code&gt; is a worker that runs task commands inside a docker container.
The task payload specifies a &lt;a href=&quot;https://www.docker.com/what-docker&quot;&gt;docker&lt;/a&gt;
image as well as a command line to run, among other environment parameters.
docker-worker pulls the specified docker image and runs task commands inside it.&lt;/p&gt;

&lt;h1 id=&quot;taskcluster-worker-and-the-osx-engine&quot;&gt;taskcluster-worker and the OSX engine&lt;/h1&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;taskcluster-worker&lt;/code&gt; is a generic and modularized worker under active
development by the Taskcluster team. The worker delegates the task execution
to one of the available
&lt;a href=&quot;https://github.com/taskcluster/taskcluster-worker/tree/master/engines&quot;&gt;engines&lt;/a&gt;.
An engine is a component of taskcluster-worker responsible for running a task
under a specific system environment. Other features, like environment variable
setting, live logging, artifact uploading, etc., are handled by
&lt;a href=&quot;https://github.com/taskcluster/taskcluster-worker/tree/master/plugins&quot;&gt;worker plugins&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I am implementing the Mac OSX engine, which will mainly be used to run
Firefox automated tests in the Mac OSX environment. There is a
&lt;a href=&quot;https://github.com/walac/taskcluster-worker/tree/macosx&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;macosx&lt;/code&gt; branch&lt;/a&gt; in
my personal Github taskcluster-worker fork in which I push my commits.&lt;/p&gt;

&lt;p&gt;One specific aspect of the engine implementation is the ability to run more
than one task at the same time. For this, we need to implement some kind
of task isolation. For docker-worker, each task ran in its own docker container
so tasks were isolated by definition. But there is no such thing as a container
for OSX engine. Our earlier tries with
&lt;a href=&quot;https://en.wikipedia.org/wiki/Chroot&quot;&gt;chroot&lt;/a&gt; failed miserably, due to
incompatibilities with the OSX graphics system. Our final solution was to create a new user
on the fly and run the task with this user’s credentials. This not only provides
some task isolation, but also prevents privilege escalation attacks by running
tasks with a different user than the worker.&lt;/p&gt;

&lt;p&gt;Instead of dealing with the poorly documented
&lt;a href=&quot;https://developer.apple.com/library/mac/documentation/Networking/Conceptual/Open_Directory/Introduction/Introduction.html&quot;&gt;Open Directory Framework&lt;/a&gt;,
we chose to spawn the
&lt;a href=&quot;https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/dscl.1.html&quot;&gt;dscl&lt;/a&gt;
command to create and configure users. Tasks usually take a long time to
execute, spawning loads of subprocesses, so a few spawns of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dscl&lt;/code&gt; command
won’t have any practical performance impact.&lt;/p&gt;

&lt;p&gt;One final aspect is how we bootstrap task execution. A task boils down to
a script that executes task duties. But where does this script come from?
It doesn’t live on the machine that executes the worker. OSX engine provides a
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;link&lt;/code&gt; field in task payload that a task can specify an executable to download and
execute.&lt;/p&gt;

&lt;h1 id=&quot;running-the-worker&quot;&gt;Running the worker&lt;/h1&gt;

&lt;p&gt;OSX engine will primarily be used to execute Firefox tests on Mac OSX,
and the environment is expected to have a very specific set of tools and
configurations. Because of that, I am testing the code on a
&lt;a href=&quot;https://wiki.mozilla.org/ReleaseEngineering/How_To/Loan_a_Slave&quot;&gt;loaner machine&lt;/a&gt;.
To start the worker, it is just a matter of opening a terminal and typing:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./taskcluster-worker work macosx &lt;span class=&quot;nt&quot;&gt;--logging-level&lt;/span&gt; debug
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The worker connects to the Taskcluster queue, claims and executes the available tasks.
At the time I am writing, all tests but &lt;em&gt;Firefox UI functional&lt;/em&gt; tests were green,
running on optimized Firefox OSX builds. We intend to land Firefox tests in taskcluster-worker as
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Supported_build_configurations&quot;&gt;Tier-2&lt;/a&gt; on next quarter,
running them in parallel with Buildbot.&lt;/p&gt;
</description>
          <pubDate>Mon, 27 Jun 2016 00:00:00 +0000</pubDate>
          <link>https://walac.github.io/taskcluster-worker-macosx-engine/</link>
          <guid isPermaLink="true">https://walac.github.io/taskcluster-worker-macosx-engine/</guid>
          
          <category>taskcluster</category>
          
          
          <category>mozilla</category>
          
        </item>
      
    
      
        <item>
          <title>Overcoming browser same origin policy</title>
          <description>&lt;p&gt;One of my goals for 2016 Q1 was to write a
&lt;a href=&quot;https://tools.taskcluster.net/status/&quot;&gt;monitoring dashboard&lt;/a&gt; for Taskcluster.
It basically pings Taskcluster services to check if they are alive and also
acts as a feed aggregator for services Taskcluster depends on. One problem with
this approach is the
&lt;a href=&quot;https://en.wikipedia.org/wiki/Same-origin_policy&quot;&gt;same origin policy&lt;/a&gt;, in which
web pages are only allowed to make requests to their own domain. For web servers
for which it is safe to make these cross-domain requests, they can either implement
&lt;a href=&quot;https://en.wikipedia.org/wiki/JSONP&quot;&gt;jsonp&lt;/a&gt; or
&lt;a href=&quot;https://en.wikipedia.org/wiki/Cross-origin_resource_sharing&quot;&gt;CORS&lt;/a&gt;. CORS is the
preferred way so we will focus on it for this post.&lt;/p&gt;

&lt;h2 id=&quot;cross-origin-resource-sharing&quot;&gt;Cross-origin resource sharing&lt;/h2&gt;

&lt;p&gt;CORS is a mechanism that allows the web server to tell the browser that it is safe to
accomplish a cross-domain request. It consists of a set of HTTP headers with details
for the conditions to accomplish the request. The main response header is
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Access-Control-Allow-Origin&lt;/code&gt;, which contains either a list of allowed domains or
a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;, indicating any domain can make a cross request to this server. In a CORS
request, only a small set of headers is exposed to the response object. The server
can tell the browser to expose additional headers through the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Access-Control-Expose-Headers&lt;/code&gt; response header.&lt;/p&gt;

&lt;p&gt;But what if the web server doesn’t implement CORS? The only solution is to provide
a proxy that will make the actual request and add the CORS headers.&lt;/p&gt;

&lt;h2 id=&quot;cors-proxy&quot;&gt;cors-proxy&lt;/h2&gt;

&lt;p&gt;To allow the monitoring dashboard to make requests for status state on remote services
that do not implement CORS, we created the
&lt;a href=&quot;https://github.com/taskcluster/cors-proxy&quot;&gt;cors-proxy&lt;/a&gt;. It exports a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/request&lt;/code&gt;
endpoint that allows you to make requests to any remote host. cors-proxy redirects
it to the remote URL and sends the responses back, with appropriate CORS headers set.&lt;/p&gt;

&lt;p&gt;Let’s see an example:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ajax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;https://cors-proxy.taskcluster.net/request&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;POST&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;contentType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;application/json&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;https://queue.taskcluster.net/v1/ping&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;done&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The information about the remote request is sent in the proxy request body. All
parameter fields are shown in the project page.&lt;/p&gt;

&lt;p&gt;Before you think of using the hosted server to bypass your own requests, cors-proxy
only honors requests from a
&lt;a href=&quot;https://github.com/taskcluster/cors-proxy/blob/master/server.js#L12-L15&quot;&gt;whitelist&lt;/a&gt;.
So, only some subdomains under Taskcluster domain can use cors-proxy.&lt;/p&gt;

</description>
          <pubDate>Fri, 01 Apr 2016 00:00:00 +0000</pubDate>
          <link>https://walac.github.io/cors-proxy/</link>
          <guid isPermaLink="true">https://walac.github.io/cors-proxy/</guid>
          
          <category>taskcluster</category>
          
          
          <category>taskcluster</category>
          
        </item>
      
    
      
        <item>
          <title>In tree tasks configuration</title>
          <description>&lt;p&gt;This post is about our plans for representing Taskcluster tasks inside
the gecko tree. &lt;a href=&quot;https://jonasfj.dk/&quot;&gt;Jonas&lt;/a&gt;,
&lt;a href=&quot;https://code.v.igoro.us/&quot;&gt;Dustin&lt;/a&gt; and I had a discussion in Berlin about this,
here I summarize what we have so far. We currently store tasks in an
&lt;a href=&quot;https://yaml.org/&quot;&gt;YAML&lt;/a&gt; file and they translate to JSON format using the
mach command. The syntax we have now is not the most flexible one, it is hard
to parameterize the task and very difficult to represent task relationships.&lt;/p&gt;

&lt;p&gt;Let us illustrate the shortcomings with two problems we currently have.
Both apply to B2G.&lt;/p&gt;

&lt;p&gt;B2G (as in Android) has three different
&lt;a href=&quot;https://source.android.com/source/building.html#choose-a-target&quot;&gt;build variants&lt;/a&gt;:
user, userdebug and eng. Each one has slightly different task configurations.
As there is no flexible way to parameterize tasks, we end up with one different
task file for each build variant.&lt;/p&gt;

&lt;p&gt;When doing nightly builds, we must send update data to the OTA server.
We have plans to run a build task, then run the test tasks on this build,
and if all tests pass, we run a task responsible for updating the OTA server.
The point is that today we have no way to represent this relationship
inside the task files.&lt;/p&gt;

&lt;p&gt;For the first problem Jonas has a prototype for
&lt;a href=&quot;https://github.com/jonasfj/json-parameterization&quot;&gt;json parameterization&lt;/a&gt;. There
were discussions at the Berlin work week about whether we should stick with yaml files
or use Python files for task configuration. We do want to keep the syntax
declarative, which favors yaml, but storing configurations in Python files
brings much more expressiveness and flexibility, but this can result in
the same configuration hell we have with Buildbot.&lt;/p&gt;

&lt;p&gt;The second problem is more complex, and we still haven’t reached a final design.
The first question is how we describe task dependencies, top-down, i.e., we
specify which task(s) should run after a completed task, or ground up, a task
specifies which tasks it depends on. In general, we all agreed to go to a
top-down syntax, since most scenarios call for a top-down approach. Another
question is whether to put the description of task relationships inside the task
files or in a separate configuration file. We would like to represent task
dependencies inside the task file, the problem is how to check what’s the
root task for the task graph. One suggestion is having a task file called
root.yml which only contains root tasks.&lt;/p&gt;
</description>
          <pubDate>Fri, 09 Oct 2015 00:00:00 +0000</pubDate>
          <link>https://walac.github.io/in-tree-config/</link>
          <guid isPermaLink="true">https://walac.github.io/in-tree-config/</guid>
          
          <category>taskcluster</category>
          
          
          <category>taskcluster</category>
          
        </item>
      
    
      
        <item>
          <title>Running phone builds on Taskcluster</title>
          <description>&lt;p&gt;In this post I am going to talk about my work for phone builds inside the
&lt;a href=&quot;https://docs.taskcluster.net/&quot;&gt;Taskcluster&lt;/a&gt; infrastructure. Mozilla is
slightly moving from Buildbot to Taskcluster. Here I am going to
give a survival guide on Firefox OS phone builds.&lt;/p&gt;

&lt;h2 id=&quot;submitting-tasks&quot;&gt;Submitting tasks&lt;/h2&gt;

&lt;p&gt;A task is nothing more than a JSON file containing the description 
of the job to execute. But you don’t need to handle the JSON directly, all tasks
are written in &lt;a href=&quot;https://en.wikipedia.org/wiki/YAML&quot;&gt;YAML&lt;/a&gt;, and it is then processed
by the &lt;a href=&quot;https://mzl.la/1MkZ4gz&quot;&gt;mach&lt;/a&gt; command. The in tree tasks are located
at &lt;a href=&quot;https://mzl.la/1MkYOhw&quot;&gt;testing/taskcluster/tasks&lt;/a&gt; and the build tasks are
inside the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;builds/&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;My favorite command to try out a task is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mach taskcluster-build&lt;/code&gt; command.
It allows you to process a single task and output the JSON-formatted task ready
for Taskcluster submission.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./mach taskcluster-build &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--head-repository&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;https://hg.mozilla.org/mozilla-central 
    &lt;span class=&quot;nt&quot;&gt;--head-rev&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;tip &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--owner&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;foobar@mozilla.com &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    tasks/builds/b2g_desktop_opt.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Although we specify a Mercurial repository, Taskcluster also accepts git
repositories interchangeably.&lt;/p&gt;

&lt;p&gt;This command will print out the task to the console output. To
run the task, you can copy the generated task and paste it in the
&lt;a href=&quot;https://tools.taskcluster.net/task-creator/&quot;&gt;task creator&lt;/a&gt; tool. Then just
click on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Create Task&lt;/code&gt; to schedule it to run. Remember that you need
&lt;a href=&quot;https://auth.taskcluster.net/&quot;&gt;Taskcluster Credentials&lt;/a&gt; to run Taskcluster
tasks. If you have
&lt;a href=&quot;https://www.npmjs.com/package/taskcluster-cli/&quot;&gt;taskcluster-cli&lt;/a&gt;
installed, you can then pipe the mach output to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;taskcluster run-task&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The tasks are effectively executed inside a &lt;a href=&quot;https://www.docker.com/&quot;&gt;docker&lt;/a&gt;
&lt;a href=&quot;https://dxr.mozilla.org/mozilla-central/source/testing/docker&quot;&gt;image&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;mozharness&quot;&gt;Mozharness&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://wiki.mozilla.org/ReleaseEngineering/Mozharness&quot;&gt;Mozharness&lt;/a&gt;
is what we use to effectively build stuff. The Mozharness
architecture, despite its code size, is quite simple. Under the 
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scripts&lt;/code&gt; directory you find the harness scripts. We are specifically
interested in the &lt;a href=&quot;https://tinyurl.com/nlm8mjm&quot;&gt;b2g_build.py&lt;/a&gt; script. As the script
name says, it is responsible for B2G builds. The B2G harness configuration
files are located at the &lt;a href=&quot;https://tinyurl.com/nzqlkfe&quot;&gt;b2g/config&lt;/a&gt; directory. Not
surprisingly, all files starting with “taskcluster” are for Taskcluster
related builds.&lt;/p&gt;

&lt;p&gt;Here are the most common configurations:&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;default_vcs&lt;/dt&gt;
  &lt;dd&gt;This is the default vcs used to clone repositories when no other is given.
  [tc_vcs](https://tc-vcs.readthedocs.org/en/latest/) allows mozharness to
  clone either git or mercurial repositories transparently, with repository
  caching support.&lt;/dd&gt;
  &lt;dt&gt;default_actions&lt;/dt&gt;
  &lt;dd&gt;The actions to execute. They must be present and in the same order as
  in the build class `all_actions` attribute.&lt;/dd&gt;
  &lt;dt&gt;balrog_credentials_file&lt;/dt&gt;
  &lt;dd&gt;The credentials to send update data to the OTA server.&lt;/dd&gt;
  &lt;dt&gt;nightly_build&lt;/dt&gt;
  &lt;dd&gt;`True` if this is a nightly build.&lt;/dd&gt;
  &lt;dt&gt;upload&lt;/dt&gt;
  &lt;dd&gt;Upload info. Not used for Taskcluster.&lt;/dd&gt;
  &lt;dt&gt;repo_remote_mappings&lt;/dt&gt;
  &lt;dd&gt;Maps external repositories to [mozilla domain](https://git.mozilla.org).&lt;/dd&gt;
  &lt;dt&gt;env&lt;/dt&gt;
  &lt;dd&gt;Environment variables for commands executed inside mozharness.&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;The listed actions map to Python methods inside the build class, with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt; replaced
by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_&lt;/code&gt;. For example, the action &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;checkout-sources&lt;/code&gt; maps to the method
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;checkout_sources&lt;/code&gt;. That’s where the mozharness simplicity comes from: everything boils
down to a sequence of method calls, just that, no secrets.&lt;/p&gt;

&lt;p&gt;For example, here is how you run mozharness to build a flame image:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;python &amp;lt;gecko-dir&amp;gt;/testing/mozharness/scripts/b2g_build.py &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--config&lt;/span&gt; b2g/taskcluster-phone.py &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--disable-mock&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--variant&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;user &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--work-dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;B2G &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--gaia-languages-file&lt;/span&gt; locales/languages_all.json &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--log-level&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;debug &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;flame-kk &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--b2g-config-dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;flame-kk &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--repo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;https://hg.mozilla.org/mozilla-central &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Remember you need your flame connected to the machine so the build system
can extract the blobs.&lt;/p&gt;

&lt;p&gt;In general you don’t need to worry about mozharness command line because it is wrapped
by the &lt;a href=&quot;https://tinyurl.com/py798c3&quot;&gt;build scripts&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;hacking-taskcluster-b2g-builds&quot;&gt;Hacking Taskcluster B2G builds&lt;/h2&gt;

&lt;p&gt;All Taskcluster tasks run inside a docker container. Desktop and emulator B2G builds
run inside the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;builder&lt;/code&gt; docker image. Phone builds are more complex, because:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Mozilla is not allowed to publicly redistribute phone binaries.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Phone build tasks need to access the &lt;a href=&quot;https://wiki.mozilla.org/Balrog&quot;&gt;Balrog&lt;/a&gt;
  server to send OTA update data.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Phone build tasks need to upload symbols to the
  &lt;a href=&quot;https://mzl.la/1Ta6jfY&quot;&gt;crash reporter&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Due to (1), only users authenticated with a @mozilla account are allowed
to download phone binaries (this works the same way as private builds). And
because of (1), (2) and (3), the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;phone-builder&lt;/code&gt; docker image is secret,
so only authorized users can submit tasks to it.&lt;/p&gt;

&lt;p&gt;If you need to create a build task for a new phone, most of the time you will
start from an existing task (Flame and Aries tasks are preferred) and then
make your customizations. You might need to add new features to the
&lt;a href=&quot;https://tinyurl.com/py798c3&quot;&gt;build scripts&lt;/a&gt;, which currently are not the most
flexible scripts around.&lt;/p&gt;

&lt;p&gt;If you need to customize mozharness, make sure your changes are Python 2.6
compatible, because mozharness is used to run Buildbot builds too, and the
Buildbot machines run Python 2.6. The best way to minimize risk of breaking
stuff is to submit your patches to try with “-p all -b do” flags.&lt;/p&gt;

&lt;p&gt;Need help? Ask at the #taskcluster channel.&lt;/p&gt;
</description>
          <pubDate>Mon, 05 Oct 2015 00:00:00 +0000</pubDate>
          <link>https://walac.github.io/taskcluster-b2g/</link>
          <guid isPermaLink="true">https://walac.github.io/taskcluster-b2g/</guid>
          
          <category>taskcluster</category>
          
          
          <category>mozilla</category>
          
        </item>
      
    
      
    
      
    
  </channel>
</rss>
