<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>chris' random ramblings (Posts about mozilla)</title><link>https://atlee.ca/</link><description></description><atom:link href="https://atlee.ca/categories/mozilla.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><lastBuildDate>Sat, 22 Feb 2025 20:04:32 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Hello Again, World!</title><link>https://atlee.ca/posts/hello-world-2022/</link><dc:creator>chris</dc:creator><description>&lt;p&gt;First off, hello, it's been a while!&lt;/p&gt;
&lt;p&gt;Since my &lt;a href="https://atlee.ca/posts/updated-firefox-gpg-key-2019/"&gt;last post&lt;/a&gt; over &lt;em&gt;three years ago&lt;/em&gt; 🤦,  life has been pretty busy.&lt;/p&gt;
&lt;p&gt;First, a global pandemic.&lt;/p&gt;
&lt;p&gt;Next, we welcomed a new baby into the family the summer of 2020, right in
the middle of said pandemic.&lt;/p&gt;
&lt;p&gt;Then in the fall of 2020, I resigned from my job of nearly 12 years at
Mozilla and I took on a new role as Staff Developer with
&lt;a href="https://shopify.ca"&gt;Shopify&lt;/a&gt;. I've been doing backend product development
work, focusing on making our themes more customizable by merchants, and
extensible by third party apps.&lt;/p&gt;
&lt;p&gt;I even got to publish a video describing a new feature I helped to build!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://youtu.be/xYz_XMY7jEU?t=226" title="Theme App Extensions"&gt;&lt;img alt="Shopify Unite 2021" src="https://img.youtube.com/vi/xYz_XMY7jEU/0.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(Look, I'm on the internet!)&lt;/p&gt;
&lt;p&gt;I've really enjoyed the move so far. It's been great to switch gears from
infrastructure work in Python to product development in Ruby. I intend to
blog a bit about my experience learning Ruby as a relatively experienced
Python developer. tl;dr - I'm glad that I did. Learning new programming
languages and tools is almost always beneficial, as it helps you to think
about problems in different ways.&lt;/p&gt;</description><category>mozilla</category><category>shopify</category><guid>https://atlee.ca/posts/hello-world-2022/</guid><pubDate>Wed, 10 Aug 2022 00:17:04 GMT</pubDate></item><item><title>Updated GPG key for signing Firefox Releases</title><link>https://atlee.ca/posts/updated-firefox-gpg-key-2019/</link><dc:creator>chris</dc:creator><description>&lt;p&gt;The GPG key used to sign the Firefox release manifests is expiring soon, and so we're going to be switching over to new key shortly.&lt;/p&gt;
&lt;p&gt;The new GPG subkey's fingerprint is &lt;code&gt;097B 3130 77AE 62A0 2F84  DA4D F1A6 668F BB7D 572E&lt;/code&gt;, and it expires 2021-05-29.&lt;/p&gt;
&lt;p&gt;The public key can be fetched from
&lt;a href="https://archive.mozilla.org/pub/firefox/candidates/68.0b9-candidates/build1/KEY"&gt;KEY&lt;/a&gt;
files from Firefox 68 beta releases, or from below. This can be used to validate
existing releases signed with the current key, or future releases signed with
the new key.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="gh"&gt;-----BEGIN PGP PUBLIC KEY BLOCK-----&lt;/span&gt;

