<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>David Lynch</title>
 <link href="https://davidlynch.org/atom.xml" rel="self"/>
 <link href="https://davidlynch.org/"/>
 <updated>2026-06-07T14:26:26-05:00</updated>
 <id>https://davidlynch.org/</id>
 <author>
   <name>David Lynch</name>
   <email>kemayo@gmail.com</email>
 </author>

 
 <entry>
   <title>Respect</title>
   <link href="https://davidlynch.org/blog/2026/06/respect/"/>
   <updated>2026-06-07T10:22:40-05:00</updated>
   <id>https://davidlynch.org/blog/2026/06/respect</id>
   <content type="html">&lt;p&gt;What does it mean to have respect for someone? To demand respect? To object that someone is not being respectful towards you?&lt;/p&gt;

&lt;p&gt;Unfortunately, this is &lt;a href=&quot;/blog/2026/01/strength/&quot;&gt;another case&lt;/a&gt; of multiple meanings.&lt;/p&gt;

&lt;p&gt;Respect can be:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Mutual. Treating others with dignity, trying to understand their viewpoint even when you disagree.&lt;/li&gt;
  &lt;li&gt;Earned. People see how you act, and decide how to treat you in response.&lt;/li&gt;
  &lt;li&gt;Hierarchical. Obedience, deferring to someone because of their position.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For the most part in your life, you’re dealing with mutual and earned respect. You treat your spouse, your friends, and random strangers with respect. If you “demand respect” you’re asking that they treat you how they’d like to be treated. You tell them what you want, and if they think it’s the right thing to do then they’ll do it. You “earn” respect by acting and showing that you can be relied upon.&lt;/p&gt;

&lt;p&gt;It’s when power comes into the situation that the meaning of “respect” shifts. It’s now about obedience and deference. You have to obey your boss, or a police officer, or your parent, regardless of whether you think they’re in the right. If you disagree with them you have to weigh whether they’ll even allow you to express that, or whether there will be &lt;em&gt;consequences&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Evil begins when you begin to treat people as things”&lt;/p&gt;

  &lt;p&gt;— &lt;cite&gt;Terry Pratchett, I Shall Wear Midnight&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Putting my thumb on the scale here, I think hierarchical respect is the worst form of respect.&lt;/p&gt;

&lt;p&gt;This isn’t to say that hierarchical respect is inherently bad. I’m not an anarchist; hierarchies exist for a reason, and in the best case they result in the ability to efficiently accomplish large scale goals for the overall good of everyone involved. You do what the person above you says because you trust that they know more than you, and that results in rapidly accomplishing things without a need to persuade everyone of the merits of, say, reorganizing your division to launch a new product line.&lt;/p&gt;

&lt;p&gt;When done right, the hierarchy operates with mutual respect between leaders and those at the bottom, and earns respect from the lower ranks by proving that it has their interests in mind and can succeed at its goals. You aren’t using the implicit coercion of the hierarchy, because you (or the position you’re in) have earned respect.&lt;/p&gt;

&lt;p&gt;The failure mode comes when you rely on hierarchy without bothering with mutual or earned respect to back it up. It’s really easy to sacrifice the accumulated hierarchical trust: made a bad choice, dismiss feedback, force underlings to push it through or lose their jobs, and deflect blame once it all goes wrong.&lt;/p&gt;

&lt;p&gt;Strip all the pretty varnish away and what’s left is the backstop of hierarchical authority: “do what I say or I will harm you”. Depending on the form of authority the harm varies, from minor monetary consequences, to losing your chance to ascend the hierarchy yourself, to losing your job, all the way to losing your life. It’s coercion nonetheless.&lt;/p&gt;

&lt;p&gt;It’s a one-way door, because once someone has forced you to obey because of their position, you’re going to stop considering whether they’re &lt;em&gt;right&lt;/em&gt; in the future. It’s now very hard for them to win you over through competence and good deeds, because the underlying truth of power that they’re willing to resort to has been made clear, &lt;em&gt;particularly&lt;/em&gt; if they were shown to be wrong about the thing they wanted you to do. All future orders will carry the implicit threat.&lt;/p&gt;

&lt;p&gt;Note that this is bad for those at the top of the hierarchy as well. They get obedience, but they lose out on honest advice. Since nobody can be right all the time this results in mistakes, which are then amplified by nobody feeling they’re in a position to intervene.&lt;/p&gt;

&lt;p&gt;You’ve probably seen someone high up in power make a decision that you think is obviously not going to work. Maybe they start a war, maybe they direct a company’s resources into immersive VR, maybe they thought everything would be on the blockchain, whatever. It fails, and you were right. Sometimes this is just misaligned incentives, and they’re doing it because they don’t care about whether it works but instead because they personally will be rewarded for it. I think it’s more common for it to be hierarchical insulation, though. If it’s obvious to you as a lowly employee that something is a bad idea, that knowledge has to travel up through 5 layers of “respectful” feedback to reach your CEO. It only takes one of those layers having sabotaged mutual respect to stop this knowledge going any further.&lt;/p&gt;

&lt;p&gt;So remember, if your boss says you need to “be more respectful”, they &lt;em&gt;might&lt;/em&gt; mean “stop swearing at people”, but it’s more likely that they mean “stop pushing back against things you think are a bad idea, and especially stop saying you told me so”.&lt;/p&gt;

&lt;p&gt;What to do about this? Being aware of the different types of respect helps. Don’t get caught up in the trap of the hierarchy, and when you find yourself holding power over others don’t resort to it. You might not ever be a CEO or a President, but you’re relatively likely to be an adult in a child’s life at some point, and modeling mutual respect within a hierarchy in your own life can set people on the right track.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Corpospeak</title>
   <link href="https://davidlynch.org/blog/2026/06/corpospeak/"/>
   <updated>2026-06-04T14:56:55-05:00</updated>
   <id>https://davidlynch.org/blog/2026/06/corpospeak</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;You had to admire the way perfectly innocent words were mugged, ravished, stripped of all true meaning and decency, and then sent to walk the gutter for Reacher Gilt, although “synergistically” had probably been a whore from the start.&lt;/p&gt;

  &lt;p&gt;— &lt;cite&gt;Terry Pratchett, Going Postal&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There’s an art to speaking without meaning. To talking for minutes at a time, without ever communicating a position. Giving the impression that you’re agreeing, you’re sympathizing, you’re on the listener’s side… without ever committing to that, or giving any details.&lt;/p&gt;

