<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Posts on Brodie Kurczynski</title>
        <link>/posts/</link>
        <description>Recent content in Posts on Brodie Kurczynski</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en-us</language>
        <copyright>&lt;a href=&#34;https://creativecommons.org/licenses/by-nc/4.0/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;CC BY-NC 4.0&lt;/a&gt;</copyright>
        <lastBuildDate>Tue, 15 Oct 2024 16:06:20 -0700</lastBuildDate>
        <atom:link href="/posts/index.xml" rel="self" type="application/rss+xml" />
        
        <item>
            <title>Go Proxy</title>
            <link>/posts/2024/10/go-proxy/</link>
            <pubDate>Tue, 15 Oct 2024 16:06:20 -0700</pubDate>
            
            <guid>/posts/2024/10/go-proxy/</guid>
            <description>I&amp;rsquo;ve been using a lot of Go lately and I don&amp;rsquo;t have a whole lot of meaningful complaints about it, but I am still figuring out all the bastard gotchas. The most recent one I learned about the hard way was module caching using the Go proxy while building several microservices for a side project. Because it&amp;rsquo;s a side project, a lot of the planning has been done on a whiteboard and by writing shitty throw away code before implementing anything useful.</description>
            <content type="html"><![CDATA[<p>I&rsquo;ve been using a lot of Go lately and I don&rsquo;t have a whole lot of meaningful complaints about it, but I am still
figuring out all the bastard gotchas. The most recent one I learned about the hard way was module caching using the Go
proxy while building several microservices for a side project. Because it&rsquo;s a side project, a lot of the planning has
been done on a whiteboard and by writing shitty throw away code before implementing anything useful. A side effect from
this is that the data structures used across the microservices are defined in each service which is fine while
everything is still in flux.</p>
<p>Once changes to the data structures slowed down a bit I started to define them in a more respectable way by putting them
in a common library to be used across services. This was great but
because <a href="https://martinfowler.com/bliki/TwoHardThings.html">naming is extremely difficult</a>, I went back and forth a few
times with the module name and its packages. Well, this broke all my services using the common library and gave me
dependency naming errors that I knew damn well were wrong. I tried all the fixes I found on the internets:</p>
<ul>
<li><code>go mod tidy</code></li>
<li><code>go clean -modcache</code></li>
<li><code>go clean -cache</code></li>
<li>Manually deleting the dependencies in <code>GOPATH</code></li>
</ul>
<p>I even tried a nonsensical Hail Mary of deleting my <code>go.mod</code> and generating a new one. Nothing. Eventually I scrolled
way down on a <a href="https://stackoverflow.com/a/77261496/1053066">Stack Overflow post</a> and found something that didn&rsquo;t even
cross my mind:</p>
<pre tabindex="0"><code>Since Go 1.13, the go command by default downloads and authenticates modules using the Go module mirror and Go checksum database.
</code></pre><p>Ah! That&rsquo;s why it worked at first but started failing when I made changes to the common library quickly, the changes
hadn&rsquo;t been picked up by the proxy cache yet. This works perfectly if you just need a specific version of a dependency
but not so much for rapid development. To directly interact with the dependency&rsquo;s repo without any caching, you just
need to configure <code>GOPROXY</code> like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>GOPROXY<span style="color:#f92672">=</span>direct go build main.go
</span></span></code></pre></div><h3 id="bonus">Bonus</h3>
<p>Even though this solves my initial problem of quickly updating my common library, I still need to commit changes, push
changes, and pull those changes back to my workstation which is pretty cumbersome. Fortunately, Go has an answer for
this with the <a href="https://go.dev/doc/tutorial/call-module-code">replace directive</a> which allows you to point your
dependency to a different location:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>go mod edit -replace gitlab.com/common/lib<span style="color:#f92672">=</span>../common/lib
</span></span></code></pre></div><p>This will update your <code>go.mod</code> to seamlessly use the local module in <code>../common/lib</code> instead of the remote module at
<code>gitlab.com/common/lib</code>. Then, once you&rsquo;re done making frequent changes to the dependency, you can put it back to use
the original remote location for the dependency:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>go mod edit -drporeplace gitlab.com/common/lib
</span></span></code></pre></div><p>This is awesome for making changes quickly. Now I just have to figure out a way to use this when I want to do rapid
development using containers&hellip;</p>
]]></content>
        </item>
        
        <item>
            <title>Git Index</title>
            <link>/posts/2024/07/git-index/</link>
            <pubDate>Wed, 17 Jul 2024 15:52:22 -0700</pubDate>
            
            <guid>/posts/2024/07/git-index/</guid>
            <description>TL;DR Be careful how file path values are written to the git index because they can be set to any value (not just filenames) if you&amp;rsquo;re manipulating the index manually instead of with git. I created a repo with all the code snippets to make things easier to follow instead having of digging through my project with of unrelated application logic.
