<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.3">Jekyll</generator><link href="https://www.deweysasser.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.deweysasser.com/" rel="alternate" type="text/html" /><updated>2024-09-02T17:37:57+00:00</updated><id>https://www.deweysasser.com/feed.xml</id><title type="html">DeweySasser.com</title><subtitle>Software Engineering, Systems Engineering, and other geek pursuits</subtitle><author><name>Dewey Sasser</name></author><entry><title type="html">Recent GitHub Projects</title><link href="https://www.deweysasser.com/content/github-projects" rel="alternate" type="text/html" title="Recent GitHub Projects" /><published>2024-09-02T00:00:00+00:00</published><updated>2024-09-02T00:00:00+00:00</updated><id>https://www.deweysasser.com/content/github-projects</id><content type="html" xml:base="https://www.deweysasser.com/content/github-projects"><![CDATA[<p>I’ve been doing work in Golang and writing some things for Kubernetes that I haven’t indexed here.  See my <a href="../page/projects.html">projects</a> for details.</p>]]></content><author><name>Dewey Sasser</name></author><summary type="html"><![CDATA[I’ve been doing work in Golang and writing some things for Kubernetes that I haven’t indexed here. See my projects for details.]]></summary></entry><entry><title type="html">New Publishing Workflow</title><link href="https://www.deweysasser.com/content/new-publishing-workflow" rel="alternate" type="text/html" title="New Publishing Workflow" /><published>2024-09-01T00:00:00+00:00</published><updated>2024-09-01T00:00:00+00:00</updated><id>https://www.deweysasser.com/content/new-publishing-workflow</id><content type="html" xml:base="https://www.deweysasser.com/content/new-publishing-workflow"><![CDATA[<p>This site now has a new publishing workflow.  Hopefully this will reduce friction and encourage me to write more.</p>

<p>I have a <a href="https://jekyllrb.com/">Jekyll</a> based builder with site contents in a private github repo.  I use <a href="https://obsidian.md/">Obsidian</a> to edit it, because Obsidian.</p>

<p>When I’m happy with a page, I push it to my private repo.  I have an action set up that will then build the site with the following docker file:</p>

<div class="language-Dockerfile highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">FROM</span><span class="w"> </span><span class="s">ruby:3.3</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="s">builder  </span>
<span class="k">WORKDIR</span><span class="s"> /site  </span>
<span class="k">ADD</span><span class="s">  Gemfile Gemfile.lock ./  </span>
<span class="k">RUN </span>bundle <span class="nb">install</span>
</code></pre></div></div>

<p>and then I publish it using <a href="https://pages.github.com/">Github Pages</a>, using this workflow:</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">name</span><span class="pi">:</span> <span class="s">Makefile CI</span>  
  
<span class="na">on</span><span class="pi">:</span>  
  <span class="na">push</span><span class="pi">:</span>  
    <span class="na">branches</span><span class="pi">:</span> <span class="pi">[</span> <span class="s2">"</span><span class="s">main"</span> <span class="pi">]</span>  
  <span class="na">pull_request</span><span class="pi">:</span>  
    <span class="na">branches</span><span class="pi">:</span> <span class="pi">[</span> <span class="s2">"</span><span class="s">main"</span> <span class="pi">]</span>  
  
<span class="na">jobs</span><span class="pi">:</span>  
  <span class="na">build</span><span class="pi">:</span>  
  
    <span class="na">runs-on</span><span class="pi">:</span> <span class="s">ubuntu-latest</span>  
  
    <span class="na">steps</span><span class="pi">:</span>  
    <span class="pi">-</span> <span class="na">uses</span><span class="pi">:</span> <span class="s">actions/checkout@v4</span>  
  
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Build Site</span>  
      <span class="na">run</span><span class="pi">:</span> <span class="s">make</span>  
  
    <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Push directory to another repository</span>  
      <span class="na">uses</span><span class="pi">:</span> <span class="s">cpina/github-action-push-to-another-repository@v1.7.2</span>  
      <span class="na">env</span><span class="pi">:</span>  
        <span class="na">SSH_DEPLOY_KEY</span><span class="pi">:</span> <span class="s">$</span>  
      <span class="na">with</span><span class="pi">:</span>  
          <span class="na">user-email</span><span class="pi">:</span> <span class="s1">'</span><span class="s">dewey@deweysasser.com'</span>  
          <span class="na">destination-repository-name</span><span class="pi">:</span> <span class="s1">'</span><span class="s">deweysasser.github.io'</span>  
          <span class="na">destination-github-username</span><span class="pi">:</span> <span class="s1">'</span><span class="s">deweysasser'</span>  
          <span class="na">source-directory</span><span class="pi">:</span> <span class="s1">'</span><span class="s">_site'</span>  
          <span class="na">target-branch</span><span class="pi">:</span> <span class="s1">'</span><span class="s">main'</span>