&lt;p&gt;Someone’s asking a question, and the honest answer is going to upset them. So you talk around it and, even if ultimately the dodge is plain, they’re not left with a direct quote from you saying that. They’ll have to paraphrase you, and you can always quibble with that.&lt;/p&gt;

&lt;p&gt;Congratulations, you’re &lt;a href=&quot;https://en.wikipedia.org/wiki/Corporate_jargon&quot;&gt;talking like an executive&lt;/a&gt;. A corpo, if you will.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Can you rule out cutting your prices for other non-Creative Cloud products?” journalist David Ramli asked.&lt;/p&gt;

  &lt;p&gt;Narayen said: “You know we’re always looking at pricing around the world and I think the meeting today is all about sharing where we’re heading as a company with the Creative Cloud and the Marketing Cloud.&lt;/p&gt;

  &lt;p&gt;— &lt;cite&gt;&lt;a href=&quot;https://www.stuff.co.nz/technology/digital-living/8304924/Adobe-chief-dodges-questions-over-pricing&quot;&gt;Adobe chief dodges questions over pricing&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a skill people cultivate because it’s surprisingly effective. Some people won’t notice you’re doing it, and will be happily brushed aside without realizing they’ve been misled. Others will realize, but won’t be able to push back against you, because of politeness, format constraints, or structural imbalances. If you’re in an interview or Q&amp;amp;A of some sort, signalling that any question want to dodge is going to cost the questioner a big chunk of their question-asking time and require follow-up questions to see if they can pin you down is often enough to make them decide it’s not worth it.&lt;/p&gt;

&lt;p&gt;(Insofar as executives are a specialized form of politician, you can see the parallels with political communication. Politicians are often better at it, because they tend to know to couch their initial communication in more normal-sounding speech, and just fall back on the media-training for questions, tending more towards repeating practiced talking-points rather than obscuring through circuitous language.)&lt;/p&gt;

&lt;p&gt;The problem with this is twofold.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Once people are sensitized to this, it becomes incredibly grating to listen to.&lt;/li&gt;
  &lt;li&gt;Many executives spend so much time immersed in this type of communication that they think it’s normal. It’s just how they talk now. They misdirect even when there’s no point to it, when plain speech would serve them better.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want people to trust you, you should probably work out how to talk to them in a way that doesn’t inherently read as insincere.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Strength</title>
   <link href="https://davidlynch.org/blog/2026/01/strength/"/>
   <updated>2026-01-21T19:51:19-06:00</updated>
   <id>https://davidlynch.org/blog/2026/01/strength</id>
   <content type="html">&lt;p&gt;There are two popular definitions of strength, of what it means to be a strong person. Unfortunately, to someone who values one of these definitions, someone who values the other is probably going to look weak.&lt;/p&gt;

&lt;p&gt;When you see someone described as “showing strength” or “being strong”, consider that this says much about the person saying it and what they value, and relatively little about some objective “strength” possessed by another.&lt;/p&gt;

&lt;p&gt;The two types of strength are external and internal.&lt;/p&gt;

&lt;p&gt;External strength is the ability to impose your will upon others. It is aggression, dominance, lacking constraints. The externally strong person does what they want, and others have to react to that.&lt;/p&gt;

&lt;p&gt;Internal strength is the ability to impose your will upon yourself. It is self-control, composure, and restraint. The internally stong person knows what they want, and others cannot move them from that.&lt;/p&gt;

&lt;p&gt;If you value external strength, someone who possesses internal strength may look like they’re weak because they aren’t pushing at others. They may take provocations and turn the other cheek, rather than striking back. Who could be strong if others do not fear them?&lt;/p&gt;

&lt;p&gt;If you value internal strength, someone who possesses external strength may look like they’re weak because they don’t control themself. They may seem transparently insecure, lashing out at others because they fear their own weaknesses. Who could be strong if they’re controlled by their own fears?&lt;/p&gt;

&lt;p&gt;This is a false choice, of course. The external strength and internal strength aren’t mutually exclusive. Someone with self-confidence and control can turn that outwards, and this strength of purpose can let them move others and accomplish great things.&lt;/p&gt;

&lt;p&gt;So isn’t it a shame when someone so unbalanced has so much power over us all?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Subscribe Prompts</title>
   <link href="https://davidlynch.org/blog/2025/08/subscribe-prompts/"/>
   <updated>2025-08-10T11:42:26-05:00</updated>
   <id>https://davidlynch.org/blog/2025/08/subscribe-prompts</id>
   <content type="html">&lt;p&gt;I’m perplexed by one particular piece of user interaction design: the subscribe-to-my-newsletter popup.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2025/08/medium-prompt.png&quot; alt=&quot;A Substack &amp;quot;subscribe&amp;quot; overlay&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Not &lt;em&gt;that&lt;/em&gt; it exists, but rather the timing with which people choose to deploy it. Substack is the worst example here, because they show it pretty much as soon as you start scrolling. This is (a) deliberately interrupting me in the middle of a task, so my motivation is to just close the box and return to the task, and (b) I will &lt;em&gt;never&lt;/em&gt; want to subscribe to someone’s newletter before I’ve finished reading what they wrote.&lt;/p&gt;

&lt;p&gt;I imagine that this is something that has been a/b tested to death, and “wait until the end to show the subscribe popup” presumably converts readers at a lower rate. It’s wild to imagine such a person existing, though.&lt;/p&gt;