&lt;span class="s"&gt;mQINBFWpQAQBEAC+9wVlwGLy8ILCybLesuB3KkHHK+Yt1F1PJaI30X448ttGzxCz&lt;/span&gt;
&lt;span class="s"&gt;PQpH6BoA73uzcTReVjfCFGvM4ij6qVV2SNaTxmNBrL1uVeEUsCuGduDUQMQYRGxR&lt;/span&gt;
&lt;span class="s"&gt;tWq5rCH48LnltKPamPiEBzrgFL3i5bYEUHO7M0lATEknG7Iaz697K/ssHREZfuuc&lt;/span&gt;
&lt;span class="s"&gt;B4GNxXMgswZ7GTZO3VBDVEw5GwU3sUvww93TwMC29lIPCux445AxZPKr5sOVEsEn&lt;/span&gt;
&lt;span class="s"&gt;dUB2oDMsSAoS/dZcl8F4otqfR1pXg618cU06omvq5yguWLDRV327BLmezYK0prD3&lt;/span&gt;
&lt;span class="s"&gt;P+7qwEp8MTVmxlbkrClS5j5pR47FrJGdyupNKqLzK+7hok5kBxhsdMsdTZLd4tVR&lt;/span&gt;
&lt;span class="s"&gt;jXf04isVO3iFFf/GKuwscOi1+ZYeB3l3sAqgFUWnjbpbHxfslTmo7BgvmjZvAH5Z&lt;/span&gt;
&lt;span class="s"&gt;asaewF3wA06biCDJdcSkC9GmFPmN5DS5/Dkjwfj8+dZAttuSKfmQQnypUPaJ2sBu&lt;/span&gt;
&lt;span class="s"&gt;blnJ6INpvYgsEZjV6CFG1EiDJDPu2Zxap8ep0iRMbBBZnpfZTn7SKAcurDJptxin&lt;/span&gt;
&lt;span class="s"&gt;CRclTcdOdi1iSZ35LZW0R2FKNnGL33u1IhxU9HRLw3XuljXCOZ84RLn6M+PBc1eZ&lt;/span&gt;
&lt;span class="s"&gt;suv1TA+Mn111yD3uDv/u/edZ/xeJccF6bYcMvUgRRZh0sgZ0ZT4b0Q6YcQARAQAB&lt;/span&gt;
&lt;span class="s"&gt;tC9Nb3ppbGxhIFNvZnR3YXJlIFJlbGVhc2VzIDxyZWxlYXNlQG1vemlsbGEuY29t&lt;/span&gt;
&lt;span class="s"&gt;PohGBBARAgAGBQJVrP9LAAoJEHYlQD1/DRWxU2QAoOOFRbkbIU1zKP2i3jy/6VKH&lt;/span&gt;
&lt;span class="s"&gt;kYEgAJ9N6f9Gmjm1/vtSrvjjlxWzzQQrkIhGBBARAgAGBQJVrTrjAAoJEMNOV0fi&lt;/span&gt;
&lt;span class="s"&gt;PdZ3BbkAoJUNHEqNv9dioaGMEIpiFtDjEm44AJ9UinMTfAYsL9yb15SdJWe/56VC&lt;/span&gt;
&lt;span class="s"&gt;coheBBARCAAGBQJWBldjAAoJEAJasBBrF+oerNYA/13MQehk3AfkljGi252/cU6i&lt;/span&gt;
&lt;span class="s"&gt;1VOFpCuOeT7lK2c5unGcAP0WZjIDJgaHijtrF4MKCZbUnz37Vxm0OcU8qcGkYUwH&lt;/span&gt;
&lt;span class="s"&gt;i4heBBARCgAGBQJVrSz+AAoJEPCp59zTnkUulAYA/31nYhIpb7sVigone8OvFO19&lt;/span&gt;
&lt;span class="s"&gt;xtkR9/vy5+iKeYCVlvZtAP9rZ85ymuNYNqX06t+ruDqG2RfdUhJ6aD5IND+KD5ve&lt;/span&gt;
&lt;span class="s"&gt;7IkBHAQQAQIABgUCVaz9fgAKCRCzxalYUIpD8muMB/sH58bMSzzF9zTXRropldw7&lt;/span&gt;
&lt;span class="s"&gt;Vbj9VrRD7NyoX4OlDArtvdLqgPm0JUoP2gXINeSuVPpOfC676yVnBEMjIfqEjq09&lt;/span&gt;
&lt;span class="s"&gt;vcbwayS+Ncx4vQh2BmzDUNLE3SlnRn2bEWr9SQL/pOYUDUgmY5a0UIf/WKtBapsP&lt;/span&gt;
&lt;span class="s"&gt;E+Zan51ezYSEfxDNfUpA4T2/9iWwJ2ZOy0yIfLdHyvumuyiekJrfrMaF4L9Q0OnJ&lt;/span&gt;
&lt;span class="s"&gt;wp1PwkvN4IVwhZeYDtIJN4nRcJK5LrwU7B97uef2hqBBll7/qCHl5y4Khb0csFan&lt;/span&gt;
&lt;span class="s"&gt;Ig+pQLPUJdIiYtzoFtlgykB61pxqtU9rqGKW02JzEUT8DdPUXxmMBy6A8oGeBRH/&lt;/span&gt;
&lt;span class="s"&gt;iQEcBBABAgAGBQJVrRdcAAoJEGVzgtv/JREKQJgH/3nD/3/SumL7nG2g7Y1HQqWp&lt;/span&gt;
&lt;span class="s"&gt;hUbn40XWvjZcHq3uBUn1QYXeZ5X56SANLM2t+uirGnNaZXW3cxEl5IyZVLbmcLWE&lt;/span&gt;
&lt;span class="s"&gt;BlVAcp2Bf3FXFbdJK59f+M+y2+jZT9feTyrw+EtLoiGTxgkLdJyMyI0xGmQhMx5V&lt;/span&gt;
&lt;span class="s"&gt;1ex1CxhZK2JPjzCVYriBI0wIbmKi90YNMQoSsdMhYmX9bHl6XWS9TCDWsqj25FLY&lt;/span&gt;
&lt;span class="s"&gt;JL+WeVXpjO0NjRwEE6pc/qldeJYG5Vbf0snGxIerXe+l5D8Yd4PEAnpj58+5pXeo&lt;/span&gt;
&lt;span class="s"&gt;GYZn3WjX8eTFMAEU+QhLKWQ+j/Y8Kijge7fUxnSNBZ2KEnuDN/4Hv/DrCFLv14CJ&lt;/span&gt;
&lt;span class="s"&gt;ARwEEAECAAYFAlWtZVoACgkQ5DJ8bD4CmcBzsAf/RMqDdVHggQHc0/YLt1f/vY9Y&lt;/span&gt;
&lt;span class="s"&gt;7QQ6HwnDrtcNxxErSVcMguD8K6Oxir0TMSh+/YuZAW8K4KSgEURwZqz4na8/eOxj&lt;/span&gt;
&lt;span class="s"&gt;8bluNmlcAseQDHswqU6CyB95Woy3BocihH7L0eDXZOMzsa33vRQHBMioLxIbpnVt&lt;/span&gt;
&lt;span class="s"&gt;VbFR1z7tmyfjcOrzP32xo5QoPoczKX26luMBjAvbw1FC0is2INnmUSYM4uH7iFZu&lt;/span&gt;
&lt;span class="s"&gt;XGPFYxcAqODqy5ys3MoPa4oZ71d0HoiRil1+s0Y+2ByddZ19pE2TXp4ZXNYNUj/2&lt;/span&gt;
&lt;span class="s"&gt;aRj8b4sTjR4rqhHIx/vfoK+VCNy/skFUZOyPdbbymE0stTRSJ1gr9CZLcBWYF4kB&lt;/span&gt;
&lt;span class="s"&gt;HAQQAQIABgUCVcFZcAAKCRCJFz+VfFX5XqApB/938p+CJiDRnh2o7eDWnjSyAu7F&lt;/span&gt;
&lt;span class="s"&gt;WmWGkOQnjI/kraKx1vojsYnKRXD6mjq1QJ8Hsp4taJnLQjcokNTUiST4m/e4ZJEx&lt;/span&gt;
&lt;span class="s"&gt;PWuJKkwlralWGH6NpqYcgWPajSYb0eYQC4YqS0kfyzolrHdKI8Y4NGEU7yy5zsHw&lt;/span&gt;
&lt;span class="s"&gt;WkHt/mpNQMrYnXwyWdIrc03X/OXo51dJyshJDRw3InREyBblFJcLvArNHz219wMr&lt;/span&gt;
&lt;span class="s"&gt;XAicPytw4wfPpVrmDx6GrZcI8q8ECWCjwSXXv7hRpEuFLSy5XPhMc+wYBJjNlUoi&lt;/span&gt;
&lt;span class="s"&gt;FBAF/7zENd3rMn9SCQLiIFYe0ubmO+bpeGy7TizbxOaCIfgUouyy0BQXNuJBiQEc&lt;/span&gt;
&lt;span class="s"&gt;BBABAgAGBQJV0hrqAAoJEK18uZ+CSLoPzEIH/1D6sJMNAJtZCRGhJXvv6SYhv4pU&lt;/span&gt;
&lt;span class="s"&gt;VNyDF9FnUvRsovliojoe4IkuBTWKhPGrxbiD5IO/izr38shqNhhm9JE2/SQZHObY&lt;/span&gt;
&lt;span class="s"&gt;Pi+lyfDKbJgImTNxmS4F7JHnRLr37VxK1sVvuNkynJnqvCcp1g5xwNIx1rKcka3i&lt;/span&gt;
&lt;span class="s"&gt;uqJj6toM8XQfgsTHH1rUkWHbUV3QwNzXm+yhFm2s6QzxBooPzmFn8AY7CXD4pvcM&lt;/span&gt;
&lt;span class="s"&gt;R+M0Zy+e42nngd8lzRnmTBVig4pRq0GCMulFG+XjeVQZFpoIIxo2k1lczbRmGttO&lt;/span&gt;
&lt;span class="s"&gt;NdGWSjxBUxReoTbSwM3C/50NrobycGQgY0gd6LGtWtU8/uEfklEy2NluxYWJARwE&lt;/span&gt;
&lt;span class="s"&gt;EAEIAAYFAlWtAUYACgkQVu5xjc4OFUs0OAf+LM0dyyvUFGdXfJDpP2xMknXzsHAX&lt;/span&gt;
&lt;span class="s"&gt;WFEtH5jein58mv6dD3fTVcCouo1vMQH3WFFSLYZvwtNnHGrSBqFbNKqZ0ATQ5tcY&lt;/span&gt;
&lt;span class="s"&gt;aWsSZ+MVJJMXJDXFG/Oihg1nNOM33VdfV0RGPKP1I4cEROxms3TUFkHW3cSCgMzs&lt;/span&gt;
&lt;span class="s"&gt;8I1OxfSoLrm6da8EN+2ct2InqzdQL2yisyTyrdmXoNpwXDxApKYkvVHQ4+9eJI5m&lt;/span&gt;
&lt;span class="s"&gt;0ZAr0mBjIeJdATcw4/lIVKTrV7UhrChxiffYJcz4SSC1crmr+2Fzw53CyAsAmYal&lt;/span&gt;
&lt;span class="s"&gt;UHep3Yr05oQ4oJRX9X3VrY/yELHwwxXaxCAdwwHbbXAMhZsPk9Mc20J6BokBHAQQ&lt;/span&gt;
&lt;span class="s"&gt;AQgABgUCVa0isQAKCRCj1lIXO3Y+j6ZeB/91Q9/qr5oMWgOMsix8kflBLw2f/t+t&lt;/span&gt;
&lt;span class="s"&gt;RR0SWDw90bG1npJB6nq5Hl+Bz4/A4SWFTFrrrlZi1Enjn1FYBiZuHaSQ/+loYF/2&lt;/span&gt;
&lt;span class="s"&gt;dbQDbBKShfIk3J0lxqfKPAfKopRsEuxckC8YW1thGxt5eQQ8zkJoqBFTBzwiXOj3&lt;/span&gt;
&lt;span class="s"&gt;/ncJkX9q9krgUlfTSVmrT9nx0hjyNQQXrghsmBtpR7WCS7G7vNRGCNUorhtviUvL&lt;/span&gt;
&lt;span class="s"&gt;+ze1F7TTSGspVsVxo2ghmz5WT/cD9MV1gcVjojYmksh5JIl39jCHr9hl8aRId/Of&lt;/span&gt;
&lt;span class="s"&gt;zsN+TKuBcpAxDkm9BCAps7oY8FlLKDFZTtHa000AkodKHT88nwnvKuqPiQEcBBAB&lt;/span&gt;
&lt;span class="s"&gt;CAAGBQJVrTkDAAoJEPbQ92HczOykK9YH/0MARo3HlYXeS2bDqM/lwK/rQcPCCyYk&lt;/span&gt;
&lt;span class="s"&gt;e6wbICjncbCOjgXHqG/lBhClNs7hp/7gqkUaR7H5tmeI4lalP40mSHHnnFvMD3Tc&lt;/span&gt;
&lt;span class="s"&gt;yhn350igK0bgrjWQDaYxhKlHT3vIXd/C24/vRSAxmqIKbP+IoXOyt2GMTQq8GOm2&lt;/span&gt;
&lt;span class="s"&gt;dgYRaTkwyHnGWnMaibctX8D4oCYR0/D4YJqPkfqobf8+1ZfP5GaMbSxE/Jwdo0kJ&lt;/span&gt;
&lt;span class="s"&gt;a4vPjEzFXbygAbncapzdwN6zgel2zh885rz7B7vIpMr/Y7eV85Q68qdyyhLe8cL8&lt;/span&gt;
&lt;span class="s"&gt;Y18YPzpFf+/PZNbgYxouafvnFwBhPQwg0gUF/+1eM3UE2ua+saSTGduJARwEEAEK&lt;/span&gt;
&lt;span class="s"&gt;AAYFAlWtCVsACgkQM0LhtmejiGMovwf8CfYJHNbwiwSMUoP4n7FrmElhBtxvlbnC&lt;/span&gt;
&lt;span class="s"&gt;MZKz08v+lFsfS3wU1LUN69GqirfF0vkQRSlSBp7niCLHQCfSoqHMLgxF0P2xgXLj&lt;/span&gt;
&lt;span class="s"&gt;aYM/t/rxXDawJmW18G04dqFrtCPZTbwMT2PsPHTiWQdaN0e50lXk9Vo+l6VbwQMg&lt;/span&gt;
&lt;span class="s"&gt;4zH7icZadeJgQooxFalHYFVXUVeex9t8/YdanFVrHFa3tao6azBTSUkJvZtIu14S&lt;/span&gt;
&lt;span class="s"&gt;fxigDWIIwsx0xpVfJf3a/xC6HY3Q1a3NeBz3i6DwaK5wYqijZKl0WVdULKyqU98o&lt;/span&gt;
&lt;span class="s"&gt;F6y0mUv3d2o/p07Cqgeo6xxMkHqu83OLa2a0C7tYPLgL4EFc2FtikYkCHAQQAQIA&lt;/span&gt;
&lt;span class="s"&gt;BgUCVaz7KAAKCRCWO3gxCjexfKxrD/4npm1rB7+pPlotbqK37Mur7egPbVSAzVNU&lt;/span&gt;
&lt;span class="s"&gt;/zUKPAuGUeP3C64YN77ETx1kDuS+meAqMDHFc9Bf8HivPbtj6QcK96U5KstbmSh1&lt;/span&gt;
&lt;span class="s"&gt;Ow9YiQtxJgxGjg/CzREgZAFcjy0MhoklyPsFhv07s6MLOJMSM/krEN5nqjifQ0Wd&lt;/span&gt;
&lt;span class="s"&gt;mTk02FLoHVWcLdjfgMiPiSjGbU3k7luvjPyRNzk831szE5mfa74rEYh4TBklse+2&lt;/span&gt;
&lt;span class="s"&gt;uB4DFQ/3oHZ1Sj6OBK6ujmNKQjIP7Cl+jmjr7+QK0OJcRaj/8AckDA5qXTZACh1S&lt;/span&gt;
&lt;span class="s"&gt;2syCDDMnX0V+dTxGCIoWOK+tt9mLohMzpEeD4NIX4qdpbbCRzeYZMHSomyBIsbA6&lt;/span&gt;
&lt;span class="s"&gt;B+/ftDE7W1N0/FtJ9adkkCynKULvh2CH5c5hgOOL22M+2spnywRoeJRUWU7hBM5O&lt;/span&gt;
&lt;span class="s"&gt;UH3JjA4Tu4j/cwp7dD7QzZrzmC9f5LQJ3OelejvVowWPQd3/tky4o1q6wlmFqAcA&lt;/span&gt;
&lt;span class="s"&gt;gtu97UwgBOSR9sJPGDlt1iC91UYAiBQQAA7ya8uXUS84mCQwTlr8j+YrowvEHK4I&lt;/span&gt;
&lt;span class="s"&gt;xpPREytT1LzzV/4Am4ndDFtujy83QjL0qaIIim1xIwoEosd4yidhpczw7f3b9dQp&lt;/span&gt;
&lt;span class="s"&gt;uBIFeQuhM7JsxP4tmE7S6k6GlEmqa3INPVaPGnsUGS7+xSMlcJXLtimPCSQvFma9&lt;/span&gt;
&lt;span class="s"&gt;YiGV5vtLy4kCHAQQAQIABgUCVaz8uAAKCRASy06X4H5n0dg0D/9QoxIh9LRt1jor&lt;/span&gt;
&lt;span class="s"&gt;7OHG4xKUjKiXxn/KeQNlJnxI55dlWIvJEJGheFjaDomzKBYuxmm2Ejx+eV5CHDLU&lt;/span&gt;
&lt;span class="s"&gt;YsLFYwWf8+JGOP75Ueglgr8A0/bdsL63KX6NP2DCg8XR4Z1aeei3WMY7p/qMWpqb&lt;/span&gt;
&lt;span class="s"&gt;QoAv9c3p49Ss2jSNuthWsRR6vbQ9iwze2oaUaA44WKQyhhbCwBU4SHYjlKCLqIBh&lt;/span&gt;
&lt;span class="s"&gt;/HXZFhZ4rDfuWgPBKvYU1nnOPF0jJRCco3Vgx3T9F+LZ3zo5UPt1Xapr3hMVS9ia&lt;/span&gt;
&lt;span class="s"&gt;Jyl1w4z2miApUaZuHPuWKuO4CJ1GF1mS5T6vG8gB3Ts5zdtBF2xQIkCz+SM7vW/2&lt;/span&gt;
&lt;span class="s"&gt;i/82oq6P8EuLHEhrQPR4oTjXIvXdEJ9kgbjqcj8Xk+8teEOnuwh6iEhay9i/bf0D&lt;/span&gt;
&lt;span class="s"&gt;3Jd+roFN5dnWPxhOVjzrI3fwlK1/ylsZYqUYBEzt7Wj0MdhjeKssI5YICcqYXXjB&lt;/span&gt;
&lt;span class="s"&gt;ttMw4B7DZXPFXzz3kHB56jZ/II4YUjpLO85Jo5A9SV+aIqa0mvCt6DvVWy/rhfxf&lt;/span&gt;
&lt;span class="s"&gt;oUdqNlhX11gkVLaA7xxgn/NqPOf+h5hVO2mwWkmart9YHKMZ3ukCdke65ITL/nsY&lt;/span&gt;
&lt;span class="s"&gt;Sm2ZhG7OYjaCfu9jPWtkBstOEWyT9q4JTdViR7wN3eMefEG6rb49rxOYvGJu+cTV&lt;/span&gt;
&lt;span class="s"&gt;kp3SCpl0w1j+tPj4tkj7ENzPMXdnuYkCHAQQAQIABgUCVa0s4gAKCRCKsTKWOgZT&lt;/span&gt;
&lt;span class="s"&gt;euMyEACKOySKAd/xDcPcHg7Prvdws04Z8DIR0dY2qUlbRVx2jTmIXyry63CqbOJF&lt;/span&gt;
&lt;span class="s"&gt;bDg9uk5x0+lSotvrWtZ+NKSrg9VM6vyV4cc2P9rhqIBi3wO2elzAmpOaS2KKOjQ+&lt;/span&gt;
&lt;span class="s"&gt;2fS/xqh91ElJUu09xXQXJ0vMrqgui+zN1YBDiJV0WOmm90Mm2NPiihcWZmBmDorO&lt;/span&gt;
&lt;span class="s"&gt;qMQabwbjBLi0yUVHgAlkilY3mAB4tmEKDeN+4pYSAAhXAll9U+nyoVMgwMJscZya&lt;/span&gt;
&lt;span class="s"&gt;zOp4MqMbmFjyr4p5AGzv+OOJtjtCNKT6oW9Y+URLY0YKeOsPk0v5PlbQCVBlLeSB&lt;/span&gt;
&lt;span class="s"&gt;sNZudKav/Gvo7Mvz5uLTcneBFb+haYIiXO/FQm4uBHkzdNFLgaph81Wzh62AhbtB&lt;/span&gt;
&lt;span class="s"&gt;lfBOj/lbzN3k/xRwo64QU+2Z9GOhFlhjfROquY70FCQcspwNuqCdZybnkdpF2Qrr&lt;/span&gt;
&lt;span class="s"&gt;6Pi0qKR/Xb9Vd7PW0/gKQdwwlYTiDemgA21mYeJrYw873/7U/+kLFRvmPAEX4IOI&lt;/span&gt;
&lt;span class="s"&gt;OEN6XVjxvu78REi6CmXxOoYnH4aRSXDRyi1nsGjB43AtfAMMNCUigDgFP4sUsZAG&lt;/span&gt;
&lt;span class="s"&gt;1RAoxBhOsO/g9S5wx8H3rKITCXDjQh2SYeBwHFcU03EMcyzEQhbZNighN+aRKGIi&lt;/span&gt;
&lt;span class="s"&gt;bteRxISiKU+kcWaHolemeo6wGF87QXEpJaQ2OwIoIxQYvDDmQokCHAQQAQgABgUC&lt;/span&gt;
&lt;span class="s"&gt;Vaz/8QAKCRA/8xuvEEv54t06D/9n1Nyn2QSUN1mXd7pomoaka+I2ogDbQpu9iuFq&lt;/span&gt;
&lt;span class="s"&gt;bkqfcH3UuG8yTKlPp9lYDBs0IEfG85Js6iVxJIultocrcDmOyDkyEsnYbdel/tn3&lt;/span&gt;
&lt;span class="s"&gt;X4yqD8eI6ImRoCE+gnQ3LoEIHuODfJoosM/jAHANs4fsla4/u5CZDXaaq7pYXGiT&lt;/span&gt;
&lt;span class="s"&gt;t7ndsfmLiCa7dAg7bVFfJagsnL/VjlfeWM9nW01rDL9LPxSN4tq7ZKXWZDonFZYJ&lt;/span&gt;
&lt;span class="s"&gt;4unsK/Cn6Pqco4Wb+FUOWCcWt8in1pgeNHZ9WnAgXG999/3iCbbQTLB6uVwY4Ax5&lt;/span&gt;
&lt;span class="s"&gt;P7VApnLVXV6QFVf7bN1DxE8kZk+pfLGcuD1LJSF0skE80M17kAt+iV+fam8EYzeG&lt;/span&gt;
&lt;span class="s"&gt;dG6cY6w+srndaMaq9ddiHIiQkR35SjJAGnrNRj8ooUr/vKOBnFfuwJLA2MOUVPZ8&lt;/span&gt;
&lt;span class="s"&gt;HWB+WXW8qhihw9CXa38Hdt4o5knMGRIyTWEF0TQDtRGQ6hisVBN3OxJRXBj7/QgC&lt;/span&gt;
&lt;span class="s"&gt;G/GoYpweGKcsMU43p57TzbnXVVUytJsLFyexOGNzrUIxgDVPEvTUnNvdAihNZPdb&lt;/span&gt;
&lt;span class="s"&gt;W3YdFkP9pdwOyDpQwebXELUx1kp4ql0laueex4L1v+0a6rDYQeK1gOq5UGY+THRS&lt;/span&gt;
&lt;span class="s"&gt;gB2xsHl5zeryfgnjlUkUlxKuumz+9FI2fRtSpxmWllJkRF2oFMGRuLPGAWe8nHvf&lt;/span&gt;
&lt;span class="s"&gt;gkuGVokCHAQQAQgABgUCVa0bowAKCRCVY0f2+/OkFWKREACZ9TOmzvY6mrfWVEdl&lt;/span&gt;
&lt;span class="s"&gt;dcYPj8cU/1LJhGdbNo5YYMx+A72nchxGXepHA65OEK+f6rFMeZFPwpQPy6Sj3MhT&lt;/span&gt;
&lt;span class="s"&gt;623H/PECfeG87WcLOyJbfc3i9T5jvxS+ztG6abYI2J/50oMvjUWdWkDX3VvdPc0Z&lt;/span&gt;
&lt;span class="s"&gt;Z+KC+oHvx9a/9Yki48m4CEKglgVsrRW/b9AXZQCj07bB0GjQQtkqY/m1Z8m4ttzx&lt;/span&gt;
&lt;span class="s"&gt;fO7OBo/jHNF2An4/4gUDirXNDj0UdB5FYFJaTEUCneIj2x0fk1r4u6na8tINhiZ0&lt;/span&gt;
&lt;span class="s"&gt;M7IgjnDlBD5jwzvwG+3kYE6TnYp9Mfeg2MPC13tp7jrJatLLutrOzvmSVLGLXbkh&lt;/span&gt;
&lt;span class="s"&gt;9w+v+vx7qO3TxZUNlFqTmYs+vI2V/9j7KYV7Ttoind6Io7X9ImnYrvd8JOyVcO38&lt;/span&gt;
&lt;span class="s"&gt;67MplKnrnqHJvFStE+JcHEcw5aRw+WVmoFd/obGc34V3K62T977QQGOkrTYDEdje&lt;/span&gt;
&lt;span class="s"&gt;KADfjXXZkZMZc0IvzLBOJ1XB45+PKqJYCcJJS8Xr55+NGCDaaUPWDpkNGIqmX2n9&lt;/span&gt;
&lt;span class="s"&gt;kYROMKG6uWkZIqG0JlZkga3THSJIvLiy6uoOvDC4GoQ9JnTwpGv6r1Hwcg+4DCOr&lt;/span&gt;
&lt;span class="s"&gt;YKOoPKMMU24vHx2FtRRUgCXtr2cmi2ymHlUrtz8EXS4tblic8lixcbvPUqLEvbJ2&lt;/span&gt;
&lt;span class="s"&gt;gfWQvjXNd1whYE/wfvI9WBTEIokCHAQQAQgABgUCVa0b3wAKCRC8FzAbSRs/IQhX&lt;/span&gt;
&lt;span class="s"&gt;EADiKbCnsN/+Plllxn6SQHACEU75ackx+Q02XiD/u+wUptYUGmJi4aaW9f6mgzed&lt;/span&gt;
&lt;span class="s"&gt;OxYK4S+/dCiFtkcYlL+FjaR0C7G6tMjrDgW+8nQCTPUNQA0gX2B8n06a7Zmdv3Eb&lt;/span&gt;
&lt;span class="s"&gt;V/PIJJwTNSBp/dqKbvPKnRquOOpH+ayZ3awKOq/LlWBErbW1gB+FabN0lCe0iUIQ&lt;/span&gt;
&lt;span class="s"&gt;TF9OH3GC4QsMtIrePueBmVrVPcHATV2Vw9UPqX1uX/tlXm5eai06oVT7V0FwUbg0&lt;/span&gt;
&lt;span class="s"&gt;o1eacblNXvHciHpe33zZIKkGBWwSjDVcU9/SN+U8GfoMYmyCma4iN3KaCklpzBkJ&lt;/span&gt;
&lt;span class="s"&gt;iQZtNKPAB5KJti8LDUxFi2sJd3sqWaZDGFhO+/PKhBKpqIhAzx1ppd11zLgh0eg6&lt;/span&gt;
&lt;span class="s"&gt;gQlXN8D8ELISRvQqGGNNZdChEFdzGElg5SMfmeEd37OaX4wceLLV0v7EA0doHMVo&lt;/span&gt;
&lt;span class="s"&gt;0enFhSwU3YwtwxbiukKc7H/ylG7+jvntjY+z7KktRsY/FkklrbrNhddMBQMMSAQU&lt;/span&gt;
&lt;span class="s"&gt;Uz1GJ+6NUKmzXjqxFuuh3OAhqNzhJyABZWQcNMph+rogEslkenwoHV9gWRWtS3CM&lt;/span&gt;
&lt;span class="s"&gt;ybJkKkbsWpYhMZNY6hFtgCwida7NPs8369v+yTTE6TU/NIlXUKYIf2LMqtOpEBTj&lt;/span&gt;
&lt;span class="s"&gt;aN3jKpUi5DeE3zBeh6iVKUrfCXbt8O0rYQPNWGSW+MZ2t4kCHAQQAQgABgUCVvA4&lt;/span&gt;
&lt;span class="s"&gt;GwAKCRBE9G4UbQI5XfS9D/9XPK7jg0lmsNZ2sDIyeAw5n6ohSR5F20ocTMAVeXqN&lt;/span&gt;
&lt;span class="s"&gt;7VkvJdNpIqHJa13EP408DgTy9BsSptym/OQGE6B82BU7FZTEL6eMHnGGDg+5ktx9&lt;/span&gt;
&lt;span class="s"&gt;+b73xLedzK75ti6ED+QuA4kDYcvW8hASht0zRcmFUzwbtuEopJ1Lk1R3oFLwCAov&lt;/span&gt;
&lt;span class="s"&gt;lhduC45nANWrTK5U+D1U2obl5PAvx+9mEfgvojlGH/C/WD74W+cQZFH7t4+muRza&lt;/span&gt;
&lt;span class="s"&gt;mckLyPftnTxjNF/lpYIm7z0QOwvzBYj+PJ09wYueK00RE5+i9Ff8DrjtVSXsziQv&lt;/span&gt;
&lt;span class="s"&gt;SjJuUlv0kVvM8r3th4zBBNRhA4cinwqxhgqO4G+r2r9Gv0M2nKKOnWmyF+MSIRnh&lt;/span&gt;
&lt;span class="s"&gt;gONOQZe5a7kQxKVWkLicS2IGUpPeQyTWaqZzYXsD+Dm6DXD57vYTURtUkwO0CDON&lt;/span&gt;
&lt;span class="s"&gt;zT5XiS1HG1MZrw+V/Jai4HAvpF5WkTJXPc1Lv75BxJj3wOAw4MzEWCCdr/N/dt5/&lt;/span&gt;
&lt;span class="s"&gt;+ULpEaSQfIg4L4iEj6rvabQyN0KbOxIDx+pPQ81izfj36wIrDqhyCNIdmVH/yARl&lt;/span&gt;
&lt;span class="s"&gt;tkL4XDEl/pt7Y3t6jqFhy057lektowClWcPeq3DoL0LFYnjNPpYvIjRIAXdhaYiA&lt;/span&gt;
&lt;span class="s"&gt;u2ViF8WdGzQ5tFeI7u3PQUG5NcPe+WOPOru3wMMrUhLgLHkCdNkjivP79qIPSTkC&lt;/span&gt;
&lt;span class="s"&gt;GYkCHAQQAQgABgUCVvA48gAKCRC3hu8lqKOJoLRMEACmlyePsyE5CH7JALOWPDjT&lt;/span&gt;
&lt;span class="s"&gt;f+ERbn+JUTKF+QS0XyWclA/BIK8qmGWfgH38T9nocFnkw17D3GP8msv8ll+T4TzW&lt;/span&gt;
&lt;span class="s"&gt;9Kz9+GCUJcHzdsWj99npyeqG5tw+VfJctIBjsnX3mf4N0idvNrkAG5olbpR5UdsY&lt;/span&gt;
&lt;span class="s"&gt;Yz62HstLqxibOg4zWhTyYvO6CjnszZrRJk0TYZON4cXN14WYq2OTrMaElx0My8o1&lt;/span&gt;
&lt;span class="s"&gt;qVBnK58pIRzv72PmvQqUk5ZjhUyp9gxjqqCJDz0hVK61ZuGP6iKK8KCLTfSxeat0&lt;/span&gt;
&lt;span class="s"&gt;5LAbz8aC58qlg5DVktevHOjBgnTa8B7BgJ7bQ9PLMa3lF4H1eSiR9+8ecpzEfGHI&lt;/span&gt;
&lt;span class="s"&gt;LoeIDIYH7z7J/S0mTgV3u5brOMYO+mE9CEfps85tVVoyJrIR8mGEdtE2YmdQpdFz&lt;/span&gt;
&lt;span class="s"&gt;YIYvRfq9tnXZjVsAAsC20Smw0LnjhYzAt9QJwZ9pFMXUTg6lC5xT+6LNrEY+JR3w&lt;/span&gt;
&lt;span class="s"&gt;C16q36bcbCNj0cBv1A3x6OI5OQfpexhLPDgoDiI+qozJIdj8MzJ8W6KU1Z3yb3dq&lt;/span&gt;
&lt;span class="s"&gt;ACk77yv37rGO6uduSHnSti26c/cUIy6XZBbXBdobE9O3tr8hwvTQ1FXBmYnBrdiz&lt;/span&gt;
&lt;span class="s"&gt;U6tgxEA5czRC9HOkdk6y6ocbjmONpF6MxkpJAvTMk7IqC2/hisbV9x4utla+7tmN&lt;/span&gt;
&lt;span class="s"&gt;ZU137QGcaK2AGQablVAy4YkCHAQQAQgABgUCVvCMigAKCRCkhaDtUbi3xAU7D/9g&lt;/span&gt;
&lt;span class="s"&gt;UPZSJ8pbZV9TLaKD57Bc7B78HNV/B438ib4dI33iihMTBHnCB1giPE9X54QoV8AS&lt;/span&gt;
&lt;span class="s"&gt;xrO/xveS1kkj78jERqUcED6ZHhMLb9SWs6CxUKdMdgovnIlFUc+t05D5mb6STi+z&lt;/span&gt;
&lt;span class="s"&gt;NihwO0JI+n79qhETy73WLpC7RR0aMx7zYcbqp3NWPptcf1kVGJZGx+QbEHfVye98&lt;/span&gt;
&lt;span class="s"&gt;T5pkH5Wp+7LSlup6AldQT/oifxdGxLXbECTnwozRvyMpAaphoEHrET1YOmKnmw/J&lt;/span&gt;
&lt;span class="s"&gt;yi6DLpTb3XvSf5Tntzr7HklCEcL9FvYCoHxiXWawLhuPhSyrFYeYtF1ypmzTgaJW&lt;/span&gt;
&lt;span class="s"&gt;yuTZ8sN9J+y7Tbchk/I6FpX+3YoTgPCcC7hv1Krs803N/3KuyBEvhzg7NYRikzO3&lt;/span&gt;
&lt;span class="s"&gt;fxXlBG0RMm+662E7KlERU24izbWhGiYwl34+MaxrIO4oDvF79LEN7y0+SjL4V0B9&lt;/span&gt;
&lt;span class="s"&gt;689d+HI1ZfS9O1xkOlW6y0QyagOzsTOUF12s2mWydFmipbYnIwsSsu6Nzk3yO4M+&lt;/span&gt;
&lt;span class="s"&gt;qYABJXJ3tIFQPTd7xqmPNlJ8mFtmzHDhb3Pv6sRNFLLujYM9cJpuNMbAHWdohz1b&lt;/span&gt;
&lt;span class="s"&gt;jBT9pZQ3zWpll5wotUvGmJd6hTAXdUgmZ7lh7Uq6axClMmiLe1WYntcNpb04PyyE&lt;/span&gt;
&lt;span class="s"&gt;m2+GU5x123UTiSX2LGKa4t+HNSM8nJL8BJiGk80xVIkCHAQQAQoABgUCVa0OAwAK&lt;/span&gt;
&lt;span class="s"&gt;CRDDvTXkbdRdpVR+D/4/37e8WqKOHNPteQu42sj0ZOfcqyVMA9TQ578F0s9MwoQu&lt;/span&gt;
&lt;span class="s"&gt;qfVhXGSWevOctuMv2qTBjBfFjkdPrKR5L4LNAgMsu1epHU0DPcRZUCbh1P7Gpolm&lt;/span&gt;
&lt;span class="s"&gt;Z8KgnjT5Wpl1AcuOCaP08VMrt/e/JndTHp6btn6HsLVtryNhlL7oaeYbDr6/ovHN&lt;/span&gt;
&lt;span class="s"&gt;GHVIVSZgGP9f4Y8FiDpyfKav71vYLBMxtzM7lc3eFT1S10XhSW6k+8S5XldYWkLD&lt;/span&gt;
&lt;span class="s"&gt;riRXDE85C+9QndpOoQaIICp3ye3JVnUxa1qhvsYj9uPt1M6hKiBSoXdplrB+hQc+&lt;/span&gt;
&lt;span class="s"&gt;nqLNN3jxpGdmGmwrjtjqMhocMIguEqgARJOek3XKOppEhu+IcnJgU4edARJNLsBa&lt;/span&gt;
&lt;span class="s"&gt;uiVBWY/6mZOFlZq6H48tVyziS2n/oIpi+aCc/fQeGs9zMTtFUohPfYtTcy9PecXM&lt;/span&gt;
&lt;span class="s"&gt;OYpSu4p4tQ07oucnxfBkRUgTdM5VwX7YwTcRwp9XhHACUEGBhrwMH8Iz+sK2jLF3&lt;/span&gt;
&lt;span class="s"&gt;FhJGkef1vFs0vqSf4I8DBFkYAKF848YyEcGHeINQloi3v0Kr2PpBxlRh+GPWwi++&lt;/span&gt;
&lt;span class="s"&gt;QPKXQFzlTiyVtMzoo/lpmAWUJwj0dbAbH/mohtvWtA1WPHC2JRZ52JLThhpDrK3t&lt;/span&gt;
&lt;span class="s"&gt;//Jdt2WHE91cMx7/2B0PK4O8/j7UVlsOJXpVPsGX5SFCeTB/iS4JtIwWN275zIkC&lt;/span&gt;
&lt;span class="s"&gt;MwQQAQgAHRYhBFnKni0qMx3iUaokJ18Dx2fCR6TVBQJZDvZCAAoJEF8Dx2fCR6TV&lt;/span&gt;
&lt;span class="s"&gt;oGkQAIjqaQ7tpdhDJ6ORNtLIt0TsWg0jg2rpoq+9Au36+UYBMuBJ3Py/tAsZ3cqQ&lt;/span&gt;
&lt;span class="s"&gt;lig7lJiQqOuQZkbg1vcY4Kdad7AGa8Kq3sLn8h2XUlNU90X0KAwdCTA/YXxODlfU&lt;/span&gt;
&lt;span class="s"&gt;CD2hl4vJEoH/FZtfUsaLNHLmz0brKGrWvChq00j5bPfp90KYKqamGb3a4/LG4DHL&lt;/span&gt;
&lt;span class="s"&gt;4lmEBtP++YA0YqUQ3laOvKune2YwSGe4nKRarZnFiIn2OnH9w0vKN/x9IMGEtc5M&lt;/span&gt;
&lt;span class="s"&gt;bQVgGtmT5km3DUuXMDforshue6c7ao4nMOC96ajkWYZhybqHJgLOrEGPVUkOaEe7&lt;/span&gt;
&lt;span class="s"&gt;s1kx4ye9Ph3w/LXEE8Y8VFiZorkA/8PTtx0M9hrCVkDp0w8YTzFJ9DFutrImuPT6&lt;/span&gt;
&lt;span class="s"&gt;+mNIk+0NQeuDsv492m/JXGLw/LRl97TmHpKME+vDd5NBLo4OShlDKHwPszYcpSJT&lt;/span&gt;
&lt;span class="s"&gt;G9+5++csR95al3tWnuGX9V0/dO1s7Mv0f/z07nLB/tL+hEpqqA5aRiGzdx/KOrPZ&lt;/span&gt;
&lt;span class="s"&gt;uhCTyfA3b2wvOblwf4A/E1yO7uzPTuSWnx1E14iZuaCPyZPXEh3XSYCLEnQ05jy5&lt;/span&gt;
&lt;span class="s"&gt;0uGXCDVR+xiE/5i/L3IxyhJk6zn5GOW5b8Taq5s/dFS3zWiFS6l0zQ1VQmJH8jdG&lt;/span&gt;
&lt;span class="s"&gt;LoBFvdVLZoAa1bihLo+nJVPR2RauWnxWoWk1NQoT3l02Lk6DiQI4BBMBAgAiBQJV&lt;/span&gt;
&lt;span class="s"&gt;qUAEAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRBht7Um2Y8DU1CqD/9G&lt;/span&gt;
&lt;span class="s"&gt;vr9Xu4uqsjDHRQWSfI0lqxElmFSRjF0awsPXzM7Q1rxV7dCxik4LeiOmpoVTOmqb&lt;/span&gt;
&lt;span class="s"&gt;oo2/x5d938q7uPdYav2Q+RuNk2CG/LpXku9rgmTE7oszEqQliqKoXajUZ91rw19w&lt;/span&gt;
&lt;span class="s"&gt;rTwYXLgLQvzM3CUAO+Z0yjjfza2Yc0ZtNN+3sF5VpGsT3Fb14aYZDaNg6yPFvkyx&lt;/span&gt;
&lt;span class="s"&gt;p0B1lS4rwgL3lkeVQNHeAf0qqF9tBankGj3bgqK/5/YlTM2usb3x46bVBvwX2t4/&lt;/span&gt;
&lt;span class="s"&gt;NnYM5hEnI57inwamX6SiMJc2e2QmBzAnVrXJETrDL1HOl4GUJ6hC4tL3Yw2d7515&lt;/span&gt;
&lt;span class="s"&gt;BlSyRNkWhhdRp1/q9t1+ovSe48Ip2X2WF5/VA3ATfQhHKa3p+EkIV98VCMZ14x9K&lt;/span&gt;
&lt;span class="s"&gt;IIeBwjyJyFBuvOEEIYZHdsAdqf1zYRtD6m6obcBrRiNfoNsYmNY4joDrVupI96ks&lt;/span&gt;
&lt;span class="s"&gt;IxVpepXaZkQhplZ1mQ4eOdGtToIl1cb/4PibVgFnBgzrR4mQ27h4wzAwWdGweJZ/&lt;/span&gt;
&lt;span class="s"&gt;tuGoqm3C6TwfIganajiPyKqsVFUkRsr9y12EDcfUCUq6D182t/AJ+qE0JIGO73tX&lt;/span&gt;
&lt;span class="s"&gt;TdTbqPTgkyf2etnZQQZum3L7w41NvfxZfn+gLrUGDBXwqLjovDJvt8iZTPPyMTze&lt;/span&gt;
&lt;span class="s"&gt;mOHuzf40Iq+9sf5V9PXZ/5X9+ymE3cTAbAk9MLd9fbkCDQRVqUD0ARAAr/Prvt+m&lt;/span&gt;
&lt;span class="s"&gt;hVSPjNDPSDrTBVZ/7XLaUZvyIVggKa+snJoStrlJGTKKFgDVaYTOE3hP/+0fDdQh&lt;/span&gt;
&lt;span class="s"&gt;97rjr4aRjd4hBbaNj0MzZdoSWYw3yT+/nidufmgPus0TIJMVO8I6rl3vgcfW/D3o&lt;/span&gt;
&lt;span class="s"&gt;vNrLW/LjkTuM9a+p+D1J7woCfMSWiFMmOLPKFT7RBuY8edCVjyA6RP9K9Gj1sURS&lt;/span&gt;
&lt;span class="s"&gt;eqNaHR9Gr4rW10s+FwUHWxxzbmIWqH0gApQYO6vyND5IMcKOBCWQU6Detuq1pQ6d&lt;/span&gt;
&lt;span class="s"&gt;Uc+iF+sEz3Rk3C6d4WBBjtkVJSJ0KKan8Q3gJefOCMNhdRQDjZLwbzr4bgoAkLba&lt;/span&gt;
&lt;span class="s"&gt;BFCjiZxWZ6HAdMfSCV8uZQrtMS7b0DUpY0vdH9Htl3JqOOkK9RorYDQBuPdkTYFI&lt;/span&gt;
&lt;span class="s"&gt;NsmtWVsFV/LmR891mOF3fBRaoVoMeJVwiZyNlFY+dyWWFzLp+GoTLcQtmuR7OkmO&lt;/span&gt;
&lt;span class="s"&gt;cBGxWSKPcZfPqhf4dVQud7bDR2RNfJ1Hqa5kj8Z422sseYDwHf/T9OWWYvLwKGZh&lt;/span&gt;
&lt;span class="s"&gt;lUgpnzO3WCGrd/6EVNeC1mKXt4F7BmADov4Rdcrp1mPXiVt7oIxLaS6eBNf2y1TW&lt;/span&gt;
&lt;span class="s"&gt;zjYj5ZFuKqIukDEJfqpwsE5asnCw56nae+7luGs8em1J9GEXhWzXG15UVyQJaFwu&lt;/span&gt;
&lt;span class="s"&gt;B1iL8l7VcEQz4ABVrSTUWLLAKDsyqUbq2gsAEQEAAYkERAQYAQIADwUCValA9AIb&lt;/span&gt;
&lt;span class="s"&gt;AgUJA8JnAAIpCRBht7Um2Y8DU8FdIAQZAQIABgUCValA9AAKCRAcacTlXpkF2y/F&lt;/span&gt;
&lt;span class="s"&gt;D/oDrZm143Rv9NV9InnVJ0brpqbB7aulFfhR1LDuJ/GjeqGAQgJCZdHlzT2pfCXX&lt;/span&gt;
&lt;span class="s"&gt;swUlYzcWEatvGcDkoaB5Ya2qs+6nhBk8pT6XYRrZAtIlKIGrlCqoSBm9HXguGv+E&lt;/span&gt;
&lt;span class="s"&gt;IaEECr2z/Funx9so0mP+5aJn65M9u3lPmuAonj6DcHoM07WsfsXvQ4ut3fabFmzi&lt;/span&gt;
&lt;span class="s"&gt;lLGeAdEDKIw8Hn3JBUOxUyFrQlOoL4/3qK1TO+cidz/2bATQQyIG2kNOSgHBslU+&lt;/span&gt;
&lt;span class="s"&gt;e6/7sWOQ4ufmzm7dEsf197zPXGdXR88LT+d2uU2K4GkCffNUKxZqy9bXxXPwr4JB&lt;/span&gt;
&lt;span class="s"&gt;jxLDQnDvl50GAWjPZAwXEd8Okwl5+8xp0HuZ217WUqT8ib0oUUfwh2H1vrMPRr/4&lt;/span&gt;
&lt;span class="s"&gt;6i6O6THpCkV8BWF7axPYIibaeYwC4BkjZwK3tIL5ESf2f0xK4hbE3xhMTeqABQHo&lt;/span&gt;
&lt;span class="s"&gt;Xd5rQ7SEaUuX7PlQ59fRs0Cz55vH8/o9zMm0PN6qmZFvRBeqjnklZcu+ZdP9+CMX&lt;/span&gt;
&lt;span class="s"&gt;t81NMuzIK1X7EfpkUoam8YkYkwcCkRvPZrSHLXZFkfnx4jW543dPOfycjnv6hhKy&lt;/span&gt;
&lt;span class="s"&gt;oXD9CBx0ZcOicsYmw9XMilBGD3b8ZdK6RYX4ywKNU6KUdFJjXB88+Ynv6QxDit1e&lt;/span&gt;
&lt;span class="s"&gt;mMCHA1glzV9/k36iYLEIqgWBiwJeUUIcUqzgnBFtN13cyS6oEACUGUiPKbw3IkgG&lt;/span&gt;
&lt;span class="s"&gt;W19ZyS6FBNfgGIGW0Y82Br0KlCyaXnX0R4+4u2h7kfR9NSnhRhsvRnPIkiZATa7D&lt;/span&gt;
&lt;span class="s"&gt;+Ew1nfpsDTnti0c6g/gVw9TC/rCyXkkLztRHVcWEBdvnFJTSp2LeFaHSGbvvZfoI&lt;/span&gt;
&lt;span class="s"&gt;GUzyUzoa1P98NmRIY1cxBoizVf8729/zAaD4fAslxoK/JsjjDvDUrRHtaNZmUle6&lt;/span&gt;
&lt;span class="s"&gt;0Jl/yFFzR3zxb+pJliigoP2rZLt+ipomHJIhoXXWwfkRO9U/egJ8ZUhWEpZvROna&lt;/span&gt;
&lt;span class="s"&gt;Nc9eVct5EBADxL7gHWjlceIz4ndI1eE9AdEZDdUZwOfjmK2DcXjFBfZC+jhJXjY0&lt;/span&gt;
&lt;span class="s"&gt;xh3pPKQz90h9DIkM5WDcJPf6ep+MKSd/3hI2/JmmscQ+alwN6x6g8zDySMo3APA9&lt;/span&gt;
&lt;span class="s"&gt;cUvEFGe0+CepVcNw03jU4faSrHiMXsUuVGbA2kHaYVUfzF5W5GbuHZZlGxoSiq+K&lt;/span&gt;
&lt;span class="s"&gt;+HNG0RJUDa6bkSDvrcJVNw1iUrowP+LLwnNsy5kGuU4evnwcoN1w7LVbTPaq4RIa&lt;/span&gt;
&lt;span class="s"&gt;iqvAD33kiA9q//UNKnK4k81z+hRNaWGliyGpgqh+V7MDIqPfT5TMLdH+ZjTeuLrN&lt;/span&gt;
&lt;span class="s"&gt;S8KBcc2BmUpSwzdUReTqHmgO5peeIcsvO7GNMFWsgucZiAdIVE/zQv+SfP6jhS+r&lt;/span&gt;
&lt;span class="s"&gt;jCPs0eeu5zl8/V+gXFE2wy3jTJEl9bkCDQRZS9m1ARAAvh1Nh4GgjpTFZy7uQRFz&lt;/span&gt;
&lt;span class="s"&gt;5PPXdZTBI+Y4hTpF2heoFzZDI6SLyz64Ooglum3ZglQ9ac+ChTSsO36aw4b22kCM&lt;/span&gt;
&lt;span class="s"&gt;9WDmkcl7wf21fG9o8gJDVjFjDWbwTWREaKjgS6s/Yb8f9gje/BGySojxynTi3zyT&lt;/span&gt;
&lt;span class="s"&gt;UN94q9dhVjfiQ79UzXZdN9FyyIx2YO5tOo09hTWSZg16oxP47Mj1ATaS6UIrQMcM&lt;/span&gt;
&lt;span class="s"&gt;nOp0kuc6SufXPSWsUA+g2lW0dmHgPvIHwUfcjWqT2elF01e9KOFe7im29G6zOS2M&lt;/span&gt;
&lt;span class="s"&gt;Rx8cr6KRg/eNWpHh5aI4quRUhYk4Kw4ohQTbs9ed0YttS4PMK+sq6xHpb28X6Zgr&lt;/span&gt;
&lt;span class="s"&gt;WnelPY9hfwcR4m7Ot3VQUG8JY9/aTlFCoeTgkhop+MCUI+dJeY8depIa0PTzdEmE&lt;/span&gt;
&lt;span class="s"&gt;WRvPhTTv+CUdZ6v4z5LD6FhP+/5c6FCbcIb89Rp5fa53oYV5/KZf+0DUVgmpXFU7&lt;/span&gt;
&lt;span class="s"&gt;J7ZrGgDeU7vIzmwr8kcx0vtsVm1dVwYLACpTaaQPbISQUDM8sEcqKAqD7hWKaxNs&lt;/span&gt;
&lt;span class="s"&gt;b2M85L6q2/rnHq4g46yJzdR3b8EH+V9u+mUi9DIljDwcpvw7ReRQ9wPdDWLynngl&lt;/span&gt;
&lt;span class="s"&gt;IeGImbjYfr324yaIl4vNORAkbsoCkS/qc5v6MvKvYNle5fzb9S9kCbNZmD9c5/bH&lt;/span&gt;
&lt;span class="s"&gt;Pjj9ENeQvzrl2pFh6dc1o5cAEQEAAYkEcgQYAQgAJhYhBBTyZoLQkWzdgeN7bWG3&lt;/span&gt;
&lt;span class="s"&gt;tSbZjwNTBQJZS9m1AhsCBQkDwmcAAkAJEGG3tSbZjwNTwXQgBBkBCAAdFiEE3OrF&lt;/span&gt;
&lt;span class="s"&gt;2WE1uRxOpnKru769uyTG81UFAllL2bUACgkQu769uyTG81UFUw//bW5T7w2k8ukG&lt;/span&gt;
&lt;span class="s"&gt;fpIcm0gB98VgxKenSCmU6N+Ii0DwcNtzW+pmVWl2TbHIXDpvuD69ODWBDMXu6gBk&lt;/span&gt;
&lt;span class="s"&gt;rVzNEsK3uhzGe0tWA+5I7Vke3iEkbll7VRQlIOrw+n5NMvjeuDqKsMt1gMEEdgRK&lt;/span&gt;
&lt;span class="s"&gt;ddYApEAi49vV7XnqkB2lLKfAnf6o/KqPm8MuQ+u0xYanupZCldwdpcx5rybj79Es&lt;/span&gt;
&lt;span class="s"&gt;0iO9Gh/+3qOtR6ubOz3Vn78Lc3y6AP9pmtdOI2QX8foGK4hNmgHSP6uPLh/ERC9N&lt;/span&gt;
&lt;span class="s"&gt;ir0Lc2hoEhHEkQ8CnEaccp70r03VkEQuMJQJPUyRsGZ/gIm0SAm9JJxWHXJk2/5N&lt;/span&gt;
&lt;span class="s"&gt;UN83pHAX0LA4zxtWs4fVW5f8v9eIhFFPTZ4au+/cS9D4GFx4mlY34awcpAzrny2t&lt;/span&gt;
&lt;span class="s"&gt;ntGEejY9HSJv4PuFZCmtyS2q61N9EU8yuBwVM9cp5HntzG+OT4HYugtI6ibehM0S&lt;/span&gt;
&lt;span class="s"&gt;1Roy4ETwT+Ns41ffhCwdYMp8tzdeksQ35s7rkB9OJHj+q2dkGaV0FQb3FutbSpxb&lt;/span&gt;
&lt;span class="s"&gt;P4zk/dLqyxuivdUPHGtf4W/qklxzCWBg0VDFA7PwatmEXRxTjx77RelTY0V7K54d&lt;/span&gt;
&lt;span class="s"&gt;DyVv3Jh2+FzuaQZzzuIhv4gtqHntaqLnYl3h/QNLbOTE3ppvn9RUSR983Bd+M3Qh&lt;/span&gt;
&lt;span class="s"&gt;bbwZrgG1m+hdUZUmji+wbK0wV0xHNEH+4BAAjbVzdNOs7hMvjY1wVDRFjvICVorN&lt;/span&gt;
&lt;span class="s"&gt;dNdU3ELy/9BAoiwOs2+zjDXmsX+3YtdzwKvdpQ24O0TvH4Vo3BkvKkJ75EU7LroA&lt;/span&gt;
&lt;span class="s"&gt;bYQ2423m1MY3eaBslmX7TUJ3XE+k7OZF8AmcftgP4nhC4IQSCtoBc9+ncyGN4da1&lt;/span&gt;
&lt;span class="s"&gt;BpYO7b19tO0/HST8GHSrEcU9bGGdimS2eNkSgybA8wF6K0K9yvrpTNSZ7OBVlzQf&lt;/span&gt;
&lt;span class="s"&gt;En8s70Gyzs/d6C/rTA+defnv3AMaciuINSEdFyfYq4wjt5PikvgceMAAkH/z69xT&lt;/span&gt;
&lt;span class="s"&gt;Ng+6q3FQt/lyK7xX5qPMe2oFyDA1H+Cb/uL7ioo+jXh9gF+0fk8OP2IPzxYhBful&lt;/span&gt;
&lt;span class="s"&gt;pVtgclmOuaekzaKeIv8NFW7GoA9OghziExePxg95OpL/VyQ7PJiAUj1pFovFk5HS&lt;/span&gt;
&lt;span class="s"&gt;6ejVZNEGJ/A5zLc1PBIcr/phu0luqhXAhImsZS6858GWQllWULNWw8bX5Blo8Avc&lt;/span&gt;
&lt;span class="s"&gt;fFVdq9iAK7aHN7g45ZR7Ze6qKHDyFv4XWuE/rj9C2mM/GAstvU0gGmbo6B1mNGMJ&lt;/span&gt;
&lt;span class="s"&gt;uX3Gd3dG8fqFjE77OB2feJyfZ8UeF1nvG1hxlmuD1A5e6/osO9V7kjhXKzM2zSO1&lt;/span&gt;
&lt;span class="s"&gt;1zHQ/5PlUisoUBjJ/QIK4v9RBNGtbRKso5X9Fke692lVgrdggDJ3j2QqMuTo71rA&lt;/span&gt;
&lt;span class="s"&gt;VDLtxerc+GNq0GK5Ag0EXPA56gEQAK3x5otbuNfefm1BD4gJ4Y4EhVvMCdeUf1uN&lt;/span&gt;
&lt;span class="s"&gt;1OqiWUz6KLCR2UE00QaS7v65D11Oh96bpxtJRe6HmQk0vLm1QgbigZku+kCMt0c/&lt;/span&gt;
&lt;span class="s"&gt;zOyWBOCVDKahZJu/ayzimrzGgNunoTnV2SjCTIVK4QtkowUeA+Ilt9hfFCZvASIW&lt;/span&gt;
&lt;span class="s"&gt;Eazj7bWXC0ji1U73OzVdvMkP1e2ibGRxhp494HGkj0metYhQq3vQk9mL9BzE8wba&lt;/span&gt;
&lt;span class="s"&gt;yL9iK2cJVqZxXDxauL5bswAlbdLI2MlSrH9wg6Jvy91lXG91ZEhmZ2RaQU7q+/gi&lt;/span&gt;
&lt;span class="s"&gt;i0QEJ+W3pwPQQjLciOfecMN/n2/vCl1ZeJ2PNWMoXQXyNSJfpL9m4TPiW92i2kKA&lt;/span&gt;
&lt;span class="s"&gt;kaEOZ2LilUJhuZKEpt9+BxIn8FafjAI4co8D5cHvnPM+PXt1xZHwP0Yz+yC6wnLZ&lt;/span&gt;
&lt;span class="s"&gt;9scNw50AM/Kcpbc6TUIQ0kPHsNMPCbZ89Ey63i61IvUUxKXvMENFptw+vWfD7MRG&lt;/span&gt;
&lt;span class="s"&gt;OZKObdH3VrKtD1QqU//g/xeSGNzcUVatFDVDv9KWRSatOpKi5Bw6iUYxrYQ02Co1&lt;/span&gt;
&lt;span class="s"&gt;45jugTnGc+zrhMsDND3Prq7R0dMw4MBLUDoLSXrous9VgahAsOQztZCfvPOcV2cp&lt;/span&gt;
&lt;span class="s"&gt;Haew85SLSYx3Ksb/raIBG02+4XjF2xQCgIq2LfA6xdG5SGJd6Lg3ip2vwhogQgWB&lt;/span&gt;
&lt;span class="s"&gt;gQoq1qrPABEBAAGJBHIEGAEKACYWIQQU8maC0JFs3YHje21ht7Um2Y8DUwUCXPA5&lt;/span&gt;
&lt;span class="s"&gt;6gIbAgUJA8JnAAJACRBht7Um2Y8DU8F0IAQZAQoAHRYhBAl7MTB3rmKgL4TaTfGm&lt;/span&gt;
&lt;span class="s"&gt;Zo+7fVcuBQJc8DnqAAoJEPGmZo+7fVcuilAQAIq/yZi3hoxzSgDblQlcxGKDaVck&lt;/span&gt;
&lt;span class="s"&gt;Oo5kFRK8UWby3peB0bTMV3MWjiCqmN7ryQ3K3126G84yxXCTNSv7kOLsVxy+DBx5&lt;/span&gt;
&lt;span class="s"&gt;TdfmeBamdX8ZxeDv2bm+KKlZR0FGjJn3SiLgPkrp+GWazOZbKIPsoOuN20h0aeMC&lt;/span&gt;
&lt;span class="s"&gt;6mvO2Rz8kGUjCWa7/jQnINHkN/GnbnoOXOwn8cfwtt2Mkb8XRe+1lTBwd59ruYNe&lt;/span&gt;
&lt;span class="s"&gt;0hazOwygmcSgvM6Rm8nXeuElxMdVAiYKXJLej34+ToNN/LgB3TD72cXStmn7z8Zd&lt;/span&gt;
&lt;span class="s"&gt;kaKV+f81cyPR6Vi7laLIIGpquBGSsel5s0pb2PFFxrTZoNLZit/x2Wx47V30Vdk8&lt;/span&gt;
&lt;span class="s"&gt;4FYjENEb75OpGEErwVRbTQOKREOutXlGwiJe2C1Gof6HCScTfeLybz8ooLn+lSXc&lt;/span&gt;
&lt;span class="s"&gt;B/l/68wqxPezWYxfbMD42YtTEkJcvPvRaouhKEjxASP5EuT3K6T3tujsqg1K/rE3&lt;/span&gt;
&lt;span class="s"&gt;Bei0krOnTxUCdU1f9B12ZXpntKehwSz5LpnQvr2wR98yBRoKQfT2Yi3XK7QNp46X&lt;/span&gt;
&lt;span class="s"&gt;t8zaIPdVw7qMn3gODyiWSEGCtkRF7exdHZ9yIW2yofFhz3M/tjIvu89tRDwGiDER&lt;/span&gt;
&lt;span class="s"&gt;8hBk8Z2mcbmlMzQ1Jf+aCQ5YjZUkUN7+s4VN1OT7yYpWcV1pR8cDjyoh5LRXTMwt&lt;/span&gt;
&lt;span class="s"&gt;3g5mStiVbeIq9mmzogAQAJq6KK9Z28q8mAozKLd++JxefiovydXVfqWY4GoOfhtv&lt;/span&gt;
&lt;span class="s"&gt;Q3Sa2mKpd+8b3nT7b2twIlKPqpIxWPxke7BWS2sShZfqWkltbAR1SH7fkOeN8Y5g&lt;/span&gt;
&lt;span class="s"&gt;3yBbxvHQJ/KoTHnRb74MrlaP4v4MvuOAn+Xt0wrEt2OKOSD6/jIjnXqfNFuvHfHv&lt;/span&gt;
&lt;span class="s"&gt;tTyf4fVX1sesN9JwRKevc+1ZLjN7jIOuv1en5grwDtGQhy0fZOjISLGKfy6299rn&lt;/span&gt;
&lt;span class="s"&gt;p0alRqLuAhFn7Ru1ZjQVfqD9VEfDCEsjNOxoW95Aa7MVtdoaQ6FEBKK0q1tCjZ8P&lt;/span&gt;
&lt;span class="s"&gt;f2oAyLGQo5y030D+cDd1lTwGUmPvbnz4/fqNAM6KWvZjtGVNJNlLlpd4A9vAgvAo&lt;/span&gt;
&lt;span class="s"&gt;I1wONXSR56sZKqJXbOSIfS8AlzFWiSf6IyPpU5ozVHLGySAVqtrRW3ci4COeKsRL&lt;/span&gt;
&lt;span class="s"&gt;85W4iSGCl5uYZcE9weotakUO0R0u/pi07BJwTR5hvn9IDdeyYreqDMQDMF9yHCXg&lt;/span&gt;
&lt;span class="s"&gt;+oCGJAB/+1vHkSABRsWbCERyB33ExjnDr7z/kWOhfAdiZ1+MpP2IPtDEXcufKayS&lt;/span&gt;
&lt;span class="s"&gt;gpBAZYEeLAmNoDwtg+milSD3B7TTM11IY1e/Utq70Az/8BOK6wfyIsmPfeh9CHoW&lt;/span&gt;
&lt;span class="s"&gt;+JAbpbdOUs+rH+gjHE2Pls8BDLp1EoHVPGVavhfSlRbG6oF45s+gdL2PTKzEo+u7&lt;/span&gt;
&lt;span class="s"&gt;=xFcH&lt;/span&gt;
&lt;span class="gh"&gt;-----END PGP PUBLIC KEY BLOCK-----&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</description><category>mozilla</category><category>releng</category><guid>https://atlee.ca/posts/updated-firefox-gpg-key-2019/</guid><pubDate>Thu, 13 Jun 2019 16:50:48 GMT</pubDate></item><item><title>Smaller Firefox Updates</title><link>https://atlee.ca/posts/smaller-firefox-updates/</link><dc:creator>chris</dc:creator><description>&lt;p&gt;Back in &lt;a href="https://atlee.ca/posts/firefox-update-sizes/"&gt;2014&lt;/a&gt; I blogged about several ideas about
how to make Firefox updates smaller.&lt;/p&gt;
&lt;p&gt;Since then, we have been able to implement some of these ideas, and we also
landed a few unexpected changes!&lt;/p&gt;
&lt;h2 id="tldr"&gt;&lt;strong&gt;tl;dr&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;It's hard to measure exactly what the impact of all these changes are over
time. As Firefox continues to evolve, new code and dependencies are added,
old code removed, while at the same time the build system and
installer/updater continue to see improvements. Nevertheless I was
interested in comparing what the impact of all these changes would be.&lt;/p&gt;
&lt;p&gt;To attempt a comparison, I've taken the latest release of Firefox as of
March 6, 2019, which is Firefox 65.0.2. Since most of our users are on
Windows, I've downloaded the win64 installer.&lt;/p&gt;
&lt;p&gt;Next, I tried to reverse some of the changes made below. I re-compressed
omni.ja, used bz2 compression for the MAR files, re-added the deleted
images and startup cache, and used the old version of mbsdiff to generate
the partial updates.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Format&lt;/th&gt;
&lt;th style="text-align: right;"&gt;Current Size&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th style="text-align: right;"&gt;"Old" Size&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th style="text-align: right;"&gt;Improvement (%)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Installer&lt;/td&gt;
&lt;td style="text-align: right;"&gt;45,693,888&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td style="text-align: right;"&gt;56,725,712&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td style="text-align: right;"&gt;19%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Complete Update&lt;/td&gt;
&lt;td style="text-align: right;"&gt;49,410,488&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td style="text-align: right;"&gt;70,366,869&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td style="text-align: right;"&gt;30%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Partial Update (from 64.0.2)&lt;/td&gt;
&lt;td style="text-align: right;"&gt;14,935,692&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td style="text-align: right;"&gt;28,080,719&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td style="text-align: right;"&gt;47%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="small-updates-ftw"&gt;&lt;strong&gt;Small updates FTW!&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Ideally most of our users are getting partial updates from version to
version, and a nearly 50% reduction in partial update size is quite
significant! Smaller updates mean users can update more quickly and
reliably!&lt;/p&gt;
&lt;p&gt;One of the largest contributors to our partial update sizes right now are
the binary diff size for compiled code. For example, the patch for xul.dll
alone is 13.8MB of the 14.9MB partial update right now. Diffing algorithms
like &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=504624"&gt;courgette&lt;/a&gt; could
help here, as could investigations into making our PGO
process more deterministic.&lt;/p&gt;
&lt;p&gt;Here are some of the things we've done to reduce update sizes in Firefox.&lt;/p&gt;
&lt;h4 id="shipping-uncompressed-omnija-files"&gt;&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1362377"&gt;Shipping uncompressed omni.ja files&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;This one is a bit counter-intuitive. omni.ja files are basically just zip
files, and originally were shipped as regular compressed zips. The zip
format compressed each file in the archive independently, in contrast to
something like .tar.bz2 where the entire archive is compressed at once.
Having the individual files in the archive compressed makes both types of
updates inefficient: complete updates are larger because compressing (in the MAR file)
already compressed data (in the ZIP file) doesn't yield good results, and partial updates are
larger because calculating a binary diff between two compressed blobs also
doesn't yield good results. Also, our Windows installers have been using
LZMA compression for a long time, and after switching to LZMA for update
compression, we can achieve much greater compression ratios with LZMA of
the raw data versus LZMA of zip (deflate) compressed data.&lt;/p&gt;
&lt;p&gt;The expected impact of this change was ~10% smaller complete updates, ~40%
smaller partial updates, and ~15% smaller installers for Windows 64 en-US
builds.&lt;/p&gt;
&lt;h4 id="using-lzma-compression-for-updates"&gt;&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=641212"&gt;Using LZMA compression for updates&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Pretty straightforward idea: LZMA does a better job of compression than
bz2. We also looked at brotli and zstd for compression, but LZMA performs
the best so far for updates, and we're willing to spend quite a bit of CPU
time to compress updates for the benefit of faster downloads.&lt;/p&gt;
&lt;p&gt;LZMA compressed updates were first shipped for Firefox 56.&lt;/p&gt;
&lt;p&gt;The expected impact of this change was 20% reduction for Windows 64 en-US
updates.&lt;/p&gt;
&lt;h4 id="disable-startup-cache-generation"&gt;&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1351071"&gt;Disable startup cache generation&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;This came out of some investigation about why partial updates were so
large. I remember digging into this in the Toronto office with Jeff
Muizelaar, and we noticed that one of the largest contributors to partial
update sizes were the startup cache files. The buildid was encoded into the
header of startup cache files, which effectively changes the entire
compressed file. It was unclear whether shipping these provided any
benefit, and so we experimented with turning them off. Telemetry didn't
show any impact to startup times, and so we stopped shipping the startup
cache as of Firefox 55.&lt;/p&gt;
&lt;p&gt;The expected impact of this change was about 25% for a Windows 64 en-US partial update.&lt;/p&gt;
&lt;h4 id="optimized-bsdiff"&gt;&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1434513"&gt;Optimized bsdiff&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Adam Gashlin was working on a new binary diffing tool called bsopt, meant
to generate patch files compatible with bspatch. As part of this work, he
discovered that a few changes to the current mbsdiff implementation could
substantially reduce partial update sizes. This first landed in Firefox 61.&lt;/p&gt;
&lt;p&gt;The expected impact of this change was around 4.5% for partial updates for
Window 64 builds.&lt;/p&gt;
&lt;h4 id="removed-unused-theme-images"&gt;&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1363853"&gt;Removed unused theme images&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;We removed nearly 1MB of unused images from Firefox 55. This shrinks all
complete updates and full installers by about 1MB.&lt;/p&gt;
&lt;h4 id="optimize-png-images"&gt;&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1234008"&gt;Optimize png images&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;By using a tool called &lt;code&gt;zopflipng&lt;/code&gt;, we were able to losslessly recompress PNG
files in-tree, and reduce the total size of these files by 2.4MB, or about 25%.&lt;/p&gt;
&lt;h4 id="reduce-duplicate-files-we-ship"&gt;&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1303184"&gt;Reduce duplicate files we ship&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;We removed a few hundred kilobytes of duplicate files from Firefox 52, and put
in place a check to prevent further duplicates from being shipped. It's hard to
measure the long term impact of this, but I'd like to think that we've kept
bloat to a minimum!&lt;/p&gt;</description><category>mozilla</category><category>releng</category><guid>https://atlee.ca/posts/smaller-firefox-updates/</guid><pubDate>Mon, 11 Mar 2019 22:03:00 GMT</pubDate></item><item><title>PyCon Canada 2018</title><link>https://atlee.ca/posts/pycon-canada-2018/</link><dc:creator>chris</dc:creator><description>&lt;p&gt;I've very happy to have had the opportunity to attend and speak at &lt;a href="https://2018.pycon.ca/"&gt;PyCon
Canada&lt;/a&gt; here in Toronto last week.&lt;/p&gt;
&lt;p&gt;PyCon has always been a very well organized conference. There are a wide
range of talks available, even on topics not directly related to Python.
I've attended previous PyCon events in the past, but never the Canadian
one!&lt;/p&gt;
&lt;p&gt;My talk was titled &lt;a href="https://2018.pycon.ca/talks/talk-PC-55508/"&gt;How Mozilla uses Python to Build and Ship
Firefox.&lt;/a&gt; The
slides are available &lt;a href="https://mzl.la/2yUhiqH"&gt;here&lt;/a&gt; if you're interested. I
believe the sessions were recorded, but they're not yet available online. I
was happy with the attendance at the session, and the questions during and
after the talk.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://twitter.com/alexsnurnikov/status/1061302031246376961"&gt;&lt;img src="https://atlee.ca/posts/biggraph.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As part of the talk, I mentioned how Release Engineering is
a very distributed team. Afterwards, many people had followup questions
about how to work effectively with remote teams, which gave me a great
opportunity to recommend John O'Duinn's new book, &lt;a href="https://www.amazon.com/Distributed-Teams-Practice-Together-Physically/dp/1732254907/"&gt;Distributed
Teams&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Some other highlights from the conference:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://2018.pycon.ca/talks/talk-PC-55249/"&gt;CircuitPython: Python on
  hardware&lt;/a&gt;
  I really enjoyed learning about
  &lt;a href="https://www.adafruit.com/circuitpython"&gt;CircuitPython&lt;/a&gt;, and the work
  that &lt;a href="https://www.adafruit.com/"&gt;Adafruit&lt;/a&gt; is doing to make programming
  and electronics more accessible.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://2018.pycon.ca/talks/talk-PC-53179/"&gt;Using Python to find Russian Twitter troll tweets aimed at
  Canada&lt;/a&gt;
  A really interesting dive into 3 million tweets that
  &lt;a href="https://fivethirtyeight.com/features/why-were-sharing-3-million-russian-troll-tweets/"&gt;FiveThirtyEight&lt;/a&gt;
  made available for analysis.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://2018.pycon.ca/talks/talk-PC-55520/"&gt;PEP 572: The Walrus
  Operator&lt;/a&gt;
  My favourite quote from the talk: "Dictators are people too!"
  If you haven't followed Python governance, Guido stepped down as BDFL
  (Benevolent Dictator for Life) after the PEP was resolved. Dustin focused
  much of his talk about how we in the Python community, and more generally
  in tech, need to treat each other better.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://2018.pycon.ca/talks/talk-PC-55520/"&gt;Who's There? Building a home security system with Pi &amp;amp;
  Slack&lt;/a&gt;
  A great example of how you can get started hacking on home automation
  with really simple tools.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Froilán Irzarry's Keynote talk on the second day was really impressive.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://2018.pycon.ca/talks/talk-PC-52228/"&gt;You Don't Need That!&lt;/a&gt;
  Design patterns in Python
  My main takeaway from this was that you shouldn't try and write Python
  code as if it were Java or C++ :) Python has plenty of language features
  built-in that make many classic design patterns unnecessary or trivial to
  implement.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://2018.pycon.ca/talks/talk-PC-53293/"&gt;Numpy to PyTorch&lt;/a&gt;
  Really neat to learn about PyTorch, and leveraging the GPU to accelerate
  computation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://2018.pycon.ca/talks/talk-PC-53944/"&gt;Flying Python - A reverse engineering dive into Python
  performance&lt;/a&gt;
  Made me want to investigate &lt;a href="https://wiki.mozilla.org/Balrog"&gt;Balrog&lt;/a&gt;
  performance, and also look at ways we can improve Python startup time.
  Some neat tips about examining disassembled Python bytecode.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://2018.pycon.ca/talks/talk-PC-53735/"&gt;Working with Useless
  Machines&lt;/a&gt;
  Hilarious talk about (ab)using IoT devices.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://2018.pycon.ca/talks/talk-PC-52797/"&gt;Gathering Related Functionality: Patterns for Clean API
  Design&lt;/a&gt;
  I really liked his approach for creating clean APIs for things like class
  constructors. He introduced a module called
  &lt;a href="https://variants.readthedocs.io/en/latest/"&gt;variants&lt;/a&gt; which lets you
  write variants of a function / class initializer to support varying types
  of parameters. For example, a common pattern is to have a function that
  takes either a string path to a file, or a file object. Instead of having
  one function that supports both types of arguments, variants allows you
  to make distinct functions for each type, but in a way that makes it
  easy to share underlying functionality and also not clutter your
  namespace.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description><category>mozilla</category><category>pycon</category><category>python</category><category>releng</category><guid>https://atlee.ca/posts/pycon-canada-2018/</guid><pubDate>Tue, 20 Nov 2018 19:20:02 GMT</pubDate></item><item><title>So long Buildbot, and thanks for all the fish</title><link>https://atlee.ca/posts/so-long-buildbot/</link><dc:creator>chris</dc:creator><description>&lt;p&gt;Last week, without a lot of fanfare, we shut off the last of the