Project I was working on a Go project recently that needed to interact with a git repo that took me down a very unexpected, but interesting, rabbit hole.</description>
            <content type="html"><![CDATA[<h2 id="tldr">TL;DR</h2>
<p>Be careful how file path values are written to the git index because they can be set to <em>any</em> value (not just
filenames) if you&rsquo;re manipulating the index manually instead of with git. I created
a <a href="https://gitlab.com/kurczynski-web/git-index">repo</a> with all the code snippets to make things easier to follow instead
having of digging through my project with of unrelated application logic.</p>
<h1 id="project">Project</h1>
<p>I was working on a <a href="https://gitlab.com/kurczynski/helm-bump">Go project</a> recently that needed to interact with a git
repo that took me down a very unexpected, but interesting, rabbit hole. Without going into a bunch of unrelated detail,
my project needed to accomplish the following things in a git repo:</p>
<ul>
<li>Read a file in the repo</li>
<li>Update the contents of the file</li>
<li>Write the changes to disk</li>
<li>Add the file changes to git</li>
<li>Commit the file changes</li>
</ul>
<h1 id="implementation">Implementation</h1>
<p>I&rsquo;m writing this project in Go, so I&rsquo;ll need a way to interact with git. I decided to
use <a href="https://github.com/go-git/go-git">go-git</a> because it was one of the first libraries that popped up. But first,
let&rsquo;s read the file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">ReadFile</span>(<span style="color:#a6e22e">filename</span> <span style="color:#66d9ef">string</span>) (<span style="color:#66d9ef">string</span>, <span style="color:#66d9ef">error</span>) {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">b</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">ReadFile</span>(<span style="color:#a6e22e">filename</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> string(<span style="color:#a6e22e">b</span>), <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Update the file contents that is returned from the function above:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">updatedContent</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">strings</span>.<span style="color:#a6e22e">ReplaceAll</span>(<span style="color:#a6e22e">content</span>, <span style="color:#e6db74">&#34;great&#34;</span>, <span style="color:#e6db74">&#34;good&#34;</span>)
</span></span></code></pre></div><p>Write the updated contents to file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">WriteFile</span>(<span style="color:#a6e22e">filename</span> <span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">content</span> <span style="color:#66d9ef">string</span>) <span style="color:#66d9ef">error</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">tmpFile</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Sprintf</span>(<span style="color:#e6db74">&#34;%s.tmp&#34;</span>, <span style="color:#a6e22e">filename</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">fout</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Create</span>(<span style="color:#a6e22e">tmpFile</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">defer</span> <span style="color:#a6e22e">fout</span>.<span style="color:#a6e22e">Close</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">bufOut</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">bufio</span>.<span style="color:#a6e22e">NewWriter</span>(<span style="color:#a6e22e">fout</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">defer</span> <span style="color:#a6e22e">bufOut</span>.<span style="color:#a6e22e">Flush</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">err</span> = <span style="color:#a6e22e">bufOut</span>.<span style="color:#a6e22e">WriteString</span>(<span style="color:#a6e22e">content</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">err</span> = <span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Rename</span>(<span style="color:#a6e22e">tmpFile</span>, <span style="color:#a6e22e">filename</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Finally, add the updated file to git:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">AddToRepo</span>(<span style="color:#a6e22e">repo</span> <span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">filepath</span> <span style="color:#66d9ef">string</span>) <span style="color:#66d9ef">error</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">gitRepo</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">git</span>.<span style="color:#a6e22e">PlainOpen</span>(<span style="color:#a6e22e">repo</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">gitWorktree</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">gitRepo</span>.<span style="color:#a6e22e">Worktree</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">err</span> = <span style="color:#a6e22e">gitWorktree</span>.<span style="color:#a6e22e">Add</span>(<span style="color:#a6e22e">filepath</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">err</span> = <span style="color:#a6e22e">gitWorktree</span>.<span style="color:#a6e22e">Commit</span>(<span style="color:#e6db74">&#34;Updated file contents&#34;</span>, <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">git</span>.<span style="color:#a6e22e">CommitOptions</span>{})
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Bring it all together to run:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#f92672">package</span> <span style="color:#a6e22e">main</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> (
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;bufio&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;fmt&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;github.com/go-git/go-git/v5&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;os&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;strings&#34;</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">repo</span> <span style="color:#f92672">:=</span> <span style="color:#e6db74">&#34;.&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">filename</span> <span style="color:#f92672">:=</span> <span style="color:#e6db74">&#34;my-file&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">filepath</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">strings</span>.<span style="color:#a6e22e">Join</span>([]<span style="color:#66d9ef">string</span>{<span style="color:#a6e22e">repo</span>, <span style="color:#a6e22e">filename</span>}, string(<span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">PathSeparator</span>))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">content</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">ReadFile</span>(<span style="color:#a6e22e">filepath</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Exit</span>(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">updatedContent</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">strings</span>.<span style="color:#a6e22e">ReplaceAll</span>(<span style="color:#a6e22e">content</span>, <span style="color:#e6db74">&#34;great&#34;</span>, <span style="color:#e6db74">&#34;good&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">err</span> = <span style="color:#a6e22e">WriteFile</span>(<span style="color:#a6e22e">filepath</span>, <span style="color:#a6e22e">updatedContent</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Exit</span>(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">err</span> = <span style="color:#a6e22e">AddToRepo</span>(<span style="color:#a6e22e">repo</span>, <span style="color:#a6e22e">filepath</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Exit</span>(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">ReadFile</span>(<span style="color:#a6e22e">filename</span> <span style="color:#66d9ef">string</span>) (<span style="color:#66d9ef">string</span>, <span style="color:#66d9ef">error</span>) {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">b</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">ReadFile</span>(<span style="color:#a6e22e">filename</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> string(<span style="color:#a6e22e">b</span>), <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">WriteFile</span>(<span style="color:#a6e22e">filename</span> <span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">content</span> <span style="color:#66d9ef">string</span>) <span style="color:#66d9ef">error</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">tmpFile</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Sprintf</span>(<span style="color:#e6db74">&#34;%s.tmp&#34;</span>, <span style="color:#a6e22e">filename</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">fout</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Create</span>(<span style="color:#a6e22e">tmpFile</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">defer</span> <span style="color:#a6e22e">fout</span>.<span style="color:#a6e22e">Close</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">bufOut</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">bufio</span>.<span style="color:#a6e22e">NewWriter</span>(<span style="color:#a6e22e">fout</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">defer</span> <span style="color:#a6e22e">bufOut</span>.<span style="color:#a6e22e">Flush</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">err</span> = <span style="color:#a6e22e">bufOut</span>.<span style="color:#a6e22e">WriteString</span>(<span style="color:#a6e22e">content</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">err</span> = <span style="color:#a6e22e">os</span>.<span style="color:#a6e22e">Rename</span>(<span style="color:#a6e22e">tmpFile</span>, <span style="color:#a6e22e">filename</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">AddToRepo</span>(<span style="color:#a6e22e">repo</span> <span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">filepath</span> <span style="color:#66d9ef">string</span>) <span style="color:#66d9ef">error</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">gitRepo</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">git</span>.<span style="color:#a6e22e">PlainOpen</span>(<span style="color:#a6e22e">repo</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">gitWorktree</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">gitRepo</span>.<span style="color:#a6e22e">Worktree</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">err</span> = <span style="color:#a6e22e">gitWorktree</span>.<span style="color:#a6e22e">Add</span>(<span style="color:#a6e22e">filepath</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">err</span> = <span style="color:#a6e22e">gitWorktree</span>.<span style="color:#a6e22e">Commit</span>(<span style="color:#e6db74">&#34;Updated file contents&#34;</span>, <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">git</span>.<span style="color:#a6e22e">CommitOptions</span>{})
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Now let&rsquo;s make sure git looks like it&rsquo;s supposed to:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ git status
</span></span><span style="display:flex;"><span>On branch master
</span></span><span style="display:flex;"><span>Changes to be committed:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">(</span>use <span style="color:#e6db74">&#34;git restore --staged &lt;file&gt;...&#34;</span> to unstage<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>        new file:   ./my-file
</span></span><span style="display:flex;"><span>        new file:   my-file
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Changes not staged <span style="color:#66d9ef">for</span> commit:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">(</span>use <span style="color:#e6db74">&#34;git add &lt;file&gt;...&#34;</span> to update what will be committed<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">(</span>use <span style="color:#e6db74">&#34;git restore &lt;file&gt;...&#34;</span> to discard changes in working directory<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>        modified:   my-file
</span></span></code></pre></div><p>What the hell? I made a change to a single file, but now I have two staged changes and one unstaged change all for the
same file??</p>
<h2 id="troubleshooting">Troubleshooting</h2>
<h2 id="sanity-check">Sanity check</h2>
<p>Just to make sure I&rsquo;m not forgetting something from the way I normally interact with git, let&rsquo;s try doing it in bash:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>file<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;my-file&#39;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>cat <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>file<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>content<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">$(</span>&lt; <span style="color:#e6db74">${</span>file<span style="color:#e6db74">}</span><span style="color:#66d9ef">)</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>printf <span style="color:#e6db74">&#34;%s\n&#34;</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>content/great/good<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> &gt; my-file.tmp
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>mv my-file.tmp my-file
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>cat <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>file<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>git add <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>file<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>git commit -m <span style="color:#e6db74">&#34;Updated file contents&#34;</span>
</span></span></code></pre></div><p>Nothing exciting here, mostly just the usual flow of git commands. Now let&rsquo;s check how things look in git here:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ git status
</span></span><span style="display:flex;"><span>On branch master
</span></span><span style="display:flex;"><span>Your branch is ahead of <span style="color:#e6db74">&#39;origin/master&#39;</span> by <span style="color:#ae81ff">1</span> commit.
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>use <span style="color:#e6db74">&#34;git push&#34;</span> to publish your local commits<span style="color:#f92672">)</span>
</span></span></code></pre></div><p>Well, this is what I was expecting all along. So what&rsquo;s being done differently between <code>git</code> and <code>go-git</code>?</p>
<h2 id="git-index">Git index</h2>
<p>I started digging in deeper to the git side of things by comparing the state of the repo with each approach. This is the
initial state of the git index before any changes are made to the repo:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ git ls-files --stage my-file
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">100644</span> 09721149f4f734c171891b7da25c4f7db30ea616 <span style="color:#ae81ff">0</span>       my-file
</span></span></code></pre></div><p>Now let&rsquo;s run the <a href="#sanity-check">sanity check</a> implementation and check the index again:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ git ls-files --stage my-file
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">100644</span> 47c9021d2cbbd8f691d9ff2e1df9a053ad7b28ee <span style="color:#ae81ff">0</span>       my-file
</span></span></code></pre></div><p>Okay, things look good. The updated file is there and the hash has been updated as expected (because the file was
modified). Now let&rsquo;s put the repo back to its original state:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ git reset --hard origin/master
</span></span></code></pre></div><p>Then run the <a href="#implementation">Go implementation</a> and check the index again:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ git ls-files --stage my-file 
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">100644</span> 09721149f4f734c171891b7da25c4f7db30ea616 <span style="color:#ae81ff">0</span>       my-file
</span></span></code></pre></div><p>Weird, the hash is the same as the original file even though it&rsquo;s been changed. Let&rsquo;s look at the whole index:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ git ls-files --stage
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">100644</span> 47c9021d2cbbd8f691d9ff2e1df9a053ad7b28ee <span style="color:#ae81ff">0</span>       ./my-file
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">100644</span> 09721149f4f734c171891b7da25c4f7db30ea616 <span style="color:#ae81ff">0</span>       my-file
</span></span></code></pre></div><p>Well this doesn&rsquo;t make any goddamned sense. The hash for <code>my-file</code> is the same as the hash for the original file and the
hash for <code>./my-file</code> is the same as the hash for the updated file. So does that mean the <code>go-git</code> library is updating
the git index wrong?</p>
<p><strong>Spoiler alert</strong>: yes it does.</p>
<h2 id="debugging">Debugging</h2>
<p>I&rsquo;ll spare you the actual process of setting breakpoints in the <code>go-git</code> library to chase down exactly where this
problem arises, but it ends up boiling down to this section
of <a href="https://github.com/go-git/go-git/blob/v5.12.0/worktree_status.go#L336">worktree_status.go</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> <span style="color:#f92672">||</span> !<span style="color:#a6e22e">fi</span>.<span style="color:#a6e22e">IsDir</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">added</span>, <span style="color:#a6e22e">h</span>, <span style="color:#a6e22e">err</span> = <span style="color:#a6e22e">w</span>.<span style="color:#a6e22e">doAddFile</span>(<span style="color:#a6e22e">idx</span>, <span style="color:#a6e22e">s</span>, <span style="color:#a6e22e">path</span>, <span style="color:#a6e22e">ignorePattern</span>)
</span></span><span style="display:flex;"><span>} <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">added</span>, <span style="color:#a6e22e">err</span> = <span style="color:#a6e22e">w</span>.<span style="color:#a6e22e">doAddDirectory</span>(<span style="color:#a6e22e">idx</span>, <span style="color:#a6e22e">s</span>, <span style="color:#a6e22e">path</span>, <span style="color:#a6e22e">ignorePattern</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>In this case, I&rsquo;m concerned about <code>doAddFile()</code> which passes the filepath as <code>./my-file</code> and takes me further down into
the library where the index is actually being modified
in <a href="https://github.com/go-git/go-git/blob/v5.12.0/plumbing/format/index/index.go#L61">index.go</a>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> (<span style="color:#a6e22e">i</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">Index</span>) <span style="color:#a6e22e">Add</span>(<span style="color:#a6e22e">path</span> <span style="color:#66d9ef">string</span>) <span style="color:#f92672">*</span><span style="color:#a6e22e">Entry</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">e</span> <span style="color:#f92672">:=</span> <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">Entry</span>{
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">Name</span>: <span style="color:#a6e22e">filepath</span>.<span style="color:#a6e22e">ToSlash</span>(<span style="color:#a6e22e">path</span>),
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">i</span>.<span style="color:#a6e22e">Entries</span> = append(<span style="color:#a6e22e">i</span>.<span style="color:#a6e22e">Entries</span>, <span style="color:#a6e22e">e</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">e</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And there it is!! The path that is being passed is <code>./my-file</code> <em>instead</em> of <code>my-file</code> which means the index is being
updated with the wrong filename or at least a different filename than the git CLI uses.</p>
<p>I&rsquo;ll create an issue with the <code>go-git</code> people to see about getting this fixed if it&rsquo;s not the intended behavior (it
would be strange if this was the intended behavior). Either way, now I can just update my application to <a href="https://pkg.go.dev/path/filepath#Clean">clean up the
filepath</a> before sending it over to <code>go-git</code>. Plus, this little speed bump
forced me to dive into the git internals to track down my issue, so I guess it wasn&rsquo;t a complete waste of time.</p>
]]></content>
        </item>
        
        <item>
            <title>Go Application Version</title>
            <link>/posts/2024/07/go-application-version/</link>
            <pubDate>Mon, 08 Jul 2024 14:40:23 -0700</pubDate>
            
            <guid>/posts/2024/07/go-application-version/</guid>
            <description>Until recently, I didn&amp;rsquo;t really think about how to get an application&amp;rsquo;s version into its binary without some horrendous use of sed or manually changing hardcoded values. Normally my application&amp;rsquo;s version is just the Docker image tag, but how do I get the version info into the actually binary? Digging through the internet I found a super easy way to have the linker do it with ldflags.