&lt;p&gt;That said, given that it’s Substack, maybe it’s a &lt;a href=&quot;https://leavesubstack.com&quot;&gt;mismanaged nazi thing&lt;/a&gt;?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>I Don't Get It</title>
   <link href="https://davidlynch.org/blog/2025/07/i-dont-get-it/"/>
   <updated>2025-07-21T11:01:34-05:00</updated>
   <id>https://davidlynch.org/blog/2025/07/i-dont-get-it</id>
   <content type="html">&lt;p&gt;LLM powered chatbots are pretty big, these days. There’s constant speculation about the big LLM companies putting these chatbots into devices that’ll just let you talk out loud to them, and they’ll chat back to you and do your bidding. Recreating “Her”, as Sam Altman unsubtly yearns to do.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2025/07/agent-smith-removes-his-sunglasses.jpg&quot; alt=&quot;Agent Smith from the Matrix movies removing his sunglasses&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I hate it.&lt;/p&gt;

&lt;p&gt;Putting aside any qualms one might have about the underlying technology, of which I have a few, the interface paradigm is unbearable to me. I cannot fathom &lt;em&gt;wanting&lt;/em&gt; to have a verbal back and forth with my computer. I particularly can’t see it being something I’d ever want to do in public, in an open office or a coffee shop or whatever.&lt;/p&gt;

&lt;p&gt;I’d think this might be a programmer thing, craving specificity and precise control over what’s happening, but “vibe coding” is a notable part of this trend so that’s presumably not it.&lt;/p&gt;

&lt;p&gt;The appeal of &lt;a href=&quot;https://www.forbes.com/sites/neilsahota/2024/07/18/how-ai-companions-are-redefining-human-relationships-in-the-digital-age/&quot;&gt;“AI companions”&lt;/a&gt; also doesn’t register to me. If we had AI, and not spicy autocomplete, I could understand it… but the fundamental knowledge that you’re talking to a predictive model ruins any appeal I could see.&lt;/p&gt;

&lt;p&gt;Am I so out of touch? No. It’s the children who are wrong.&lt;/p&gt;

&lt;p&gt;(That said, I’m amused that my previous use of the “opinion” tag on this site turns out to have been me &lt;a href=&quot;/blog/2015/01/video-kiled-the-tutorial-stars/&quot;&gt;complaining about a similar issue with disliking everything switching from text to video&lt;/a&gt;.)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>"Liberation Day"</title>
   <link href="https://davidlynch.org/blog/2025/04/liberation-day/"/>
   <updated>2025-04-02T19:24:16-05:00</updated>
   <id>https://davidlynch.org/blog/2025/04/liberation-day</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Forget the myths the media has created about the White House. The truth is, these are not very bright guys, and things got out of hand.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;– &lt;cite&gt;All The President’s Men (1976)&lt;/cite&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>American Corruption</title>
   <link href="https://davidlynch.org/blog/2025/01/american-corruption/"/>
   <updated>2025-01-31T13:09:37-06:00</updated>
   <id>https://davidlynch.org/blog/2025/01/american-corruption</id>
   <content type="html">&lt;p&gt;The only time I’ve ever been pulled over by the police was when I was driving from California to Missouri back in my mid 20s. It was a long, straight freeway in the middle of Kansas, and I was definitely speeding. The police officer wrote me a ticket, and then told me that it could go away without any moving-violation associated with my license if I mailed a check to the “Sherrif’s benevolent association” for around the amount of the fine.&lt;/p&gt;

&lt;p&gt;I was surprised, because I’d only heard that kind of phrasing used as a punchline in jokes about corruption before. I didn’t think it actually happened in real life, or at least not in such an up-front manner.&lt;/p&gt;

&lt;p&gt;I paid the bribe – morally, if not necessarily strictly legally. The ticket went away.&lt;/p&gt;

&lt;p&gt;It’s what comes to mind. America has never been better than this. It has, sometimes, been less blatant about it.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Migrating from WordPress to Jekyll... again</title>
   <link href="https://davidlynch.org/blog/2025/01/migrating-from-wordpress-to-jekyll-again/"/>
   <updated>2025-01-13T20:31:31-06:00</updated>
   <id>https://davidlynch.org/blog/2025/01/migrating-from-wordpress-to-jekyll-again</id>
   <content type="html">&lt;p&gt;There’s been a lot of &lt;a href=&quot;https://techcrunch.com/2025/01/12/wordpress-vs-wp-engine-drama-explained/&quot;&gt;drama with WordPress&lt;/a&gt; lately, and the way Matt has been behaving has left me less than confident about having this blog using WordPress. Particularly not with automatic updates turned on. As such, I decided to move this back to Jekyll.&lt;/p&gt;

&lt;p&gt;My &lt;a href=&quot;/blog/2015/12/wordpress-again/&quot;&gt;original reason&lt;/a&gt; for returning to WordPress was that the workflow for updating jekyll was much less user-friendly. But these days, particularly with Gutenberg being so awkward to use, I don’t really feel there’s much of a practical difference. I won’t be able to update this when I’m away from a real computer… but I wasn’t doing that anway.&lt;/p&gt;

&lt;p&gt;Who knows, maybe I’ll post more than once a year again?&lt;/p&gt;

&lt;p&gt;…or procrastinate about that until we get a “migrating to Hugo” post. 🤔&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Windows symlinks and how they help with WoW addon development</title>
   <link href="https://davidlynch.org/blog/2023/11/windows-symlinks-and-how-they-help-with-wow-addon-development/"/>
   <updated>2023-11-15T23:53:00-06:00</updated>
   <id>https://davidlynch.org/blog/2023/11/windows-symlinks-and-how-they-help-with-wow-addon-development</id>
   <content type="html">&lt;p&gt;The Battle.net client has a very irritating bug that only really affects people who’re actively developing World of Warcraft addons on Windows: it can get stuck checking whether the game client needs to be updated, stopping you from launching the game. If you’ve ever seen it stick on “Updating” with its status message just saying “Initializing…” for minutes at a time, followed by it asking for you to approve admin permissions for the client so it can try again (regardless of whether it already has them), then you’ve been bitten by this bug.&lt;/p&gt;