&lt;a href="https://buildbot.net/"&gt;Buildbot&lt;/a&gt;
infrastructure here at Mozilla.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://media.giphy.com/media/96quMvXlWpwRO/giphy.gif"&gt;&lt;/p&gt;
&lt;p&gt;Our primary release branches have been &lt;a href="https://atlee.ca/posts/so-long-buildbot/migration-status-3.html"&gt;switched over to taskcluster&lt;/a&gt; for
some time now. We needed to keep buildbot running to support the old
ESR52 branch. With the release of Firefox 60.2.0esr earlier this month,
ESR52 is now officially end-of-life, and therefore so is buildbot here at
Mozilla.&lt;/p&gt;
&lt;p&gt;Looking back in time, the first commits to our
&lt;a href="https://hg.mozilla.org/build/buildbot-configs"&gt;buildbot-configs&lt;/a&gt;
repository was over &lt;strong&gt;10 years ago&lt;/strong&gt; on April 27, 2008 by Ben Hearsum: &lt;a href="https://hg.mozilla.org/build/buildbot-configs/rev/584471372a7e"&gt;"Basic Mozilla2
configs"&lt;/a&gt;.
Buildbot usage at Mozilla actually predates that by at least two years,
Ben was working on &lt;a href="https://wiki.cdot.senecacollege.ca/wiki/Extending_the_Buildbot/Archive"&gt;some
patches&lt;/a&gt; in 2006.&lt;/p&gt;
&lt;p&gt;Earlier in my career here at Mozilla, I was doing a lot of work with
Buildbot, and &lt;a href="https://atlee.ca/categories/buildbot.html"&gt;blogged&lt;/a&gt; quite a bit about our
experiences with it.&lt;/p&gt;
&lt;p&gt;Buildbot served us well, especially in the early days. There really were no
other CI systems at the time that could operate at Mozilla's scale.&lt;/p&gt;
&lt;p&gt;Unfortunately, as we kept increasing the scale of our CI and release
infrastructure, even buildbot started showing some problems. The main
architectural limitations of buildbot we encountered were:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Long lived TCP sessions had to stay connected to specific server
   processes. If the network blipped, or you needed to restart a server,
   then any jobs running on workers were interrupted.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Its monolithic design meant that small components of the project were hard
   to develop independently from each other.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The database schema used to implement the job queue became a bottleneck
   once we started doing hundreds of thousands of jobs a day.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;On top of that, our configuration for all the various branches and
