<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Teapotcoder</title>
  
  
  <link href="/feed.xml" rel="self"/>
  
  <link href="http://teapotcoder.com/"/>
  <updated>2018-10-03T20:02:25.184Z</updated>
  <id>http://teapotcoder.com/</id>
  
  <author>
    <name>David Roberts</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Using git with self signed certificates</title>
    <link href="http://teapotcoder.com/post/using-git-with-self-signed-certificates/"/>
    <id>http://teapotcoder.com/post/using-git-with-self-signed-certificates/</id>
    <published>2018-10-04T00:41:16.000Z</published>
    <updated>2018-10-03T20:02:25.184Z</updated>
    
    <content type="html"><![CDATA[<p>Using git internally to access an external git repository? Behind a corporate proxy that has an self signed CA cert? Is git complaining about ‘SSL certificate problem: unable to get local issuer certificate’? Here ya go.</p><p>High level:</p><ol><li>Get the self-signed cert in a base 64 encoded file.</li><li>git config http.sslCAInfo “path/to/that/file.cer”</li></ol><blockquote><blockquote><blockquote></blockquote><p>You will hear a lot about setting <code>http.sslVerify</code> to false. <strong>Please</strong> don’t do this. If you leave the environment having the self-signed cert then git will not be verifying <strong>any</strong> TLS/SSL traffic, opening you up to man in the middle attacks.</p><blockquote></blockquote></blockquote></blockquote><h4 id="Detailed-with-scripts-for-Windows-I’ll-work-on-Linux-later"><a href="#Detailed-with-scripts-for-Windows-I’ll-work-on-Linux-later" class="headerlink" title="Detailed with scripts for Windows (I’ll work on Linux later)."></a>Detailed with scripts for Windows (I’ll work on Linux later).</h4><p>You need to get the self-signed certificate in a base 64 encoded file. There are a couple ways to do this depending on your situation.</p><h5 id="On-Windows-when-the-certificate-is-only-available-from-the-remote-git-server-itself"><a href="#On-Windows-when-the-certificate-is-only-available-from-the-remote-git-server-itself" class="headerlink" title="On Windows when the certificate is only available from the remote git server itself."></a>On Windows when the certificate is only available from the remote git server itself.</h5><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># powershell</span></span><br><span class="line">CLEAR</span><br><span class="line"></span><br><span class="line"><span class="built_in">Write-Host</span> <span class="string">"Getting certificate for internal site"</span></span><br><span class="line"></span><br><span class="line"><span class="variable">$request</span> = [Net.WebRequest]::Create(<span class="string">"https://internalsite.supercorp"</span>)</span><br><span class="line"><span class="variable">$request</span>.GetResponse() | <span class="built_in">Out-Null</span></span><br><span class="line"><span class="variable">$cert</span> = <span class="variable">$request</span>.ServicePoint.Certificate</span><br><span class="line"><span class="variable">$bytes</span> = <span class="variable">$cert</span>.Export([Security.Cryptography.X509Certificates.X509ContentType]::Cert)</span><br><span class="line"><span class="built_in">Set-Content</span> -value <span class="variable">$bytes</span> -encoding byte -path <span class="string">"internalsite.supercorp.cer"</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">Write-Host</span> <span class="string">"Getting chain for CA cert"</span></span><br><span class="line"><span class="variable">$chain</span> = <span class="built_in">New-Object</span> -TypeName System.Security.Cryptography.X509Certificates.X509Chain</span><br><span class="line"><span class="variable">$chain</span>.Build(<span class="variable">$cert</span>)</span><br><span class="line"></span><br><span class="line"><span class="variable">$root</span> = <span class="variable">$chain</span>.ChainElements | Select -Last <span class="number">1</span></span><br><span class="line"></span><br><span class="line"><span class="variable">$bytes</span> = <span class="variable">$root</span>.Certificate.Export([Security.Cryptography.X509Certificates.X509ContentType]::Cert)</span><br><span class="line"><span class="built_in">Set-Content</span> -value <span class="variable">$bytes</span> -encoding byte -path <span class="string">"supercorp.ca.cer"</span></span><br></pre></td></tr></table></figure><h5 id="On-Windows-when-the-certificate-is-in-the-Windows-cert-store"><a href="#On-Windows-when-the-certificate-is-in-the-Windows-cert-store" class="headerlink" title="On Windows when the certificate is in the Windows cert store."></a>On Windows when the certificate is in the Windows cert store.</h5><p>This may be typical for corporate environments. Easy to tell, if git complains about self-signed cert but your Chrome or Edge browser doesn’t complain then it’s likely the cert is already on your computer.</p><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># powershell</span></span><br><span class="line"><span class="variable">$rootCA</span> = dir Cert:\LocalMachine\Root | Where DnsNameList <span class="nomarkup">-Contains</span> <span class="string">"NAME OF YOUR ROOT CA CERT"</span> | Select -First <span class="number">1</span></span><br><span class="line"><span class="variable">$rootCA</span> = @(<span class="string">"-----BEGIN CERTIFICATE-----"</span>,[System.Convert]::ToBase64String(<span class="variable">$rootCA</span>.RawData),<span class="string">"-----END CERTIFICATE-----"</span>)</span><br><span class="line"><span class="variable">$rootCAPath</span> = <span class="string">"<span class="variable">$Home</span>\where-you-want-the-file-ca.cer"</span></span><br><span class="line"><span class="variable">$rootCA</span> | <span class="built_in">Out-File</span> <span class="variable">$rootCAPath</span> -Encoding ascii</span><br></pre></td></tr></table></figure><p>The <code>Where</code> above may need to be modified to find the appropriate cert in your cert store.</p><h3 id="Tell-git-to-trust-that-certificate"><a href="#Tell-git-to-trust-that-certificate" class="headerlink" title="Tell git to trust that certificate."></a>Tell git to trust that certificate.</h3><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git<span class="built_in"> config </span>http.sslCAInfo <span class="string">"path-to-file-above.cer"</span></span><br></pre></td></tr></table></figure><p><strong> Special thanks </strong></p><p>I must thank Philip Kelly for posting an article on this exact situation back in 2014. I also want to say thank you to Alejandro Campos Magencio for the post on getting the certificate chain. I put those two together with the exporting of the certifcate to a file to produce this post.</p><p><a href="https://blogs.msdn.microsoft.com/phkelley/2014/01/20/adding-a-corporate-or-self-signed-certificate-authority-to-git-exes-store/" target="_blank" rel="noopener">Philip Kelley’s post</a></p><p><a href="https://blogs.msdn.microsoft.com/alejacma/2011/06/21/how-to-verify-validity-of-certificates-with-net/" target="_blank" rel="noopener">Alejandro Campos Magencio’ post</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;Using git internally to access an external git repository? Behind a corporate proxy that has an self signed CA cert? Is git complaining a
      
    
    </summary>
    
    
      <category term="git tls self-signed" scheme="http://teapotcoder.com/tags/git-tls-self-signed/"/>
    
  </entry>
  
  <entry>
    <title>How to fix git ssh asking for password on Windows 10</title>
    <link href="http://teapotcoder.com/post/how-to-fix-git-ssh-asking-for-password-on-windows-10/"/>
    <id>http://teapotcoder.com/post/how-to-fix-git-ssh-asking-for-password-on-windows-10/</id>
    <published>2018-09-20T08:39:14.000Z</published>
    <updated>2018-10-03T20:02:25.183Z</updated>
    
    <content type="html"><![CDATA[<p>TL;DR<br><figure class="highlight ebnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">Get-Command ssh</span></span><br></pre></td></tr></table></figure></p><p>If the output of that lists an executable <strong>not</strong> in your git usr/bin directory then do this:</p><figure class="highlight dsconfig"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">git </span><span class="string">config </span><span class="string">core.</span><span class="string">sshCommand </span>(<span class="built_in">get-command</span> <span class="string">ssh)</span>.<span class="string">Source.</span><span class="string">Replace(</span><span class="string">'\'</span>,<span class="string">'/'</span>)</span><br></pre></td></tr></table></figure><p>Or, if you want to test this in your current PowerShell session w/o messing with Git config<br><figure class="highlight dsconfig"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$<span class="string">ENV:GIT_SSH_COMMAND </span>= (<span class="built_in">get-command</span> <span class="string">ssh)</span>.<span class="string">Source.</span><span class="string">Replace(</span><span class="string">'\'</span>,<span class="string">'/'</span>)</span><br></pre></td></tr></table></figure></p><h3 id="Why-does-this-work"><a href="#Why-does-this-work" class="headerlink" title="Why does this work?"></a>Why does this work?</h3><p>When you install git, it <strong>comes with ssh</strong>. But if you have a newer version of Windows 10, Windows has an install of SSH that comes with it. Installed in <code>C:\Windows\System32\OpenSSH</code>. <strong>That</strong> gets put into the environment PATH and so testing:<br><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">ssh</span> <span class="selector-tag">-T</span> <span class="selector-tag">git</span>@<span class="keyword">github</span>.<span class="keyword">com</span></span><br></pre></td></tr></table></figure></p><p>Uses your key you added via <code>ssh-add</code> using the Windows provided binaries. But git is using the ssh stuff within the git usr/bin folder. Different set of keys. So you’d end up getting prompted for your passphrase every single time you git pull.</p><h5 id="Nearly-drove-me-crazy-this-did"><a href="#Nearly-drove-me-crazy-this-did" class="headerlink" title="Nearly drove me crazy, this did."></a>Nearly drove me crazy, this did.</h5>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;TL;DR&lt;br&gt;&lt;figure class=&quot;highlight ebnf&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pr
      
    
    </summary>
    
    
      <category term="git ssh windows10" scheme="http://teapotcoder.com/tags/git-ssh-windows10/"/>
    
  </entry>
  
  <entry>
    <title>VSTS: Disable features/services API</title>
    <link href="http://teapotcoder.com/post/vsts-disable-features-services-api/"/>
    <id>http://teapotcoder.com/post/vsts-disable-features-services-api/</id>
    <published>2018-06-29T02:01:51.000Z</published>
    <updated>2018-10-03T20:02:25.184Z</updated>
    
    <content type="html"><![CDATA[<p>VSTS is rolling out a <a href="https://blogs.msdn.microsoft.com/devops/2018/06/19/new-navigation/" target="_blank" rel="noopener">new navigation</a>. One of the features in it is the ability to turn off certain services/features, such as Test, Build and Release, etc. But you have to go into each project individually. That’s manual work, I want to automate it.</p><p>So if you want to disable some services/features in VSTS across multiple projects there is a REST API that you can use. It’s in <strong>preview</strong>, and you’ll have to script the calls but here you go:</p><figure class="highlight xquery"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">PATCH https://&#123;account&#125;.visualstudio.com/_apis/FeatureManagement/FeatureStates/host/project/&#123;project-id&#125;/&#123;feature-id&#125;?api-version=<span class="string">'4.1-preview.1'</span></span><br><span class="line">content-type: application/json</span><br><span class="line"></span><br><span class="line">&#123;<span class="string">"featureId"</span>:<span class="string">"&#123;feature-id&#125;"</span>,<span class="string">"scope"</span>:&#123;<span class="string">"settingScope"</span>:<span class="string">"project"</span>,<span class="string">"userScoped"</span>:false&#125;,<span class="string">"state"</span>:<span class="number">0</span>&#125;</span><br></pre></td></tr></table></figure><p>Replace <code>account</code>,<code>project-id</code> and <code>feature-id</code> as appropriate. Here are the feature id’s I know of.</p><ul><li>ms.vss-build.pipelines</li><li>ms.vss-test-web.test</li><li>ms.vss-work.agile</li><li>ms.vss-code.version-control</li></ul><h3 id="Using-the-VSTeam-PowerShell-module"><a href="#Using-the-VSTeam-PowerShell-module" class="headerlink" title="Using the VSTeam PowerShell module"></a>Using the <a href="https://www.powershellgallery.com/packages/VSTeam/" target="_blank" rel="noopener">VSTeam PowerShell module</a></h3><figure class="highlight pf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Get the build feature setting</span></span><br><span class="line"><span class="variable">$buildFeature</span> = Invoke-VSTeamRequest -Area FeatureManagement -Resource FeatureStates -Id <span class="string">"host/project/$($project.Id)/ms.vss-build.pipelines"</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Adjust the setting: 0 | 1 | 'undefined'</span></span><br><span class="line"><span class="variable">$buildFeature</span>.<span class="keyword">state</span> = <span class="number">0</span> </span><br><span class="line"></span><br><span class="line"><span class="comment"># Update VSTS</span></span><br><span class="line">Invoke-VSTeamRequest -method patch -ContentType 'application/json' -body (<span class="variable">$buildFeature</span> | ConvertTo-Json -Depth <span class="number">5</span> -Compress) -Area FeatureManagement -Resource FeatureStates -Id <span class="string">"host/project/$($project.Id)/ms.vss-build.pipelines"</span> -version '<span class="number">4.1</span>-preview.<span class="number">1</span>' | Out-Null</span><br></pre></td></tr></table></figure><h3 id="Host-level-settings"><a href="#Host-level-settings" class="headerlink" title="Host level settings"></a>Host level settings</h3><p>You can also do the above at the ‘host’ level. From my experimentation that’s the project collection as a whole.</p><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https:<span class="regexp">//</span>&#123;account&#125;.visualstudio.com<span class="regexp">/_apis/</span>FeatureManagement<span class="regexp">/FeatureStates/</span>host<span class="regexp">/&#123;feature-id&#125;</span></span><br></pre></td></tr></table></figure><p>Same payload, in that case you are simply ignoring the project. <strong>However</strong>, this doesn’t actually remove the service/feature from all the projects. What it does is removes them from the services page. You won’t even see a ‘Build and Release’ toggle for example. So be careful, if you disable a service at the host level but it’s enabled at the project level (or undefined) then the project can still use that service as usual, but you won’t be able to turn it on/off via the new navigation ui.</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;VSTS is rolling out a &lt;a href=&quot;https://blogs.msdn.microsoft.com/devops/2018/06/19/new-navigation/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;new nav
      
    
    </summary>
    
    
      <category term="vsts api" scheme="http://teapotcoder.com/tags/vsts-api/"/>
    
  </entry>
  
  <entry>
    <title>IIS Cannot create file</title>
    <link href="http://teapotcoder.com/post/iis-cannot-create-file/"/>
    <id>http://teapotcoder.com/post/iis-cannot-create-file/</id>
    <published>2016-08-18T09:45:13.238Z</published>
    <updated>2018-10-03T20:02:25.183Z</updated>
    
    <content type="html"><![CDATA[<p>I just helped a co-worker deploy a ASP.NET MVC app to a new server. But the IIS Powershell cmdlet kept failing saying:</p><p><code>Cannot create a file when that file already exists.</code></p><p>The eventual source of the problem didn`t fall in line with the error message, big surprise I know.<br><a id="more"></a></p><h2 id="TL-DR"><a href="#TL-DR" class="headerlink" title="TL;DR"></a>TL;DR</h2><h5 id="Check-your-app-settings-for-duplicates"><a href="#Check-your-app-settings-for-duplicates" class="headerlink" title="Check your app settings for duplicates."></a>Check your app settings for duplicates.</h5><h2 id="A-bit-longer"><a href="#A-bit-longer" class="headerlink" title="A bit longer"></a>A bit longer</h2><p>Part of my deployment process using <a href="https://www.octopus.com" target="_blank" rel="noopener">Octopus Deploy</a> is to set the authentication settings for the web application. Octopus Deploy was helpful in giving quick easy access to the error log. I didn`t need to hunt down and ask why it was failing. Just had to figure out what was actually wrong with my scripting. Using Powershell trying to enable anonymous authentication:</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">Set</span>-WebConfigurationProperty -filter /system.webServer/<span class="keyword">security</span>/<span class="keyword">authentication</span>/anonymousAuthentication -<span class="keyword">name</span> enabled -<span class="keyword">value</span> <span class="string">"$enableAnonymous"</span> -location $IisItemPath -PSPath <span class="string">"IIS:\"</span></span><br></pre></td></tr></table></figure><p>Which may result in the following error:</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">Set</span>-WebConfigurationProperty : Cannot <span class="keyword">create</span> a <span class="keyword">file</span> <span class="keyword">when</span> that <span class="keyword">file</span> already exists. (<span class="keyword">Exception</span> <span class="keyword">from</span> HRESULT: <span class="number">0x800700B7</span>)</span><br></pre></td></tr></table></figure><p>I’m familiar with this error but usually with the <code>Start-Website</code> cmdlet. In that case it usually means that you have two sites with the same bindings. That’s likely due to creating a new site and not removing the default, thus having two sites listening on port 80 or port 443 with same host header. But that wasn’t the case here.</p><p>So what made me think there was something wrong with the <code>web.config</code> file? <strong>Experience</strong>. So I just started with something simple to eliminate it as a problem. The <code>appSettings</code>, surely that’s not part of the problem. However, that was exactly the problem. Usually ASP.NET will tell you that you have duplicate configuration items, but in this case it didn`t for whatever reason. It only gave the error above. It will also give you a similar error if you try to edit the authentication (or other) settings via the IIS GUI.</p><p><img src="/images/cannot-create-file-iis.png" alt="screenshot of error"></p><p>Rule of thumb, don`t trust the error messages to tell you what <strong>your</strong> problem is. It’ll only tell you what its problem is.</p><p>And make sure you don’t have duplicate app setting entries in your web.config.</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;I just helped a co-worker deploy a ASP.NET MVC app to a new server. But the IIS Powershell cmdlet kept failing saying:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Cannot create a file when that file already exists.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The eventual source of the problem didn`t fall in line with the error message, big surprise I know.&lt;br&gt;
    
    </summary>
    
    
      <category term="iis" scheme="http://teapotcoder.com/tags/iis/"/>
    
      <category term="web.config" scheme="http://teapotcoder.com/tags/web-config/"/>
    
      <category term="powershell" scheme="http://teapotcoder.com/tags/powershell/"/>
    
  </entry>
  
  <entry>
    <title>Post site screenshots to Github PR</title>
    <link href="http://teapotcoder.com/post/post-site-screenshots-to-github-pr/"/>
    <id>http://teapotcoder.com/post/post-site-screenshots-to-github-pr/</id>
    <published>2015-11-19T05:41:21.000Z</published>
    <updated>2018-10-03T20:02:25.184Z</updated>
    
    <content type="html"><![CDATA[<p>I continue the <a href="/post/automating-static-sites-with-hexo-io-circleci-and-github-pages/">automation of hexo.io</a> by taking the <a href="/post/generate-screenshots-of-website-during-build/">website screenshots</a> generated during the continuous integration proccess and posting them to the Github PR as a comment.<br><a id="more"></a><br>The code you are about to see is not the prettiest JavaScript you will see. But I felt it would be beneficial to see this code evolve over time. I’ll make additional posts talking about how I improve things with this. You can see the full repository on my Github account, <a href="https://github.com/davidroberts63/suede-halibut" target="_blank" rel="noopener">suede-halibut</a>.</p><h3 id="What-it-does"><a href="#What-it-does" class="headerlink" title="What it does"></a>What it does</h3><p>This node app is just a RESTish/ful/whatever API. When CircleCI is done with the build it will issue a POST to the ‘/pr-build-completion’ url of my deployed heroku app. The request body from CircleCI contains the project name, the build number and the pull request number among many other things. The app will call into CircleCI to get the artifacts for that build number of that project. Then take the image artifacts and post them to the Github PR that triggered the CircleCI build.</p><h3 id="How-it-does-it"><a href="#How-it-does-it" class="headerlink" title="How it does it"></a>How it does it</h3><p>First thing to do. Pick a Node.js web application framework. For this I picked <a href="http://expressjs.com/" target="_blank" rel="noopener">Express.js</a> because it seemed the simplest to work with for such a simple app as this.</p><h4 id="Getting-all-the-things"><a href="#Getting-all-the-things" class="headerlink" title="Getting all the things"></a>Getting all the things</h4><p>My <code>app.js</code> is where my Express.js app lives and is configured. The first part contains all the <code>require</code>ments and initial objects.</p><figure class="highlight ebnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">var request</span> = require(<span class="string">"request"</span>);</span><br><span class="line"><span class="attribute">var poster</span> = require(<span class="string">"./postissue"</span>);</span><br><span class="line"></span><br><span class="line"><span class="attribute">var bodyParser</span> = require(<span class="string">"body-parser"</span>);</span><br><span class="line"><span class="attribute">var express</span> = require(<span class="string">"express"</span>);</span><br><span class="line"><span class="attribute">var app</span> = express();</span><br><span class="line"><span class="attribute">var router</span> = express.Router();</span><br></pre></td></tr></table></figure><p><code>request</code> is for making HTTP requests to CircleCI. <code>poster</code> is my own module that does the actual posting of images to the Github PR. <code>bodyParser</code> is Express.js middleware for parsing the request body as JSON. Then you see Express.js, the creation of the app and getting the Express.js router.</p><h4 id="Get-the-configuration"><a href="#Get-the-configuration" class="headerlink" title="Get the configuration"></a>Get the configuration</h4><p>I need some private information to be able to talk to CircleCI and to Github. These environment variables are set in heroku manually.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="string">"Getting settings"</span>);</span><br><span class="line"><span class="keyword">var</span> settings = &#123;&#125;;</span><br><span class="line">settings.circleCiAccount = process.env[<span class="string">"CIRCLE_CI_ACCOUNT"</span>];</span><br><span class="line">settings.circleCiToken = process.env[<span class="string">"CIRCLE_CI_TOKEN"</span>];</span><br><span class="line">settings.githubUsername = process.env[<span class="string">"GITHUB_USERNAME"</span>];</span><br><span class="line">settings.githubApiKey = process.env[<span class="string">"GITHUB_APIKEY"</span>];</span><br><span class="line">settings.orgName = process.env[<span class="string">"GITHUB_ORGNAME"</span>];</span><br></pre></td></tr></table></figure><p>The way it’s setup right now is that it only works for one Github organization/account. At the time of writing that’s just <a href="http://techlahoma.org/" target="_blank" rel="noopener">techlahoma</a>. That’s the same for the CircleCI part as well because it’s using the name of the Github account as the CI account. It was a little confusing at first but CircleCI just ‘follows’ a repository so goes along with that nomenclature. Just using API keys for CircleCI and Github. You never want to have to use your actual username and password for automation. An API key shows up as you but can’t be used to login as you to the website. So it’s likely not able to change your normal login password.</p><h4 id="Smoke-test-route-and-request-logging"><a href="#Smoke-test-route-and-request-logging" class="headerlink" title="Smoke test route and request logging."></a>Smoke test route and request logging.</h4><p>Because I’m new to Express.js and to Node apps in general I wanted to create a simple route in Express.js that would let me know I did at least one thing right. Also, because Express.js is awesome it was trivial to add my own middleware to log requests coming in.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">router.use(<span class="function"><span class="keyword">function</span>(<span class="params">req, res, next</span>) </span>&#123;</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">"Incoming: %s %s"</span>, req.method, req.url);</span><br><span class="line">next();</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">router.get(<span class="string">"/"</span>, <span class="function"><span class="keyword">function</span>(<span class="params">req, res</span>) </span>&#123;</span><br><span class="line">res.send(<span class="string">"Ready when you are"</span>);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>If you are not familiar with Express.js most of that should still make some sense. First the log part. <code>router.use</code> inserts middleware into the request pipeline. In this case it is an anonymous function that just sends some of the details of the request to the console. <code>next();</code> is the callback I have to call to allow the pipeline to continue. If I don’t call that function then the pipeline stops there. This happens for every request that comes in that is matched to any route.</p><p>The <code>router.get</code> defines a route that Express.js will respond to. The <code>get</code> part defines the HTTP method. Then you see the URL path which is the root of the site in this case. The function called by Express.js receives the request object and a response object to write a response. All I do here is write out a message that let’s me know I actually hit the site.</p><h4 id="The-POST"><a href="#The-POST" class="headerlink" title="The POST"></a>The POST</h4><p>The next route is the main one for this app. It’s the only other route defined. It’s a bit long so I’ll step through it in chunks.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">router.post(<span class="string">"/pr-build-completion"</span>, bodyParser.json(), <span class="function"><span class="keyword">function</span>(<span class="params">req, res</span>) </span>&#123;</span><br></pre></td></tr></table></figure><p>The route is defined to respond to POST requests made to the <code>/pr-build-completion</code> url. That <code>bodyParser.json()</code> is middleware injection. Actually what’s really going on is the first parameter is the path to respond to; the rest are just taken by Express.js as a series of callbacks to execute for the matching request. Check out the docs on <a href="http://expressjs.com/4x/api.html#router.methods" target="_blank" rel="noopener">router methods</a>. I really like this part of Express.js. Make’s it very easy to individually break up request handling. But that’s for another post.</p><p>Then I get the relevant data from the request body.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="string">"POST build completion"</span>);</span><br><span class="line"><span class="keyword">var</span> project = req.body.payload.reponame;</span><br><span class="line"><span class="keyword">var</span> build = req.body.payload.build_num;</span><br><span class="line"><span class="keyword">var</span> pull = req.body.payload.pull_request_urls[<span class="number">0</span>];</span><br></pre></td></tr></table></figure><p>I get the name of the repository that triggered the build, the build number in CircleCI the artifacts of interest are located, and the pull request urls in Github that triggered the build.</p><p>You’ll notice it says <code>pull_request_urls</code> and I just get the first one. I am not sure of a situation where multiple PRs will trigger a single build but in any case there should be one here. Actually there won’t be during builds triggered by merging to <code>master</code> but that’s a defect that I’ll deal with in a later post.</p><p>Next I tease out the PR number.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">pull = pull.substring(pull.lastIndexOf(<span class="string">"/"</span>) + <span class="number">1</span>);</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">"--for build %s of pull %s in the %s project"</span>, build, pull, project);</span><br></pre></td></tr></table></figure><p>I just need the number so I know which PR to add the comment to a bit later.</p><p>Build the CircleCI url to get the build artifacts.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> url = <span class="string">"https://circleci.com/api/v1/project/"</span> + settings.circleCiAccount + <span class="string">"/"</span> + project + <span class="string">"/"</span> + build + <span class="string">"/artifacts?circle-token="</span> + settings.circleCiToken;</span><br></pre></td></tr></table></figure><p>That’s using some of the configuration settings we got from the environment earlier. <a href="https://circleci.com/docs/api" target="_blank" rel="noopener">CircleCI REST API</a></p><p>Now that I have the CircleCI url to get the artifacts just send the request.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">request(&#123;<span class="attr">url</span>: url, <span class="attr">headers</span>: &#123; <span class="string">"Accept"</span>: <span class="string">"application/json"</span>&#125; &#125;, <span class="function"><span class="keyword">function</span>(<span class="params">err, response, body</span>) </span>&#123;</span><br></pre></td></tr></table></figure><p>Specifying the url and saying we want JSON back in the response. Remember this is the HTTP request going out to CircleCI to get the artifacts for the build.</p><p>The first thing to do with the response is parse the JSON body and get just the url for any images in the artifacts.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="string">"Retrieved the artifacts payload"</span>);</span><br><span class="line"><span class="keyword">var</span> payload = <span class="built_in">JSON</span>.parse(body);</span><br><span class="line"><span class="keyword">var</span> screenshots = payload.map(theUrl).filter(forImages);</span><br><span class="line"><span class="built_in">console</span>.log(screenshots);</span><br></pre></td></tr></table></figure><p>This is not Express.js routing thus why I’m parsing the JSON manually. The payload is an array of urls to the artifacts for the build. This is a separate HTTP request going out. Also note I’m going a bit functional here. I had fun with this part as I had just watched a few <a href="https://www.youtube.com/channel/UCO1cgjhGzsSYb1rsB4bFe4Q/videos" target="_blank" rel="noopener">JavaScript videos</a> by Mattias P Johansson aka <a href="https://twitter.com/mpjme" target="_blank" rel="noopener">mpjme</a>. Very educational and enjoyable to watch. I highly recommend you watch them soon. Anyway I have two functions defined at the end of <code>app.js</code> to handle that <code>map</code> and <code>filter</code> of the parsed payload from CircleCI.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">theUrl</span>(<span class="params">artifact</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> &#123; <span class="attr">url</span>: artifact.url,</span><br><span class="line">    name: artifact.url.substring(artifact.url.lastIndexOf(<span class="string">"/"</span>) + <span class="number">1</span>, artifact.url.lastIndexOf(<span class="string">"-"</span>))</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">forImages</span>(<span class="params">image</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> image.url.substring(image.url.length - <span class="number">3</span>) == <span class="string">"png"</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>theUrl</code> just maps the larger artifact object to just it’s url and a name to use in the PR comment. <code>forImages</code> filters out everything except for the screenshots generated during the build. When used in the mapping and filtering of the payload I really like how it reads.</p><p>Back to the handling of the artifact response. After getting just the data we need from the payload we apply a little configuration and use my <code>poster</code> module to send the images to the Github PR.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="string">"Posting to Github PR"</span>);</span><br><span class="line">settings.prNumber = pull;</span><br><span class="line">settings.repoName = project;</span><br><span class="line"></span><br><span class="line">poster.postImagesToIssue(settings, screenshots, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  res.type(<span class="string">"json"</span>);</span><br><span class="line">  res.json(&#123;<span class="attr">completum</span>: <span class="string">"yep"</span>&#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>First off, I don’t like that I’m using the <code>settings</code> object to communicate additional details for the <code>poster</code> to use. At least I’m putting that in as a parameter but it still feels a bit off. That’ll be a later post. But I give it those settings so it knows where to put the screenshots supplied in the second argument. Finally a callback that will just return a simple ‘yep’ to the originall caller. CircleCI in this case but I do the ‘yep’ for testing.</p><h4 id="Starting-Express-js"><a href="#Starting-Express-js" class="headerlink" title="Starting Express.js"></a>Starting Express.js</h4><p>So we’ve defined the primary route we want. Now we tell Express.js to start listening.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">app.use(<span class="string">"/"</span>, router);</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> port = process.env[<span class="string">"PORT"</span>] || <span class="number">8080</span>;</span><br><span class="line"><span class="keyword">var</span> ipaddress = <span class="string">"127.0.0.1"</span>;</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">"Preparing to listen on %s:%d"</span>, ipaddress, port);</span><br><span class="line"><span class="keyword">var</span> server = app.listen(port, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">'%s: Node server started on %s:%d ...'</span>, <span class="built_in">Date</span>(<span class="built_in">Date</span>.now() ), ipaddress, port);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>First we tell Express.js to use ‘/‘ as the base path for all routes defined in the <code>router</code> object. This is useful in the case where you have different sections of your app and you don’t want to have to repeate the same root part of the path. Think of an admin section verses the normal part of the website.</p><p>Then get the port and ip address that will be used to tell Express.js what to listen on. I originally did this on OpenShift so that’s where the IP address comes in but it’s not used on heroku.</p><blockquote><p>See, real code, none of that nice, clean, prepared stuff.</p></blockquote><h4 id="The-poster"><a href="#The-poster" class="headerlink" title="The poster"></a>The poster</h4><p>The <code>poster</code> is my own module in <code>postissue.js</code>. It’s what takes the urls of the screenshots and puts them in the Github PR comment. When it’ called the first thing we do is prepare the info for connecting to the Github API.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> GithubApi = <span class="built_in">require</span>(<span class="string">"github"</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports.postImagesToIssue = <span class="function"><span class="keyword">function</span>(<span class="params">settings, cdnUrls, callback</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> github = <span class="keyword">new</span> GithubApi(&#123;</span><br><span class="line">    version: <span class="string">"3.0.0"</span>,</span><br><span class="line">    protocol: <span class="string">"https"</span>,</span><br><span class="line">    host: <span class="string">"api.github.com"</span>,</span><br><span class="line">    timeout: <span class="number">5000</span></span><br><span class="line">  &#125;);</span><br></pre></td></tr></table></figure><p>I’m using the <a href="https://www.npmjs.com/package/github" target="_blank" rel="noopener">Github package</a> to handle all the HTTP requests to Github’s api. </p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">github.authenticate(&#123;</span><br><span class="line">  type: <span class="string">"basic"</span>,</span><br><span class="line">  username: settings.githubUsername,</span><br><span class="line">  password: settings.githubApiKey</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>Setup the authentication. You can generate those API tokens at the <a href="https://github.com/settings/tokens" target="_blank" rel="noopener">Personal access tokens</a> page of your profile.</p><p>Next just generate the markdown for the comment to post to the PR.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> comment = <span class="string">""</span>;</span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">var</span> image <span class="keyword">of</span> cdnUrls) &#123;</span><br><span class="line">  comment += image.name + <span class="string">"\r\n"</span> + <span class="string">"!["</span> + image.name + <span class="string">" screenshot]("</span> + image.url + <span class="string">")\r\n"</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>I’m simply concatenating the name of the image and the url to it for each image that was generated during the build. The ‘![…](…)’ part is the markdown for pulling in an image.</p><p>Finally I create the comment on the PR.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="string">"Issue comment:"</span>);</span><br><span class="line"><span class="built_in">console</span>.log(comment);</span><br><span class="line"></span><br><span class="line">github.issues.createComment(&#123;</span><br><span class="line">  user: settings.orgName,</span><br><span class="line">  repo: settings.repoName,</span><br><span class="line">  number: settings.prNumber,</span><br><span class="line">  body: comment</span><br><span class="line">&#125;, <span class="function"><span class="keyword">function</span>(<span class="params">err, res</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(err);</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">"=================="</span>);</span><br><span class="line">  <span class="built_in">console</span>.log(res);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">callback(<span class="literal">null</span>);</span><br></pre></td></tr></table></figure><p>First some logging for diagnosis later on when needed. The user in this case will be ‘techlahoma’.  The repo is equivalent to the website. ‘okcsharp-website’ in my case at the moment. But that is gathered from what CircleCI tells us. So if I just setup a different build within the techlahoma organization it should just work. The pull request number triggering the build and then finally the comment with the markdown.</p><p>Once that request has completed it executes the callback function provided. It just sends the results to the console for diagnosis later on when needed.</p><p>The last thing I do here is execute the callback given. Which in this case just allowes the route handling to continue by writing the response.</p><h4 id="In-closing"><a href="#In-closing" class="headerlink" title="In closing"></a>In closing</h4><p>Overall it works very well. You can push a commit to a PR and stay on the PR page. In a few minutes you will see Github display the new comment without doing anything yourself. This let’s me and other organizers see the resulting changes in a mostly accurate way; without having to pull it down and run hexo.io ourselves.</p><p>In fact the December post for the <a href="http://okcsharp.net/" target="_blank" rel="noopener">OKCsharp</a> website was done completely in the Github UI. I made a new file and committed it to a new branch in my fork. Sent it as a PR. Waited to see the screenshots looked correct. I noticed an error, made the correction, saw the new screenshots in the PR then merged. All directly from the Github website. Neat.</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;I continue the &lt;a href=&quot;/post/automating-static-sites-with-hexo-io-circleci-and-github-pages/&quot;&gt;automation of hexo.io&lt;/a&gt; by taking the &lt;a href=&quot;/post/generate-screenshots-of-website-during-build/&quot;&gt;website screenshots&lt;/a&gt; generated during the continuous integration proccess and posting them to the Github PR as a comment.&lt;br&gt;
    
    </summary>
    
    
      <category term="node, github, screenshots, hexo, heroku, express" scheme="http://teapotcoder.com/tags/node-github-screenshots-hexo-heroku-express/"/>
    
  </entry>
  
  <entry>
    <title>Generate screenshots of hexo websites during build</title>
    <link href="http://teapotcoder.com/post/generate-screenshots-of-website-during-build/"/>
    <id>http://teapotcoder.com/post/generate-screenshots-of-website-during-build/</id>
    <published>2015-11-07T06:00:00.000Z</published>
    <updated>2018-10-03T20:02:25.183Z</updated>
    
    <content type="html"><![CDATA[<p>In this post I continue detailing the <a href="/post/automating-static-sites-with-hexo-io-circleci-and-github-pages/">automation of hexo.io</a> by generating screenshots of the generated site. This is primarily useful when it is run in the continuous integration process so I can quickly check on content submissions.<br><a id="more"></a><br>Something you have to understand is asynchronous work in JavaScript. Callbacks, async, promises, promises, promises. I don’t need a promise, just need it to work. Eventually I chose the <a href="https://www.npmjs.com/search?q=async" target="_blank" rel="noopener">async</a> npm package because I got it to work and the <code>queue</code> made sense for the moment. The <code>queue</code> function will call the given task function for every item in the queue. Here is an example of using async.queue.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> <span class="keyword">async</span> = <span class="built_in">require</span>(<span class="string">"async"</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// Define the 'task' objects which</span></span><br><span class="line"><span class="comment">// will be passed into the queue function</span></span><br><span class="line"><span class="keyword">var</span> tasks = [</span><br><span class="line">     &#123;<span class="attr">name</span>: <span class="string">"John"</span>, <span class="attr">age</span>:<span class="number">42</span>&#125;,</span><br><span class="line">     &#123;<span class="attr">name</span>: <span class="string">"Susan"</span>, <span class="attr">age</span>:<span class="number">35</span>&#125;</span><br><span class="line">];</span><br><span class="line"></span><br><span class="line"><span class="comment">// Create new queue passing in the function that will be</span></span><br><span class="line"><span class="comment">// called for every task object pushed to the queue</span></span><br><span class="line"><span class="keyword">var</span> queue = <span class="keyword">async</span>.queue(<span class="function"><span class="keyword">function</span>(<span class="params">task, callback</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">"%s is %d years old."</span>, task.name, task.age);</span><br><span class="line">  </span><br><span class="line">  <span class="comment">// If there was an error pass it into the callback</span></span><br><span class="line">  callback();</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// Define a function to be called when the last item</span></span><br><span class="line"><span class="comment">// in the queue is returned from the worker/task function</span></span><br><span class="line">queue.drain = <span class="function"><span class="keyword">function</span>(<span class="params">err</span>) </span>&#123;</span><br><span class="line">     <span class="built_in">console</span>.log(<span class="string">"Last item returned from worker"</span>);</span><br><span class="line">     <span class="built_in">console</span>.log(<span class="string">"Err (if any):"</span>);</span><br><span class="line">     <span class="built_in">console</span>.log(err);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Filling the queue</span></span><br><span class="line">queue.push(tasks[<span class="number">0</span>]);</span><br><span class="line">queue.push(tasks[<span class="number">1</span>]);</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">"Done"</span>);</span><br></pre></td></tr></table></figure><p>Each item will be processed concurrently if possible. There is no guarantee as to the order the task objects will be processed. So make sure to do some setup before hand if needed. You can view the <a href="https://github.com/techlahoma/okcsharp-website/blob/df853f0a9a337c4a8687cce82790960cdaf50530/screenshots.js" target="_blank" rel="noopener">whole file</a> on GitHub if you want. But I will be going over each part below.</p><p>My goal for this step of my hexo site deployment is to generate screenshots. For that I use <a href="http://phantomjs.org/" target="_blank" rel="noopener">PhantomJS</a>. With PhantomJS I can simulate the browser at various window sizes and urls snapping screenshots along the way. First up, get the tools for the job. After installing PhantomJS and the <code>async</code> npm package I start a <code>screenshots.js</code> file.</p><p>Get the needed modules for the script.<br><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">var<span class="built_in"> system </span>= require(<span class="string">"system"</span>);</span><br><span class="line">var webpage = require(<span class="string">"webpage"</span>);</span><br><span class="line">var async = require(<span class="string">"async"</span>);</span><br></pre></td></tr></table></figure></p><p>The first two modules are provided by PhantomJS. <code>system</code> is how you interact with the machine. It’s what you use instead of <code>process</code> in Node. <code>webpage</code> is well, the webpage you are browsing with PhantomJS. <code>async</code> is what I’m using to handle the asynchronous work here.</p><p>Setup the destination for the screenshots and the sizes of screenshots desired.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> destination = system.env[<span class="string">"CIRCLE_ARTIFACTS"</span>] || <span class="string">"screenshots"</span>;</span><br><span class="line"><span class="keyword">var</span> sizes = [</span><br><span class="line">&#123; <span class="attr">width</span>: <span class="number">1024</span>, <span class="attr">height</span>: <span class="number">768</span> &#125;, <span class="comment">// Desktop</span></span><br><span class="line">&#123; <span class="attr">width</span>: <span class="number">750</span>,  <span class="attr">height</span>: <span class="number">1334</span>&#125;  <span class="comment">// iPhone 6</span></span><br><span class="line">];</span><br></pre></td></tr></table></figure><p>Here is where we use <code>system</code> to get an environment variable or just use <code>screenshots</code> as a default when run locally. <code>CIRCLE_ARTIFACTS</code> is set by CircleCI during the build process. Once the build is done CircleCI will retain any files stored in that location along with the build. I did a short amount of Googling for the iPhone screenshot size so if it’s inaccurate just let me know.</p><p>Next startup a new queue.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> queue = <span class="keyword">async</span>.queue(handle);</span><br><span class="line">queue.drain = done;</span><br><span class="line">queue.pause();</span><br><span class="line">primeTheQueue();</span><br></pre></td></tr></table></figure><p>Specify the function that will <code>handle</code> the tasks. I also like to know when the process is complete. That’s what the <code>drain</code> member is for. The <code>done</code> method will be called once all is…well, done. The <code>queue.pause</code> may actually not be required, I have not really tested it but I know it does what it says. It pauses the queue from processing until told otherwise. That last call to <code>primeTheQueue</code> does just that. It loads up the queue with the tasks to process.</p><p>Let’s look into how the tasks get into the queue first. Each task object looks like this:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  name: <span class="string">"Name of page for display purposes"</span>,</span><br><span class="line">  url: <span class="string">"Full url of page to open"</span>,</span><br><span class="line">  page: &#123;PhantomJS webpage object&#125;,</span><br><span class="line">  size: &#123;<span class="attr">width</span>: x, <span class="attr">height</span>: y&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>The <code>name</code> and <code>url</code> should be obvious. The <code>page</code> and <code>size</code> are used to indicate a different step in the screenshot generation. I’ll get to them in just a bit so ignore them for the moment. Here is the <code>primeTheQueue</code> function:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">primeTheQueue</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  queue.push(&#123;<span class="attr">name</span>: <span class="string">"home"</span>, <span class="attr">url</span>: <span class="string">"http://localhost:4000/"</span>&#125;, errorOut);</span><br><span class="line"></span><br><span class="line">  <span class="keyword">var</span> home = webpage.create();</span><br><span class="line">  home.open(<span class="string">"http://localhost:4000/"</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line"><span class="keyword">var</span> firstPost = <span class="keyword">this</span>.evaluate(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">      <span class="built_in">console</span>.log(<span class="string">"Getting first article"</span>);</span><br><span class="line">  <span class="keyword">return</span> <span class="built_in">document</span>.querySelector(<span class="string">"section#main article:first-child a.article-title"</span>);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">queue.push(&#123;<span class="attr">name</span>: <span class="string">"post"</span>, <span class="attr">url</span>: firstPost.href&#125;, errorOut);</span><br><span class="line">queue.resume();</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>I always want screenshots of the home page so just add that immediately. But I also want a screenshot of the most recent post. To get that I need to open the webpage and find that first link. Create the webpage and open to the home page. The callback will then <code>evaluate</code> the css query selection on that webpage. That query selector path is specific to the layout of our website template. So it will be different for you most likely. It just finds the link to the first post on the page. Add a new task object to the queue with an appropriate name and the url from the webpage. I also add an <code>errorOut</code> function to report problems processing that particular task object.</p><p>Next let’s take a look at the function that is called for each task object.</p><figure class="highlight verilog"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> handle(<span class="keyword">task</span>, callback) &#123;</span><br><span class="line">  <span class="keyword">if</span>(<span class="keyword">task</span><span class="variable">.page</span> === undefined) &#123;</span><br><span class="line">    open(<span class="keyword">task</span>, callback);</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    renderPage(<span class="keyword">task</span>, callback);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Short and simple, it just passes onto an appropriate processing method based on if the url has been opened in PhantomJS already. If it has already been opened, as indicated by a defined <code>task.page</code> member on the task object, then render the page out to file. If it has not been opened then open it.</p><p>Speaking of opening a url.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">open</span>(<span class="params">task, callback</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">"Opening "</span> + task.name);</span><br><span class="line">  <span class="keyword">var</span> page = webpage.create();</span><br><span class="line">  </span><br><span class="line">  page.open(task.url, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">var</span> i = <span class="number">0</span>; i &lt; sizes.length; i++) &#123;</span><br><span class="line">      queue.push(&#123;<span class="attr">name</span>: task.name, <span class="attr">size</span>: sizes[i], <span class="attr">page</span>: <span class="keyword">this</span>&#125;);</span><br><span class="line">    &#125;</span><br><span class="line">    callback();</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>The <code>open</code> function will be called when a task object is to be processed but it does not have a defined <code>page</code> member. <code>open</code> creates the new PhantomJS <code>webpage</code> object; opens the url specified in the task object; then pushes additional task objects onto the same queue but providing the <code>webpage</code> object used to open that url. Note that it’s not just one task object for each url to open; it’s a task object per url per window size to render. That <code>callback</code> must be called for the queue to know that we have finished with this task object. If there was a problem we could pass the <code>callback</code> function an error object.</p><p>Eventually the queue will have to process a task object that has been opened. Which the <code>handle</code> function will pass off to <code>renderPage</code>.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">renderPage</span>(<span class="params">task, callback</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">"Rendering "</span> + task.name + <span class="string">" at "</span> + task.size.width + <span class="string">"x"</span> + task.size.height);</span><br><span class="line">  <span class="keyword">var</span> page = task.page;</span><br><span class="line">  page.viewportSize = task.size;</span><br><span class="line">  page.clipRect = &#123; <span class="attr">top</span>: <span class="number">0</span>, <span class="attr">left</span>: <span class="number">0</span>, <span class="attr">width</span>: task.size.width, <span class="attr">height</span>: (task.size.height * <span class="number">2</span>) &#125;;</span><br><span class="line">  </span><br><span class="line">  <span class="keyword">var</span> renderPath = destination + <span class="string">"/"</span> + task.name + <span class="string">"-"</span> + page.clipRect.width + <span class="string">"x"</span> + page.clipRect.height + <span class="string">".png"</span></span><br><span class="line">  page.render(renderPath);</span><br><span class="line">  </span><br><span class="line">  callback();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Here we set the size of the <code>page</code>. That simulates the size of the browser window. The <code>clipRect</code> is set taller so that I grab more content. Think of it like taking a screenshot of a web page while scrolling down the page a bit more. Then just tell the <code>page</code> to render to the path defined. Using the name plus size gives me decently unique name for the file. Each build has it’s own artifacts so I’m not going to bump into a file from a previous build with the same name.</p><p>The last functions are the ones for when the queue has been drained of all task objects, as well as an error function to report any problems when processing a task.</p><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> done() &#123;</span><br><span class="line">  console.log(<span class="string">"Done"</span>);</span><br><span class="line">  phantom.<span class="keyword">exit</span>();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> errorOut(ex) &#123;</span><br><span class="line">  <span class="keyword">if</span>(ex !== undefined) &#123;</span><br><span class="line">    console.log(<span class="string">"ERROR on task "</span> + ex);</span><br><span class="line">    phantom.<span class="keyword">exit</span>();</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Please note that it’s important to put the <code>phantom.exit();</code> inside the <code>done</code> function. If you put it outside of that (for example at the end of the js file) then your process will just sit there and do nothing. Why is that? Because if <code>phantom.exit();</code> was outside the functions it would get called before the queue is empty. Which would result in the <code>webpage</code> objects not responding. It’s important to pay attention to what actually happens at what time with asynchronous calls. It can get weird.</p><p>Now just run the script.<br><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">phantomjs screenshots.js</span><br></pre></td></tr></table></figure></p><p>Then check in the artifacts directory (screenshots locally). You should see some image files. Adding this to your CI process will depend on which tool you use. For CircleCI it’s an edit to your <code>circle.yml</code> file.</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">test:</span></span><br><span class="line"><span class="attr">  override:</span></span><br><span class="line"><span class="bullet">    -</span> <span class="string">npm</span> <span class="string">install</span> <span class="bullet">-g</span> <span class="string">hexo-cli</span></span><br><span class="line"><span class="bullet">    -</span> <span class="string">hexo</span> <span class="attr">server:</span></span><br><span class="line"><span class="attr">        background:</span> <span class="literal">true</span></span><br><span class="line"><span class="bullet">    -</span> <span class="string">sleep</span> <span class="number">2</span></span><br><span class="line"><span class="bullet">    -</span> <span class="string">phantomjs</span> <span class="string">./screenshots.js</span></span><br></pre></td></tr></table></figure><p>In CirceCI the <code>test</code> field in your yml file is what they use to run custom tests. What I’m doing here is making sure hexo is available for me to use. I start the <code>hexo server</code> just like you would do locally. This is what PhantomJS will call to get the website.</p><p>Note that I specify that <code>background: true</code> field for the <code>hexo server</code> call. That’s special for CircleCI. Each command  is a separate SSH connection. So if you just <code>hexo server</code> the hexo server would stop running as soon as the SSH connection closed and moved onto the next command. But with that additional field set CircleCI knows to run that command in the background to keep it going even after the SSH connection closes.</p><p>I sleep for a few seconds to give hexo time to generate. Two seconds is plenty of time. Then just run the screenshot script in PhantomJS. Once it’s done the ‘tests’ are complete. CircleCI will gather the artifacts which happen to be screenshots.</p><p>There are a few improvements I want to make to this. Namely the ability to do more than just the home and the post, although I may call YAGNI on it. But I would like to use that excuse in order to get a better handle on the asynchronous patterns. I’d also like to make this a NPM package sometime. To make it easier for others to utilize this functionality.</p><p>In my next post I’ll talk about using node.js to send those screenshots to a GitHub PR as a comment. Take a look at some of the closed pull requets on the <a href="https://github.com/techlahoma/okcsharp-website/pulls?q=is%3Apr+is%3Aclosed" target="_blank" rel="noopener">okcsharp website repository</a> to see what it looks like.</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;In this post I continue detailing the &lt;a href=&quot;/post/automating-static-sites-with-hexo-io-circleci-and-github-pages/&quot;&gt;automation of hexo.io&lt;/a&gt; by generating screenshots of the generated site. This is primarily useful when it is run in the continuous integration process so I can quickly check on content submissions.&lt;br&gt;
    
    </summary>
    
    
      <category term="screenshots phantomjs hexo javascript circleci" scheme="http://teapotcoder.com/tags/screenshots-phantomjs-hexo-javascript-circleci/"/>
    
  </entry>
  
  <entry>
    <title>Watch your artifacts web people</title>
    <link href="http://teapotcoder.com/post/watch-your-artifacts-web-people/"/>
    <id>http://teapotcoder.com/post/watch-your-artifacts-web-people/</id>
    <published>2015-11-02T03:55:37.000Z</published>
    <updated>2018-10-03T20:02:25.184Z</updated>
    
    <content type="html"><![CDATA[<p>I just switched to using <a href="https://hexo.io/" target="_blank" rel="noopener">hexo.io</a> for my personal blog. But something was bugging me. A static site taking six to eight seconds to load? Must fix.<br><a id="more"></a><br>At first I thought it was just because I was using the <code>hexo server</code> command to test the site locally. But upon first deploying I still saw the same 6+ second delay in the site completely downloading. I pull up the developer console (happen to be using Edge which is very nice by the way) and look at the network activity of the site. Look at this (removed a few columns for space):</p><p><img src="/images/long-load-time-network.png" alt=""></p><p>CSS and font files? On a CDN? Taking a total of about six seconds to load? Taking a bit of a deeper look into what the Edge browser is telling me I notice those blue bars on the right. Most of the time connecting to <code>*.useso.com</code> is just connecting. <strong>Nothing</strong> is going on. Not sending the request or downloading a response. Just waiting for a connection to do anything.</p><p>I needed to figure out where the request was being initiated from. At first I thought it was something in my template. Sort of. Searching for <code>fontstatic</code> yielded nothing. But I did find some <code>useso.com</code> stylesheets references. If you look at the network activity again you’ll see under the <code>Initiator/Type</code> it says ‘style’ for some of those font files. That means a style sheet is specifying the url. The other top ones are from ‘localhost’ (testing the site) so it’s directly from my HTML. If you follow the path (mentally speaking):</p><ol><li>Browser loads HTML</li><li>HTML specifies stylesheet</li><li>Browser loads stylesheets (top three from above)</li><li>Stylesheet specifies font url</li><li>Browser loads fonts (next five from above)</li><li>Visitor closes page because my blog takes to long to load.</li><li>Nothing here to see.</li></ol><p>So if I remove the stylesheet reference I solve the problem. But I need the stylesheet right? It came with the template. Unfortunately many of us have tendencies to <a href="http://teapotcoder.com/post/net-default-syndrome">stick with the default</a>. Well I decide to see how it will affect the page look and feel. I find the stylesheet reference to anything on useso.com and remove them:</p><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&lt;link <span class="attribute">href</span>=<span class="string">"//fonts.useso.com/css?family=Source+Code+Pro:400,700"</span> <span class="attribute">rel</span>=<span class="string">"stylesheet"</span> <span class="attribute">type</span>=<span class="string">"text/css"</span>&gt;  </span><br><span class="line">&lt;link <span class="attribute">href</span>=<span class="string">'//fonts.useso.com/css?family=Open+Sans:300,600'</span> <span class="attribute">rel</span>=<span class="string">'stylesheet'</span> <span class="attribute">type</span>=<span class="string">'text/css'</span>&gt;</span><br></pre></td></tr></table></figure><p>Those two reference match the first two requests. Run the site again loading the currently deployed site side by side against my local one and…</p><p>Nothing</p><p>Not one single difference that is visible or noticable. There are other fonts being used; font awesome for instance. But those two references add no value to my site. They only cost it time. Checked the page load time now and it dropped by a full four seconds. Okay, so not the six seconds to 110 milliseconds I mentioned on twitter.</p><blockquote><p>Page load time: 6 seconds. Remove two CDN css links that use about 4 fonts.<br>Page load time: 135 milliseconds<br>Watch your artifacts people</p><footer><strong>@davidroberts63</strong><cite><a href="https://twitter.com/davidroberts63/status/660935770320990208" target="_blank" rel="noopener">twitter.com/davidroberts63/status/660935770320990208</a></cite></footer></blockquote><p>But it wasn’t until I started writing this that I realized I was comparing network activity with an empty cache to one that had a full cache. Still three seconds is significant. Especially all that connecting time. I still don’t know what that’s all about. Any connections to *.useso.com did that. None of the others showed that kind of waiting to connect; including google analytics and disqus.</p><p>To make a long story short; I did some optimization of my static blog because I thought it was taking to long to load (still is). But I did it after I got it working. When I compared the before and after of the removal I knew that I wasn’t going to have to put it back in later on. I didn’t accept the defaults and took a deeper look to make adjustments. But I didn’t go crazy right yet. I will still look into some bundling of stylesheets. Watch what you (and others) put into your websites.</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;I just switched to using &lt;a href=&quot;https://hexo.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;hexo.io&lt;/a&gt; for my personal blog. But something was bugging me. A static site taking six to eight seconds to load? Must fix.&lt;br&gt;
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Automating static sites with Hexo.io, CircleCI and Github Pages</title>
    <link href="http://teapotcoder.com/post/automating-static-sites-with-hexo-io-circleci-and-github-pages/"/>
    <id>http://teapotcoder.com/post/automating-static-sites-with-hexo-io-circleci-and-github-pages/</id>
    <published>2015-10-31T21:12:05.000Z</published>
    <updated>2018-10-03T20:02:25.183Z</updated>
    
    <content type="html"><![CDATA[<p>I recently became one of the organizers of the <a href="http://okcsharp.net" target="_blank" rel="noopener">OKCsharp</a> user group in Oklahoma City. They use <a href="http://hexo.io" target="_blank" rel="noopener">Hexo.io</a> to publish the user group static website onto Github. Hexo is a Node.js package that generates a static site and will update the appropriate <code>gh-pages</code> branch for Github to host.<br><a id="more"></a></p><h4 id="Hexo-io"><a href="#Hexo-io" class="headerlink" title="Hexo.io"></a>Hexo.io</h4><p>I’m not going into the use of Hexo; their website has very good documentation. Pay special attention to the <a href="https://hexo.io/docs/deployment.html" target="_blank" rel="noopener">Hexo deployment</a> section. That’s what I will be modifying a bit here in this post.</p><p>I handle a large part of the automated development pipeline process where I work fulltime so the idea of doing a git pull and</p><figure class="highlight verilog"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo deploy --<span class="keyword">generate</span></span><br></pre></td></tr></table></figure><p>to deploy the website, although short and simple (much nicer than others I’ve used) is still so <strong>manual</strong>. It just feels…wasteful.</p><p>So I fixed it with continuous integration.</p><h4 id="Using-CircleCI"><a href="#Using-CircleCI" class="headerlink" title="Using CircleCI"></a>Using CircleCI</h4><p>I ended up using <a href="https://circleci.com" target="_blank" rel="noopener">CircleCI</a>. It’s fast. And I mean super fast. Much faster than TravisCI (and cheaper if you end up needing more). CircleCI will also build pull requests from forks which is awesome (so will TravisCI). Connect CircleCI to your Github account and have CircleCI ‘follow’ the appropriate repository. You will need a <code>circle.yml</code> file in your root of the repository to do this process.</p><figure class="highlight haml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">deployment:</span><br><span class="line">  production:</span><br><span class="line">    branch: master</span><br><span class="line">    commands:</span><br><span class="line">      -<span class="ruby"> git config --global user.name <span class="string">"CircleCI"</span></span></span><br><span class="line"><span class="ruby">      - git config --global user.email <span class="string">"noone@okcsharp.net"</span></span></span><br><span class="line"><span class="ruby">      - sed -i<span class="string">''</span> <span class="string">"s~https://github.com/techlahoma/okcsharp-website.git~https://$&#123;GH_TOKEN&#125;:x-oauth-basic@github.com/techlahoma/okcsharp-website.git~"</span> _config.yml</span></span><br><span class="line"><span class="ruby">      - rm -rf .deploy_git/</span></span><br><span class="line"><span class="ruby">      - hexo clean</span></span><br><span class="line"><span class="ruby">      - hexo generate</span></span><br><span class="line"><span class="ruby">      - hexo deploy</span></span><br></pre></td></tr></table></figure><p>The <code>production</code> name is just for the set of commands for the deployment; it has no other effect. The <code>branch</code> field tells CircleCI which branch this deployment will run for. In this case I only deploy the website when a commit to <code>master</code> is made. So pull requests will not trigger this. This lets us review a PR and then merge it to master when we want to. Then CircleCI handles the rest.</p><p>The <code>commands</code> simply contain shell commands needed to deploy the hexo website to Github. That <code>sed</code> command is used to modify the deployment section of the hexo <code>_config.yml</code> file to allow it to deploy to Github with the appropriate token having commit permissions.</p><figure class="highlight dts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"># Deployment section of hexo _config.yml</span></span><br><span class="line"><span class="meta">## Docs: http:<span class="comment">//hexo.io/docs/deployment.html</span></span></span><br><span class="line"><span class="symbol">deploy:</span></span><br><span class="line"><span class="symbol">  type:</span> git</span><br><span class="line"><span class="symbol">  repository:</span> https:<span class="comment">//github.com/techlahoma/okcsharp-website.git</span></span><br><span class="line"><span class="symbol">  branch:</span> gh-pages</span><br></pre></td></tr></table></figure><p>It changes the <code>repository</code> field to use basic OAuth.<br><figure class="highlight less"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">deploy</span>:</span><br><span class="line">  <span class="attribute">type</span>: git</span><br><span class="line">  <span class="attribute">repository</span>: <span class="attribute">https</span>:<span class="comment">//$&#123;Value of GH_TOKEN&#125;:x-oauth-basic@github.com/techlahoma/okcsharp-website.git</span></span><br><span class="line">  <span class="attribute">branch</span>: gh-pages</span><br></pre></td></tr></table></figure></p><p>That <code>${GH_TOKEN}</code> is an environment variable set in the CircleCI web ui. You can generate that token in Github by going to your Github settings then <a href="https://github.com/settings/tokens" target="_blank" rel="noopener">Personal Access Tokens</a>. Put the token into the CircleCI project settings <a href="https://circleci.com/docs/environment-variables#custom" target="_blank" rel="noopener">environment variables</a>.</p><h5 id="Environment-Variable-Security"><a href="#Environment-Variable-Security" class="headerlink" title="Environment Variable Security"></a>Environment Variable Security</h5><p>A very important note about environment variables in CircleCI; environment variables specified in the <code>circle.yml</code> are available in fork builds. Environment variables specified in the CircleCI web UI are <strong>not</strong> available during fork builds. This is a security precaution. Anyone randomly could fork your public repo, modify the commands and have it export your sensitive environment variables to another server.</p><p>After updating the hexo <code>_config.yml</code> file to be able to commit to Github appropriately the rest of the commands just run the appropriate hexo commands to generate and deploy the website.</p><p>The end result is someone can send us a pull request containing a new post. We look it over and decide to merge it using the Github web UI. CircleCI is notified of that commit and takes care of the rest. In short:</p><h4 id="One-click-hexo-deployments"><a href="#One-click-hexo-deployments" class="headerlink" title="One click hexo deployments"></a>One click hexo deployments</h4><p>Oh, that sounds like a good name for a talk. But before I get to that I need to mention that I didn’t stop there. In my next post I’ll describe how I generated screenshots of the PR and even put those screenshots onto the PR as a comment.</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;I recently became one of the organizers of the &lt;a href=&quot;http://okcsharp.net&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;OKCsharp&lt;/a&gt; user group in Oklahoma City. They use &lt;a href=&quot;http://hexo.io&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Hexo.io&lt;/a&gt; to publish the user group static website onto Github. Hexo is a Node.js package that generates a static site and will update the appropriate &lt;code&gt;gh-pages&lt;/code&gt; branch for Github to host.&lt;br&gt;
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>How I got in the world of software</title>
    <link href="http://teapotcoder.com/post/how-i-got-in-the-world-of-software/"/>
    <id>http://teapotcoder.com/post/how-i-got-in-the-world-of-software/</id>
    <published>2015-03-30T05:00:00.000Z</published>
    <updated>2018-10-03T20:02:25.183Z</updated>
    
    <content type="html"><![CDATA[<p>Now, this is the story all about how<br>My life got flipped-turned upside down<br>And I’d like to take a minute, just sit right there<br>I’ll tell you how I became a coder in the world of software<br><a id="more"></a><br>In Oklahoma City, from a small computer store<br>On a XT dual floppies where I learned my trade<br>Hackin’ out, thinkin’, learnin’ the bits<br>And writin’ a B-ball card app inside BASIC</p><p>When I sent in a card to get some college info<br>Called me up saying ‘hey we think we can help you’<br>I got in one small job a friend thought I’d do well<br>And I said, “This is the work that with life is swell”</p><p>I typed out some VB for an inventory app<br>The users said it’s awesome, better than other smack<br>I went on to PHP…..left and never looked back<br>But I learned a lot in there, this world of software</p><p>I left that first place after years of six or seven<br>And said to the next place “Yeah I can help ya”<br>Looked inside seeing imposter syndrome start<br>Still building with my co-workers in the world of software</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Now, this is the story all about how&lt;br&gt;My life got flipped-turned upside down&lt;br&gt;And I’d like to take a minute, just sit right there&lt;br&gt;I’ll tell you how I became a coder in the world of software&lt;br&gt;
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Developing behind a proxy</title>
    <link href="http://teapotcoder.com/post/developing-behind-a-proxy/"/>
    <id>http://teapotcoder.com/post/developing-behind-a-proxy/</id>
    <published>2015-03-03T06:00:00.000Z</published>
    <updated>2018-10-03T20:02:25.183Z</updated>
    
    <content type="html"><![CDATA[<p>Working behind a proxy can be annoying at times but it’s not difficult to work with, most of the time that is. This is mostly here for my own reference in the future and you get the added benefit.<br><a id="more"></a></p><p>##GIT<br>You need to set two settings to allow git to use your proxy:</p><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git<span class="built_in"> config </span>--global http.proxy <span class="string">"http://[username]:[password]@[address/url]:[port]"</span></span><br><span class="line">git<span class="built_in"> config </span>--global https.proxy <span class="string">"http://[username]:[password]@[address/url]:[port]"</span></span><br></pre></td></tr></table></figure><p>Note both of the above settings. http.proxy and https.proxy.</p><p>You may also need to turn off secure certificate verification. Why? Some places use a self signed certificates on the proxy for use with internal domain names.</p><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git<span class="built_in"> config </span>--global http.sslVerify <span class="literal">false</span></span><br></pre></td></tr></table></figure><p>##NPM<br>More proxy settings:<br><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm<span class="built_in"> config </span><span class="builtin-name">set</span><span class="built_in"> proxy </span><span class="string">"http://[username]:[password]@[address/url]:[port]"</span></span><br><span class="line">npm<span class="built_in"> config </span><span class="builtin-name">set</span> https-proxy <span class="string">"http://[username]:[password]@[address/url]:[port]"</span></span><br></pre></td></tr></table></figure></p><p>Turning off secure certificate verification.</p><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm<span class="built_in"> config </span><span class="builtin-name">set</span> strict-ssl <span class="literal">false</span></span><br></pre></td></tr></table></figure><p>Thank you to the following for their posts providing the above information:</p><p><a href="">http://jjasonclark.com/how-to-setup-node-behind-web-proxy</a><br><a href="">http://stackoverflow.com/questions/783811/getting-git-to-work-with-a-proxy-server</a><br><a href="">http://stackoverflow.com/questions/12537763/git-ssl-without-env-git-ssl-no-verify-true</a></p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Working behind a proxy can be annoying at times but it’s not difficult to work with, most of the time that is. This is mostly here for my own reference in the future and you get the added benefit.&lt;br&gt;
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>OctoPygmy</title>
    <link href="http://teapotcoder.com/post/octopygmy/"/>
    <id>http://teapotcoder.com/post/octopygmy/</id>
    <published>2015-02-28T06:00:00.000Z</published>
    <updated>2018-10-03T20:02:25.183Z</updated>
    
    <content type="html"><![CDATA[<p>I am a great fan of Octopus Deploy. In the interest of improving it in any way I can I released a beta version of OctoPygmy, a Chrome extension for Octopus Deploy.<a id="more"></a>Right now it has the following features:</p><ul><li>Filter the dashboard by project groupings.</li><li>Filter the machines by environment.</li><li>Filter the machines by name or role.</li></ul><p>Where I work full time we have about 50 projects (never really counted) using Octopus Deploy. For the individual teams the dashboard is fine. They only see what they have access to. But for me and the team I’m on. We see all of them. It gets a bit tedious scrolling every where to find the right project that needs looking into on occasion. The dropdown that OctoPygmy adds makes it much easier to focus on the projects at hand for us.</p><p><img src="/images/EnvironmentFilterSmall.png" alt=""></p><p>Similar item for the machines (Tentacles). We have about 70+ machines at the moment being used with Octopus Deploy. There are many more in the company but not for apps. The environment dropdown helps focus on the environment and then the filter by name and role helps even further.</p><p>I’ve read other articles where they have configurations with well over a 100 machines spread across multiple countries. I’m blown away by the scale that others are becoming much more effective and deploying more often in a repeatable way with Octopus Deploy. I hope that this extension finds them and helps them with their larger scale use of Octopus Deploy.</p><p>It’s open source on github at davidroberts63/OctoPygmy. If you’d like to lend a hand just add an issue and lets talk a bit before you put work into it so we are all on the same page. Right now with this initial version 0.6 the source is not ideal. I want to do a few things before adding some more features, without to much of a delay that is:</p><ul><li>Add unit tests</li><li>Get it on a continuous build, maybe Travis-CI or AppVeyor</li><li>Refactor the code to get DRYer</li><li>Look into moving away from the mutation events to start using the mutation observer.</li></ul><p>Later on I’d like to get a better logo for it. The round circle with eight sided starburst in the middle is what I (non-artist graphic person) did in five minutes using Sketch.io.</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;I am a great fan of Octopus Deploy. In the interest of improving it in any way I can I released a beta version of OctoPygmy, a Chrome extension for Octopus Deploy.
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>The case for abstract IoC</title>
    <link href="http://teapotcoder.com/post/the-case-for-abstract-ioc/"/>
    <id>http://teapotcoder.com/post/the-case-for-abstract-ioc/</id>
    <published>2014-12-15T06:00:00.000Z</published>
    <updated>2018-10-03T20:02:25.184Z</updated>
    
    <content type="html"><![CDATA[<p>I really value the IoC libraries out there and the features each one provides. I use one in nearly all the applications I write. Along with IoC libraries there has been the occasional discussion on abstracting it away from the application. I’m not a fan of this idea.<br><a id="more"></a><br>By abstracting the IoC I mean to abstract out the registration of classes and the resolving of the types during runtime. If I did both then I would lose the features of the library I chose because the abstraction has to go to the lowest common denominator of IoC features. Once I lost those features then I wonder why I picked that library over any other library at all.</p><p>Many frameworks (<a href="http://www.asp.net/mvc" target="_blank" rel="noopener">ASP.NET MVC</a>, <a href="http://nancyfx.org" target="_blank" rel="noopener">Nancy</a>, <a href="http://mvc.fubu-project.org" target="_blank" rel="noopener">FubuMVC</a>) do abstract out the IoC. Mostly just the resolving of types but some also do the registration as well. Doing that in the framework is fine because it’s intended to be used by many different types of applications. But in the application itself I see no reason to abstract out the registration of classes. The rest of the application should rely on the dependency injection the IoC provides. Any application factories can require an abstracted resolver  since that should just be providing the ability to resolve a type.</p><p>If I try to convince myself that abstracting the IoC library would be beneficial I simply remember that I will always have to learn the new IoC library API. I feel the abstraction would give me a false sense of security when switching IoC libraries. If switching IoC libraries turns out to be difficult then I likely used the IoC in the wrong way in my application.</p><p>I’ll keep the registration of classes in the IoC soley in my application startup, keep the unique features of the IoC library and know what the IoC is doing with my classes.</p><p>The case for abstracting IoC libraries doesn’t exist for my application, but it can for a framework.</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;I really value the IoC libraries out there and the features each one provides. I use one in nearly all the applications I write. Along with IoC libraries there has been the occasional discussion on abstracting it away from the application. I’m not a fan of this idea.&lt;br&gt;
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>I did TDD wrong</title>
    <link href="http://teapotcoder.com/post/i-did-tdd-wrong/"/>
    <id>http://teapotcoder.com/post/i-did-tdd-wrong/</id>
    <published>2014-10-13T05:00:00.000Z</published>
    <updated>2018-10-03T20:02:25.183Z</updated>
    
    <content type="html"><![CDATA[<h4 id="My-mind-still-thinks-procedurally"><a href="#My-mind-still-thinks-procedurally" class="headerlink" title="My mind still thinks procedurally."></a>My mind still thinks procedurally.</h4><p>I like TDD, I really do. I’m just doing it wrong. TDD is about DRIVING the design. But many people (and evidently myself) just do it in a ‘Test First’ way. That really doesn’t give you much of an advantage other than a higher code coverage.<a id="more"></a>Which is nice on it’s own. However you don’t really get the full benefit that TDD is going for. Driving the design by using your tests doesn’t say ‘You need to write the test first’, it requires that to be done by it’s definition in order for your test to drive the design. I will give a recent example of my own that illustrates the point.</p><p>I needed to create a process that would inform people of updates to things. Let’s just say it is updates to RSS feeds you follow. In a procedural way and mentally I imagine for most of us it would go like this.</p><ul><li>Get the list of RSS feeds to find updates about</li><li>Go get the updates about those RSS feeds</li><li>Associate the updates to the people that want to know about them</li><li>Tell the people about their RSS feed update.</li></ul><p>How I did it the wrong way was I wrote some tests first to make sure I could get the updates about the RSS feeds (second step). This was done in a class definition. At first this seems okay, and it was for the most part. Where I failed is the next thing I did. I wrote a test for the first step (list of rss feeds) WITHOUT a test that made me need to do that step. This is the important part. If you don’t write a test that causes you to need to do that step stop writing. The test driving the design should fall across something that is missing at some point. It might be a method, a class, a whole library, anything. Many times writing the test will likely not compile (in whatever fashion your language compiles) when you discover the next step.</p><p>With TDD you should write a test to accomplish that first goal and drive the design to something effective, simple and maintainable. Nothing more and nothing less. Don’t think about the latter steps. Just focus on that one. Then do it again for any requirement to get that first step to complete. Repeat that process for each subsequent step. Also, focus in on one thing. Don’t try to stuff everything into one flow. When you get done with step one consider that you may be done with that thing/class/object. You may in fact need to have a separate object for the next step.</p><p>As you complete each step of your process you can and should look at how you solved it and potentially refactor the code. Remember refactoring is not intended to change behavior; just how you go about accomplishing the behavior. Your test should change minimally if at all.</p>]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;My-mind-still-thinks-procedurally&quot;&gt;&lt;a href=&quot;#My-mind-still-thinks-procedurally&quot; class=&quot;headerlink&quot; title=&quot;My mind still thinks procedurally.&quot;&gt;&lt;/a&gt;My mind still thinks procedurally.&lt;/h4&gt;&lt;p&gt;I like TDD, I really do. I’m just doing it wrong. TDD is about DRIVING the design. But many people (and evidently myself) just do it in a ‘Test First’ way. That really doesn’t give you much of an advantage other than a higher code coverage.
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Show &amp; Tell: Powerargs</title>
    <link href="http://teapotcoder.com/post/show-tell-powerargs/"/>
    <id>http://teapotcoder.com/post/show-tell-powerargs/</id>
    <published>2014-06-27T05:00:00.000Z</published>
    <updated>2018-10-03T20:02:25.184Z</updated>
    
    <content type="html"><![CDATA[<p>About a month ago I finished a contribution to the <a href="http://github.com/adamabdelhamed/PowerArgs" target="_blank" rel="noopener">PowerArgs</a> project and <a href="/fork-pull-powerargs">wrote about it</a>. A week or two later I thought it would be a great idea to make my first screen cast about it.<br><a id="more"></a><br><div class="video-container"><iframe src="//www.youtube.com/embed/Egw6toDINdA" frameborder="0" allowfullscreen></iframe></div></p><p>The <a href="http://github.com/adamabdelhamed/PowerArgs" target="_blank" rel="noopener">PowerArgs</a> project is a very nice one and I plan on contributing more to this project as I hope you will consider the same. I also hope you consider using it in your projects where you need command line parsing.</p><p>I learned a lot from this first screen cast of mine. I am going to look into <a href="http://www.telestream.net/screenflow" target="_blank" rel="noopener">Screenflow</a>, <a href="http://www.shinywhitebox.com/ishowu-v1" target="_blank" rel="noopener">iShowU</a>, or <a href="http://www.techsmith.com/camtasia" target="_blank" rel="noopener">Camtasia</a> depending on how often I do screencasts. Also trying to figure out how to handle it with my Windows VM on the Mac. Any suggestions are appreciated.</p><p>Thanks for watching and hope you have a great day! Come back again.</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;About a month ago I finished a contribution to the &lt;a href=&quot;http://github.com/adamabdelhamed/PowerArgs&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PowerArgs&lt;/a&gt; project and &lt;a href=&quot;/fork-pull-powerargs&quot;&gt;wrote about it&lt;/a&gt;. A week or two later I thought it would be a great idea to make my first screen cast about it.&lt;br&gt;
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Fixing my own blunder with powershell</title>
    <link href="http://teapotcoder.com/post/fixing-my-own-blunder-with-powershell/"/>
    <id>http://teapotcoder.com/post/fixing-my-own-blunder-with-powershell/</id>
    <published>2014-06-16T05:00:00.000Z</published>
    <updated>2018-10-03T20:02:25.183Z</updated>
    
    <content type="html"><![CDATA[<p>I installed a service a while back that uses Java. When I installed it I followed with a flow of installing Java to a different path from the default (oh no). There are different reasons for that which have now been totally debunked. The service that uses java (Subversion Edge in this case) has a windows service with a path to Java at the time (the non default path).<br>Then a patch got applied.</p><p>It uninstalled the original one and installed the updated one in the default location. So now the windows service is trying to run Java from a location that no longer exists. So how does one fix such a problem given that you can’t change the path the windows service is using from the user interface?</p><p><strong>Power</strong>shell</p><p>Thanks to <a href="http://4sysops.com/jeffery-hicks/" target="_blank" rel="noopener">Jeffery Hicks</a> and his posts on <a href="http://4sysops.com/archives/managing-services-the-powershell-way-part-6/" target="_blank" rel="noopener">Managing Services the Powershell way</a> I was able to very easily correct the executable path of that service.</p><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">$theService</span> = <span class="built_in">Get-WmiObject</span> win32_service -Filter <span class="string">"name='CSVNConsole'"</span></span><br><span class="line"></span><br><span class="line"><span class="variable">$updatedPath</span> = <span class="variable">$theService</span>.PathName.Replace(<span class="string">'E:\MyOldPathToJava'</span>, <span class="string">'C:\Program Files\Java\jre7'</span>)</span><br><span class="line"></span><br><span class="line"><span class="variable">$theService</span> | <span class="built_in">Invoke-WmiMethod</span> -Name Change -ArgumentList @(<span class="literal">$null</span>, <span class="literal">$null</span>, <span class="literal">$null</span>, <span class="literal">$null</span>, <span class="literal">$null</span>, <span class="variable">$updatedPath</span>) | Select ReturnValue</span><br><span class="line"></span><br><span class="line"><span class="comment"># Verify the change took.</span></span><br><span class="line"><span class="built_in">Get-WmiObject</span> win32_service -Filter <span class="string">"name='CSVNConsole'"</span> | Select *</span><br><span class="line"></span><br><span class="line"><span class="built_in">Start-Service</span> CSVNSonsole</span><br></pre></td></tr></table></figure><p>When using the <code>Invoke-WmiMethod</code> it’s important to know what the order of parameters is. What’s documented may not be correct. so use <code>$theService.GetMethodParameters(&quot;Change&quot;)</code> to determine the proper order. Ignore those that start with an underscore.</p><p>All of this is in very good detail at Jeffery Hicks’ blog about this.</p><p>On a side note be sure to use <code>Start-Transcript</code> when working on stuff like this. It’s wonderful to be able to go back and read everything that you did and what the outcome of it was.</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;I installed a service a while back that uses Java. When I installed it I followed with a flow of installing Java to a different path from
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Vagrant for development environments</title>
    <link href="http://teapotcoder.com/post/vagrant-for-development-environments/"/>
    <id>http://teapotcoder.com/post/vagrant-for-development-environments/</id>
    <published>2014-06-08T05:00:00.000Z</published>
    <updated>2018-10-03T20:02:25.184Z</updated>
    
    <content type="html"><![CDATA[<p>I have been using <a href="http://www.vagrantup.com/" target="_blank" rel="noopener">Vagrant</a> for my development environments for about six months now. It’s a wonderful setup that eases the ability to keep different configurations separate as well as to keep my host machine clean from inadvertent changes.<br><a id="more"></a><br>When I do the lite development with Ruby or Python I use Vagrant to manage the runtime environment. I continue to actually write the code using my host machine. This way I can use my Sublime and other development tools setup across all the development machines. Then I can quickly change the runtime, testing environment without affecting the writing envirnonment.</p><p>You can use the ‘<a href="http://docs.vagrantup.com/v2/synced-folders/basic_usage.html" target="_blank" rel="noopener">config.vm.synced_folder</a>‘ property in the Vagrantfile to keep a host folder synced up as a mounted folder on your guest Linux machine. From that point if you clone your repository into that folder on your host machine You will also have them in your guest machine.</p><p>You may also keep your Vagrantfile under version control. Just check it out to a separate folder. I do this so I can use the same vagrant setup for multiple environments when needed.</p><p>Vagrant checkout of Ruby Vagrant config (Vagrantfile and puppet/ansible config)</p><p><code>/Users/johndoe/devenvironments/rubydev</code></p><p>Ruby project checkout</p><p><code>/Users/johndoe/development/my-project</code></p><p>I set the ‘config.vm.synced_folder’ to the <code>/Users/johndoe/development</code> folder. Change to the rubydev folder on my host and <code>vagrant up</code>. In the vm I can change to that dir using the name I specified in the vagrantfile. In this case <code>/development</code></p><p><code>config.vm.synced_folder &quot;/Users/johndoe/development&quot;, &quot;/development&quot;</code></p><p>I continue writing in my host but runtime, web server (via forwarded ports) and testing are in the vm. This does cause me to switch between host and guest when checking test results or dealing with gems. I would like to get growl setup to talk to the host from the guest so that my test results show as I’m writing within my host machine. But that’s for a later time.</p><p>Note this also works for .NET development in Windows. Same principle just a different OS. I’m currently using Puppet to manage the configuration. Not sure of the road map of Windows support in Ansible yet.</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;I have been using &lt;a href=&quot;http://www.vagrantup.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Vagrant&lt;/a&gt; for my development environments for about six months now. It’s a wonderful setup that eases the ability to keep different configurations separate as well as to keep my host machine clean from inadvertent changes.&lt;br&gt;
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Strong Naming .NET and Key Containers</title>
    <link href="http://teapotcoder.com/post/strong-naming-net-and-key-containers/"/>
    <id>http://teapotcoder.com/post/strong-naming-net-and-key-containers/</id>
    <published>2014-06-03T05:00:00.000Z</published>
    <updated>2018-10-03T20:02:25.184Z</updated>
    
    <content type="html"><![CDATA[<p>There’s a lot of documentation about strong naming .NET assemblies. Most talk about using an open strong name file (snk). Some talk about the password protected file (pfx). Even fewer mention the key container.<a id="more"></a> I’ll just get right to the situation and the point.</p><p>I’m strong naming assemblies primarily so they can be added to the GAC. Can’t let the full pfx sit on the developers’ laptops for security concerns. Delay signing just seems like it’s going to cause more troubles than it is worth. Since we are using a central build server I’m just telling msbuild to sign the assemblies on the fly. Yeah for automation!</p><p>When you do that by specifying the <code>AssemblyOriginatorKeyFile</code> msbuild property and that file is password protected (a pfx file) then msbuild will complain about the password. It will also tell you that you can import it into a key container with a name that msbuild has specified. So I do that. Well, not me really but the security team. They are the ones with the password anyway.</p><figure class="highlight taggerscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">C:<span class="symbol">\P</span>rogram Files (x86)<span class="symbol">\M</span>icrosoft SDKs<span class="symbol">\W</span>indows<span class="symbol">\v</span>8.0A<span class="symbol">\b</span>in<span class="symbol">\N</span>ETFX 4.0 Tools<span class="symbol">\s</span>n.exe -i [PATH_TO_YOUR_PFX_FILE] [KEY_FROM_MSBUILD_ERROR_OUTPUT]</span><br></pre></td></tr></table></figure><p>The import is tied to the contents of the file. Not the file name or the path.</p><p>Now from my thinking the key is inside that key container; so I don’t need to use the <code>AssemblyOriginatorKeyFile</code> property anymore right? To back that up there is another msbuild property called <code>AssemblyKeyContainerName</code>, heck there’s even one called <code>AssemblyKeyName</code> although that’s in an extension pack. So out with <code>AssemblyOriginatorKeyFile</code> and in with <code>AssemblyKeyContainerName</code>.</p><p><strong>Nope.</strong></p><p>Doesn’t work. No one’s going to tell you directly either.</p><p>I assumed something. We all know what that means.</p><p>If you do import the password protected pfx into that key container then you still must specify that <code>AssemblyOriginatorKeyFile</code> pointing to the pfx file. MSBuild will look in its container for the private key data corresponding to that file you specified and the container it told you earlier.</p><p>Oh and the <code>AssemblyKeyContainerName</code> msbuild property does absolutely nothing as far as I can tell. I wish it did because the container name that msbuild wants (VS_KEY_RANDOMALPHANUM) is nice and ugly.</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;There’s a lot of documentation about strong naming .NET assemblies. Most talk about using an open strong name file (snk). Some talk about the password protected file (pfx). Even fewer mention the key container.
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Fork &amp; Pull: Powerargs</title>
    <link href="http://teapotcoder.com/post/fork-pull-powerargs/"/>
    <id>http://teapotcoder.com/post/fork-pull-powerargs/</id>
    <published>2014-05-29T05:00:00.000Z</published>
    <updated>2018-10-03T20:02:25.183Z</updated>
    
    <content type="html"><![CDATA[<p>I came across the <a href="http://github.com/adamabdelhamed/PowerArgs" target="_blank" rel="noopener">PowerArgs</a> command line parsing .NET library while exploring the latest updated repositories on <a href="http://github.com" target="_blank" rel="noopener">Github</a> looking for a project to contribute to. Checking its <a href="http://github.com/adamabdelhamed/PowerArgs/pulse" target="_blank" rel="noopener">pulse</a> was encouraging and it had a simple enough <a href="https://github.com/adamabdelhamed/PowerArgs/issues/11" target="_blank" rel="noopener">issue</a> for me to cut my teeth on for the project.<a id="more"></a>It was not until halfway through my work on that issue that I discovered that the attention grabbing project <a href="http://scriptcs.net/" target="_blank" rel="noopener">ScriptCS</a> uses it. Wonderful! I say to myself and forge ahead improving the project the little bit that I can.</p><p>Oh, and it has tests. Note to other projects, you have tests? Yes? Good, thank you. That helps me know when I screw up.</p><p>You can see by the <a href="https://github.com/adamabdelhamed/PowerArgs/issues/11" target="_blank" rel="noopener">execptions issue</a> comments that someone else was trying to get to this item. However it seemed as though time eluded that individual. I do hope that person is able to contribute in the future.</p><p>I prefer to give some notice of intent to contribute so as to avoid duplication of work if someone else is already working on it. A few days to give others a chance to chime in sounded like a decent notice and that it was. <a href="https://github.com/adamabdelhamed" target="_blank" rel="noopener">Adam</a> is nice to work with. Responded in a good amount of time and was appreciative of my <a href="https://github.com/adamabdelhamed/PowerArgs/pull/19" target="_blank" rel="noopener">contribution</a>. I’m glad he asked what my approach to the issue would be as this is a good sign of project invovlement and forces contributors to think a bit before making serious modifications.</p><p>I did make some changes to the tests that are a bit different from the rest of the tests. Any tests that I touched I renamed to describe what was being tested in a bit more detail. Following the ‘ThingDoesActionWhenSituation’ and ‘ThingThrowsWhenSituation’ somewhat. Also adusted how some of the assertions were being performed. I see a lot of people (in several other projects) using Assert.IsTrue when an AreEqual can provide better feedback when the test fails. AreEqual will tell you what the actual data that came back is so you can better determine what the problem is.</p><p>I did offer to revert the naming and assertion changes I had made. They are my opinonated changes but I will always defer to the owner and main contributors to follow the project style if they request. It’s important to balance moving the code in a direction with keeping it consistent across contributors. This helps the readability of the code so you don’t find your self context switching just because someone else wrote the code.</p><p>I may end up working on another issue <a href="https://github.com/adamabdelhamed/PowerArgs/issues/17" target="_blank" rel="noopener">multiple shortcuts</a>. <a href="https://twitter.com/gblock" target="_blank" rel="noopener">Glenn Block</a> himself has requested it. I might just contact him online to see if it’s still an issue for him.</p><p>Overall, I’m glad that I was able to help. I hope to help some more. Take a look at it yourself and make your command line argument parsing so much easier. You can get it via <a href="http://nuget.org/packages/PowerArgs/" target="_blank" rel="noopener">Nuget</a> as well. I’ll be posting a short 10 minute video on it as sort of a show and tell soon so be sure to keep an eye out for that as well.</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;I came across the &lt;a href=&quot;http://github.com/adamabdelhamed/PowerArgs&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PowerArgs&lt;/a&gt; command line parsing .NET library while exploring the latest updated repositories on &lt;a href=&quot;http://github.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Github&lt;/a&gt; looking for a project to contribute to. Checking its &lt;a href=&quot;http://github.com/adamabdelhamed/PowerArgs/pulse&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;pulse&lt;/a&gt; was encouraging and it had a simple enough &lt;a href=&quot;https://github.com/adamabdelhamed/PowerArgs/issues/11&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;issue&lt;/a&gt; for me to cut my teeth on for the project.
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Automated Install of Octopus Deploy Server</title>
    <link href="http://teapotcoder.com/post/automated-install-of-octopus-deploy-server/"/>
    <id>http://teapotcoder.com/post/automated-install-of-octopus-deploy-server/</id>
    <published>2014-05-13T05:00:00.000Z</published>
    <updated>2018-10-03T20:02:25.182Z</updated>
    
    <content type="html"><![CDATA[<p>I have been using Octopus Deploy for a while at work and now upgrading to their 2.0 line. It’s a wonderful product and you should check it out if you haven’t yet. One of the things I always want to do is automate the install of application infrastructure items (such as this) so that I can burn and build the servers. This allows me to be better prepared for server outages.<br><a id="more"></a><br>One of the great things about Octopus Deploy 2.X is that at the end of the server configuration wizard you have the option to get the script to reproduce the configuration.</p><p><img src="/images/OctopusDeployConfigureScript.png" alt=""></p><p>The only missing part is the actual installation of the Octopus Deploy server files. The running of the msi. It’s simple enough to automate as most msi installers are:</p><script src="//gist.github.com/3e0a05579e883476fac6.js?file=Install-OctopusServer.ps1"></script><p>Notice that I take the given script and use it within Powershell. Using the Start-Process with the -Wait and -Verb RunAs keeps the commands running in sequence and as the running account. Powershell needs to be running as an administrator in this case or it won’t install.</p><p>Then run your script that you got from the Octopus Setup Wizard. Here’s my complete script:</p><script src="//gist.github.com/3e0a05579e883476fac6.js?file=InstallConfigure-OctopusDeployServer.ps1"></script><p>The only thing I have not figured out is how to set the RavenDb backup location via this wizard or command line configuration. You can do it via the website api (though I have not verified it myself yet). The only problem is that you won’t know what the admin user api key is until you logon to the website. At that time you might as well just set the backup location manually. It is not a problem, just a small change that I know I will always do.</p><p>Overall I really like this installation process, especially the providing of the script. It was very simple and fluid. The Octopus Deploy team puts a lot of thought into this and it shows.</p><p>If you don’t see the embedded gists above just use the links. I’m having a bit of trouble with embedded gists at the moment</p><p>Update</p><p>I just caught up on my blog reading and the Octopus Deploy team has released the server and tentacle as Chocolatey packages. If your server can access chocolatey.org then it’s even easier. Check the octopus blog for details. <a href="http://octopusdeploy.com/blog/cinst-octopusdeploy" target="_blank" rel="noopener">http://octopusdeploy.com/blog/cinst-octopusdeploy</a></p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;I have been using Octopus Deploy for a while at work and now upgrading to their 2.0 line. It’s a wonderful product and you should check it out if you haven’t yet. One of the things I always want to do is automate the install of application infrastructure items (such as this) so that I can burn and build the servers. This allows me to be better prepared for server outages.&lt;br&gt;
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>NancyFX Testing with an authenticated user</title>
    <link href="http://teapotcoder.com/post/nancyfx-testing-with-an-authenticated-user/"/>
    <id>http://teapotcoder.com/post/nancyfx-testing-with-an-authenticated-user/</id>
    <published>2014-05-08T05:00:00.000Z</published>
    <updated>2018-10-03T20:02:25.183Z</updated>
    
    <content type="html"><![CDATA[<p>I’ve been trying <a href="http://nancyfx.org" target="_blank" rel="noopener">NancyFx</a> lately and ran across a bit of a misunderstanding on my part and a minor missing point in the Nancy documentation. I’m testing my modules and some require authentication.<a id="more"></a> By way of:</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">this</span>.RequiresAuthentication();</span><br></pre></td></tr></table></figure><p>The <a href="https://github.com/NancyFx/Nancy/wiki/Authentication-overview#what-did-you-say-your-name-was-again" target="_blank" rel="noopener">Authentication</a> documentation for Nancy states that if the <code>NancyContext.CurrentUser</code> property is <code>null</code> then the current request has not been authenticated otherwise the request has been authenticated. Well, not quite. Nancy checks that <code>CurrentUser</code> property for null. It also checks that the <code>UserName</code> property is not empty. So be sure that your identity has the <code>UserName</code> set which is almost always the case.</p><p>But for testing I usually setup the minimum amount of data required to keep the distractions as low as possible. What I also do for testing is create a custom bootstrapper just for use in my tests.</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title">BootstrapperWithLoggedInUser</span> : <span class="title">MyApplicationCustomBootstrapper</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">override</span> <span class="keyword">void</span> <span class="title">RequestStartup</span>(<span class="params">TinyIocContainer container, IPipelines pipelines, NancyContext context</span>)</span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">base</span>.RequestStartup(container, pipelines, context)</span><br><span class="line"></span><br><span class="line">        context.CurrentUser = <span class="keyword">new</span> MyApplicationUserIdentity() &#123; UserName = <span class="string">"Douglas Adams"</span> &#125;;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>That bootstrapper sets up every request with a logged in user. So I don’t have to do it on every request in my tests on the <code>BrowserContext.FormsAuth</code>. What I initially did in the bootstrapper was not specify a <code>UserName</code> for the current user. Everything kept getting redirected to the login page. Once I set the username everything started working correctly in my tests.</p><p>For those that may be interested the code in Nancy that does the actual checking for an authenticated user is the <a href="https://github.com/NancyFx/Nancy/blob/master/src/Nancy/Security/UserIdentityExtensions.cs#L19-21" target="_blank" rel="noopener">UserIdentityExtensions.cs</a> file in Nancy.Security.</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;I’ve been trying &lt;a href=&quot;http://nancyfx.org&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;NancyFx&lt;/a&gt; lately and ran across a bit of a misunderstanding on my part and a minor missing point in the Nancy documentation. I’m testing my modules and some require authentication.
    
    </summary>
    
    
  </entry>
  
</feed>