&lt;p&gt;I’m told it’s because of some sort of interaction with the (hidden) .git folders (and the vast number of files contained within them) in addons that’ve been checked out for development. Fortunately, there’s a way to keep your source-controlled addon development practices while also stopping the Battle.net client from getting stuck, and that is: &lt;a href=&quot;https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10/&quot;&gt;Windows symlinks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What’s a symlink? It’s short for “symbolic link”, and it’s a way to tell your operating system that file or directory should pretend to be in multiple places at once. In practice, it’s a useful tool to either organize files that other programs need to look at, or to avoid having to manually synchronize changes between files.&lt;/p&gt;

&lt;p&gt;In the case of World of Warcraft, for whatever reason – presumably some specifics of the exact choice of file-monitoring APIs Blizzard chose to use – if you make your addon directories into symbolic links to another place that you’ve checked them out, it’ll stop the Battle.net client from getting confused.&lt;/p&gt;

&lt;p&gt;You may want to read a longer explanation of all the details about &lt;a href=&quot;https://www.howtogeek.com/16226/complete-guide-to-symbolic-links-symlinks-on-windows-or-linux/&quot;&gt;symbolic links and what you might need to do to enable them&lt;/a&gt;, but as a quick summary:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Create a new directory for your development checkouts of addons to live. I’ll use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c:\src\wow\&lt;/code&gt; for these examples.&lt;/li&gt;
  &lt;li&gt;Move all your existing checked out addons there. You can leave other addons that &lt;em&gt;aren’t&lt;/em&gt; a git checkout where they’ve always lived. (I think it’s handy for getting a quick overview of what’s yours, honestly.)&lt;/li&gt;
  &lt;li&gt;Create the symbolic links, by opening a command prompt and typing something like this for each of your addons: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mklink /D &quot;C:\World of Warcraft\_retail_\Interface\Addons\MyAddon&quot; &quot;C:\src\wow\MyAddon&quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;automating-that&quot;&gt;Automating that&lt;/h3&gt;

&lt;p&gt;Now, I found myself with a classic programmer problem of wanting to avoid a very tedious task: typing almost the same mklink command 41 times in a row. As such, I spent longer than the tedious option would have taken to write &lt;a href=&quot;https://gist.github.com/kemayo/de9d4db00cea5bb59c86ab2cb0aea709&quot;&gt;a script that’ll do it for me&lt;/a&gt;. Fortunately, it’ll also serve as documentation for me on what to do next time I need a new addon checked out. 🤩&lt;/p&gt;

&lt;p&gt;Personally, I use &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/wsl/install&quot;&gt;WSL to run Linux tools on my Windows machine&lt;/a&gt; for development purposes, and so I naturally went for a bash script. I could totally have kept it all inside pure Windows and written a batch script or similar, but that sounds quite awful and so I didn’t.&lt;/p&gt;

&lt;p&gt;A lot of the time writing this stemmed from the important complication: the WSL / Linux ln command will not create a Windows symbolic link. As such, I had to learn how to call out to cmd.exe and also to convert WSL file paths into Windows file paths. I’d never had to do this before, so it was time well spend.&lt;/p&gt;

&lt;p&gt;The result is &lt;a href=&quot;https://gist.github.com/kemayo/de9d4db00cea5bb59c86ab2cb0aea709&quot;&gt;this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;link.sh&lt;/code&gt; script&lt;/a&gt;. When run from inside your development addons folder, it’ll make a symbolic link in the main WoW addons folder to every addon you have checked out there. Feel free to use it if you want, just note that you may need to change the WoW install location that’s hardcoded at the top of the script.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Hosting: Linode</title>
   <link href="https://davidlynch.org/blog/2021/07/hosting-linode/"/>
   <updated>2021-07-13T11:15:00-05:00</updated>
   <id>https://davidlynch.org/blog/2021/07/hosting-linode</id>
   <content type="html">&lt;p&gt;Last year, after almost a decade of using them as my host, &lt;a href=&quot;https://www.webfaction.com&quot;&gt;WebFaction&lt;/a&gt; started shutting down. They’d been sold to GoDaddy back in 2018 and had mysteriously stopped working on any feature-development about then, so it wasn’t a huge surprise.&lt;/p&gt;

&lt;p&gt;So, I bit the bullet, and switched to &lt;a href=&quot;https://www.linode.com/?r=f3d9aa2a781c2d2c412b3642b28d3c407a08117e (this is a referral link)&quot;&gt;Linode&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This isn’t entirely something I’d recommend to everyone who’s used to using a service like WebFaction. WebFaction, despite being more fiddly than many hosts, still handled a lot of things for you. It ran servers and managed their configuration; you just told it that you wanted an app of type X to run, and it did.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.linode.com/?r=f3d9aa2a781c2d2c412b3642b28d3c407a08117e (this is a referral link)&quot;&gt;Linode&lt;/a&gt;, by contrast, is a VPS host. That means you get a virtual server, and have to manage it yourself. So I’m spending $5/month for their shared 1GB plan, and it gets me a virtual machine (I picked Debian) that I have to ssh into and cope with.&lt;/p&gt;

&lt;p&gt;Now, &lt;a href=&quot;https://www.linode.com/?r=f3d9aa2a781c2d2c412b3642b28d3c407a08117e (this is a referral link)&quot;&gt;Linode&lt;/a&gt; &lt;em&gt;does&lt;/em&gt; offer &lt;a href=&quot;https://www.linode.com/docs/&quot;&gt;a lot of guides&lt;/a&gt; to setting up servers, which I found very helpful. It’s still a fiddly learning experience – tuning the software to work on your VPS is a pain, and I wound up with Apache using slightly too many resources that led to a CPU spiral over a few days.&lt;/p&gt;