platforms had grown over the years to a complex set of inheritance rules,
defaults, and overrides. Only a few brave souls outside of RelEng managed
to effectively make changes to these configs.&lt;/p&gt;
&lt;p&gt;Today, much &lt;em&gt;much&lt;/em&gt; more of the CI and release configuration lives &lt;a href="https://hg.mozilla.org/mozilla-central/file/tip/taskcluster/ci"&gt;in
tree&lt;/a&gt;. This has &lt;a href="http://code.v.igoro.us/posts/2016/08/whats-so-special-about-in-tree.html"&gt;many
benefits&lt;/a&gt;
including:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Changes are local to the branches they land on. They ride the trains
   naturally. No need for ugly
   &lt;a href="https://hg.mozilla.org/build/buildbot-configs/file/b89147016685/mozilla/config.py#l2178"&gt;looooooops.&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Developers can self-service most of their own requests. Adding new types
   of tests, or even &lt;a href="https://glandium.org/blog/?p=3888"&gt;changing the
   compiler&lt;/a&gt; are possible without any
   involvement from RelEng!&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Buildbot is dead! Long live &lt;a href="https://taskcluster.net"&gt;taskcluster&lt;/a&gt;!&lt;/p&gt;</description><category>buildbot</category><category>mozilla</category><category>releng</category><guid>https://atlee.ca/posts/so-long-buildbot/</guid><pubDate>Thu, 20 Sep 2018 13:24:49 GMT</pubDate></item><item><title>Firefox release speed wins</title><link>https://atlee.ca/posts/faster-releases/</link><dc:creator>chris</dc:creator><description>&lt;p&gt;Sylvestre