</code></pre></div></div>

<p>Obviously, I have a <code class="language-plaintext highlighter-rouge">Makefile</code> to stitch this all together, but that only does a <code class="language-plaintext highlighter-rouge">docker build</code>, then a <code class="language-plaintext highlighter-rouge">docker run</code> with the current path mapped into the container, so it can produce the site output.  I <em>could</em> do that in straight up ruby on GitHub Actions, but I want the same build process locally as in GHA, and this keeps it nice and consistent.</p>

<p>Once the generated site is committed to the public site repo, I use the default Action to publish a static site.</p>

<h1 id="potential-improvements">Potential improvements</h1>

<ul>
  <li>use the <a href="https://github.com/Enveloppe">Obsidian Enveloppe</a> plugin to allow me to use all of the rich set of Obsidian rendering in my blog.</li>
  <li>use the Obsidian Git Plugin to automate the commits</li>
</ul>

<p>These two approaches are likely in conflict, so I probably won’t do both.  I’ll likely go with the latter choice until I <em>need</em> something like <a href="https://blacksmithgu.github.io/obsidian-dataview/">Dataview</a> (which is utterly awesome for doing things in Obsidian).</p>

<ul>
  <li>deploy the site directly from my private repo</li>
  <li>make my private repo the public one</li>
</ul>

<p>I’m currently on a free GitHub plan, so I can’t have pages associated with a private site, but…there’s really nothing private in my public site (though I should scrutinize that before committing to it), so I will quite probably at some point make the <em>source</em> public, and not just the site.</p>]]></content><author><name>Dewey Sasser</name></author><summary type="html"><![CDATA[This site now has a new publishing workflow. Hopefully this will reduce friction and encourage me to write more.]]></summary></entry><entry><title type="html">Second System Effect Impacts Traefik</title><link href="https://www.deweysasser.com/content/second-system-effect-impacts-traefik" rel="alternate" type="text/html" title="Second System Effect Impacts Traefik" /><published>2022-10-17T00:00:00+00:00</published><updated>2022-10-17T00:00:00+00:00</updated><id>https://www.deweysasser.com/content/second-system-effect-impacts-traefik</id><content type="html" xml:base="https://www.deweysasser.com/content/second-system-effect-impacts-traefik"><![CDATA[<p>Ahhh, the <a href="https://en.wikipedia.org/wiki/Second-system_effect">Second System Effect</a>,
a perennial project killer.</p>

<p>For some years, this site has run in a Kubernetes cluster with several others, and
used <a href="https://traefik.io/traefik/">Traefik Proxy</a>, which has been an excellent piece of code, to
multiplex sites through one load balancer.</p>

<p>For better or worse, my provider has just forced a kubernetes upgrade…which removed some
deprecated APIs…on which traefik 1.7 depended.</p>

<p>And, instead of maintaining the same standard API of reading annotations from standard Ingress
objects, traefik has gone the “custom resource definition” route, destroying the simple and
elegant (and standard!) way of using it in favor of complicated and proprietary ways of specifying
everything.</p>

<p>Of course, it’s always possible that Traefik is doing this to contribute to monetizing their
software. My opinion on that is a topic for another day.</p>

<p>I will update this page later with some details, but for now, the result is that TLS on this (and
several other) sites are broken until I can either reconfigure everything to use their new system,
or replace them with other methods.</p>