&lt;p&gt;Still, if you’re willing to put the work in, or just have more complex needs than “HTML is here”, it’s a good hosting option.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>World of Warcraft addon packaging but with GitHub Actions this time</title>
   <link href="https://davidlynch.org/blog/2020/09/world-of-warcraft-addon-packaging-but-with-github-actions-this-time/"/>
   <updated>2020-09-19T16:22:00-05:00</updated>
   <id>https://davidlynch.org/blog/2020/09/world-of-warcraft-addon-packaging-but-with-github-actions-this-time</id>
   <content type="html">&lt;p&gt;I wrote about addon-packaging &lt;a href=&quot;/blog/2019/09/world-of-warcraft-classic-addon-packaging/&quot;&gt;a year ago&lt;/a&gt;, mostly in the context of wanting to package addons for Classic. Since then, the environment has shifted a bit due to &lt;a href=&quot;https://blizzardwatch.com/2020/06/23/overwolf-buys-curseforge-addons/&quot;&gt;Overwolf buying Curse&lt;/a&gt;, and also &lt;a href=&quot;https://github.com/features/actions&quot;&gt;GitHub Actions&lt;/a&gt; being released.&lt;/p&gt;

&lt;p&gt;There’s no particular reason to think Overwolf will be any worse a steward of Curse and its addon-tooling than Twitch was, but controlling one’s own packaging and thus being able to easily shift to other platforms if needed appeals.&lt;/p&gt;

&lt;p&gt;If you’re sticking your addon on GitHub anyway, it seems to make some sense to use GitHub Actions rather than (lightly) abusing Travis’ continuous-integration features for something which is only continuous-integration if you squint at it.&lt;/p&gt;

&lt;h3 id=&quot;basic-setup&quot;&gt;Basic setup&lt;/h3&gt;

&lt;p&gt;You need to have an addon which is configured for the BigWigs packager to know what it’s doing. The &lt;a href=&quot;/blog/2019/09/world-of-warcraft-classic-addon-packaging/&quot;&gt;previous post&lt;/a&gt; walks you through that – just don’t do the “Travis” part.&lt;/p&gt;

&lt;h3 id=&quot;making-actions&quot;&gt;Making actions&lt;/h3&gt;

&lt;p&gt;Much like Travis was controlled by a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.travis.yml&lt;/code&gt; file, Actions are defined in your repo in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.github/workflows/&lt;/code&gt; directory. GitHub will walk you through making one on the website, or you can just make the file and commit it.&lt;/p&gt;

&lt;p&gt;Create &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.github/workflows/package.yml&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;name: Package Addon

on:
  push:
    branches: [ main ]
    tags: [ &apos;*&apos; ]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Create Package
        uses: BigWigsMods/packager@master
        env:
           CF_API_KEY: $
           WOWI_API_TOKEN: $
           GITHUB_OAUTH: $
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You’ll need to configure those secrets, which you can do through the “settings” page of your repo. The &lt;a href=&quot;/blog/2019/09/world-of-warcraft-classic-addon-packaging/&quot;&gt;previous post&lt;/a&gt; walks you through generating the relevant API keys. You can skip the GitHub one, as Actions magically gives you a token for that.&lt;/p&gt;

&lt;p&gt;And… that’s it. Every time you push a commit or tag to this repo, the BigWigs packager will run and upload the addon to the sites you’ve configured API and TOC keys for.&lt;/p&gt;

&lt;p&gt;EDIT 2021-07-13: the bigwigs packager has an official action now, so I replaced the use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl&lt;/code&gt; to fetch the script.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>World of Warcraft Classic addon packaging</title>
   <link href="https://davidlynch.org/blog/2019/09/world-of-warcraft-classic-addon-packaging/"/>
   <updated>2019-09-08T11:46:00-05:00</updated>
   <id>https://davidlynch.org/blog/2019/09/world-of-warcraft-classic-addon-packaging</id>
   <content type="html">&lt;p&gt;UPDATE: there’s a sequel to this post, which tells you &lt;a href=&quot;/blog/2020/09/world-of-warcraft-addon-packaging-but-with-github-actions-this-time/&quot;&gt;how to do this with GitHub Actions instead&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you’re writing an addon which needs to work in just the retail version of WoW, or just in Classic, this post doesn’t really apply to you. But if you want to maintain versions of your addon that work in both environments, you may want some tooling around that. Or you might just want to handle your own packaging, in which case this will also help.&lt;/p&gt;

&lt;h3 id=&quot;the-environment&quot;&gt;The Environment&lt;/h3&gt;

&lt;p&gt;World of Warcraft addon development has been heavily shaped by &lt;a href=&quot;https://www.wowace.com&quot;&gt;WowAce&lt;/a&gt;/&lt;a href=&quot;https://www.curseforge.com/wow/addons&quot;&gt;CurseForge&lt;/a&gt;, which popularized a continuous-integration style of development. You start a project, it gives you a code repository, and it automatically packages up the contents of that repository for distribution. It also lets you tag releases, to give addon users stable points to work with.&lt;/p&gt;

&lt;p&gt;Curseforge supports having retail and Classic versions of an addon living in the same project, but &lt;em&gt;doesn’t&lt;/em&gt; support any way of packaging that up automatically. It’ll package up the current state of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; branch of your repository, and flag it as classic/retail depending on the TOC metadata. This makes keeping a dual release impractical.&lt;/p&gt;

&lt;h3 id=&quot;why-not-just-keep-entirely-separate-projects&quot;&gt;Why not just keep entirely separate projects?&lt;/h3&gt;

&lt;p&gt;It’s so much more wooooooork.&lt;/p&gt;

&lt;p&gt;But seriously, Classic is based on a fairly recent version of the WoW client, and is nearly completely API-compatible with the retail version. This means that most addons are going to need fairly minor tweaks to work in both. A long-lived &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;classic&lt;/code&gt; branch with the necessary tweaks and cherry-picked future feature updates is very practical here.&lt;/p&gt;

&lt;h3 id=&quot;run-your-own-packager&quot;&gt;Run your own packager&lt;/h3&gt;

&lt;p&gt;The BigWigs addon, for various historical reasons, have written &lt;a href=&quot;https://github.com/BigWigsMods/packager&quot;&gt;their own version&lt;/a&gt; of the WowAce addon-packager script. It supports everything we want to do, unlike the standard WowAce packager.&lt;/p&gt;