&lt;a href="https://hacks.mozilla.org/2018/03/shipping-a-security-update-of-firefox-in-less-than-a-day/"&gt;wrote&lt;/a&gt;
about how we were able to ship new releases for Nightly, Beta, Release and ESR versions of Firefox for Desktop and Android in less than a day in response to the
&lt;a href="https://en.wikipedia.org/wiki/Pwn2Own"&gt;pwn2own&lt;/a&gt; contest.&lt;/p&gt;
&lt;p&gt;People commented on how much faster the Beta and Release releases were
compared to the ESR release, so I wanted to dive into the releases on the
different branches to understand if this really was the case, and if so,
why?&lt;/p&gt;
&lt;h2 id="chemspill-timings"&gt;Chemspill timings&lt;/h2&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;                    | Firefox ESR 52.7.2 | Firefox 59.0.1  | Firefox 60.0b4
 ------------------ | ------------------ | --------------- | --------------
 Fix landed in HG   | 23:33:06           | 23:31:28        | 23:29:54
 en-US builds ready | 03:19:03 +3h45m    | 01:16:41 +1h45m | 01:16:47 +1h46m
 Updates ready      | 08:43:03 +5h42m    | 04:21:17 +3h04m | 04:41:02 +3h25m
 Total              | 9h09m              | 4h49m           | 5h11m
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;(All times UTC from 2018-03-15 -&amp;gt; 2018-03-16)&lt;/p&gt;
&lt;!---
## Firefox ESR 52.7.2
[hg](https://hg.mozilla.org/releases/mozilla-esr52/rev/494e5d5278ba6f5fdda9a2bb9ac7ca772653ee4a)
[treeherder](https://treeherder.mozilla.org/#/jobs?repo=mozilla-esr52&amp;revision=494e5d5278ba6f5fdda9a2bb9ac7ca772653ee4a)
[taskgroup](https://tools.taskcluster.net/groups/JF41dvVxTy2q4RjgpBlU4A)

    Fix landed in HG            2018-03-15 23:33:06Z
    en-US builds ready          2018-03-16 03:19:03Z  +3h45m
    Updates ready for testing   2018-03-16 08:43:03Z  +5h24m
    Total time                                         9h09m

## Firefox 59.0.1
[hg](https://hg.mozilla.org/releases/mozilla-release/rev/3db9e3d52b17563efca181ccbb50deb8660c59ae)
[treeherder](https://treeherder.mozilla.org/#/jobs?repo=mozilla-release&amp;revision=3db9e3d52b17563efca181ccbb50deb8660c59ae)
[taskgroup](https://tools.taskcluster.net/push-inspector/#/eQGHNp4jT2yM_G_uP7A3og)

    Fix landed in HG            2018-03-15 23:31:28Z
    en-US builds ready          2018-03-16 01:16:41Z  +1h45m
    Updates ready for testing   2018-03-16 04:21:17Z  +3h04m
    Total time                                         4h49m

## Firefox Beta 60.0b4
[hg](https://hg.mozilla.org/releases/mozilla-beta/rev/1dfbedb54c39abae38da9329f4a79571fee74661)
[treeherder](https://treeherder.mozilla.org/#/jobs?repo=mozilla-beta&amp;revision=1dfbedb54c39abae38da9329f4a79571fee74661)
[taskgroup](https://tools.taskcluster.net/groups/MIUq4oRVRXGMfyduHB3W3Q)

    Fix landed in HG            2018-03-15 23:29:54Z
    en-US builds ready          2018-03-16 01:16:47Z  +1h46m
    Updates ready for testing   2018-03-16 04:41:02Z  +3h25m
    Total time                                         5h11m
--&gt;

&lt;h2 id="summary"&gt;Summary&lt;/h2&gt;
&lt;iframe src="https://giphy.com/embed/3oriNYQX2lC6dfW2Ji" width="480" height="270" frameborder="0" class="giphy-embed" allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;&lt;a href="https://giphy.com/gifs/foxhomeent-xmen-quicksilver-3oriNYQX2lC6dfW2Ji"&gt;via
GIPHY&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see that Firefox 59 and 60.0b4 were significantly faster to run than ESR
52 was! What's behind this speedup?&lt;/p&gt;
&lt;p&gt;Release Engineering have been busy migrating release automation from
&lt;a href="https://atlee.ca/posts/migration-status-3/"&gt;buildbot to taskcluster&lt;/a&gt; . Much of ESR52 still runs on buildbot, while
Firefox 59 is mostly done in Taskcluster, and Firefox 60 is entirely done
in Taskcluster.&lt;/p&gt;
&lt;p&gt;In ESR52 the initial builds are still done in buildbot, which has been
missing out on many performance gains from the build system and AWS side.
Update testing is done via buildbot on slower mac minis or windows hardware.&lt;/p&gt;
&lt;p&gt;The Firefox 59 release had much faster builds, and update verification is
done in Taskcluster on fast linux machines instead of the old mac minis or
windows hardware.&lt;/p&gt;
&lt;p&gt;The Firefox 60.0b4 release also had much faster builds, and ended up
running in about the same time as Firefox 59. It turns out that we hit
several intermittent infrastructure failures in 60.0b4 that caused this
release to be slower than it could have been. Also, because we had
multiple releases running simultaneously, we did see some resource
contention for tasks like signing.&lt;/p&gt;
&lt;p&gt;For comparison, here's what 60.0b11 looks like:&lt;/p&gt;
&lt;!---
## Firefox Beta 60.0b11
[hg](https://hg.mozilla.org/releases/mozilla-beta/rev/5b9ee6a707a068cd1ee79ea2fff7ff4147c694eb)
[treeherder](https://treeherder.mozilla.org/#/jobs?repo=mozilla-beta&amp;revision=5b9ee6a707a068cd1ee79ea2fff7ff4147c694eb)
[taskgroup](https://tools.taskcluster.net/groups/XP_KLzLiSSq8ApFDzZrtFA)

    Fix landed in HG            2018-04-09 18:45:45Z
    en-US builds ready          2018-04-09 20:41:53Z  +1h56m
    Updates ready for testing   2018-04-09 22:19:30Z  +1h37m
    Total time                                         3h33m
--&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;                    | Firefox 60.0b11
 ------------------ | --------------- 
 Fix landed in HG   | 18:45:45
 en-US builds ready | 20:41:53 +1h56m
 Updates ready      | 22:19:30 +1h37m
 Total              | 3h33m
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Wow, down to 3.5 hours!&lt;/p&gt;
&lt;p&gt;In addition to the faster builds and faster update tests, we're seeing a
lot of wins from increased parallelization that we can do now using
taskcluster's much more flexible scheduling engine.  There's still more we
can do to speed up certain types of tasks, fix up intermittent failures,
and increase parallelization. I'm curious just how fast this pipeline can
be :)&lt;/p&gt;</description><category>firefox</category><category>mozilla</category><category>releng</category><guid>https://atlee.ca/posts/faster-releases/</guid><pubDate>Wed, 25 Apr 2018 17:20:00 GMT</pubDate></item><item><title>Taskcluster migration update: we're finished!</title><link>https://atlee.ca/posts/migration-status-3/</link><dc:creator>chris</dc:creator><description>&lt;h2 id="were-done"&gt;We're done!&lt;/h2&gt;
&lt;p style="text-align:center"&gt;
&lt;img src="https://media.giphy.com/media/26tPo1I4XyWzIBjFe/giphy.gif"&gt;
&lt;/p&gt;

&lt;p&gt;Over the past few weeks we've hit a few major milestones in our project to
migrate all of Firefox's CI and release automation to
&lt;a href="https://docs.taskcluster.net/"&gt;taskcluster&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Firefox 60 and higher are now &lt;strong&gt;100% on taskcluster!&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="tests"&gt;Tests&lt;/h3&gt;
&lt;p&gt;At the end of March, our Release Operations and Project Integrity teams &lt;a href="https://hg.mozilla.org/mozilla-central/rev/08c54405586b"&gt;finished
migrating&lt;/a&gt; Windows tests onto new hardware machines, all running
taskcluster. That work was later &lt;a href="https://hg.mozilla.org/releases/mozilla-beta/rev/cfe7adda153d"&gt;uplifted to
beta&lt;/a&gt; so
that CI automation on beta would also be completely done using taskcluster.&lt;/p&gt;
&lt;p&gt;This marked the last usage of buildbot for Firefox CI.&lt;/p&gt;
&lt;h3 id="periodic-updates-of-blocklist-and-pinning-data"&gt;Periodic updates of blocklist and pinning data&lt;/h3&gt;
&lt;p&gt;Last week we &lt;a href="https://hg.mozilla.org/mozilla-central/rev/6d0dcc642e1a"&gt;switched
off&lt;/a&gt; the buildbot versions of the periodic update
jobs. These jobs keep the in-tree versions of blocklist, HSTS and HPKP
lists up to date.&lt;/p&gt;
&lt;p&gt;These were the last buildbot jobs running on trunk branches.&lt;/p&gt;
&lt;h3 id="partner-repacks"&gt;Partner repacks&lt;/h3&gt;
&lt;p&gt;And to wrap things up, yesterday the &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1398803"&gt;final patches
landed&lt;/a&gt; to migrate
partner repacks to taskcluster. Firefox 60.0b14 was built yesterday and shipped
today 100% using taskcluster.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;massive&lt;/strong&gt; amount of work went into migrating partner repacks from
buildbot to taskcluster, and I'm really proud of the whole team for pulling
this off.&lt;/p&gt;
&lt;p&gt;So, starting today, Firefox 60 and higher will be completely off
taskcluster and not rely on buildbot.&lt;/p&gt;
&lt;p&gt;It feels really good to write that :)&lt;/p&gt;
&lt;p&gt;We've been working on migrating Firefox to taskcluster for over three
years! Code archaeology is hard, but I think the first Firefox jobs to start
running in Taskcluster were the Linux64 builds, done by Morgan in &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1155749"&gt;bug
1155749&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="into-the-glorious-future"&gt;Into the glorious future&lt;/h2&gt;
&lt;p&gt;It's great to have migrated everything off of buildbot and onto
taskcluster, and we have endless ideas for how to improve things now that
we're there. First we need to spend some time cleaning up after ourselves
and paying down some technical debt we've accumulated. It's a good time to
start ripping out buildbot code from the tree as well.&lt;/p&gt;
&lt;p&gt;We've got other plans to make release automation easier for other people to
work with, including doing staging releases on try(!!), making the nightly
release process more similar to the beta/release process, and for exposing
different parts of the release process to release management so that releng
doesn't have to be directly involved with the day-to-day release mechanics.&lt;/p&gt;</description><category>firefox</category><category>mozilla</category><category>releng</category><category>taskcluster</category><guid>https://atlee.ca/posts/migration-status-3/</guid><pubDate>Fri, 20 Apr 2018 16:50:59 GMT</pubDate></item><item><title>Taskcluster migration update, the sequel</title><link>https://atlee.ca/posts/migration-status-2/</link><dc:creator>chris</dc:creator><description>&lt;h3 id="firefox-now-100-buildbot-free"&gt;Firefox, now 100% buildbot-free!&lt;/h3&gt;
&lt;p&gt;First, the good news - &lt;a href="http://archive.mozilla.org/pub/devedition/candidates/60.0b1-candidates/build3/"&gt;Developer Edition
60.0b1&lt;/a&gt;
will be the first release in nearly &lt;strong&gt;10 years&lt;/strong&gt; done without using buildbot.
This is an amazing milestone, and I'm incredibly proud of everybody who has
contributed to make this possible!&lt;/p&gt;
&lt;p style="text-align:center"&gt;
&lt;img src="https://media.giphy.com/media/s98VZT2GHE676/giphy.gif"&gt;
&lt;/p&gt;

&lt;h3 id="long-time-no-update"&gt;Long time, no update&lt;/h3&gt;
&lt;p&gt;How did we get here?  It's been, uh, almost 6 months since I &lt;a href="https://atlee.ca/posts/migration-status/"&gt;last posted
&lt;/a&gt; an update about our migration to Taskcluster.&lt;/p&gt;
&lt;p&gt;In my last update, I described our plans for the end of 2017...&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nx"&gt;We&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;re&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ship&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;builds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;produced&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Taskcluster&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;part&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;
&lt;span class="m m-Double"&gt;56.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;release&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;scheduled&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;late&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;September&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;After&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;that&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;only&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Firefox&lt;/span&gt;
&lt;span class="nx"&gt;builds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;being&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;produced&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;buildbot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;will&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ESR52&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="nx"&gt;Meanwhile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;we&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;ve&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;started&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tackling&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;remaining&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;parts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;release&lt;/span&gt;
&lt;span class="nx"&gt;automation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;We&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;prioritized&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;getting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;nightly&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CI&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;builds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;migrated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;
&lt;span class="nx"&gt;Taskcluster&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;however&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;there&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;are&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;still&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;parts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;release&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;
&lt;span class="nx"&gt;still&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;implemented&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Buildbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="nx"&gt;We&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;re&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;aiming&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;have&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;release&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;automation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;completely&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;migrated&lt;/span&gt;
&lt;span class="nx"&gt;off&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;buildbot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;We&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;ve&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;already&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;seen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;many&lt;/span&gt;
&lt;span class="nx"&gt;benefits&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;migrating&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CI&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Taskcluster&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;migrating&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;release&lt;/span&gt;
&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;will&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;realize&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;many&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;those&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;same&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;benefits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="howd-we-do"&gt;How'd we do?&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://media.giphy.com/media/3oxHQmsEZQYrnVKGCA/giphy.gif" style="float:right"&gt;
We're past the end of 2017, so how are we doing?&lt;/p&gt;
&lt;p&gt;Well, we successfully shipped &lt;a href="https://www.mozilla.org/en-US/firefox/56.0/releasenotes/"&gt;56.0&lt;/a&gt; with builds produced in Taskcluster. Our big
&lt;a href="https://blog.mozilla.org/blog/2017/11/14/introducing-firefox-quantum/"&gt;Firefox Quantum release (57.0)&lt;/a&gt;, was
also shipped with builds produced by Taskcluster.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(side note: 57 had the most complex update scenarios we've ever had to support for
Firefox...a subject for another post!)&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="release-scheduling"&gt;Release scheduling&lt;/h3&gt;
&lt;p&gt;Post-56.0, our release process was using Taskcluster exclusively for producing
the initial builds, and all the release process scheduling. We were still using
Buildbot for many of the post-build tasks, like l10n repacks, publishing
updates, pushing files to S3, etc.  Once again we relied on the &lt;a href="https://wiki.mozilla.org/ReleaseEngineering/Applications/BuildbotBridge&amp;gt;"&gt;buildbot
bridge&lt;/a&gt;
to allow us to integrate existing buildbot components with the newer
taskcluster pipeline. I learned from &lt;a href="https://kimmoir.blog/"&gt;Kim Moir&lt;/a&gt; that
this is a great example of the &lt;a href="https://www.slideshare.net/k2moir/from-hello-world-to-goodbye-code-86090379#23&amp;gt;"&gt;strangler
pattern&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the fall of 2017, we decided to begin migrating all of the scheduling logic
for release automation into taskcluster using the &lt;a href="https://firefox-source-docs.mozilla.org/taskcluster/taskcluster/index.html"&gt;in-tree
taskgraph&lt;/a&gt;
scheduling system. We did this for a few reasons...&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Having the release scheduling logic ride the trains is much more
   maintainable. Previous to this we had an externally defined release pipeline
   in our &lt;a href="https://github.com/mozilla-releng/releasetasks"&gt;releasetasks repo&lt;/a&gt;. It
   was hard to keep this repository in sync with changes required for beta/release
   and ESR branches.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;More importantly, having the release scheduling logic in-tree meant that we could then
   rely on &lt;a href="http://scriptworker.readthedocs.io/en/latest/chain_of_trust.html"&gt;chain-of-trust&lt;/a&gt;
   to verify artifacts produced by the release pipeline.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We felt that having the complete release pipeline defined in taskcluster would make it
   easier for us to tackle the remaining buildbot bridge tasks in parallel.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We hit this milestone in the 58 cycle. Starting with 58.0b3, Firefox and Fennec releases
were completely scheduled using the in-tree taskgraph generation. We also migrated over the
l10n repacks at the same time, removing a longstanding source of problems where repacks
would fail when we first got to beta due to environmental differences between taskcluster
and buildbot.&lt;/p&gt;
&lt;h3 id="no-bbb-releases"&gt;No-BBB Releases&lt;/h3&gt;
&lt;p&gt;Still, as of 58, much of release automation still ran on buildbot, even if
Taskcluster was doing all the scheduling.&lt;/p&gt;
&lt;p&gt;Since December, we've been working on removing these last few pieces of buildbot from the
release process. Progress was initially a bit slow, given
&lt;a href="https://flic.kr/p/DjgGn6"&gt;Austin&lt;/a&gt; and Christmas, but we've been hard at work
in the new year.&lt;/p&gt;
&lt;p&gt;That brings us to today.&lt;/p&gt;
&lt;p&gt;We've moved &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1398796"&gt;uptake monitoring&lt;/a&gt;,
&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1398793"&gt;update verify&lt;/a&gt; (and made it 2x
faster too!), &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1332341"&gt;update submission&lt;/a&gt;,
&lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1415981"&gt;final verify&lt;/a&gt;, &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1433459"&gt;bouncer
submission&lt;/a&gt;, &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1398787"&gt;version bumping and
tagging&lt;/a&gt;, &lt;a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1438735"&gt;balrog submission&lt;/a&gt; all to run in Taskcluster via various kinds of scriptworkers.&lt;/p&gt;
&lt;p&gt;As I mentioned above, &lt;a href="https://www.mozilla.org/en-US/firefox/developer/"&gt;DevEdition&lt;/a&gt;
60.0b1 will be the first release in nearly &lt;strong&gt;10 years&lt;/strong&gt; done without using buildbot. The
rest of the 60 release cycle will follow suit, and once 60 hits the release channel, only
ESR52 will remain on buildbot!&lt;/p&gt;</description><category>mozilla</category><category>releng</category><category>taskcluster</category><guid>https://atlee.ca/posts/migration-status-2/</guid><pubDate>Sat, 03 Mar 2018 12:26:55 GMT</pubDate></item><item><title>Taskcluster migration update</title><link>https://atlee.ca/posts/migration-status/</link><dc:creator>chris</dc:creator><description>&lt;section id="all-your-nightlies-are-belong-to-taskcluster"&gt;
&lt;h2&gt;All your nightlies are belong to Taskcluster&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://atlee.ca/posts/nightly-builds-from-taskcluster/"&gt;In January&lt;/a&gt; I announced that we
had just migrated Linux nightly builds to &lt;a class="reference external" href="https://docs.taskcluster.net/"&gt;Taskcluster&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We completed a huge milestone in July: starting in Firefox 56, we've been
doing &lt;strong&gt;all&lt;/strong&gt; our nightly Firefox builds in Taskcluster.&lt;/p&gt;
&lt;a class="reference external image-reference" href="https://giphy.com/gifs/excited-applause-minions-MOWPkhRAUbR7i?utm_source=media-link&amp;amp;utm_medium=landing&amp;amp;utm_campaign=Media%20Links&amp;amp;utm_term="&gt;&lt;img alt="https://media.giphy.com/media/MOWPkhRAUbR7i/giphy.gif" src="https://media.giphy.com/media/MOWPkhRAUbR7i/giphy.gif"&gt;&lt;/a&gt;
&lt;p&gt;This includes all &lt;a class="reference external" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1267427"&gt;Windows&lt;/a&gt;, &lt;a class="reference external" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1267425"&gt;macOS&lt;/a&gt;, Linux, and Android builds. You can
see all the builds and repacks on &lt;a class="reference external" href="https://treeherder.mozilla.org/#/jobs?repo=mozilla-central&amp;amp;filter-searchStr=nightly"&gt;Treeherder&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In August, after 56 merged to Beta, we've also been doing our Firefox
Beta builds using Taskcluster. We're on track to be shipping Firefox 56, built from Taskcluster to release users at the end of September.&lt;/p&gt;
&lt;p&gt;Windows and macOS each had their own challenges to get them ready to
build and ship to our nightly users.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="windows-signing"&gt;
&lt;h2&gt;Windows signing&lt;/h2&gt;
&lt;p&gt;We've had Windows builds running in Taskcluster for quite a while now.
The biggest missing piece stopping us from shipping these builds was
&lt;a class="reference external" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1277591"&gt;signing&lt;/a&gt;.
Windows builds end up being a bit complicated to sign.&lt;/p&gt;
&lt;p&gt;First, each compiled .exe and .dll binary needs to be signed.
Signing binaries in windows changes their contents, and so we need to
regenerate some files that depend on the exact contents of binaries.
Next, we need to create packages in various formats: a "setup.exe" for
installing Firefox, and also &lt;a class="reference external" href="https://wiki.mozilla.org/Software_Update:MAR"&gt;MAR&lt;/a&gt; files for updates.
Each of these package formats in turn need to be signed.&lt;/p&gt;
&lt;p&gt;In buildbot, this process was monolithic. All of the binary
generation and signing happened as part of the same build process. The
same process would also publish symbols to the &lt;a class="reference external" href="https://developer.mozilla.org/en-US/docs/Mozilla/Using_the_Mozilla_symbol_server"&gt;symbol server&lt;/a&gt; and
publish updates to &lt;a class="reference external" href="https://github.com/mozilla/balrog"&gt;Balrog&lt;/a&gt; The downside of this monolithic process
is that it adds additional dependencies to the build, which is already
a really long process. If something goes wrong with signing, or
publishing updates, you don't want to have to restart a 2 hour build!&lt;/p&gt;
&lt;p&gt;As part of our migration to Taskcluster, we decided that builds should
minimize their external dependencies. This means that the build task
produces only unsigned binaries, and it is the responsibility of
downstream tasks to sign them. We also wanted discrete tasks for
symbol and update submission.&lt;/p&gt;
&lt;p&gt;One wrinkle in this approach is that the logic that defines how to
create a setup.exe package or a MAR file lives &lt;a class="reference external" href="https://dxr.mozilla.org/mozilla-central/source/toolkit/mozapps/installer/packager.mk"&gt;in tree&lt;/a&gt;. We didn't
want to run that code in the same context as the code that generates
signatures.&lt;/p&gt;
&lt;p&gt;Our solution to this was to create a sequence of build -&amp;gt;
signing -&amp;gt; repackage -&amp;gt; signing tasks. The signing tasks run in a
restricted environment while the build and repackage tasks have access to
the build system in order to produce the required artifacts. Using the
&lt;a class="reference external" href="http://escapewindow.dreamwidth.org/249409.html"&gt;chain of trust&lt;/a&gt;, we can demonstrate that the artifacts weren't
tampered with between intermediate tasks.&lt;/p&gt;
&lt;p&gt;Finally, we need to consider &lt;a class="reference external" href="https://wiki.mozilla.org/L10n:Home_Page"&gt;l10n&lt;/a&gt; repacks. We ship Firefox in over 90
&lt;a class="reference external" href="https://hg.mozilla.org/mozilla-central/file/tip/browser/locales/all-locales"&gt;locales&lt;/a&gt;. The repacking process downloads the en-US build and replaces
the English strings with localized strings. Each of these repacks
needs to be based on the signed en-US build. Each will also generate
its own setup.exe and complete MAR for updates.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="macos-performance-and-why-your-build-directory-matters"&gt;
&lt;h2&gt;macOS performance (and why your build directory matters)&lt;/h2&gt;
&lt;p&gt;Like Windows, we've had macOS builds running on Taskcluster for a long
time. Also like Windows, we had to solve &lt;a class="reference external" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1376550"&gt;signing for macOS&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, the biggest blocker for the macOS build migration, was a
&lt;a class="reference external" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1338651"&gt;performance bug&lt;/a&gt;. Builds
produced on Taskcluster showed some serious performance regressions as
compared to the builds produced on buildbot.&lt;/p&gt;
&lt;p&gt;Many very smart people looked at this bug since it was first
discovered in February. They compared library versions being used.
They compared compiler versions and compiler flags. They even
inspected the generated assembly code from both systems.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://gittup.org/blog/"&gt;Mike Shal&lt;/a&gt; stumbled across the first clue to what was going on in
&lt;a class="reference external" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1338651#c111"&gt;June&lt;/a&gt;:
if he stripped the Taskcluster binaries, then the performance problems
disappeared! At this point we decided that we could go ahead and ship
these builds to nightly users, knowing that the performance regression
would disappear on beta and release.&lt;/p&gt;
&lt;p&gt;Later on, Mike realized that it's not the presence or absence of
symbols in the binary that cause the performance hit, it's &lt;em&gt;what
directory the builds are done in.&lt;/em&gt; On buildbot we build under
/builds/..., and on Taskcluster we build under /home/...&lt;/p&gt;
&lt;a class="reference external image-reference" href="https://giphy.com/gifs/confused-huh-mark-wahlberg-zjQrmdlR9ZCM?utm_source=media-link&amp;amp;utm_medium=landing&amp;amp;utm_campaign=Media%20Links&amp;amp;utm_term="&gt;&lt;img alt="https://media.giphy.com/media/zjQrmdlR9ZCM/giphy.gif" src="https://media.giphy.com/media/zjQrmdlR9ZCM/giphy.gif"&gt;&lt;/a&gt;
&lt;p&gt;Read the &lt;a class="reference external" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1338651"&gt;bug&lt;/a&gt; for more gory details. This is definitely one of the
strangest bugs I've seen.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="lessons-learned"&gt;
&lt;h2&gt;Lessons learned&lt;/h2&gt;
&lt;p&gt;We learned quite a bit in the process of migrating Windows and macOS
nightly builds to Taskcluster.&lt;/p&gt;
&lt;p&gt;First, we gained a huge amount of experience with the &lt;a class="reference external" href="https://firefox-source-docs.mozilla.org/taskcluster/taskcluster/index.html"&gt;in-tree scheduling system&lt;/a&gt;.
There's a bit of a learning curve to climb, but it's an
extremely powerful and flexible system. Many kudos to &lt;a class="reference external" href="http://code.v.igoro.us/"&gt;Dustin&lt;/a&gt; for his work creating the foundation of
this system here. His blog post, "&lt;a class="reference external" href="http://code.v.igoro.us/posts/2016/08/whats-so-special-about-in-tree.html"&gt;What's So Special About "In-Tree"?&lt;/a&gt;",
is a great explanation of why having this code as part of Firefox's
repository is so important.&lt;/p&gt;
&lt;p&gt;One of the killer features of having all the scheduling logic live
in-tree is that you can do quite a bit of work locally, without
requiring any build infrastructure. This is extremely useful when
working on the complex build / signing / repackage sequence of tasks
described above. You can make your changes, generate a new task graph,
and inspect the results.&lt;/p&gt;
&lt;p&gt;Once you're happy with your local changes, you can push them to try to
validate your local testing, get your patch reviewed, and then finally
landed in gecko. Your scheduling changes will take effect as soon as
they land into the repo. This made it possible for us to do a lot of
testing on another project branch, and then merge the code to central
once we were ready.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="what-s-next"&gt;
&lt;h2&gt;What's next?&lt;/h2&gt;
&lt;p&gt;We're on track to ship builds produced in Taskcluster as part of the
56.0 release scheduled for late September. After that the only Firefox
builds being produced by buildbot will be for ESR52.&lt;/p&gt;
&lt;p&gt;Meanwhile, we've started tackling the remaining parts of release
automation. We prioritized getting nightly and CI builds migrated to
Taskcluster, however, there are still parts of the release process
still implemented in Buildbot.&lt;/p&gt;
&lt;p&gt;We're aiming to have release automation completely migrated
off of buildbot by the end of the year. We've already seen many
benefits from migrating CI to Taskcluster, and migrating the release
process will realize many of those same benefits.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="thanks"&gt;
&lt;h2&gt;Thanks!&lt;/h2&gt;
&lt;p&gt;Thank you for reading this far!&lt;/p&gt;
&lt;p&gt;Members from the Release Engineering, Release Operations, Taskcluster,
Build, and Product Integrity teams all were involved in finishing up
this migration. Thanks to everyone involved (there are a lot of you!)
to getting us across the finish line here.&lt;/p&gt;
&lt;p&gt;In particular, if you come across one of these fine individuals at the
office, or maybe on IRC, I'm sure they would appreciate a quick
"thank you":&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;p&gt;Aki Sasaki&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dustin Mitchell&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Greg Arndt&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Joel Maher&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Johan Lorenzo&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Justin Wood&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Kim Moir&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mihai Tabara&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mike Shal&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nick Thomas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rail Aliiev&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rob Thijssen&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simon Fraser&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wander Costa&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;</description><category>mozilla</category><category>releng</category><category>taskcluster</category><guid>https://atlee.ca/posts/migration-status/</guid><pubDate>Wed, 30 Aug 2017 09:40:39 GMT</pubDate></item><item><title>Nightly builds from Taskcluster</title><link>https://atlee.ca/posts/nightly-builds-from-taskcluster/</link><dc:creator>chris</dc:creator><description>&lt;p&gt;Yesterday, for the very first time, we started shipping Linux Desktop and
Android Firefox nightly builds from &lt;a class="reference external" href="https://docs.taskcluster.net/"&gt;Taskcluster&lt;/a&gt;.&lt;/p&gt;
&lt;img alt="74851712.jpg" src="https://atlee.ca/posts/nightly-builds-from-taskcluster/74851712.jpg"&gt;
&lt;p&gt;We now have a much more secure, resilient, and hackable nightly
build and release process.&lt;/p&gt;
&lt;p&gt;It's more secure, because we have developed a chain of trust that allows
us to verify all generated artifacts back to the original decision task
and docker image. Signing is no longer done as part of the build process,
but is now split out into a discrete task after the build completes.&lt;/p&gt;
&lt;p&gt;The new process is more resilient because we've split up the monolithic
build process into smaller bits: build, signing, symbol upload, upload to
CDN, and publishing updates are all done as separate tasks. If any one of
these fail, they can be retried independently. We don't have to re-compile
the entire build again just because an external service was temporarily
unavailable.&lt;/p&gt;
&lt;p&gt;Finally, it's more hackable - in a good way! All the configuration files
for the nightly build and release process are contained in-tree. That
means it's easier to inspect and change how nightly builds are done.
Changes will automatically ride the trains to aurora, beta, etc.&lt;/p&gt;
&lt;p&gt;Ideally you didn't even notice this change! We try and get these changes
done quietly, smoothly, in the background.&lt;/p&gt;
&lt;p&gt;This is a giant milestone for Mozilla's &lt;a class="reference external" href="https://wiki.mozilla.org/ReleaseEngineering"&gt;Release Engineering&lt;/a&gt; and Taskcluster teams, and
is the result of many months of hard work, planning, coding, reviewing and
debugging.&lt;/p&gt;
&lt;p&gt;Big big thanks to jlund, Callek, mtabara, kmoir, aki, dustin, sfraser, jlorenzo,
coop, jmaher, bstack, gbrown, and everybody else who made this possible!&lt;/p&gt;</description><category>mozilla</category><category>releng</category><category>taskcluster</category><guid>https://atlee.ca/posts/nightly-builds-from-taskcluster/</guid><pubDate>Fri, 20 Jan 2017 13:35:25 GMT</pubDate></item></channel></rss>