<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Artsy Engineering</title>
    <description></description>
    <link>http://artsy.github.io/</link>
    <atom:link href="http://artsy.github.io/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 04 May 2016 12:03:11 +0000</pubDate>
    <lastBuildDate>Wed, 04 May 2016 12:03:11 +0000</lastBuildDate>
    <generator>Jekyll v2.5.3</generator>
    
      <item>
        <title>Why does my team&#39;s Podfile.lock Podspec checksums change?</title>
        <description>&lt;p&gt;We use CocoaPods, and &lt;a href=&quot;https://github.com/artsy/eigen/issues/418&quot;&gt;we don&#39;t check in our Pods&lt;/a&gt; directory for one of our fastest moving apps, &lt;a href=&quot;https://github.com/artsy/eigen/&quot;&gt;Eigen&lt;/a&gt;. This sometimes can cause an &lt;a href=&quot;https://github.com/artsy/eigen/pull/1464&quot;&gt;interesting data churn&lt;/a&gt; inside the &lt;code&gt;Podfile.lock&lt;/code&gt; when developers have different sha checksums for their Pods. This is weird, what gives?&lt;/p&gt;

&lt;!-- more --&gt;


&lt;h3&gt;What are the Lockfiles?&lt;/h3&gt;

&lt;p&gt;First off, to ensure we&#39;re talking about the same thing, this is our &lt;a href=&quot;https://github.com/artsy/eigen/blob/master/Podfile.lock&quot;&gt;Podfile.lock&lt;/a&gt;. The lockfile is used on &lt;code&gt;pod install&lt;/code&gt; to ensure all the members of your team have the &lt;em&gt;exact same&lt;/em&gt; version of the libraries as each other. Otherwise, with a Podfile like:&lt;/p&gt;

&lt;div class=&#39;bogus-wrapper&#39;&gt;&lt;notextile&gt;&lt;figure class=&#39;code&#39;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#39;line-number&#39;&gt;1&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;2&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;pre&gt;&lt;code class=&#39;ruby&#39;&gt;&lt;span class=&#39;line&#39;&gt;&lt;span class=&quot;n&quot;&gt;platform&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:ios&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;9.3&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;&lt;span class=&quot;n&quot;&gt;pod&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;AFNetworking/Serialization&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;~&amp;gt; 3.0&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;&lt;span class=&quot;n&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;MyApp&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/notextile&gt;&lt;/div&gt;


&lt;p&gt;A developer running &lt;code&gt;pod install&lt;/code&gt; would get the latest &lt;code&gt;3.x&lt;/code&gt; version, which could be &lt;code&gt;3.1&lt;/code&gt; originally, but then 6 months later they could get &lt;code&gt;3.4&lt;/code&gt; - without a lockfile there is no way to keep track of the specific build. This is why it should always be in your code repo. In the case above my lockfile looks like this:&lt;/p&gt;

&lt;div class=&#39;bogus-wrapper&#39;&gt;&lt;notextile&gt;&lt;figure class=&#39;code&#39;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#39;line-number&#39;&gt;1&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;2&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;3&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;4&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;5&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;6&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;7&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;8&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;9&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;10&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;11&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;12&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;pre&gt;&lt;code class=&#39;yaml&#39;&gt;&lt;span class=&#39;line&#39;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;PODS&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;  &lt;span class=&quot;p-Indicator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;AFNetworking/Serialization (3.1.0)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;DEPENDENCIES&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;  &lt;span class=&quot;p-Indicator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;AFNetworking/Serialization (~&amp;gt; 3.0)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;SPEC CHECKSUMS&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;AFNetworking&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;5e0e199f73d8626b11e79750991f5d173d1f8b67&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;PODFILE CHECKSUM&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;876ceaa409f4ade2b3d58d310dbe026393824bcc&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;COCOAPODS&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;1.0.0.beta.8&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/notextile&gt;&lt;/div&gt;