<p>I apologize for the inconvenience. TLS is very useful, and right now we don’t have it. Gagh!</p>]]></content><author><name>Dewey Sasser</name></author><category term="admin" /><summary type="html"><![CDATA[Traefik has changed everything, breaking TLS for this site. I'm not a fan of the redesign.]]></summary></entry><entry><title type="html">Principles Of Design</title><link href="https://www.deweysasser.com/content/principles-of-design" rel="alternate" type="text/html" title="Principles Of Design" /><published>2021-05-01T00:00:00+00:00</published><updated>2021-05-01T00:00:00+00:00</updated><id>https://www.deweysasser.com/content/principles-of-design</id><content type="html" xml:base="https://www.deweysasser.com/content/principles-of-design"><![CDATA[<p>Some random thoughts on designing systems</p>

<ul>
  <li>put the processing where the knowledge is, don’t move the knowledge to the processing</li>
  <li>Where there’s 2, there’s N</li>
  <li>Be more general</li>
  <li>keep it in the problem space as long as possible</li>
  <li>Sufficiently detailed documentation is executable</li>
  <li>DRY is good</li>
  <li>always align authority and responsibility</li>
</ul>

<p>(more will be added, along with explanations)</p>]]></content><author><name>Dewey Sasser</name></author><summary type="html"><![CDATA[A list of my pithy statements about designing systems. Eventually I'll write explanations here.]]></summary></entry><entry><title type="html">Runbook Framework</title><link href="https://www.deweysasser.com/content/runbook-framework" rel="alternate" type="text/html" title="Runbook Framework" /><published>2021-05-01T00:00:00+00:00</published><updated>2021-05-01T00:00:00+00:00</updated><id>https://www.deweysasser.com/content/runbook-framework</id><content type="html" xml:base="https://www.deweysasser.com/content/runbook-framework"><![CDATA[<p><a href="https://github.com/deweysasser/runbook-framework">See Github Project</a></p>

<hr />
<h1 id="runbook-framework">Runbook-framework</h1>

<p>“Any sufficiently detailed documentation is executable”
– me</p>

<h2 id="what-is-it">What is it?</h2>

<p>A shell (bash) framework to implement runbook scripts that help move from fully manual to fully
automated processes.</p>

<p>Based on the clever concept of
a <a href="https://blog.danslimmon.com/2019/07/15/do-nothing-scripting-the-key-to-gradual-automation/">Do Nothing Script</a>,
provide some structure for the script which allows &amp; encourages documentation and useful tracking at run time.</p>

<p>You write this code:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>runbook<span class="o">()</span> <span class="o">{</span>
  step <span class="s2">"Step One"</span>
  step <span class="s2">"Step Two, on </span><span class="nv">$env</span><span class="s2">"</span> <span class="nb">echo</span> <span class="s2">"set </span><span class="nv">$env</span><span class="s2">=</span><span class="nv">$version</span><span class="s2">"</span>
  step <span class="s2">"Wait for something to happen"</span> <span class="nb">sleep </span>10
  step <span class="s2">"Run a function"</span> run-function
  step <span class="s2">"Last thing we can do automatically"</span> <span class="nb">echo</span> <span class="s2">"Version is </span><span class="nv">$version</span><span class="s2">"</span>
  step <span class="s2">"bring it on home"</span>
  step <span class="s2">"this one will fail"</span> fail_me
<span class="o">}</span>
</code></pre></div></div>

<p>And you can run it and get</p>

<p><img src="https://github.com/deweysasser/runbook-framework/blob/master/docs/runbooks-screenshot.png?raw=true" alt="runbook example" /></p>

<p>Or if you just need to produce some documentation, you can get</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ./example-runbook --version=1.2.3 -doc
1: Step One
2: Step Two, on staging
3: Wait for something to happen
4: Run a function
5: Last thing we can do automatically
6: bring it on home
7: this one will fail
$
</code></pre></div></div>

<h2 id="background">Background</h2>

<p>I love automation, but often getting something “automated” is a long process, and you actually need
to get something done now and don’t have the time to fully automate it.</p>

<p>A few years ago I read
a <a href="https://blog.danslimmon.com/2019/07/15/do-nothing-scripting-the-key-to-gradual-automation/">blog post</a>
presenting a clever way to move from unautomated to automated processes.</p>

<p>The clever key:  start with a script that does nothing other than tell you what to do. A checklist.
Then, as time evolves, you can automate one little piece. Since the script is walking you through a
checklist, this becomes one step that’s done for you instead of you having to do it. This is one of
those simple and amazingly insightful ways of getting things done.</p>

<p>This repository implements a small library of BASH functions to support runbooks in a consistent and
useful way.</p>

<h2 id="quickstart">Quickstart</h2>

<p>Be sure to read the <a href="#important-details">“important details”</a> section.</p>

<h3 id="writing-the-script">Writing the script</h3>

<p>Create a script that looks like this:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>

<span class="nb">source </span>runbook-framework.sh

parameters p1 p2
<span class="nv">p1</span><span class="o">=</span><span class="s2">"some default value"</span>

<span class="c"># Here's where you put your actual runbook steps</span>
runbook<span class="o">()</span> <span class="o">{</span>
  step <span class="s2">"This is a manual step and you'll get a prompt"</span>
  step <span class="s2">"This is an automated step"</span> some-command
<span class="o">}</span>

<span class="c"># This must be the last line in your file</span>
main <span class="s2">"</span><span class="nv">$@</span><span class="s2">"</span>
</code></pre></div></div>

<p>Of course, the steps should be doing whatever it is you need.  <code class="language-plaintext highlighter-rouge">some-command</code> can be a function you
define (I suggest later in the file, so the file starts with your runbook).</p>

<p>If you leave out the command, you’ve just made a prompt. If you include the command, it will be
executed. The status of all commands will be printed as they are executed.</p>

<h3 id="running-the-script">Running the script</h3>

<p>The framework provides some overall features, including</p>

<ul>
  <li>-help or -h – show how to run this runbook, including the parameters</li>
  <li>-doc – show the checklist <em>without</em> executing it</li>
  <li>-verbose or -v – show the output of each command as it happens</li>
</ul>

<h3 id="what-happened-to-the-output">What happened to the output?</h3>

<p>The output of each step is stored away and shown only on error or on request.</p>

<h3 id="important-details">Important Details</h3>

<p>The script sets up bash to be pretty paranoid, specifically:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">set</span> <span class="nt">-ueo</span> pipefail
</code></pre></div></div>

<p>The short form is:  unexpanded variables will be an error, any error (that’s not in a conditional)
will stop the script, and it counts errors in the middle of a pipeline, not just the result of the
last command in the pipeline.</p>

<h2 id="passing-parameters">Passing Parameters</h2>

<p>You can set the <code class="language-plaintext highlighter-rouge">parameters</code> variable to a list of parameters you want to use in your script. They
will be set as (global) environment variables, exactly as you type them. All names that begin with
an underscore (‘_’) are reserved.</p>

<p>When you call the script, you may pass these variables on the command line as command line options.
If any of them are unset, the script will stop. So, if you want a default value, make sure you set
it.</p>

<h2 id="examples">Examples</h2>

<h3 id="just-try-to-run-it">Just try to run it</h3>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./example-runbook
Parameter <span class="s1">'version'</span> required
Usage: ./example-runbook <span class="o">[</span><span class="nt">-h</span>|-help] <span class="o">[</span><span class="nt">-show</span><span class="o">]</span> <span class="o">[</span><span class="nt">--env</span><span class="o">=</span>VALUE] <span class="nt">--version</span><span class="o">=</span>VALUE 
Defaults:
   <span class="nb">env</span> <span class="o">=</span> staging
</code></pre></div></div>

<h3 id="get-some-documentation-on-the-process">Get some documentation on the process</h3>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./example-runbook  <span class="nt">--version</span><span class="o">=</span>1.2.3 <span class="nt">-doc</span>
1: Step One
2: Step Two, on staging
3: Wait <span class="k">for </span>something to happen
4: Run a <span class="k">function
</span>5: Last thing we can <span class="k">do </span>automatically
6: bring it on home
7: this one will fail
</code></pre></div></div>

<h3 id="actually-run-the-runbook">Actually run the runbook</h3>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./example-runbook  <span class="nt">--version</span><span class="o">=</span>1.2.3
 1: <span class="o">(</span>00:52<span class="o">)</span> Step One...<span class="o">(</span>press enter when <span class="k">done</span><span class="o">)</span> <span class="o">(</span>5 s<span class="o">)</span> DONE
 2: <span class="o">(</span>00:52<span class="o">)</span> Step Two, on staging... <span class="o">(</span>0 s<span class="o">)</span> DONE
 3: <span class="o">(</span>00:52<span class="o">)</span> Wait <span class="k">for </span>something to happen... <span class="o">(</span>10 s<span class="o">)</span> DONE
 4: <span class="o">(</span>00:52<span class="o">)</span> Run a <span class="k">function</span>... <span class="o">(</span>0 s<span class="o">)</span> DONE
 5: <span class="o">(</span>00:52<span class="o">)</span> Last thing we can <span class="k">do </span>automatically... <span class="o">(</span>0 s<span class="o">)</span> DONE
 6: <span class="o">(</span>00:52<span class="o">)</span> bring it on home...<span class="o">(</span>press enter when <span class="k">done</span><span class="o">)</span> <span class="o">(</span>12 s<span class="o">)</span> DONE
 7: <span class="o">(</span>00:53<span class="o">)</span> this one will fail... <span class="o">(</span>0 s<span class="o">)</span> FAILED
    <span class="o">&gt;&gt;</span> it<span class="s1">'s time we stop
    &gt;&gt; Hey, what'</span>s that sound
    <span class="o">&gt;&gt;</span> Everybody look, what<span class="s1">'s going down?
</span></code></pre></div></div>

<h2 id="the-future">The Future</h2>

<ul>
  <li>the -doc argument should extract some documentation from the comment blocks and include it.</li>
  <li>can we do some kind of time estimate and make that useful information? (<a href="https://github.com/deweysasser/runbook-framework/discussions/9">discussion here</a>)</li>
</ul>

<h3 id="documentation">Documentation</h3>

<p>I’d like to make a “generate a fairly complete markdown document describing the process” be a feature.  The question is how to do that without obscuring the actual logic.  See <a href="https://github.com/deweysasser/runbook-framework/discussions/6">the github discussion</a></p>

<h3 id="managing-state">Managing state</h3>

<p>Would it be interesting to manage the current state of “a run”  in a persistent way, particularly so it could be resumed later if e.g. a step failed or something? (<a href="https://github.com/deweysasser/runbook-framework/discussions/10">discussion here</a>)</p>]]></content><author><name>Dewey Sasser</name></author><category term="shell" /><category term="sysadmin" /><category term="automation" /><summary type="html"><![CDATA[A new a shell framework to construct manual and automated runbooks]]></summary></entry><entry><title type="html">2021 Site Refresh</title><link href="https://www.deweysasser.com/content/2021-site-refresh" rel="alternate" type="text/html" title="2021 Site Refresh" /><published>2021-04-25T00:00:00+00:00</published><updated>2021-04-25T00:00:00+00:00</updated><id>https://www.deweysasser.com/content/2021%20site%20refresh</id><content type="html" xml:base="https://www.deweysasser.com/content/2021-site-refresh"><![CDATA[<p>It’s been a while since I set up the technology behind this site, and times have changed.</p>