Just create a global variable where your main function lives:</description>
            <content type="html"><![CDATA[<p>Until recently, I didn&rsquo;t really think about how to get an application&rsquo;s version into its binary without some horrendous
use of <code>sed</code> or manually changing hardcoded values. Normally my application&rsquo;s version is just the Docker image tag, but
how do I get the version info into the actually binary? Digging through the internet I found a super easy way to have
the linker do it with <code>ldflags</code>.</p>
<p>Just create a global variable where your main function lives:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#f92672">package</span> <span style="color:#a6e22e">main</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> <span style="color:#e6db74">&#34;fmt&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> (
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Version</span> <span style="color:#66d9ef">string</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Printf</span>(<span style="color:#e6db74">&#34;Version: %s\n&#34;</span>, <span style="color:#a6e22e">Version</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And set the flag when you build your application:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>go build -ldflags<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;-X main.Version=1.0.0&#34;</span>
</span></span></code></pre></div><p>Where <code>main</code> is the package that your variable <code>Version</code> lives. Now when we put it all together we can see the version
that was passed in:</p>
<pre tabindex="0"><code>$ go build -ldflags=&#34;-X main.Version=1.0.0&#34;
$ ./main
Version: 1.0.0
</code></pre><p>You can take this a step further by setting more details in a <code>Makefile</code> dynamically using info from git. Same idea in
the source file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#f92672">package</span> <span style="color:#a6e22e">main</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> <span style="color:#e6db74">&#34;fmt&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> (
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Version</span> <span style="color:#66d9ef">string</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Commit</span>  <span style="color:#66d9ef">string</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Printf</span>(<span style="color:#e6db74">&#34;Version: %s Commit: %s\n&#34;</span>, <span style="color:#a6e22e">Version</span>, <span style="color:#a6e22e">Commit</span>)
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Assuming your project is in a git repo, create the <code>Makefile</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-makefile" data-lang="makefile"><span style="display:flex;"><span>LD_FLAGS <span style="color:#f92672">:=</span> -X main.Commit<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>shell git rev-parse HEAD<span style="color:#66d9ef">)</span> -X main.Version<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>shell git describe --always<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">build</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>    go build -ldflags<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span><span style="color:#66d9ef">$(</span>LD_FLAGS<span style="color:#66d9ef">)</span><span style="color:#e6db74">&#34;</span>
</span></span></code></pre></div><p>Build using the <code>Makefile</code> and run:</p>
<pre tabindex="0"><code>$ make build
$ ./main
Version: some-git-version Commit: some-git-commit
</code></pre><p>And now you can have version information in all your Go applications.</p>
]]></content>
        </item>
        
        <item>
            <title>Cloud Native Development</title>
            <link>/posts/2024/06/cloud-native-development/</link>
            <pubDate>Fri, 14 Jun 2024 14:08:18 -0700</pubDate>
            
            <guid>/posts/2024/06/cloud-native-development/</guid>
            <description>The use of containers is quickly becoming the de facto standard for application development whether you like it or not. Containers themselves will undoubtedly be considered to be some archaic, shitty technology at some point down the road but their contribution to providing isolation is something that will not be forgotten. There are countless articles on the internet describing how containers work under the hood and how they&amp;rsquo;re different from VMs, but I haven&amp;rsquo;t seen much talk of how to actually use the damn things effectively in your everyday developer life.</description>
            <content type="html"><![CDATA[<p>The use of containers is quickly becoming the de facto standard for application development whether you like it or not.
Containers themselves will undoubtedly be considered to be some archaic, shitty technology at some point down the road
but their contribution to providing isolation is something that will not be forgotten. There are countless articles on
the internet describing how containers work under the hood and how they&rsquo;re different from VMs, but I haven&rsquo;t seen much
talk of how to actually use the damn things effectively in your everyday developer life. Same thing goes for deployment
tools like Helm and much of the cloud native ecosystem.</p>
<p>I&rsquo;ve often seen <a href="https://dev.to/pavanbelagatti/deploying-an-application-on-kubernetes-a-complete-guide-1cj6">guides</a> on
how to write an application for Kubernetes and how it will fix all your problems by allowing &ldquo;organizations [to] achieve
increased efficiency and agility&rdquo;. Overall, that guide makes some good points about Kubernetes offering better
scalability and flexibility, but it doesn&rsquo;t talk about how I&rsquo;m supposed to use Kubernetes every day as a developer
without <del>wanting to kill myself</del> significant friction.</p>
<h2 id="problem">Problem</h2>
<p>Many of the benefits that cloud native applications offer can be a <em>huge</em> disadvantage for traditional application
development such as isolation and ephemeral runtime environments. For example, when I make changes to an application
using a traditional workflow I need to:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vim app.go
</span></span><span style="display:flex;"><span>make
</span></span><span style="display:flex;"><span>./app
</span></span></code></pre></div><p>This simple set of tasks will happen numerous times throughout the day and I can merrily develop software.</p>
<p>But when I make changes to a cloud native application, I need to:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vim app.go
</span></span><span style="display:flex;"><span>make
</span></span><span style="display:flex;"><span>docker build -t localhost/some-app:<span style="color:#66d9ef">$(</span>git describe --always<span style="color:#66d9ef">)</span> .
</span></span><span style="display:flex;"><span>docker push localhost/some-app:<span style="color:#66d9ef">$(</span>git describe --always<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>helm install some-deploy some-chart --set image.tag<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>git describe --always<span style="color:#66d9ef">)</span>
</span></span></code></pre></div><p>Not a huge number of tasks, but you have to run multiple applications and this gets very tiresome having to flip through
your Bash history all day for every single change. If you think this could be simplified by just using the <code>latest</code> tag
you would be wrong because you should <strong>never ever</strong> use the latest tag. Also, you could write a script to run these
steps which wouldn&rsquo;t be terrible but, now you have this custom script for each project that&rsquo;s going to definitely be
slightly different across projects, and you have to worry about that maintenance especially if you want to use that
script for prod deploys.</p>
<p>Plus, if you want to debug your application you&rsquo;ll have to set up a build stage in the <code>Dockerfile</code> and manually forward
ports out of the cluster.</p>
<h2 id="sane-development">Sane development</h2>
<p>Years ago when I was still fairly new to cloud native development I came across a tool
called <a href="https://skaffold.dev/">skaffold</a> which helps tie all of these tasks together. All you have to do is configure a
<code>skaffold.yaml</code> in your project, then when you make changes it will look like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vim app.go
</span></span><span style="display:flex;"><span>skaffold dev
</span></span></code></pre></div><p>That&rsquo;s it! This will:</p>
<ul>
<li>compile your application</li>
<li>build the Docker image</li>
<li>push the Docker image</li>
<li>deploy the Helm chart</li>
</ul>
<p>It will also watch source file and execute these tasks again when it detects changes.</p>
<p>And if you want to debug changes made to your application:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vim app.go
</span></span><span style="display:flex;"><span>skaffold debug
</span></span></code></pre></div><p>That will run all the tasks executed by <code>skaffold dev</code> and forward the application&rsquo;s debug port out of the cluster to
your workstation.</p>
<h2 id="try-it">Try it</h2>
<p>You&rsquo;ll probably have
some <a href="https://skaffold.dev/docs/deployers/helm/#sanitizing-the-artifact-name-from-invalid-go-template-characters">frustrating moments</a>
with Skaffold at some point. But for me, it is well worth it to have a unified method for developing, debugging, and
deploying cloud native applications and avoiding the hell of having to manually operate a Rube Goldberg machine every
time you make code changes.</p>
]]></content>
        </item>
        
        <item>
            <title>Type Inference</title>
            <link>/posts/2023/10/type-inference/</link>
            <pubDate>Fri, 06 Oct 2023 15:40:55 -0700</pubDate>
            
            <guid>/posts/2023/10/type-inference/</guid>
            <description>Backstory The other day at work, I had a coworker look over some changes I made to one of our Java applications. He gave me some pretty standard feedback: this looks good, fix this, etc. But he also told me that I really shouldn&amp;rsquo;t be using var for my variable assignments because it &amp;ldquo;makes the code less readable&amp;rdquo;. I put a lot of effort in trying to make my code as readable as possible so his comment took me back for a moment.</description>
            <content type="html"><![CDATA[<h1 id="backstory">Backstory</h1>
<p>The other day at work, I had a coworker look over some changes I made to one of our Java applications. He gave me some
pretty standard feedback: <em>this looks good</em>, <em>fix this</em>, etc. But he also told me that I really shouldn&rsquo;t
be using <code>var</code> for my variable assignments because it &ldquo;makes the code less readable&rdquo;. I put a lot of effort in trying to
make my code as readable as possible so his comment took me back for a moment. Have I been littering the code I write
with this garbage that makes difficult to understand just to use some newfangled language syntax? So I took a few
moments to try and understand why he thinks this.</p>
<h1 id="java-type-inference">Java type inference</h1>
<p>Back in 2018 Oracle released Java 10 with a bunch of fancy new features. One of these features was the introduction of
type inference though the use of the <code>var</code> identifier which can really simplify the way your code looks by stripping out
a lot of unnecessary information. Take this code for example:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MyClass</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#a6e22e">MyClass</span>() {
</span></span><span style="display:flex;"><span>        Map<span style="color:#f92672">&lt;</span>String, String<span style="color:#f92672">&gt;</span> myMap <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> HashMap<span style="color:#f92672">&lt;&gt;</span>();
</span></span><span style="display:flex;"><span>        myMap.<span style="color:#a6e22e">put</span>(<span style="color:#e6db74">&#34;some-key&#34;</span>, <span style="color:#e6db74">&#34;some-value&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> (Map.<span style="color:#a6e22e">Entry</span><span style="color:#f92672">&lt;</span>String, String<span style="color:#f92672">&gt;</span> i : myMap.<span style="color:#a6e22e">entrySet</span>()) {
</span></span><span style="display:flex;"><span>            System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(i);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The syntax for the loop is super verbose. You already know what the type of <code>myMap</code> is, so why clutter things with
typing info? Here&rsquo;s that same code using type inference:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MyClass</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#a6e22e">MyClass</span>() {
</span></span><span style="display:flex;"><span>        Map<span style="color:#f92672">&lt;</span>String, String<span style="color:#f92672">&gt;</span> myMap <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> HashMap<span style="color:#f92672">&lt;&gt;</span>();
</span></span><span style="display:flex;"><span>        myMap.<span style="color:#a6e22e">put</span>(<span style="color:#e6db74">&#34;some-key&#34;</span>, <span style="color:#e6db74">&#34;some-value&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">var</span> i : myMap.<span style="color:#a6e22e">entrySet</span>()) {
</span></span><span style="display:flex;"><span>            System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(i);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>That looks much cleaner, and it&rsquo;s easier to read. Granted this is just a meaningless few lines of code but that
reduction of redundant typing info will add up quick in large codebase.</p>
<p>Of course though, you don&rsquo;t want to use <code>var</code> if it&rsquo;s going to make your code more difficult to read or put you in a
situation to (probably)
make <a href="https://openjdk.org/projects/amber/guides/lvti-style-guide#G6">dangerous typing assumptions</a>.</p>
<h1 id="differing-opinions">Differing opinions</h1>
<p>I&rsquo;m glad I took the time to try and better understand why my coworker has the blanket opinion that using Java&rsquo;s <code>var</code>
makes code less readable, but I still completely disagree. Maybe he doesn&rsquo;t understand Java&rsquo;s typing system very well,
maybe he just doesn&rsquo;t like change, or maybe I&rsquo;m still missing something? Java is a statically typed language with strong
typing so the use of type inference is <em>usually</em> a good thing. That&rsquo;s what I still think at least. As with basically
everything else in programming, type inference can make your code easier to read when used properly.</p>
]]></content>
        </item>
        
        <item>
            <title>Initial Post</title>
            <link>/posts/2023/08/initial-post/</link>
            <pubDate>Thu, 10 Aug 2023 09:22:32 -0700</pubDate>
            
            <guid>/posts/2023/08/initial-post/</guid>
            <description>Here it is My Hugo website 🎉</description>
            <content type="html"><![CDATA[<h2 id="here-it-is">Here it is</h2>
<p>My Hugo website 🎉</p>
]]></content>
        </item>
        
    </channel>
</rss>