&lt;p&gt;You need to add some metadata to your addon’s TOC file so the packager script knows where to upload it. Find your project ID in the sidebar of your project page, and add a line like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;## X-Curse-Project-ID: [your-project-id]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Technically, you can stop at this point, download the packager, and manually run the entire process from the command line. But again, that’s a lot of work, and I’d rather keep the continuous deployment workflow. If you’d rather go do that, instructions are &lt;a href=&quot;https://github.com/BigWigsMods/packager#using-releasesh&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the rest of this I’m going to aim for continuous deployment via keeping your addon in a GitHub repository, and running the packager through Travis-CI.&lt;/p&gt;

&lt;h3 id=&quot;github&quot;&gt;GitHub&lt;/h3&gt;

&lt;p&gt;Make a repository for your addon on GitHub. &lt;a href=&quot;https://help.github.com/en/articles/importing-a-git-repository-using-the-command-line&quot;&gt;Import&lt;/a&gt; the existing code to there by going to your current checkout of the code and doing:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ git remote set-url origin [your-github-url]
$ git push --mirror origin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now go to your addon’s source settings on WowAce/CurseForge and switch it to point to your new github repo. This will disable all the normal automatic-packaging behavior, so our next step will get that back.&lt;/p&gt;

&lt;h3 id=&quot;travis&quot;&gt;Travis&lt;/h3&gt;

&lt;p&gt;Add a new file to the top level of your repository: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.travis.yml&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: minimal

script:
  - curl -s https://raw.githubusercontent.com/BigWigsMods/packager/master/release.sh | bash

notifications:
  email:
    on_success: never
    on_failure: always
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can expand this if you want to perform further checks. I &lt;a href=&quot;https://github.com/kemayo/wow-silverdragon/blob/master/.travis.yml&quot;&gt;run luacheck on everything&lt;/a&gt; to make sure there’s no likely errors, for instance.&lt;/p&gt;

&lt;p&gt;Get a &lt;a href=&quot;https://travis-ci.org/&quot;&gt;Travis CI&lt;/a&gt; account. You can sign in with your GitHub account, and it’ll have access to your repositories.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2019/09/repo-list.png&quot; alt=&quot;Repositories list&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Enable your addon’s repository, and then go into its settings. Disable “Build pushed pull requests”.&lt;/p&gt;

&lt;p&gt;Go to the &lt;a href=&quot;https://www.curseforge.com/account/api-tokens&quot;&gt;CurseForge API tokens page&lt;/a&gt; and generate an API token.&lt;/p&gt;

&lt;p&gt;In the “Environment Variables” section of the Travis settings, add one called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CF_API_KEY&lt;/code&gt; with the value you just generated.&lt;/p&gt;

&lt;p&gt;You’re now back to having continuous integration. Every time you push a commit to your github repo, the packager will run and upload an alpha build to your project. Release builds will be triggered by tags, just like they were when you were on CurseForge.&lt;/p&gt;

&lt;h3 id=&quot;but-what-about-classic&quot;&gt;But what about Classic?&lt;/h3&gt;

&lt;p&gt;Depending on your addon, the amount of changes you need to make will vary. If you can make a version that works simultaneously in retail and classic, or only needs minor tweaks…&lt;/p&gt;

&lt;h4 id=&quot;single-branch&quot;&gt;Single branch&lt;/h4&gt;

&lt;p&gt;All you’ll need to do is adjust your TOC file a bit:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#@retail@
## Interface: 80200
#@end-retail@
#@non-retail@
# ## Interface: 11302
#@end-non-retail@
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…and adjust your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.travis.yml&lt;/code&gt; so that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;script&lt;/code&gt; section is:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;script:
  - curl -s https://raw.githubusercontent.com/BigWigsMods/packager/master/release.sh | bash
  - curl -s https://raw.githubusercontent.com/BigWigsMods/packager/master/release.sh | bash -s -- -g 1.13.2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now every time you push, a retail and classic build will be triggered. The TOC will be adjusted for each build so the correct &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Interface&lt;/code&gt; version is listed.&lt;/p&gt;

&lt;h4 id=&quot;multiple-branch&quot;&gt;Multiple branch&lt;/h4&gt;

&lt;p&gt;You may need more extensive changes, or just prefer to avoid assorted feature-detection conditionals in your addon. If so, a long-lived &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;classic&lt;/code&gt; branch is an option.&lt;/p&gt;

&lt;p&gt;Make the branch:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ git checkout -b classic
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…and adjust your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.travis.yml&lt;/code&gt; so that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;script&lt;/code&gt; section is:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;script:
  - curl -s https://raw.githubusercontent.com/BigWigsMods/packager/master/release.sh | bash -s -- -g 1.13.2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now update your addon for classic, and whenever you push this branch, a new release will be uploaded for classic only.&lt;/p&gt;

&lt;p&gt;For common changes, remember that you can cherry-pick patches between branches like so:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ git commit -m &quot;Important cleanup of stuff for retail&quot;
[master cec3e72] Important cleanup of stuff for retail
$ git checkout classic
$ git cherry-pick cec3e72
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…though you might need to resolve some conflicts.&lt;/p&gt;

&lt;h3 id=&quot;i-want-wowinterface-too&quot;&gt;I want WoWInterface too!&lt;/h3&gt;

&lt;p&gt;The BigWigs packager will upload to WoWI as well. Unfortunately, WoWI doesn’t let you have versions for retail/classic in the same addon, so you’ll need to start a new addon for your classic branch. Once you have that, update each branch’s TOC with:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;## X-WoWI-ID: [wowi-addon-id]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can find the addon ID in the URL of your addon.&lt;/p&gt;

&lt;p&gt;If you’re using the single-branch setup above, you’ll need to override the ID for one of them. You can do that in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.travis.yml&lt;/code&gt; by finding the retail/classic script call and adding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-w [wowi-addon-id]&lt;/code&gt; to it.&lt;/p&gt;