<p>So, I’m moving it form Drupal to something else.</p>

<p>I’m trying out <a href="https://jekyllrb.com/">Jekyll</a> to statically generate, and it’s pretty cool.</p>

<p>I’m not sure if that’s the right long term solution or not. We’ll see. But, I
needed something now, and it’s something.</p>

<p>If you have an option on what I should use (or, better yet, what features I should support), please
let me know.</p>

<p>Some thoughts are:</p>
<ul>
  <li>discussions (could use disqus.com or commento.io)</li>
  <li>a more wiki-like structure with nice cross-links (probably dokuwiki)</li>
</ul>]]></content><author><name>Dewey Sasser</name></author><summary type="html"><![CDATA[I've refreshed the site for 2021 using Jekyll]]></summary></entry><entry><title type="html">Markdown Toc</title><link href="https://www.deweysasser.com/content/markdown-toc" rel="alternate" type="text/html" title="Markdown Toc" /><published>2021-02-24T00:00:00+00:00</published><updated>2021-02-24T00:00:00+00:00</updated><id>https://www.deweysasser.com/content/markdown-toc</id><content type="html" xml:base="https://www.deweysasser.com/content/markdown-toc"><![CDATA[<p>Introducing <a href="https://github.com/deweysasser/markdown-doc">Markdown Tables of Contents</a>.</p>

<p>This project contains a script and makefile to maintain a table of contents in your markdown
documents, along with an optional git <code class="language-plaintext highlighter-rouge">pre-commit</code> hook to keep it up to date.</p>

<p>I find it useful for either long documents or long READMEs for github projects.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Markdown-doc

Add tables of contents to all markdown files in this repo.

## Contents

* [Markdown-doc](#markdown-doc)
  * [Contents](#contents)
  * [Features](#features)
  * [Usage](#usage)
    * [Generate tables of contents](#generate-tables-of-contents)
    * [Bulk html generation](#bulk-html-generation)
  * [Author and Bug Reports](#author-and-bug-reports)
  * [Notes](#notes)
  * [TODO](#todo)

## Features

* Generate Tables of Contents
* bulk translate to HTML
* ...

## Usage

### Generate tables of contents
When run on a file with a section (any level) titled "Contents" (as above), the scripts here will enable you to automatically generate and insert a Table of Contents.

If no Contents section is found, the files will not be updated.

This also provides git hooks to update the ToC on commit (WARNING:  the way it does so will make `git add -p` pretty useless.  Feel free to modify the hook to better suit your needs if this 
one doesn't work for you.)

To (manually) update the table of contents for all markdown files in this directory, run

     make contents

(or just run `make`)

To set up the git hooks for this repository so that ToCs are updatted on commit, run.

     make hooks

### Bulk html generation

`make html`

all markdown files will be rendered into HTML using 'markdown' and placed in `generated/html`

## Author and Bug Reports

Please use GitHub issues for any bug reports or change requests

## Notes

The script uses `sed` and `awk` for maximum system compatability.  It was developed on MacOS, so it's expected to run anywhere with a `sed` and `awk` more recent than 1990 or so.

It's also about the gnarliest piece of `sed` that I ever want to write, and could be used as the example on a slide for "why modern interpreted languages exist".

## TODO

* use pandoc to generate arbitrary formats
* use a static web site generator to generate a site?

</code></pre></div></div>]]></content><author><name>Dewey Sasser</name></author><category term="tools" /><category term="shell" /><summary type="html"><![CDATA[Introducing Markdown Tables of Contents.]]></summary></entry><entry><title type="html">Gnarly Sed</title><link href="https://www.deweysasser.com/content/gnarly-sed" rel="alternate" type="text/html" title="Gnarly Sed" /><published>2021-02-21T00:00:00+00:00</published><updated>2021-02-21T00:00:00+00:00</updated><id>https://www.deweysasser.com/content/gnarly-sed</id><content type="html" xml:base="https://www.deweysasser.com/content/gnarly-sed"><![CDATA[<p>Last night I wrote a script to compute a Table of Contents for Markdown documents and insert it into
the document. It handles both syntaxes for heading blocks.  (I also wrote a git hook to run this
script on commit.)</p>

<p>It contains what is probably the most gnarly sed script I’ve ever written. I am <em>so</em> glad we’ve
moved beyond sed.</p>

<p>(However, sed is also everywhere without having to install other tools on almost any system, which
is why I used sed and awk instead of something more modern.)</p>

<p>Anyway, for your reading pleasure (or torture), here it is:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/^#/ <span class="o">{</span>
        s/^<span class="se">\(</span><span class="c">#*\) */\1|/</span>
        p
        <span class="o">}</span>
        /^--<span class="k">*</span>/ <span class="o">{</span>
        x
        s/^/##|/
        p
        <span class="o">}</span>
        /^<span class="o">==</span><span class="k">*</span>/ <span class="o">{</span>
        x
        s/^/#|/
        p
        <span class="o">}</span>
        h
</code></pre></div></div>]]></content><author><name>Dewey Sasser</name></author><category term="sed" /><category term="shell" /><summary type="html"><![CDATA[Last night I wrote a script to compute a Table of Contents for Markdown documents and insert it into the document. It handles both syntaxes for heading blocks. (I also wrote a git hook to run this script on commit.)]]></summary></entry><entry><title type="html">Computer Architect</title><link href="https://www.deweysasser.com/content/computer-architect" rel="alternate" type="text/html" title="Computer Architect" /><published>2021-02-03T00:00:00+00:00</published><updated>2021-02-03T00:00:00+00:00</updated><id>https://www.deweysasser.com/content/computer-architect</id><content type="html" xml:base="https://www.deweysasser.com/content/computer-architect"><![CDATA[<p>Something that often surprises people about a Software Architect<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup> role:  it’s a people job.</p>

<p>Technical competence is table stakes.</p>

<p>To actually play the game, it’s all about communication, advocacy, communication, evangelism, communication, persuasion, communication, relationships, and communication.</p>

<p>There’s no point in designing the perfect cat tree if you can’t convince the cats to use it.
It’s really about herding cats.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>same can be said about my current “Cloud Systems Architect” role. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Dewey Sasser</name></author><summary type="html"><![CDATA[Something that often surprises people about a Software Architect1 role: it’s a people job. same can be said about my current “Cloud Systems Architect” role. &#8617;]]></summary></entry><entry><title type="html">Resetting a git-crypt system</title><link href="https://www.deweysasser.com/content/resetting-git-crypt-system" rel="alternate" type="text/html" title="Resetting a git-crypt system" /><published>2020-05-12T00:00:00+00:00</published><updated>2020-05-12T00:00:00+00:00</updated><id>https://www.deweysasser.com/content/resetting%20git-crypt%20system</id><content type="html" xml:base="https://www.deweysasser.com/content/resetting-git-crypt-system"><![CDATA[<h1 id="the-problem">The Problem</h1>

<p><a href="https://github.com/AGWA/git-crypt">git-crypt</a> is pretty awesome, but I’ve managed to do enough evil things to bork 
the decryption keys.  Here’s how to fix it.</p>

<!--break-->

<h1 id="the-background">The Background</h1>

<p><a href="https://github.com/AGWA/git-crypt">git-crypt</a> allows you to encrypt some of the files in a git repository.  It supports adding other users’ GPG keys so they will be able to encrypt/decrypt the file.  It’s pretty clever, and I like it.</p>

<p>The basic operation is that it creates a single symmetric key (which it stores in <code class="language-plaintext highlighter-rouge">.git/git-crypt/keys/default</code>), then
on request will use GPG to encrypt that key to the public key IDs you specify, and those are stored in <code class="language-plaintext highlighter-rouge">.git-crypt//keys/default/0</code>.</p>

<p>However, if you do sufficiently evil things in git repos, like using <a href="https://github.com/newren/git-filter-repo">git filter-repo</a> (another pretty awesome tool), it’s possible to drive <code class="language-plaintext highlighter-rouge">git crypt</code> into a pathological state where your keys are wrong and you can’t do anything.</p>

<p>In order to recover from this situation, make sure you have unencrypted copies of the files around somewhere, then:</p>

<h1 id="the-fix">The Fix</h1>
<ul>
  <li>create a fresh clone of your repo.  In that clone, do…</li>
  <li>save the IDs of all keys</li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">keys</span><span class="o">=</span><span class="si">$(</span><span class="nb">ls</span> .git-crypt/keys/default/0/<span class="k">*</span>.gpg | xargs <span class="nt">-n</span> 1 <span class="nt">-I</span> F <span class="nb">basename </span>F .gpg<span class="si">)</span>
</code></pre></div></div>

<ul>
  <li>Remove the existing encrypted keys</li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git <span class="nb">rm</span> <span class="nt">-r</span> .git-crypt
<span class="nb">rm</span> <span class="nt">-rf</span> .git/git-crypt
</code></pre></div></div>

<ul>
  <li>Reinitialize the encryption</li>
</ul>

<p><code class="language-plaintext highlighter-rouge">git crypt init</code></p>

<ul>
  <li>Re-add the public keys which should access the encrypted files</li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for </span>k <span class="k">in</span> <span class="nv">$keys</span><span class="p">;</span> <span class="k">do </span>git crypt add-gpg user <span class="nv">$k</span><span class="p">;</span> <span class="k">done</span>
</code></pre></div></div>

<ul>
  <li>
    <p>COPY in fresh, unencrypted copies of all previously encrypted files, however you do that</p>
  </li>
  <li>
    <p>(Optional) rebase so that all of this stuff occurs in a single commit</p>
  </li>
</ul>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git rebase <span class="nt">-i</span> origin/master
</code></pre></div></div>
<p>Note that the VI magic to “fixup” all commits into the first one is <code class="language-plaintext highlighter-rouge">2,$ s/pick/fixup/</code></p>]]></content><author><name>Dewey Sasser</name></author><category term="git" /><summary type="html"><![CDATA[The Problem]]></summary></entry></feed>