&lt;p&gt;`&lt;/p&gt;

&lt;h3&gt;What do the Spec Checksums do?&lt;/h3&gt;

&lt;p&gt;With the CocoaPods Master Specs repo, we do our best &lt;a href=&quot;https://github.com/CocoaPods/Specs/pull/12199&quot;&gt;to try&lt;/a&gt; and ensure a write-once repository of Podspecs for the public. However, there are many times when you cannot guarantee that every you have the same version of a Podspec as everyone else in your team.&lt;/p&gt;

&lt;p&gt;So, CocoaPods makes a checksum of the JSON representation of your Podspec and keeps that in the lockfile. You can easily &lt;a href=&quot;https://github.com/CocoaPods/CocoaPods/issues/3371&quot;&gt;replicate&lt;/a&gt; the work to generate a checksum with:&lt;/p&gt;

&lt;div class=&#39;bogus-wrapper&#39;&gt;&lt;notextile&gt;&lt;figure class=&#39;code&#39;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#39;line-number&#39;&gt;1&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;pre&gt;&lt;code class=&#39;sh&#39;&gt;&lt;span class=&#39;line&#39;&gt;~/D/MyApp ⏛  pod ipc spec ~/.cocoapods/repos/master/Specs/AFNetworking/3.1.0/AFNetworking.podspec.json  &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; openssl sha1
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;5e0e199f73d8626b11e79750991f5d173d1f8b67
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/notextile&gt;&lt;/div&gt;


&lt;h3&gt;So why am I seeing churn?&lt;/h3&gt;

&lt;p&gt;A normal git development flow when working with libraries is to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fork a library, change your Podfile to reflect that change&lt;/li&gt;
&lt;li&gt;Make some changes&lt;/li&gt;
&lt;li&gt;Commit them back to the main repo&lt;/li&gt;
&lt;li&gt;Update the Podspec, then make changes bringing your Podfile back to a real (tagged) release&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;CocoaPods is smart about updating your libraries behind the scenes, but it&#39;s not perfect. In order to avoid re-creating your entire Pods folder every time it will check whether your libraries are at the expected version and skip re-creating the whole process.&lt;/p&gt;

&lt;p&gt;In the example above, we used the CocoaPods&#39; Specs repo version of the Podspec. In forked repos, e,g,&lt;/p&gt;

&lt;div class=&#39;bogus-wrapper&#39;&gt;&lt;notextile&gt;&lt;figure class=&#39;code&#39;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#39;line-number&#39;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;pre&gt;&lt;code class=&#39;ruby&#39;&gt;&lt;span class=&#39;line&#39;&gt;&lt;span class=&quot;n&quot;&gt;pod&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;AFNetworking/Serialization&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:git&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;https://github.com/orta/AFNetworking.git&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:commit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;6f31b5c7bcbd59d4dac7e92e215d3c2c22f3400e&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/notextile&gt;&lt;/div&gt;


&lt;p&gt;The Podspec is saved into the &lt;code&gt;Pods&lt;/code&gt; directory in JSON format at &lt;code&gt;Pods/Local\ Podspecs/AFNetworking.podspec.json&lt;/code&gt;, this is to ensure there&#39;s always access within the CocoaPods sandbox for the Podspecs, and speed probably. This is the podspec used for generating the checksum.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So how can this get out of sync?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;During the development cycle, when working with a library you would have used &lt;code&gt;pod update [library]&lt;/code&gt; to update just that library you were working on.  This could happen multiple times as you build your changes.&lt;/li&gt;
&lt;li&gt;You continued working against your fork till it was ready for review. At this point you have a working version, you submit a PR for code review on the library.&lt;/li&gt;
&lt;li&gt;There are changes that affect the podspec that come up in review, you don&#39;t do a &lt;code&gt;pod update [library]&lt;/code&gt; but send the code back to review ( maybe you changed some metadata for example, which doesn&#39;t warrant another update to pass CI. )&lt;/li&gt;
&lt;li&gt;Once all code is reviewed, everything is merged back into master.&lt;/li&gt;
&lt;li&gt;You &lt;code&gt;pod install&lt;/code&gt; - which continues to use the older version of the Podspec inside the Pods dir, e.g. &lt;code&gt;Pods/Local\ Podspecs/AFNetworking.podspec.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You now have the older &lt;code&gt;AFNetworking.podspec.json&lt;/code&gt; inside your local Pods folder, when the next person runs &lt;code&gt;pod install&lt;/code&gt; with your changes merged, they get a different SHA, as they&#39;ve got the version with the metadata changes.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Simple Fix&lt;/h3&gt;

&lt;p&gt;The best option is to run &lt;code&gt;pod update [library]&lt;/code&gt; on the computer which is causing churn, this will tell CocoaPods specifically to request a new version of the library. If that fails to give the same checksum as the rest of your team, there&#39;s the good old fasioned &lt;code&gt;rm -rf Pods &amp;amp;&amp;amp;  pod install&lt;/code&gt;.&lt;/p&gt;
</description>
        <pubDate>Tue, 03 May 2016 12:09:00 +0000</pubDate>
        <link>http://artsy.github.io/blog/2016/05/03/podspec-checksums/</link>
        <guid isPermaLink="true">http://artsy.github.io/blog/2016/05/03/podspec-checksums/</guid>
        
        
        <category>cocoapods</category>
        
        <category>dependencies</category>
        
        <category>mobile</category>
        
      </item>
    
      <item>
        <title>Using Paw with Per-Developer Settings</title>
        <description>&lt;p&gt;I am a big fan of developer tooling, as spending time upfront on improving your process can pay a lot of dividends over time. I want to talk about one in particular: &lt;a href=&quot;https://luckymarmot.com/paw&quot;&gt;Paw&lt;/a&gt;. Paw is a native HTTP client with a bunch of features. I want to cover one that means that we can now &lt;a href=&quot;https://github.com/artsy/energy/pull/192&quot;&gt;introduce&lt;/a&gt; &lt;code&gt;[AppName].paw&lt;/code&gt; files in our mobile projects, making it easy for us to discuss networking requests.&lt;/p&gt;

&lt;!-- more --&gt;


&lt;h3&gt;OK, what is Paw?&lt;/h3&gt;

&lt;p&gt;Paw is a tool that stores collections of API endpoints, along with all the metadata required to call them. We first started using Paw during the creation &lt;a href=&quot;https://github.com/artsy/eidolon/blob/master/Kiosk/Stubbed%20Responses/Me.json&quot;&gt;of Eidolon&lt;/a&gt; as a way to keep track of the auction-related API calls we would need to stub for &lt;a href=&quot;http://cocoapods.org/pods/moya&quot;&gt;Moya&lt;/a&gt;, an iOS networking library that required stubbed data. It made it easy for us to keep track of how all the different API routes work together, and to verify that we were doing things right.&lt;/p&gt;

&lt;p&gt;&lt;/div&gt;&lt;/div&gt;&lt;a href=&#39;/images/2016-04-14-Paw/eidolon.png&#39;&gt;&lt;img src=&quot;/images/2016-04-14-Paw/eidolon.png&quot; title=&quot;paw tokens&quot; &gt;&lt;/a&gt;&lt;div class=&#39;meta-container&#39;&gt;&lt;header&gt;&amp;nbsp;&lt;/header&gt;&lt;/div&gt;&lt;div class=&#39;date-container&#39;&gt;&amp;nbsp;&lt;/div&gt;&lt;div class=&#39;content-container&#39;&gt;&lt;div class=&#39;entry-content&#39;&gt;&lt;/p&gt;

&lt;p&gt;We used environment variables to keep track of things we wanted to change, but in using them this way we couldn&#39;t publicise our Paw files, the real versions contained secrets that should stay secret.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-04-14-Paw/eidolon-env.png&quot; alt=&quot;Environments for Eidolon&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The environment tooling made it easy to change the routes, users and settings easily, but were also the thing keeping us from being able to share the files in source. Because of this, we stopped using Paw to keep track of our routes as we had to ad-hoc share the file over chat.&lt;/p&gt;

&lt;h3&gt;A Second Shot&lt;/h3&gt;

&lt;p&gt;This week, roughly a year and a half later, I started work on a &lt;a href=&quot;https://github.com/artsy/energy/pull/189&quot;&gt;large project&lt;/a&gt; that I knew would involve using new networking APIs. So I took the time to look for ways to interpret what I was going to be working with. After exploring some alternatives, I came back to Paw, and discovered they had a &lt;a href=&quot;https://blog.luckymarmot.com/posts/paw-23-keep-it-secret-keep-it-safe/&quot;&gt;new feature&lt;/a&gt;: Keychain integration. This stopped my search.&lt;/p&gt;

&lt;p&gt;In our iOS projects, as they are all open source, we use &lt;a href=&quot;https://github.com/orta/cocoapods-keys&quot;&gt;CocoaPods-Keys&lt;/a&gt; to ensure that our development configuration secrets are kept safe and outside of the project&#39;s source code. It stores the per-project keys inside a developer&#39;s Keychain. This means they can be accessed from inside the iOS app, but also from the &lt;a href=&quot;/images/2016-04-14-Paw/keychain.png&quot;&gt;developer&#39;s computer&lt;/a&gt; via a determinate location in the Keychain app.&lt;/p&gt;

&lt;div class=&#39;bogus-wrapper&#39;&gt;&lt;notextile&gt;&lt;figure class=&#39;code&#39;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#39;line-number&#39;&gt;1&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;2&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;3&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;4&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;5&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;6&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;7&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;8&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;9&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;10&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;11&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;pre&gt;&lt;code class=&#39;&#39;&gt;&lt;span class=&#39;line&#39;&gt;~/d/i/a/energy (master) ⏛  bundle exec pod keys
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;Keys for Folio
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt; ├  ArtsyAPIClientSecret - [***********]
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt; ├  ArtsyAPIClientKey - [***********]
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt; ├  HockeyAppBetaID - [***********]
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt; ├  HockeyAppLiveID - [***********]
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt; ├  IntercomAppID - [***********]
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt; ├  IntercomAPIKey - [***********]
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt; ├  SegmentProduction - [***********]
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt; ├  SegmentBeta - [***********]
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt; └  SegmentDev - [***********]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/notextile&gt;&lt;/div&gt;


&lt;p&gt;This means that we can use CocoaPods-Keys with Paw in order to use the same &lt;code&gt;ArtsyAPIClientSecret&lt;/code&gt; and &lt;code&gt;ArtsyAPIClientKey&lt;/code&gt; environment config variables. Great. This is almost enough to make the first API call to to get an access token.&lt;/p&gt;

&lt;p&gt;I re-used this idea to allow developers to have unique username and passwords. I created two more entires in Keychain, username and &lt;a href=&quot;/images/2016-04-14-Paw/keychain-password.png&quot;&gt;password&lt;/a&gt;. This is something that every developer using our Paw file has to do, otherwise Paw won&#39;t know who to log you in as.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-04-14-Paw/keychain-username.png&quot; alt=&quot;Keychain Email&quot; /&gt;&lt;/p&gt;

&lt;p&gt;With these all hooked up, I could set up Paw to use all of our Keychain entities:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-04-14-Paw/paw-adding-keychain.png&quot; alt=&quot;Paw Adding Keychain&quot; /&gt;
&lt;img src=&quot;/images/2016-04-14-Paw/paw-setting-password.png&quot; alt=&quot;Paw Setting Password&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Tada! Now I can run my route, and I&#39;ve got an access token to use with our API.&lt;/p&gt;

&lt;h3&gt;Route Resolving&lt;/h3&gt;

&lt;p&gt;Automating the route to get an access token is the first step because Paw allows you to use the output of one route inside any new route. I&#39;ll show you, then talk it through.&lt;/p&gt;

&lt;p&gt;&lt;/div&gt;&lt;/div&gt;&lt;a href=&#39;/images/2016-04-14-Paw/paw-tokens.png&#39;&gt;&lt;img src=&quot;/images/2016-04-14-Paw/paw-tokens.png&quot; title=&quot;paw tokens&quot; &gt;&lt;/a&gt;&lt;div class=&#39;meta-container&#39;&gt;&lt;header&gt;&amp;nbsp;&lt;/header&gt;&lt;/div&gt;&lt;div class=&#39;date-container&#39;&gt;&amp;nbsp;&lt;/div&gt;&lt;div class=&#39;content-container&#39;&gt;&lt;div class=&#39;entry-content&#39;&gt;&lt;/p&gt;

&lt;p&gt;I made it so that my new request ( for the route &lt;code&gt;api/v1/me&lt;/code&gt;)  passes in an header of &lt;code&gt;X-Access-Token&lt;/code&gt;, with the value being the &lt;code&gt;access_token&lt;/code&gt; from the route we just made called &lt;code&gt;Auth&lt;/code&gt;. This means that when the token expires, it will automatically re-generate a new one and we&#39;re never storing the token explicitly inside the Paw file. Our secrets stay secret, and per-developer - I don&#39;t want to know other people&#39;s passwords.&lt;/p&gt;

&lt;p&gt;Once those two routes were set up, it was a matter of looking up what routes I would need and added them to the paw file for the project. I used the group system to make it easy to show / hide sections, and experimented with using environments to differentiate between staging and production servers. Not quite figured that yet.&lt;/p&gt;

&lt;h3&gt;Wrap up&lt;/h3&gt;

&lt;p&gt;It&#39;s easier to talk about your API when any other developer can open this one file and shoot off requests at the same time as you. One of my favourite nice-touches is to be able to easily convert any request into a cURL command.&lt;/p&gt;

&lt;p&gt;I am using this event as a reminder to myself that tools evolve, and maybe your first impression on a developer tool may require re-interpreting in light of software evolution.&lt;/p&gt;
</description>
        <pubDate>Thu, 14 Apr 2016 12:09:00 +0000</pubDate>
        <link>http://artsy.github.io/blog/2016/04/14/net-working-with-paw/</link>
        <guid isPermaLink="true">http://artsy.github.io/blog/2016/04/14/net-working-with-paw/</guid>
        
        
        <category>development</category>
        
        <category>mobile</category>
        
        <category>web</category>
        
      </item>
    
      <item>
        <title>Using Xcode&#39;s Schemes to run a subset of your tests</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://github.com/artsy/eigen&quot;&gt;Eigen&lt;/a&gt; has hit the point where testing is a chore. This is a positive sign, the app has grown in terms of size, complexity, and number of developers considerably over the last 3 years. The test suite makes us feel comfortable making changes.&lt;/p&gt;

&lt;p&gt;On my fastest computer, we&#39;re just under a minute - &lt;code&gt;Executed 1105 tests, with 1 failure (0 unexpected) in 43.221 (48.201) seconds&lt;/code&gt;  for the whole suite. I think I could probably live with 20 seconds max. So I studied how &lt;a href=&quot;https://www.jetbrains.com/objc/&quot;&gt;AppCode&lt;/a&gt; handles running tests, and this will be an illustrated guide as to how you can easily run the subset of tests in Xcode based on their techniques.&lt;/p&gt;

&lt;p&gt; I &lt;a href=&quot;https://github.com/orta/life/issues/71&quot;&gt;have ideas&lt;/a&gt; on how to improve time for testing in general, based on &lt;a href=&quot;http://artsy.github.io/blog/2016/03/05/iOS-Code-Injection/&quot;&gt;Code Injection&lt;/a&gt;, but they aren&#39;t fully fleshed out and I expect it to be time-intensive to pull off. Time I haven&#39;t made yet.&lt;/p&gt;

&lt;!-- more --&gt;


&lt;h3&gt;What are Schemes?&lt;/h3&gt;

&lt;blockquote&gt;&lt;p&gt;An Xcode scheme defines a collection of targets to build, a configuration to use when building, and a collection of tests to execute.&lt;/p&gt;

&lt;p&gt;You can have as many schemes as you want, but only one can be active at a time. You can specify whether a scheme should be stored in a project—in which case it’s available in every workspace that includes that project, or in the workspace—in which case it’s available only in that workspace. When you select an active scheme, you also select a run destination (that is, the architecture of the hardware for which the products are built).&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;To &lt;a href=&quot;https://developer.apple.com/library/ios/featuredarticles/XcodeConcepts/Concept-Schemes.html&quot;&gt;quote Apple&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Hatching a Scheme&lt;/h3&gt;

&lt;p&gt;The Eigen Test Suite is around 50 test classes, these look a bit like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-04-06-Testing-Schemes/tests.png&quot; alt=&quot;Tests&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Before you start, you want to be able to say, &quot;I want to only run tests for the Fairs section of Eigen&quot;, as that is where I will be working for the next few days. To get started, I need to create a new Scheme. You will have seen the schemes before when you click on the Target side of this Targer/Sim button in the top left of Xcode.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-04-06-Testing-Schemes/empty_scheme.png&quot; alt=&quot;Empty Scheme&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This is what it looks like on mine, we want to create a new scheme. This brings up a modal window where you need to choose your App&#39;s target (this is so you can continue running by pressing &lt;code&gt;cmd + r&lt;/code&gt;.)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-04-06-Testing-Schemes/new_scheme.png&quot; alt=&quot;New Scheme&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I&#39;ve called mine &quot;Artsy just for Fairs&quot;, as I&#39;m the only person who would see it, I can name it whatever I want. Clicking &quot;OK&quot; selects it, and hides the modal. You now need to go back to the target selector, and go to &quot;Edit Schemes ...&quot; to continue though.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-04-06-Testing-Schemes/edit_schemes.png&quot; alt=&quot;Edit Schemes&quot; /&gt;&lt;/p&gt;

&lt;h3&gt;Making Amends&lt;/h3&gt;

&lt;p&gt;OK, click on &quot;Test&quot; in the sidebar, and now you&#39;re in the Schemes Test editor. This is where you do the work.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-04-06-Testing-Schemes/empty_edit_schemes.png&quot; alt=&quot;Empty Edit Schemes&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You need to hit the &quot;+&quot; in order to add your Test Target to the Scheme&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-04-06-Testing-Schemes/test_scheme.png&quot; alt=&quot;Test Scheme&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Select and &quot;Add&quot; you Targets. This adds the target, you then need to click the disclosure arrow in order to show all the Test Classes.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;OK, here&#39;s some magic&lt;/em&gt;. Hold &lt;code&gt;alt&lt;/code&gt; and click on the blue tickbox to the right of your test target to turn it off. Then click again, without &lt;code&gt;alt&lt;/code&gt;. It should then deselect all of the classes. This is standard in all Mac apps, so go wild there.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-04-06-Testing-Schemes/deselect_all.png&quot; alt=&quot;Deselect All&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This means you can go find the classes you do want to run, in my case that is the Test Classes relating to Fairs.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-04-06-Testing-Schemes/just_the_good_tests.png&quot; alt=&quot;Just The Good Tests&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now when I press &lt;code&gt;cmd + u&lt;/code&gt; it will only run those test classes.&lt;/p&gt;

&lt;h3&gt;Wrapping Up&lt;/h3&gt;

&lt;p&gt;Which means I can now get back to work at a reasonable pace. &lt;code&gt;Executed 15 tests, with 0 failures (0 unexpected) in 0.277 (0.312) seconds&lt;/code&gt;. I can then run the full suite whenever I go and make a cup of tea.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; If you want to avoid using the mouse to change scheme, the &lt;a href=&quot;/images/2016-04-06-Testing-Schemes/next_prev.png&quot;&gt;key commands&lt;/a&gt; to change between visible schemes is &lt;code&gt;cmd + ctrl + [&lt;/code&gt; and  &lt;code&gt;cmd + ctrl + ]&lt;/code&gt;.&lt;/p&gt;
</description>
        <pubDate>Wed, 06 Apr 2016 12:09:00 +0000</pubDate>
        <link>http://artsy.github.io/blog/2016/04/06/Testing-Schemes/</link>
        <guid isPermaLink="true">http://artsy.github.io/blog/2016/04/06/Testing-Schemes/</guid>
        
        
        <category>mobile</category>
        
        <category>xcode</category>
        
      </item>
    
      <item>
        <title>Artsy&#39;s Engineering Organization Stack, 2016</title>
        <description>&lt;div style=&quot;max-width: 50%; text-align: center; float: right; padding: 0 0 10px 10px; line-height: 1;&quot;&gt;&lt;img src=&quot;/images/2016-03-28-artsy-engineering-organization-stack/stack.jpg&quot;&gt;&lt;br&gt;&lt;font size=&quot;2px&quot;&gt;&lt;em&gt;The Artsy Engineering Organization &quot;Stack&quot; in 2012&lt;br&gt;from &lt;a target=&quot;_blank&quot; href=&quot;http://code.dblock.org/2011/07/12/sitting-is-killing-you-move-to-new-york.html&quot;&gt;&quot;Sitting is Killing You? Move to New York&quot;&lt;/a&gt;&lt;/em&gt;&lt;/font&gt;&lt;/div&gt;


&lt;p&gt;Artsy has now grown past 140 team members and our Engineering organization is a nimble 25. We&#39;ve recently performed a large organizational change (I highly recommend reading &lt;a href=&quot;https://www.artsy.net/article/robert-lenne-the-secret-s-to-company-re-orgs&quot;&gt;&quot;The Secret(s) to Company Re-Orgs&quot;&lt;/a&gt;), so this is a good time to describe our updated Engineering organization, starting from the top - Artsy as a company and business.&lt;/p&gt;

&lt;!-- more --&gt;


&lt;h2&gt;The Company&lt;/h2&gt;

&lt;p&gt;Artsy’s mission is to make all the world’s art accessible to anyone with an Internet connection. We are a resource for art collecting and education. Artsy features the world’s leading galleries, museum collections, foundations, artist estates, art fairs, and benefit auctions, all in one place. Our growing database of 350,000 images of art, architecture, and design by 50,000 artists spans historical, modern, and contemporary works, and includes the largest online database of contemporary art. Artsy is used by art lovers, museum-goers, patrons, collectors, students, and educators to discover, learn about, and collect art.&lt;/p&gt;

&lt;h2&gt;The Artsy Businesses&lt;/h2&gt;

&lt;p&gt;Artsy has 3 businesses: &lt;em&gt;Listings&lt;/em&gt;, &lt;em&gt;Marketplace&lt;/em&gt; and &lt;em&gt;Content&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Listings&lt;/strong&gt;: Artsy &lt;a href=&quot;https://www.artsy.net/galleries&quot;&gt;gallery partners&lt;/a&gt; pay a flat monthly subscription fee to list an unlimited number of artworks for sale, plus a host of other benefits. They do not pay a commission fee on sales made through Artsy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Marketplace&lt;/strong&gt;: In 2015 Artsy expanded into hosting commercial auctions on our platform. Much like our Listings business, we work with top auction houses. The latter pay commissions from sales. Check out &lt;a href=&quot;https://www.artsy.net/auctions&quot;&gt;current auctions on Artsy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Content&lt;/strong&gt;: We are also working on making Artsy a go-to platform for brands to co-create and distribute content that engages a global arts and culture audience. In 2015 we debuted our first sponsored content feature on Artsy, a &lt;a href=&quot;https://www.artsy.net/venice-biennale-2015&quot;&gt;series of 11 educational short films about the Venice Biennale in partnership with UBS&lt;/a&gt; (if anything, &lt;a href=&quot;https://www.artsy.net/article/artsy-editorial-behind-the-venice-biennale-2015-a-short-history-of-the-world-s-most-important-art-exhibition&quot;&gt;watch this amazing video&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;A Product Engineering Organization&lt;/h2&gt;

&lt;p&gt;We think of &lt;em&gt;Engineering&lt;/em&gt; as a service of the &lt;em&gt;Product&lt;/em&gt; organization. Products serve customers and product teams serve businesses. Each product team may contribute to one or several businesses. To make our goals crystal clear, we developed Key Performance Indicators (KPIs) for each business. For example, &lt;em&gt;churn&lt;/em&gt; is a KPI for the Listings business - a low churn shows how well we&#39;re serving our existing subscribers. Furthermore, we designed each product team to own all necessary resources to accomplish their goals. In some ways, our product teams operate like small start-ups.&lt;/p&gt;

&lt;p&gt;Each product team consists of one or more &lt;em&gt;Business People&lt;/em&gt;, a &lt;em&gt;Product Owner&lt;/em&gt; (often a &lt;em&gt;Product Manager&lt;/em&gt;), a &lt;em&gt;Designer&lt;/em&gt;, an &lt;em&gt;Engineering Lead&lt;/em&gt; and several &lt;em&gt;Engineers&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Our product teams map directly into our businesses and inherit the same KPIs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Partner Success&lt;/strong&gt;: The Partner Success team focuses on products that serve the Listings business. These include our Content Management system and &lt;a href=&quot;http://folio.artsy.net&quot;&gt;Artsy Folio&lt;/a&gt;, an iPad app used by our partners.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Auctions&lt;/strong&gt;: The Auctions product team builds all auction systems across web and mobile.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Collector GMV&lt;/strong&gt;: GMV stands for &lt;em&gt;Gross Merchandising Volume&lt;/em&gt;, a measure of artworks traded on the platform. We have two collector product teams, web and mobile, focused on various customer experiences across all our web and mobile properties.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Publishing&lt;/strong&gt;: The publishing team works on the platform used to produce and distribute all our online editorial content.&lt;/p&gt;

&lt;h2&gt;Practices&lt;/h2&gt;

&lt;p&gt;While there&#39;re many advantages of product teams operating independently, it&#39;s also very easy to create vertical inefficiencies. Multiple teams could choose to achieve similar outcomes in many different ways, creating a lot of redundant work and making it impossible for team members to move between organizations.&lt;/p&gt;

&lt;p&gt;To address this problem we&#39;ve created a separate &lt;em&gt;Platform Engineering Team&lt;/em&gt; and &lt;em&gt;Practices&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The Platform Engineering Team is responsible for systems and shared infrastructure that help product teams work smarter, scale our operations, and much more. Our &lt;em&gt;Design&lt;/em&gt; team is similar in nature to Platform Engineering, creating a consistent visual language and user experience across all products.&lt;/p&gt;

&lt;p&gt;Our &lt;em&gt;Practices&lt;/em&gt;, specifically &lt;em&gt;Web&lt;/em&gt; and &lt;em&gt;Mobile&lt;/em&gt;, are run by a handful of experienced Engineers working independently and floating between product teams to build features, while evangelizing best practices of making software or our &lt;a href=&quot;http://artsy.github.io/open-source&quot;&gt;commitment to open-source&lt;/a&gt; at the same time. Engineerers on product teams may also belong to a practice - mobile engineers on the Auctions team are members of the Mobile practice, but don&#39;t report to the Director of Mobile.&lt;/p&gt;

&lt;h2&gt;Reporting Structure&lt;/h2&gt;

&lt;p&gt;We believe that in order to help our team members grow professionally, their manager must understand their work. Engineers report to Engineering Leads in product teams. Engineering and Engineering Practice Leads report to the Head of Engineering. Product Managers report to the Head of Product. Designers report to the Design Lead, who reports to the Head of Product. It&#39;s important to note that, while preserving top-down authority and responsibility, we try to practice bottom-up leadership - the job of team leads is to help individual contributors do their best work.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;We have a very complex business, and we think our structure works well for a company that does many things at once. Your mileage may vary, so don&#39;t try to apply the same structure in your company just because this works for us! And always remember that evolving an organization is a disruptive process. It may yield better focus and can be transformational to a group. It may also produce the opposite effect, since moving individuals between teams is much more involved than drag-and-dropping a headcount in an organizational chart.&lt;/p&gt;
</description>
        <pubDate>Mon, 28 Mar 2016 00:00:00 +0000</pubDate>
        <link>http://artsy.github.io/blog/2016/03/28/artsy-engineering-organization-stack/</link>
        <guid isPermaLink="true">http://artsy.github.io/blog/2016/03/28/artsy-engineering-organization-stack/</guid>
        
        
        <category>people</category>
        
      </item>
    
      <item>
        <title>Public Speaking - Part 2: Where To Start?</title>
        <description>&lt;p&gt;So you’ve decided &lt;a href=&quot;http://artsy.github.io/blog/2016/03/09/public-speaking-part1-is-it-for-me/&quot;&gt;you’d like to give speaking a go&lt;/a&gt;, or perhaps you were always interested. By now you’re probably wondering where to start.&lt;/p&gt;

&lt;p&gt;There are various options depending on what you’re looking for. Would you prefer a smaller, intimate audience or would you like to reach far and wide? Is the topic of your choice suited for a quick talk or would you rather discuss it at length? Let’s have a look.&lt;/p&gt;

&lt;!-- more --&gt;


&lt;h3&gt;In-house / Workplace Knowledge Share&lt;/h3&gt;

&lt;p&gt;Lots of workplaces dedicate some time to knowledge sharing nowadays (and if yours doesn’t, see if you can start one!). They can be technical, for instance at Artsy we host a technical Lunch and Learn weekly. They could also be on any topic, like &lt;a href=&quot;https://www.artsy.net/article/natalia-maldonado-introduction-to-office-meditation-5-steps-to-peace-of-mind-at-work&quot;&gt;meditation&lt;/a&gt;. Anywhere between 5 and 15 minutes in length is common, and they are a perfect opportunity to talk about things you know well. This could be centred around your day to day work, spreading the knowledge to decrease &lt;a href=&quot;https://en.wikipedia.org/wiki/Bus_factor&quot;&gt;the bus factor&lt;/a&gt;, or something from your personal life. I’ve given a talk on &lt;a href=&quot;https://speakerdeck.com/mennenia/colour-theory&quot;&gt;colour theory in painting&lt;/a&gt; once.&lt;/p&gt;

&lt;p&gt;If you have a workplace you feel comfortable at, this is definitely a good place to start.&lt;/p&gt;

&lt;p&gt;One of the key elements in public speaking that is often forgotten is the fact that the audience wants you to succeed. They’re not there to poke holes or boo you off stage. They are curious to see what you have to say and learn from you. Give them that opportunity.&lt;/p&gt;

&lt;p&gt;Even if your goal is towards speaking at bigger events, any chance at practicing and putting together a well flowing talk is good and shouldn’t be ignored.&lt;/p&gt;

&lt;h3&gt;Local meet-ups&lt;/h3&gt;

&lt;p&gt;If you’re in a city that has a thriving meet-up scene, you may want to put your name forward to speak on a certain topic. A UK meet-up, &lt;a href=&quot;http://www.meetup.com/NSLondon/&quot;&gt;NSLondon&lt;/a&gt;, is a great example of this. Many different members of the community have spoken, and it’s created a lovely atmosphere where it feels like you’re exchanging interesting tidbits of information continuously. Also for newcomers it’s created a welcoming atmosphere, as the people speaking are often people they know or “just like them”.&lt;/p&gt;

&lt;p&gt;If you have a meet-up with a similar positive vibe, there’s no reason not to have a chat with the organisers and see what the next steps would be. It might even be well worth practicing a talk here, for when you’ve got a bigger event coming up and you would like feedback. Bare in mind, the audience wants you to succeed!&lt;/p&gt;

&lt;p&gt;Sidenote — if your city does not (yet) have a great meet-up, it’s well worth starting one.&lt;/p&gt;

&lt;h3&gt;Conferences&lt;/h3&gt;

&lt;p&gt;Often considered the most intimidating of all. People have purchased tickets and possibly travelled from far. The audience is usually in the hundreds, occasionally even more than a thousand. Even the most experienced speakers can get a bit nervous for this.&lt;/p&gt;

&lt;p&gt;Funnily enough, my first ever talk, since starting out as a developer, was at a &lt;a href=&quot;http://www.iosdevuk.com/&quot;&gt;conference&lt;/a&gt;. It happened to have a very friendly atmosphere and really wasn’t that scary. I can’t stress enough that, yes, the audience wants you to succeed. I remember talking through my introduction and seeing all the curious, attentive faces. They were there because they were interested. They cared for what I had to say.&lt;/p&gt;

&lt;p&gt;I will say that this doesn’t necessarily mean you should go talk about anything your heart desires. Ultimately the attendees are there to learn, so it’s only fair that as speakers you’d tailor your presentation towards your audience. But more on that in Part 3.&lt;/p&gt;

&lt;p&gt;To be considered, often conference organisers ask people to submit a CfP (Call for Papers / Call for Proposals). This is your chance to submit details on what you’d like to present on, although they may &lt;a href=&quot;http://www.osfeels.com/talk-ideas/&quot;&gt;give you suggestions&lt;/a&gt;. You usually want to include a preliminary talk title, an abstract, and a bit of background on yourself. If you’ve done any talks before and they happen to have been recorded, it’s worth including the video or otherwise previous slidedecks.&lt;/p&gt;

&lt;p&gt;As for how CfPs then get chosen depends on the conference. Most of the time the organisational committee selects talks from the proposal list. Some conferences have &lt;a href=&quot;http://www.altconf.com&quot;&gt;an independent panel&lt;/a&gt; review anonymised proposals or have a system in place where &lt;a href=&quot;http://cfp.uikonf.com/about&quot;&gt;the community votes&lt;/a&gt;. Once it’s been decided, they will get back in touch with you.&lt;/p&gt;

&lt;p&gt;Usually conferences are swarmed with CfPs so please don’t be discouraged if it takes a few tries to get picked. It’s understandable to feel rejected and give up, but bare in mind that a friend of mine felt this way yet kept applying. He got his break at NSSpain 2014, and now is incredibly active in the &lt;a href=&quot;http://www.meetup.com/swift-language/&quot;&gt;San Francisco Swift&lt;/a&gt; meet-up scene. All of this got the ball rolling and now he&#39;s given talks all around the world. &lt;a href=&quot;https://twitter.com/simjp&quot;&gt;You might even have heard of him&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Lightning talks&lt;/h3&gt;

&lt;p&gt;If a CfP is a bit too much to prepare at the moment (we’re all busy) or you didn’t get in, another option is to give a lightning talk if the conference of your choice has slots. When done well, they are great.&lt;/p&gt;

&lt;p&gt;A lightning talk is usually capped at 5 minutes, and gives you the time and space to cover one thing well. The best ones I’ve heard, have had one main message to convey and did so excellently.&lt;/p&gt;

&lt;p&gt;They require a bit of planning as you &lt;a href=&quot;http://quoteinvestigator.com/2012/04/28/shorter-letter/&quot;&gt;want to be concise&lt;/a&gt;, but will be done before you know it and gives the audience a great point of reference to engage with you. Not to mention that sometimes you might get asked to do a full talk based off these.&lt;/p&gt;

&lt;h3&gt;Preparing content&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://artsy.github.io/blog/2016/03/09/public-speaking-part1-is-it-for-me/&quot;&gt;Choosing to publicly speak&lt;/a&gt; and where is only half the battle. Deciding the content, formulating an abstract, talk title, and slides are not trivial. But fear not, Part 3 in this series will have you covered. Stay tuned!&lt;/p&gt;
</description>
        <pubDate>Mon, 14 Mar 2016 11:00:00 +0000</pubDate>
        <link>http://artsy.github.io/blog/2016/03/14/public-speaking-part2-where-to-start/</link>
        <guid isPermaLink="true">http://artsy.github.io/blog/2016/03/14/public-speaking-part2-where-to-start/</guid>
        
        
        <category>community</category>
        
        <category>learning</category>
        
        <category>oss</category>
        
        <category>speaking</category>
        
        <category>teaching</category>
        
      </item>
    
      <item>
        <title>Public Speaking - Part 1: Is It For Me?</title>
        <description>&lt;p&gt;At Artsy, sharing knowledge is heavily encouraged and so we write our code in the open, document using blog posts, and speak about our experiences. Many have &lt;a href=&quot;https://twitter.com/qnoid/status/702955785064677376&quot;&gt;bumped into us&lt;/a&gt; at various places around the world. And so I often get the question: “How did you get started? I’m interested in speaking too”.&lt;/p&gt;

&lt;p&gt;In the name of sharing experiences with others, I can’t encourage this enough. Unfortunately though, public speaking is still considered &lt;a href=&quot;https://www.washingtonpost.com/news/wonk/wp/2014/10/30/clowns-are-twice-as-scary-to-democrats-as-they-are-to-republicans/&quot;&gt;man’s biggest fear&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’d like to share with you the benefits of public speaking, tips on how to get started, and how to give great presentations.&lt;/p&gt;

&lt;!-- more --&gt;


&lt;h2&gt;Why do it?&lt;/h2&gt;

&lt;h3&gt;Communication&lt;/h3&gt;

&lt;p&gt;Without necessarily realising, you’re publicly speaking all the time. At the heart of it, it’s the act of communicating and expressing your ideas and viewpoints for others to understand.&lt;/p&gt;

&lt;p&gt;It could be as simple as ordering your morning coffee or as important as trying to convince your team that they should use a new technology. Regardless of the context, it involves restructuring your thoughts into words and metaphors that you think others can relate to in order for them to understand your concepts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Public speaking is a skill that is always good to improve on&lt;/strong&gt;. Misunderstandings happen all the time, and at the heart of that is often poor communication.&lt;/p&gt;

&lt;p&gt;I know people have refrained from speaking up in meetings at work, because they struggle with speaking in front of others. There’s no need for everyone to be a keynote speaker at a conference, but if it’s hindering you in your career, it may be worth practicing. Everyone should feel empowered to call a meeting, participate in discussions, or ask questions at an all hands.&lt;/p&gt;

&lt;h3&gt;Learning&lt;/h3&gt;

&lt;p&gt;Another reason giving talks is 👍🏽 is that it will allow you to learn more fully. One of the best ways to learn is by &lt;a href=&quot;http://ideas.time.com/2011/11/30/the-protege-effect/&quot;&gt;teaching others&lt;/a&gt;. You grasp ideas better yourself and in order to communicate them properly, you get into the habit of restructuring your ideas and concepts.&lt;/p&gt;

&lt;p&gt;Unfortunately, people often also consider this the blocker to public speaking. Not only are you afraid you’ll accidentally make a fool of yourself (“what if I trip?”) but also that it will be apparent that you don’t know something well enough. The only way to get over this is by doing it.&lt;/p&gt;

&lt;p&gt;Chances are that you are actually very knowledgeable in certain fields, you just perceive that as normal. “Yeah, but that’s not interesting… everyone knows about &lt;em&gt;that&lt;/em&gt;”. And I can bet that, well, probably not everyone knows about that. Definitely not as much as you might actually do.&lt;/p&gt;

&lt;p&gt;We all have our strengths. This is the time to play on them. We can’t be experts in both Core Image, Core Animation, and the Objective C runtime, all the while knowing everything about Swift Protocols. Pick your slice from a much wider scope. It doesn’t need to be a full framework, even just a specific use case of it, like &lt;a href=&quot;https://realm.io/news/gwendolyn-weston-ios-background-networking/&quot;&gt;background transfer services&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Furthermore, see it as a learning opportunity. Speak about a topic that truly interests you and take this time to uncover things you’ve always wanted to know. It does not require you to be an expert up front — sharing knowledge gives you the chance to become one.&lt;/p&gt;

&lt;p&gt;For example, I wanted to give a talk on the beauty of design and why beautiful things “just work”. I took this chance to read papers and books on the field of positive psychology and design, learning all kinds of fun new facts. Others have shared with me also that it wasn’t until they decided to write or speak about certain API that they fully got to understand all the ins and outs.&lt;/p&gt;

&lt;h2&gt;Ok you got me interested… now what?&lt;/h2&gt;

&lt;p&gt;That&#39;s great!&lt;/p&gt;

&lt;p&gt;Next you&#39;d probably want to figure out where you&#39;d like to speak and how to prepare a good talk. This will be covered in the next two posts, so stay tuned.&lt;/p&gt;
</description>
        <pubDate>Wed, 09 Mar 2016 11:00:00 +0000</pubDate>
        <link>http://artsy.github.io/blog/2016/03/09/public-speaking-part1-is-it-for-me/</link>
        <guid isPermaLink="true">http://artsy.github.io/blog/2016/03/09/public-speaking-part1-is-it-for-me/</guid>
        
        
        <category>community</category>
        
        <category>learning</category>
        
        <category>oss</category>
        
        <category>speaking</category>
        
        <category>teaching</category>
        
      </item>
    
      <item>
        <title>Code Injection for Xcode</title>
        <description>&lt;p&gt;I have been writing code for roughly a decade. A large chunk of that time has been sitting waiting for my project to compile. It&#39;s a nice excuse to &lt;a href=&quot;https://xkcd.com/303/&quot;&gt;practice sword fighting&lt;/a&gt; in the office, but really, deep down. It&#39;s frustrating. It&#39;s so easy to become &lt;a href=&quot;https://xkcd.com/356/&quot;&gt;nerd-sniped&lt;/a&gt; when you wait for a long time.&lt;/p&gt;

&lt;p&gt;As we integrate Swift into our projects, I&#39;ve been seeing our compile times increase. So, I took some time to look at ways to improve this. The best option, so far, has been dynamic code injection via &lt;a href=&quot;https://github.com/johnno1962/injectionforxcode&quot;&gt;Injection Plugin for Xcode&lt;/a&gt;. In a gist: This means that we don&#39;t recompile and re-launch, instead we inject new bits of code into a running application. This reduced the compile cycle on Eigen from 7 seconds to 1 second.&lt;/p&gt;

&lt;p&gt;I took some time over the weekend to try and put together a video showing how I used code injection on a trivial app to create a view controller in code. It covers the technique I&#39;ve &lt;a href=&quot;https://github.com/artsy/eigen/pull/1236&quot;&gt;started using in Eigen&lt;/a&gt; and talks a little bit about how the pieces come together.&lt;/p&gt;

&lt;p&gt;Jump &lt;a href=&quot;https://www.youtube.com/watch?v=uftvtmyZ8TM&quot;&gt;to YouTube&lt;/a&gt; for the video, or click more for a smaller inline preview.&lt;/p&gt;

&lt;!-- more --&gt;


&lt;p&gt;&lt;/div&gt;&lt;/div&gt;&lt;iframe width=&#39;100%&#39; height=&#39;600&#39; src=&#39;https://www.youtube.com/embed/uftvtmyZ8TM &#39; frameborder=&#39;0&#39; allowfullscreen&gt;&lt;/iframe&gt;&lt;div class=&#39;meta-container&#39;&gt;&lt;header&gt;&amp;nbsp;&lt;/header&gt;&lt;/div&gt;&lt;div class=&#39;content-container&#39;&gt;&lt;div class=&#39;entry-content&#39;&gt;&lt;/p&gt;
</description>
        <pubDate>Sat, 05 Mar 2016 12:09:00 +0000</pubDate>
        <link>http://artsy.github.io/blog/2016/03/05/iOS-Code-Injection/</link>
        <guid isPermaLink="true">http://artsy.github.io/blog/2016/03/05/iOS-Code-Injection/</guid>
        
        
        <category>mobile</category>
        
        <category>swift</category>
        
        <category>video</category>
        
        <category>xcode</category>
        
      </item>
    
      <item>
        <title>Being a Better Programmer When You&#39;re Actually Lazy.</title>
        <description>&lt;p&gt;I juggle a bunch of projects, both in Artsy and in the Open Source community. If you don&#39;t work with me directly, you&#39;d be mistaken for believing that I was an organized person. I&#39;m pretty far from that, and &lt;a href=&quot;https://github.com/artsy/mobile/issues/68&quot;&gt;don&#39;t really&lt;/a&gt; plan on changing that.&lt;/p&gt;

&lt;p&gt;However, I work with other people and very strongly believe that programming is mostly a social problem once you&#39;re good enough at writing code. It&#39;d be hypocritical of me to not improve the people process side, so I try to automate processes that makes me a better team-mate.&lt;/p&gt;

&lt;p&gt;I&#39;m going to cover four things I&#39;ve worked on lately to improve this: &lt;a href=&quot;https://github.com/danger/danger/&quot;&gt;Danger&lt;/a&gt;, &lt;a href=&quot;https://github.com/orta/github-clippers&quot;&gt;GitHub-Clippers&lt;/a&gt; and improving how I write commits and prefixing my name on branches.&lt;/p&gt;

&lt;!-- more --&gt;


&lt;h3&gt;Danger&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/danger/danger/&quot;&gt;Danger&lt;/a&gt; is a tool I co-created with a friend (&lt;a href=&quot;https://github.com/krausefx/&quot;&gt;Felix Krause&lt;/a&gt;), and it&#39;s namesake, &lt;a href=&quot;https://github.com/dangermcshane&quot;&gt;Gem &quot;Danger&quot; McShane&lt;/a&gt;. It came out of frustration that we couldn&#39;t easily hold ourselves accountable to better team processes. Requiring a code-reviewer to  also remember details like &quot;Add a CHANGELOG Entry&quot; isn&#39;t much to ask, but it is &quot;Yet Another Thing To Remember&quot; for both the submitter and reviewer.&lt;/p&gt;

&lt;p&gt;It&#39;s turning into a really important part of our code-review, and the ideas it generates once we had it in place make it fun to add new rules. It means we can fail fast, and not have to think about process so much. Danger will tell us if we&#39;ve missed something.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2016-03-02-Lazily-Automation/danger.png&quot; alt=&quot;Danger Example&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I expect to write a more serious post on &lt;a href=&quot;https://github.com/danger/danger/&quot;&gt;Danger&lt;/a&gt; once it&#39;s more fleshed out. For now though, the README covers what it does well.&lt;/p&gt;

&lt;h3&gt;Clippers&lt;/h3&gt;

&lt;p&gt;In every big team I operate in, other people care about keeping the repo clean of merged branches. I totally respect their opinion, but it&#39;s so low on things I care about that I just don&#39;t register the &quot;Delete Branch&quot; button on a GitHub pull request. I&#39;d rather be finding a &lt;a href=&quot;https://github.com/orta/gifs&quot;&gt;good response GIF&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So I created &lt;a href=&quot;https://github.com/orta/github-clippers&quot;&gt;a Safari Extension&lt;/a&gt; that handles automatically deleting branches on specific repos for me. It&#39;s not a biggie, it&#39;s not fancy, it&#39;s under a &lt;a href=&quot;https://github.com/orta/github-clippers/blob/master/GitHub-Clippers.safariextension/github_clippers.js&quot;&gt;hundred lines of code&lt;/a&gt; - but it automates something that annoyed others about my behavior. That counts for something.&lt;/p&gt;

&lt;h3&gt;Commit Automation&lt;/h3&gt;

&lt;p&gt;I write &lt;em&gt;reasonable&lt;/em&gt; commit messages, they&#39;re not &lt;a href=&quot;http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html&quot;&gt;amazing&lt;/a&gt;, they&#39;re &lt;a href=&quot;http://www.whatthecommit.com&quot;&gt;not terrible&lt;/a&gt;. They&#39;re just, &lt;a href=&quot;https://github.com/artsy/energy/commits/master?author=orta&quot;&gt;alright&lt;/a&gt;. I wanted to start trying to hold everyone accountable for doing better, so I advocated for copying the person with the &lt;a href=&quot;https://github.com/artsy/eigen/commits/master?author=alloy&quot;&gt;best commit style&lt;/a&gt; on our team.&lt;/p&gt;

&lt;p&gt;Their style is to have commits in a format like &lt;code&gt;[Context] Thing I did.&lt;/code&gt; - it is much better that &lt;code&gt;Thing I did.&lt;/code&gt;. So I looked into how I could automate this, because I would very quickly forget to do this. Here&#39;s what I did:&lt;/p&gt;

&lt;div class=&#39;bogus-wrapper&#39;&gt;&lt;notextile&gt;&lt;figure class=&#39;code&#39;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#39;line-number&#39;&gt;1&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;2&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;3&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;4&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;5&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;6&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;7&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;8&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;9&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;10&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;11&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;12&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;13&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;14&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;15&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;16&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;17&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;18&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;19&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;20&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;21&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;22&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;23&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;24&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;25&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;pre&gt;&lt;code class=&#39;sh&#39;&gt;&lt;span class=&#39;line&#39;&gt;// Helper &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; to get the branch info
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; git_branch_info&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;  &lt;span class=&quot;nv&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;command &lt;/span&gt;git symbolic-ref HEAD 2&amp;gt; /dev/null&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;  &lt;span class=&quot;nv&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;command &lt;/span&gt;git rev-parse --short HEAD 2&amp;gt; /dev/null&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;  &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;${ref#refs/heads/}&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; branch&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;  git checkout master&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;  git pull upstream master&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;  git checkout -b &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;  git config branch.&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;.description &lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; commit&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;  &lt;span class=&quot;nb&quot;&gt;local &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BRANCH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;git_branch_info&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;  &lt;span class=&quot;nb&quot;&gt;local &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;INFO&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;git config branch.&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$BRANCH&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;.description&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;  git commit -m &lt;span class=&quot;s2&quot;&gt;&amp;quot;[$(echo $INFO)] $argv&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;// And &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; I forget to &lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;my context
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; context&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;  &lt;span class=&quot;nb&quot;&gt;local &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BRANCH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;git_branch_info&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;  git config branch.&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$BRANCH&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;.description &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/notextile&gt;&lt;/div&gt;


&lt;p&gt;Or if you&#39;re a fish user like me, &lt;a href=&quot;https://gist.github.com/orta/902d8e576a2b75afe2df&quot;&gt;this gist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I created two shell functions, one that makes a branch that includes a context type. So for example, say I&#39;m working on artwork notifications, I&#39;d start a new branch with &lt;code&gt;$ branch artwork_notifications Notifications&lt;/code&gt;. This saves the context as &lt;code&gt;Notifications&lt;/code&gt; on the git branch metadata. Then everytime I want to commit my changes, I use &lt;code&gt;$ commit This is the thing I changed.&lt;/code&gt; - and it will be prefixed with &lt;code&gt;[Notifications]&lt;/code&gt;. It makes it easier for someone looking through the history to have an idea about the context, and makes me feel like I&#39;m improving my process without remembering the context.&lt;/p&gt;

&lt;h3&gt;Branch Prefixes&lt;/h3&gt;

&lt;p&gt;We use a Makefile in all our projects to try and help automate per-project simple tasks like running &lt;a href=&quot;https://github.com/artsy/energy/blob/e5db035225490fb53c65c74a6c1bdd660f305ab6/Makefile#L44&quot;&gt;mogenerator&lt;/a&gt;, updating &lt;a href=&quot;https://github.com/artsy/energy/blob/e5db035225490fb53c65c74a6c1bdd660f305ab6/Makefile#L49&quot;&gt;storyboard identifiers&lt;/a&gt; and updating &lt;a href=&quot;https://github.com/artsy/eigen/blob/12fe9de4d927eea27f4942d15e74b89016a6345f/Makefile#L102-L103&quot;&gt;embedded resources&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I also applied some standard make commands in our projects so that I can prefix my &lt;a href=&quot;https://github.com/artsy/eigen/blob/10106210196f096a27412a70af61dcae7fda285c/Makefile#L110-L117&quot;&gt;branches with my name&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&#39;bogus-wrapper&#39;&gt;&lt;notextile&gt;&lt;figure class=&#39;code&#39;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#39;line-number&#39;&gt;1&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;2&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;3&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;4&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;5&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;6&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;7&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;8&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;9&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;10&lt;/span&gt;
&lt;span class=&#39;line-number&#39;&gt;11&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#39;code&#39;&gt;&lt;pre&gt;&lt;code class=&#39;sh&#39;&gt;&lt;span class=&#39;line&#39;&gt;&lt;span class=&quot;nv&quot;&gt;LOCAL_BRANCH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;shell git rev-parse --abbrev-ref HEAD&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;&lt;span class=&quot;nv&quot;&gt;BRANCH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;shell &lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;github.com &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; git credential fill &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; sed -E &lt;span class=&quot;s1&quot;&gt;&amp;#39;N; s/.*username=(.+)\n?.*/\1/&amp;#39;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;-&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;shell git rev-parse --abbrev-ref HEAD&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;pr:
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;$(LOCAL_BRANCH)&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;master&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;In master, not PRing&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; git push upstream &lt;span class=&quot;s2&quot;&gt;&amp;quot;$(LOCAL_BRANCH):$(BRANCH)&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; open &lt;span class=&quot;s2&quot;&gt;&amp;quot;https://github.com/artsy/eigen/pull/new/artsy:master...$(BRANCH)&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;push:
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;$(LOCAL_BRANCH)&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;master&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;In master, not pushing&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; git push upstream &lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;LOCAL_BRANCH&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;:&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;BRANCH&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;fpush:
&lt;/span&gt;&lt;span class=&#39;line&#39;&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;$(LOCAL_BRANCH)&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;master&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;In master, not pushing&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; git push upstream &lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;LOCAL_BRANCH&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;:&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;BRANCH&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt; --force&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/notextile&gt;&lt;/div&gt;


&lt;p&gt;This works by some funky shell work to pull out your current branch into &lt;code&gt;LOCAL_BRANCH&lt;/code&gt;, then to do the same thing but prefixed with your login name for &lt;code&gt;BRANCH&lt;/code&gt;. Then the make commands handle pushing to the server. This means that everyone in the team can provide have logically named branches without having to have their local repo filled with &lt;code&gt;[my_name]-thing&lt;/code&gt; branches.&lt;/p&gt;

&lt;h2&gt;On-going&lt;/h2&gt;

&lt;p&gt;This is a work in progress, as the mobile team grows, we need to add more process when it&#39;s appropriate. This &lt;em&gt;doesn&#39;t&lt;/em&gt; mean that we have to sacrifice speed, and we can continue thinking about the problem at hand rather than devoting energy to process.&lt;/p&gt;

&lt;p&gt;It&#39;s a time trade-off that has worked out well for me so far, and I&#39;d love to know other people&#39;s hacks for having useful process, but automating it so that it&#39;s not considered overhead.&lt;/p&gt;
</description>
        <pubDate>Wed, 02 Mar 2016 12:09:00 +0000</pubDate>
        <link>http://artsy.github.io/blog/2016/03/02/Lazily-Automation/</link>
        <guid isPermaLink="true">http://artsy.github.io/blog/2016/03/02/Lazily-Automation/</guid>
        
        
        <category>automation</category>
        
        <category>culture</category>
        
        <category>teams</category>
        
      </item>
    
      <item>
        <title>Code Review: Energy Sync</title>
        <description>&lt;p&gt;We are slowly trying to do high-level code-review views for all of our iOS apps. So far, we&#39;ve covered &lt;a href=&quot;/blog/2016/01/14/eidolon-code-review/&quot;&gt;Eidolon&lt;/a&gt; and &lt;a href=&quot;/blog/2015/11/05/Emergence-Code-Review/&quot;&gt;Emergence&lt;/a&gt; and now &lt;a href=&quot;/blog/2016/02/11/Code-Review-Energy/&quot;&gt;Energy&lt;/a&gt;. This is the second part of the Energy code review. The &lt;a href=&quot;/blog/2016/02/11/Code-Review-Energy/&quot;&gt;first part&lt;/a&gt; covers the the critical codepaths that go from the App&#39;s launch to sending an email, which is the main use-case for the app. This video covers how Folio does sync between the Artsy API and the app.&lt;/p&gt;

&lt;p&gt;Sync is a complex problem. This video covers our old techniques, how we changed them, the underlying abstractions we use now and how we can test each component individually. It&#39;s an hour long, and it&#39;s a little computer-sciencey. So I think people who have shipped some small apps would get a lot out of it.&lt;/p&gt;

&lt;p&gt;Jump &lt;a href=&quot;https://www.youtube.com/watch?v=05HaKChPe_g&quot;&gt;to YouTube&lt;/a&gt; for the video, or click more for a smaller inline preview.&lt;/p&gt;

&lt;!-- more --&gt;


&lt;p&gt;&lt;/div&gt;&lt;/div&gt;&lt;iframe width=&#39;100%&#39; height=&#39;600&#39; src=&#39;https://www.youtube.com/embed/05HaKChPe_g &#39; frameborder=&#39;0&#39; allowfullscreen&gt;&lt;/iframe&gt;&lt;div class=&#39;meta-container&#39;&gt;&lt;header&gt;&amp;nbsp;&lt;/header&gt;&lt;/div&gt;&lt;div class=&#39;content-container&#39;&gt;&lt;div class=&#39;entry-content&#39;&gt;&lt;/p&gt;
</description>
        <pubDate>Fri, 12 Feb 2016 12:09:00 +0000</pubDate>
        <link>http://artsy.github.io/blog/2016/02/12/Code-Review-Energy-Sync/</link>
        <guid isPermaLink="true">http://artsy.github.io/blog/2016/02/12/Code-Review-Energy-Sync/</guid>
        
        
        <category>energy</category>
        
        <category>folio</category>
        
        <category>ios</category>
        
        <category>mobile</category>
        
        <category>oss</category>
        
        <category>review</category>
        
        <category>video</category>
        
      </item>
    
      <item>
        <title>Code Review: Energy overview</title>
        <description>&lt;p&gt;We are slowly trying to do high-level code-review views for all of our iOS apps. So far, we&#39;ve covered &lt;a href=&quot;/blog/2016/01/14/eidolon-code-review/&quot;&gt;Eidolon&lt;/a&gt; and &lt;a href=&quot;/blog/2015/11/05/Emergence-Code-Review/&quot;&gt;Emergence&lt;/a&gt;. Folio is an app that&#39;s shipped to the App Store in early 2012, it&#39;s used by our Partners to showcase their works offline, at fairs and on the go. If you want the full spiel, check out &lt;a href=&quot;http://folio.artsy.net&quot;&gt;this microsite&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This video talks through a lot of the critical codepaths that go from the App&#39;s launch to sending an email, which is the main use-case for the app. We have another video coming up which exclusively covers how Folio does sync between the Artsy API and the app.&lt;/p&gt;

&lt;p&gt;Jump &lt;a href=&quot;https://www.youtube.com/watch?v=Xhd25hFzN4o&quot;&gt;to YouTube&lt;/a&gt; for the video, or click more for a smaller inline preview.&lt;/p&gt;

&lt;!-- more --&gt;


&lt;p&gt;&lt;/div&gt;&lt;/div&gt;&lt;iframe width=&#39;100%&#39; height=&#39;600&#39; src=&#39;https://www.youtube.com/embed/Xhd25hFzN4o &#39; frameborder=&#39;0&#39; allowfullscreen&gt;&lt;/iframe&gt;&lt;div class=&#39;meta-container&#39;&gt;&lt;header&gt;&amp;nbsp;&lt;/header&gt;&lt;/div&gt;&lt;div class=&#39;content-container&#39;&gt;&lt;div class=&#39;entry-content&#39;&gt;&lt;/p&gt;
</description>
        <pubDate>Thu, 11 Feb 2016 11:09:00 +0000</pubDate>
        <link>http://artsy.github.io/blog/2016/02/11/Code-Review-Energy/</link>
        <guid isPermaLink="true">http://artsy.github.io/blog/2016/02/11/Code-Review-Energy/</guid>
        
        
        <category>energy</category>
        
        <category>folio</category>
        
        <category>ios</category>
        
        <category>mobile</category>
        
        <category>oss</category>
        
        <category>review</category>
        
        <category>video</category>
        
      </item>
    
  </channel>
</rss>