&lt;p&gt;Now go to the &lt;a href=&quot;https://www.wowinterface.com/downloads/filecpl.php?action=apitokens&quot;&gt;WoWInterface API token page&lt;/a&gt; and generate a token. Add it to your Travis-CI environment variables as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WOWI_API_TOKEN&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;WoWInterface only supports release versions of addons, so it’ll only upload there whenever you push a tag.&lt;/p&gt;

&lt;p&gt;UPDATE: there’s a sequel to this post, which tells you &lt;a href=&quot;/blog/2020/09/world-of-warcraft-addon-packaging-but-with-github-actions-this-time/&quot;&gt;how to do this with GitHub Actions instead&lt;/a&gt;.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>World of Warcraft: Classic memories</title>
   <link href="https://davidlynch.org/blog/2019/08/world-of-warcraft-classic-memories/"/>
   <updated>2019-08-25T20:28:00-05:00</updated>
   <id>https://davidlynch.org/blog/2019/08/world-of-warcraft-classic-memories</id>
   <content type="html">&lt;p&gt;WoW Classic is launching in two days time, and it’s stirring up some memories. Possibly tinted by a delightful haze of nostalgia.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2019/08/WoWScrnShot_20061220_204701.jpg&quot; alt=&quot;WoW UI screenshot&quot; title=&quot;...I modded my UI heavily&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The vanilla WoW memory that most jumps to my mind these days is the first time I really fell off the rails of playing cautiously.&lt;/p&gt;

&lt;p&gt;I was playing with my spouse, and we were questing through Stranglethorn Jungle; I as a Warlock and them as a Priest. I did not yet appreciate &lt;a href=&quot;https://www.mmo-champion.com/threads/709421-Warlock-as-a-40-man-raid-boss&quot; title=&quot;Warlocks: the 40 man raid boss&quot;&gt;what being a Warlock meant&lt;/a&gt;. I would soon learn.&lt;/p&gt;

&lt;p&gt;Vanilla was an unforgiving game by modern standards, for all that it was vastly more friendly than its contemporaries. Regular play involved carefully picking your fights, and anything more than one or two opponents at a time could very easily overwhelm you. Whole classes and specs were barely viable for solo play, or alternately completely useless for endgame play.&lt;/p&gt;

&lt;p&gt;We were doing something which involved having to fight our way through camps of trolls. These were clustered fairly tightly together, so we were carefully separating them and killing them one at a time. It was slow. Then something unfortunate happened, and we got a group of them at once. Obviously we were going to die. It was frantic; I was throwing damage-over-time spells at everything, and my spouse was furiously healing me and my pet. And then… everything died. We didn’t even get close to losing the fight. This was a surprise.&lt;/p&gt;

&lt;p&gt;Naturally, we did it again. It turned out that a Warlock with a tank-pet and a Priest on tap for healing was basically indestructible against entire camps of enemies, once you knew what you were doing.&lt;/p&gt;

&lt;p&gt;There’s nothing so special about that discovery itself, but I still fondly remember that moment when everything came together and we blew past what we thought our limits were.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/2019/08/WoWScrnShot_20070104_181349.jpg&quot; alt=&quot;Dramatic WoW screenshot&quot; title=&quot;It&apos;s like that sometimes&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I reserved that Warlock’s name again for the Classic launch. I rather doubt that I’ll stick with it; the nostalgia won’t live up to the unrelenting grind. But it’ll be interesting to dip my toes back in and see a different era once more.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>WebFaction helpers: HTTPS and www</title>
   <link href="https://davidlynch.org/blog/2018/12/webfaction-helpers-https-and-www/"/>
   <updated>2018-12-11T22:44:00-06:00</updated>
   <id>https://davidlynch.org/blog/2018/12/webfaction-helpers-https-and-www</id>
   <content type="html">&lt;p&gt;I like &lt;a href=&quot;https://www.webfaction.com/?aid=41101&quot; title=&quot;totally an affiliate link&quot;&gt;WebFaction&lt;/a&gt;, and have been using them for years now, but I’m the first to admit they’re a bit less… friendly… in some regards than many hosts.&lt;/p&gt;

&lt;p&gt;I referenced a few of these unfriendly matters &lt;a href=&quot;/blog/2013/04/hosting-switch/&quot;&gt;back when I mentioned switching to them&lt;/a&gt;, with an offhand “so I solved that”. But I’ve decided to go into a little more detail now on one of these issues – common site redirections. Specifically, adding / removing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;www&lt;/code&gt; from your URL, and enforcing HTTPS on a domain.&lt;/p&gt;

&lt;p&gt;Other simple hosts I’ve used have just had a checkbox for these features in your settings. For WebFaction, however, you need to write your own mini-application to handle it. When I say “mini”, I mean it – all you need is the bare minimum of an app configured enough that it’ll interpret an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.htaccess&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;I’ll assume from here that you’re familiar with the general WebFaction terminology, and the distinction between “application”, “domain”, and “website”.&lt;/p&gt;

&lt;h3 id=&quot;remove-www&quot;&gt;Remove www&lt;/h3&gt;

&lt;p&gt;Make a new application with type “Static” and subtype “Static/CGI/PHP-7.2”.&lt;/p&gt;

&lt;p&gt;Name the application &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;redirect_www&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;SSH in, and in the application directory create a file called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.htaccess&lt;/code&gt; with the contents:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;RewriteEngine on

RewriteCond %{HTTPS} =on
RewriteRule ^(.*)$ - [env=proto:https]
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ - [env=proto:http]

RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ %{ENV:proto}://%1%{REQUEST_URI} [R=301,QSA,NC,L]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is more complicated than it strictly has to be, because it checks and remembers whether the site is on HTTP/S without you needing to explicitly configure it or make multiple versions of the application. I wanted something generic, because I have a bunch of different websites hosted.&lt;/p&gt;

&lt;p&gt;An “add www” application is a fairly simple modification to this.&lt;/p&gt;

&lt;p&gt;Assign it to a new website, with the domain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;www.whatever-your-domain-is.com&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;enforce-https&quot;&gt;Enforce HTTPS&lt;/h3&gt;

&lt;p&gt;Make a new application with type “Static” and subtype “Static/CGI/PHP-7.2”.&lt;/p&gt;

&lt;p&gt;Name the application &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;redirect_https&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;SSH in, and in the application directory create a file called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.htaccess&lt;/code&gt; with the contents:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;RewriteEngine On

RewriteRule ^\.well-known/ - [NC,L]

RewriteCond %{HTTPS} !on [NC]
RewriteCond %{HTTP:X-Forwarded-SSL} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will redirect so long as HTTPS isn’t already enabled, ignoring the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.well-known&lt;/code&gt; subdirectory which is required to not be redirected for things like letsencrypt certificate renewal.&lt;/p&gt;

&lt;p&gt;Assign this application to a non-secure website with the same domain as a secure website you’re hosting.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Why didn't I respond to your pull request?</title>
   <link href="https://davidlynch.org/blog/2017/01/why-didnt-i-respond-to-your-pull-request/"/>
   <updated>2017-01-12T17:34:00-06:00</updated>
   <id>https://davidlynch.org/blog/2017/01/why-didnt-i-respond-to-your-pull-request</id>
   <content type="html">&lt;p&gt;I have some fairly popular open source packages up on GitHub. Happily, I get people submitting pull requests, adding features or fixing bugs. It’s great when this happens, because people are doing work that I don’t want to do / haven’t gotten to yet / didn’t think of.&lt;/p&gt;

&lt;p&gt;…but I’m pretty bad at responding to these. They tend to languish for a while before I get to them. There’s a decent number which I’ve never even replied to.&lt;/p&gt;

&lt;h2 id=&quot;why-is-this&quot;&gt;Why is this?&lt;/h2&gt;

&lt;p&gt;Fundamentally, it’s because reviewing a pull request is potentially a lot of work… and the amount of work isn’t necessarily obvious up-front. This means I only tend to do reviews for anything which isn’t obviously trivial when I’m feeling energetic and like I have a decent amount of free time.&lt;/p&gt;

&lt;p&gt;First, there’s some common potential problems which might turn up:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;It does something I don’t want to include in the project. This is the only outright deal-breaker. Project owner’s prerogative.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;It doesn’t work. This happens more often than you’d think, generally because the submitter has written code for the exact use-case they had, and hasn’t considered what will happen if someone tries to use it in a different way.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;It works, but not in the way I want it to. For instance, it might behave inconsistently with existing features, and I’d want it adjusted to match.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;It should be written differently. This tends to include feedback like “you should use this module” / “this code should really go over here” / “this duplicates code”.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;It has coding style violations. Things like indentation, variable names, or trailing whitespace. These aren’t functional problems, but I still don’t want to merge them, because I’d just have to make another commit to fix them myself.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once I’ve read the patch and given this feedback, which might itself take a while since design feedback and proper testing that exercises all code paths isn’t necessarily quick, I’ll respond asking for changes. Then there’s an unknown wait period while the submitted finds time to respond to those changes. Best-case for me, they agree with everything I said, make all requested changes perfectly, and update their pull request with them! Alas, people don’t always think I’m a font of genius, so there’s an unknowable amount of back-and-forth needed to find a compromise position we both agree on. This &lt;em&gt;generally&lt;/em&gt; involves enough time between responses that the specifics of the patch aren’t in my head any more, so I have to repeat the review process each time.&lt;/p&gt;

&lt;h2 id=&quot;what-can-i-do-better&quot;&gt;What can I do better?&lt;/h2&gt;

&lt;p&gt;One obvious fix: delegate more. Accept more people onto projects and give them commit access, so I don’t have to be the bottleneck. I’m bad at doing this, because my projects tend to start as “scratch my itch” tasks, and I worry about them drifting away from code I’m personally happy with. Plus, I feel that if the problem is “I don’t review patches promptly”, “make someone else do it instead” is perhaps disingenuous as a response. :D&lt;/p&gt;

&lt;p&gt;So, low-hanging fruit…&lt;/p&gt;

&lt;p&gt;Coding style violations, despite being trivial, are probably the most common sources of a patch sitting unmerged as I wait for someone to respond to a request to fix them. This is kind of my fault, because I have a bad habit of not &lt;em&gt;documenting&lt;/em&gt; the coding style I expect to be used in my projects, relying on people writing consistent code by osmosis. Demonstrably, this doesn’t &lt;em&gt;work&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;As such, I’m starting to add continuous integration solutions like &lt;a href=&quot;https://travis-ci.org/&quot;&gt;Travis&lt;/a&gt; to &lt;a href=&quot;https://travis-ci.org/kemayo/&quot;&gt;my projects&lt;/a&gt;. Without any particular work on my part, this lets me automatically warn contributors about coding style concerns which can be linted for, via tools like &lt;a href=&quot;http://flake8.pycqa.org/en/latest/&quot;&gt;flake8&lt;/a&gt; or &lt;a href=&quot;http://editorconfig.org/&quot;&gt;editorconfig&lt;/a&gt;. If their editing environment is set up for it, they’ll get feedback as they write their patch… and if not, they’ll be told on GitHub when a pull request fails the tests, and don’t have to wait for me to get back to them about it.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://travis-ci.org/kemayo/sublime-text-git&quot;&gt;&lt;img src=&quot;https://travis-ci.org/kemayo/sublime-text-git.svg?branch=master&quot; alt=&quot;Build Status&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The “it doesn’t work” issue can be worked into this framework as well, with a greater commitment to writing tests on my part. If my project is already well-covered, I can have the CI build check test coverage, and thus require that contributors are providing tests that cover at least most of what they’re submitting, and don’t break existing functionality.&lt;/p&gt;

&lt;p&gt;This should reduce me to having to &lt;em&gt;personally&lt;/em&gt; respond to a smaller set of “how should this be written?” issues, which I think will help.&lt;/p&gt;
</content>
 </entry>
 

</feed>
