<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Romain Lespinasse</title>
    <description>The latest articles on DEV Community by Romain Lespinasse (@rlespinasse).</description>
    <link>https://dev.to/rlespinasse</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F138535%2F2e585c63-1474-4a60-a22c-e2e6f3a0d0f1.jpg</url>
      <title>DEV Community: Romain Lespinasse</title>
      <link>https://dev.to/rlespinasse</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rlespinasse"/>
    <language>en</language>
    <item>
      <title>Pin GitHub Actions Skill: Automating SHA Pinning with AI Assistants</title>
      <dc:creator>Romain Lespinasse</dc:creator>
      <pubDate>Sun, 15 Mar 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/rlespinasse/pin-github-actions-skill-automating-sha-pinning-with-ai-assistants-5771</link>
      <guid>https://dev.to/rlespinasse/pin-github-actions-skill-automating-sha-pinning-with-ai-assistants-5771</guid>
      <description>&lt;p&gt;SHA pinning GitHub Actions is a &lt;a href="https://dev.to/posts/github-actions-commit-sha-pinning/"&gt;well-understood security practice&lt;/a&gt;.&lt;br&gt;
Replacing &lt;code&gt;actions/checkout@v4&lt;/code&gt; with a full commit SHA prevents a compromised tag from silently changing the code your CI runs.&lt;/p&gt;

&lt;p&gt;The problem is not understanding why to do it.&lt;br&gt;
The problem is doing it.&lt;/p&gt;

&lt;p&gt;A typical migration means: enumerate every &lt;code&gt;uses:&lt;/code&gt; reference across all workflow files, look up the latest release for each action, resolve the commit SHA (handling annotated tags that need dereferencing), replace every reference, add version comments, and then configure Dependabot so the SHAs stay current.&lt;br&gt;
For a repository with three workflows and six different actions, this is already tedious.&lt;br&gt;
For an organisation with dozens of repositories, it does not scale without automation.&lt;/p&gt;
&lt;h2&gt;
  
  
  What the skill does
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/rlespinasse/agent-skills" rel="noopener noreferrer"&gt;&lt;strong&gt;pin-github-actions&lt;/strong&gt;&lt;/a&gt; skill is part of the &lt;a href="https://github.com/rlespinasse/agent-skills" rel="noopener noreferrer"&gt;agent-skills&lt;/a&gt; collection.&lt;br&gt;
It guides AI coding assistants through the full migration, step by step:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Discover&lt;/strong&gt; — scan &lt;code&gt;.github/workflows/&lt;/code&gt; for all &lt;code&gt;uses:&lt;/code&gt; references and report which are already pinned&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resolve&lt;/strong&gt; — look up the latest release for each action, resolve the commit SHA via the GitHub API, and dereference annotated tags&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pin&lt;/strong&gt; — replace tag references with &lt;code&gt;SHA # vX.Y.Z&lt;/code&gt; format using exact release versions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configure Dependabot&lt;/strong&gt; — set up or update &lt;code&gt;.github/dependabot.yml&lt;/code&gt; with grouped updates for all discovered ecosystems&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confirm&lt;/strong&gt; — present every change for review before applying&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The assistant handles the API calls, the tag-versus-commit disambiguation, and the file edits.&lt;br&gt;
You review the result.&lt;/p&gt;
&lt;h2&gt;
  
  
  Major version detection
&lt;/h2&gt;

&lt;p&gt;Not every upgrade is safe.&lt;br&gt;
If your workflow uses &lt;code&gt;actions/checkout@v3&lt;/code&gt; and the latest release is &lt;code&gt;v4.2.2&lt;/code&gt;, that is a major version jump with potential breaking changes.&lt;/p&gt;

&lt;p&gt;The skill instructs the assistant to flag these jumps explicitly, link to the changelog, and ask whether to upgrade or stay on the latest patch of the current major version.&lt;br&gt;
No silent upgrades across major boundaries.&lt;/p&gt;

&lt;p&gt;This matters because a migration tool that blindly pins to the latest version can break workflows in ways that are harder to debug than the security issue it was trying to solve.&lt;/p&gt;
&lt;h2&gt;
  
  
  Dependabot with grouped updates
&lt;/h2&gt;

&lt;p&gt;Pinning to SHAs without Dependabot creates a maintenance burden — you lose the automatic update notifications that tag-based references provide.&lt;br&gt;
The skill addresses this by configuring Dependabot as part of the migration.&lt;/p&gt;

&lt;p&gt;Two design choices are built into the skill:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Grouped updates.&lt;/strong&gt;&lt;br&gt;
By default, Dependabot opens one PR per dependency update.&lt;br&gt;
For a repository with six actions, that means six PRs every time updates are available.&lt;br&gt;
The skill configures grouped updates so all action updates land in a single PR:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="na"&gt;updates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;package-ecosystem&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;github-actions'&lt;/span&gt;
    &lt;span class="na"&gt;directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/'&lt;/span&gt;
    &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;weekly'&lt;/span&gt;
    &lt;span class="na"&gt;groups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;patterns&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Multi-ecosystem discovery.&lt;/strong&gt;&lt;br&gt;
The skill does not stop at &lt;code&gt;github-actions&lt;/code&gt;.&lt;br&gt;
It scans the repository for other dependency sources — &lt;code&gt;.gitmodules&lt;/code&gt;, &lt;code&gt;package.json&lt;/code&gt;, &lt;code&gt;go.mod&lt;/code&gt;, &lt;code&gt;Gemfile&lt;/code&gt;, &lt;code&gt;Cargo.toml&lt;/code&gt;, &lt;code&gt;Dockerfile&lt;/code&gt;, Terraform files — and adds each discovered ecosystem to the Dependabot configuration with the same grouped update pattern.&lt;/p&gt;

&lt;p&gt;If a &lt;code&gt;dependabot.yml&lt;/code&gt; already exists, the skill merges with it rather than overwriting it, preserving any existing labels, reviewers, or ignore rules.&lt;/p&gt;
&lt;h2&gt;
  
  
  Evaluation with 7 scenarios
&lt;/h2&gt;

&lt;p&gt;The skill includes seven evaluation scenarios that cover the main decision paths:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pinning all actions in a repository from scratch&lt;/li&gt;
&lt;li&gt;Detecting and handling major version jumps&lt;/li&gt;
&lt;li&gt;Setting up Dependabot for a new repository&lt;/li&gt;
&lt;li&gt;Merging with an existing Dependabot configuration&lt;/li&gt;
&lt;li&gt;Auditing already-pinned actions for correctness&lt;/li&gt;
&lt;li&gt;Enforcing exact version comments (never major tags)&lt;/li&gt;
&lt;li&gt;End-to-end migration combining all steps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These scenarios define the expected behavior so the skill produces consistent results regardless of which AI assistant runs it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Installing the skill
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add https://github.com/rlespinasse/agent-skills &lt;span class="nt"&gt;--skill&lt;/span&gt; pin-github-actions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Once installed, ask the assistant to pin your GitHub Actions or migrate your workflows to SHA-pinned versions.&lt;br&gt;
The skill activates on keywords like "pin actions", "SHA pinning", "pinned versions", or "supply-chain security".&lt;/p&gt;

&lt;p&gt;If you have already installed other skills from the collection — like &lt;a href="https://dev.to/posts/conventional-commit-skill/"&gt;conventional-commit&lt;/a&gt; or &lt;a href="https://dev.to/posts/diataxis-documentation-skill/"&gt;diataxis&lt;/a&gt; — the process is the same.&lt;/p&gt;
&lt;h2&gt;
  
  
  From blog post to automation
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://dev.to/posts/github-actions-commit-sha-pinning/"&gt;earlier post on SHA pinning&lt;/a&gt; explained why pinning matters and how to do it manually.&lt;br&gt;
This skill turns that knowledge into something an AI assistant can execute on your behalf.&lt;/p&gt;

&lt;p&gt;The tedious parts — API lookups, tag dereferencing, file editing, Dependabot configuration — are handled by the assistant.&lt;br&gt;
The important parts — reviewing changes, deciding on major version upgrades, approving the final result — stay with you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add https://github.com/rlespinasse/agent-skills &lt;span class="nt"&gt;--skill&lt;/span&gt; pin-github-actions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explore the full collection at &lt;a href="https://github.com/rlespinasse/agent-skills" rel="noopener noreferrer"&gt;github.com/rlespinasse/agent-skills&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>github</category>
      <category>cicd</category>
      <category>security</category>
      <category>ai</category>
    </item>
    <item>
      <title>GitHub Actions Toolbox: A CLI Companion for Your Workflows</title>
      <dc:creator>Romain Lespinasse</dc:creator>
      <pubDate>Wed, 11 Mar 2026 10:00:00 +0000</pubDate>
      <link>https://dev.to/rlespinasse/github-actions-toolbox-a-cli-companion-for-your-workflows-1fhn</link>
      <guid>https://dev.to/rlespinasse/github-actions-toolbox-a-cli-companion-for-your-workflows-1fhn</guid>
      <description>&lt;p&gt;Over the years I have published and maintained a handful of GitHub Actions — &lt;a href="https://github.com/rlespinasse/github-slug-action" rel="noopener noreferrer"&gt;github-slug-action&lt;/a&gt;, &lt;a href="https://github.com/rlespinasse/drawio-export-action" rel="noopener noreferrer"&gt;drawio-export-action&lt;/a&gt;, &lt;a href="https://github.com/rlespinasse/release-that" rel="noopener noreferrer"&gt;release-that&lt;/a&gt;, and a few others — many of which are now part of the &lt;a href="https://dev.to/posts/actions-able-github-organisation/"&gt;actions-able organisation&lt;/a&gt;.&lt;br&gt;
Once an action gets some traction, a recurring question pops up:&lt;br&gt;
&lt;strong&gt;how many repositories actually depend on it?&lt;/strong&gt;&lt;br&gt;
GitHub surfaces that number on each repository page,&lt;br&gt;
but clicking through every project one by one gets old fast when you have half a dozen actions to keep an eye on.&lt;/p&gt;

&lt;p&gt;That itch led me to build &lt;a href="https://github.com/rlespinasse/github-actions-toolbox" rel="noopener noreferrer"&gt;&lt;strong&gt;github-actions-toolbox&lt;/strong&gt;&lt;/a&gt; — a small Go CLI called &lt;strong&gt;&lt;code&gt;ghat&lt;/code&gt;&lt;/strong&gt; designed to gather the kind of information an action maintainer regularly needs, without leaving the terminal.&lt;/p&gt;
&lt;h2&gt;
  
  
  The problem ghat solves
&lt;/h2&gt;

&lt;p&gt;GitHub's dependency graph is a fantastic feature. It tells you which repositories reference yours in their workflows. The catch is that there is no convenient API to pull those numbers in bulk. You either scrape the web UI or write throwaway scripts every time you want a snapshot.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ghat&lt;/code&gt; wraps that scraping into a single, repeatable command so you can fold it into your own dashboards, CI jobs, or just run it from your laptop on a quiet Monday morning to see how things are going.&lt;/p&gt;
&lt;h2&gt;
  
  
  Using the dependents command
&lt;/h2&gt;

&lt;p&gt;The first — and currently the main — subcommand is &lt;code&gt;dependents&lt;/code&gt;. At its simplest, you point it at one repository and it returns the dependent count:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ghat dependents rlespinasse/github-slug-action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you maintain more than one action, you can pass several repositories in a single invocation. This saves time and avoids rate-limit headaches compared to scripting individual calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ghat dependents rlespinasse/github-slug-action rlespinasse/drawio-export-action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For larger inventories, piping from a file or another command keeps things clean. Imagine a &lt;code&gt;repos.txt&lt;/code&gt; that lists every action you own — one &lt;code&gt;owner/repo&lt;/code&gt; per line — and you get a full report in seconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;repos.txt | ghat dependents
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This composability is intentional. Unix pipes are still the best glue between tools, and &lt;code&gt;ghat&lt;/code&gt; is designed to play nicely with the rest of your toolkit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting ghat on your machine
&lt;/h2&gt;

&lt;p&gt;The quickest route on macOS or Linux is through my custom &lt;a href="https://github.com/rlespinasse/homebrew-tap" rel="noopener noreferrer"&gt;Homebrew tap&lt;/a&gt;. A single command gets you the latest release, and &lt;code&gt;brew upgrade&lt;/code&gt; keeps it current from there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;rlespinasse/tap/ghat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can browse everything the tap offers with &lt;code&gt;brew search rlespinasse/tap&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you already have a Go toolchain, installing from source works just as well — and it is handy when you want to pin a specific version or hack on the code yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/rlespinasse/github-actions-toolbox@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For environments where neither Homebrew nor Go are available — CI runners, Docker images, Windows workstations — pre-built archives are published for &lt;strong&gt;Linux&lt;/strong&gt;, &lt;strong&gt;macOS&lt;/strong&gt;, and &lt;strong&gt;Windows&lt;/strong&gt; across &lt;strong&gt;amd64&lt;/strong&gt; and &lt;strong&gt;arm64&lt;/strong&gt;. Grab the one that matches your platform from the &lt;a href="https://github.com/rlespinasse/github-actions-toolbox/releases" rel="noopener noreferrer"&gt;releases page&lt;/a&gt; and drop the binary somewhere on your &lt;code&gt;PATH&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Homebrew tap behind the scenes
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/rlespinasse/homebrew-tap" rel="noopener noreferrer"&gt;&lt;strong&gt;homebrew-tap&lt;/strong&gt;&lt;/a&gt; repository deserves a quick mention of its own. It is a standard custom Homebrew tap — a Git repository that Homebrew clones locally so it can discover cask and formula definitions beyond the core taps.&lt;/p&gt;

&lt;p&gt;Right now it hosts the cask for &lt;code&gt;ghat&lt;/code&gt;, but the structure is ready to accommodate any future command-line tools I release. The whole release pipeline leans on &lt;a href="https://goreleaser.com/" rel="noopener noreferrer"&gt;goreleaser&lt;/a&gt;: when I tag a new version of &lt;code&gt;github-actions-toolbox&lt;/code&gt;, goreleaser cross-compiles the binary, packages the archives, computes checksums, and pushes an updated cask definition to the tap repository. This means the Homebrew formula is always in sync with the latest release, with zero manual intervention on my side.&lt;/p&gt;

&lt;p&gt;If you maintain your own Go-based CLI and want a frictionless distribution story, I highly recommend pairing goreleaser with a personal Homebrew tap. The setup cost is low and the convenience for your users is significant.&lt;/p&gt;

&lt;h2&gt;
  
  
  What comes next
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;dependents&lt;/code&gt; command addresses the most immediate pain point I had, but a toolbox with a single tool is not much of a toolbox yet. There are other pieces of information that are tedious to gather as a GitHub Actions maintainer — marketplace listing details, workflow usage patterns, version adoption curves — and some of those may find their way into &lt;code&gt;ghat&lt;/code&gt; over time.&lt;/p&gt;

&lt;p&gt;The architecture is intentionally subcommand-based, so adding new capabilities does not break existing workflows. If you have ideas for commands that would make your life easier as an action maintainer, issues and pull requests are very welcome on the &lt;a href="https://github.com/rlespinasse/github-actions-toolbox" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the meantime, if you want to give it a spin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;rlespinasse/tap/ghat
ghat dependents your-org/your-action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It takes about ten seconds to install and even less to get your first result.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>github</category>
      <category>cicd</category>
      <category>homebrew</category>
    </item>
    <item>
      <title>Open Source Maintenance: Do I Need to Update My License Year?</title>
      <dc:creator>Romain Lespinasse</dc:creator>
      <pubDate>Fri, 20 Feb 2026 22:05:18 +0000</pubDate>
      <link>https://dev.to/rlespinasse/open-source-maintenance-do-i-need-to-update-my-license-year-4o8e</link>
      <guid>https://dev.to/rlespinasse/open-source-maintenance-do-i-need-to-update-my-license-year-4o8e</guid>
      <description>&lt;p&gt;If you’ve been maintaining a project since 2019 and have reached a milestone like &lt;strong&gt;v5.x&lt;/strong&gt;, you might wonder if that "2019" in your &lt;code&gt;LICENSE&lt;/code&gt; file makes your project look abandoned. &lt;/p&gt;

&lt;p&gt;Here is a quick guide on how to handle license dates effectively without overthinking it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "First Publication" Rule
&lt;/h2&gt;

&lt;p&gt;In an MIT or Apache license, the year (e.g., &lt;code&gt;Copyright (c) 2019&lt;/code&gt;) marks the &lt;strong&gt;year of first publication&lt;/strong&gt;. &lt;br&gt;
It isn't an expiration date. However, as your project evolves through major versions, your code changes significantly.&lt;/p&gt;
&lt;h3&gt;
  
  
  Using the Copyright Range
&lt;/h3&gt;

&lt;p&gt;Instead of choosing between the start year and the current year, the professional standard is to use a &lt;strong&gt;range&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bad:&lt;/strong&gt; &lt;code&gt;Copyright (c) 2019&lt;/code&gt; (Looks abandoned)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better:&lt;/strong&gt; &lt;code&gt;Copyright (c) 2026&lt;/code&gt; (Wipes out the history of the original work)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best:&lt;/strong&gt; &lt;code&gt;Copyright (c) 2019-2026&lt;/code&gt; (Protects the original v1.0 and the current v5.x)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  When to Update (The SemVer Strategy)
&lt;/h2&gt;

&lt;p&gt;If you follow &lt;strong&gt;Semantic Versioning&lt;/strong&gt;, you don't need to touch the license for every patch. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Version Type&lt;/th&gt;
&lt;th&gt;Update License?&lt;/th&gt;
&lt;th&gt;Reason&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Major (v5.0.0)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Highly Recommended&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Significant refactors or breaking changes are new "works."&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Minor (v5.1.0)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Recommended&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;New features should be covered under the latest year.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Patch (v5.1.1)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Optional&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Bug fixes rarely require a copyright update.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Automation: The "Set and Forget" Method
&lt;/h2&gt;

&lt;p&gt;If you find manual updates tedious, you can use a GitHub Action to check your license at the start of every year.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/FantasticFiasco/action-update-license-year" rel="noopener noreferrer"&gt;&lt;code&gt;FantasticFiasco/action-update-license-year&lt;/code&gt;&lt;/a&gt; GitHub Action will handle it for you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Update copyright year(s) in license file&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;3&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*'&lt;/span&gt; &lt;span class="c1"&gt;# 03:00 AM on January 1&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;update-license-year&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
        &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v6&lt;/span&gt;
              &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                  &lt;span class="na"&gt;fetch-depth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;FantasticFiasco/action-update-license-year@v3&lt;/span&gt;
              &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                  &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This action will detect your &lt;code&gt;2019&lt;/code&gt; start date and automatically transform it into &lt;code&gt;2019-2026&lt;/code&gt;, keeping your project looking active and professional.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;For a project spanning several years, simply update your license header to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Copyright (c) 2019-2026 [Your Name]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells the world your project is established, battle-tested since 2019, and actively maintained in 2026.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Note&lt;br&gt;
This post was originally published on &lt;a href="https://www.romainlespinasse.dev/posts/maintaining-license-years/" rel="noopener noreferrer"&gt;my personal blog&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>opensource</category>
      <category>licensing</category>
      <category>maintenance</category>
      <category>semver</category>
    </item>
    <item>
      <title>The Simplest Way to Make Just Interactive: Use --choose</title>
      <dc:creator>Romain Lespinasse</dc:creator>
      <pubDate>Fri, 20 Feb 2026 22:02:50 +0000</pubDate>
      <link>https://dev.to/rlespinasse/the-simplest-way-to-make-just-interactive-use-choose-402a</link>
      <guid>https://dev.to/rlespinasse/the-simplest-way-to-make-just-interactive-use-choose-402a</guid>
      <description>&lt;h2&gt;
  
  
  The "Native" Way
&lt;/h2&gt;

&lt;p&gt;While you &lt;em&gt;can&lt;/em&gt; manually pipe &lt;code&gt;just --list&lt;/code&gt; into &lt;code&gt;fzf&lt;/code&gt;, &lt;code&gt;just&lt;/code&gt; has a built-in feature that handles this natively.&lt;br&gt;
If you have &lt;code&gt;fzf&lt;/code&gt; installed, you don't need a custom recipe at all.&lt;/p&gt;
&lt;h3&gt;
  
  
  The One-Liner
&lt;/h3&gt;

&lt;p&gt;Simply run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;just &lt;span class="nt"&gt;--choose&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command automatically parses your recipes, opens &lt;code&gt;fzf&lt;/code&gt;, and executes your selection once you hit Enter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Level Up with Shell Aliases
&lt;/h2&gt;

&lt;p&gt;If you find yourself running specific types of tasks frequently, you can combine &lt;code&gt;just --choose&lt;/code&gt; with a shell alias.&lt;br&gt;
This is perfect for filtering down to specific "namespaces" if you use a prefix naming convention (e.g., &lt;code&gt;docker-build&lt;/code&gt;, &lt;code&gt;docker-up&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Add this to your &lt;code&gt;.zshrc&lt;/code&gt; or &lt;code&gt;.bashrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# General interactive just&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;j&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'just --choose'&lt;/span&gt;

&lt;span class="c"&gt;# Interactive just filtered for Docker tasks only&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;jd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'just --choose --chooser "fzf --query=docker"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Customizing the UI
&lt;/h2&gt;

&lt;p&gt;You can customize the look and feel of the chooser globally by setting the &lt;code&gt;JUST_CHOOSER&lt;/code&gt; environment variable.&lt;br&gt;
This allows you to add colors or change the layout without touching your &lt;code&gt;justfile&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;JUST_CHOOSER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'fzf --header "⚡ Select Task" --height 40% --layout reverse --border'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why this is better:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Zero Boilerplate:&lt;/strong&gt; You don't need to pollute your &lt;code&gt;justfile&lt;/code&gt; with a "menu" recipe.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean Output:&lt;/strong&gt; It respects docstrings and ignores internal recipes (those starting with an underscore).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speed:&lt;/strong&gt; It’s a single binary call rather than a chain of piped commands.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The "One-Touch" Justfile
&lt;/h2&gt;

&lt;p&gt;If you want the interactive menu to appear by default when you just type &lt;code&gt;just&lt;/code&gt; in your terminal, add this to the top of your file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Run the interactive chooser by default
default:
    @just --choose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Ultimately, using &lt;code&gt;just --choose&lt;/code&gt; transforms your justfile from a static list of commands into a dynamic, user-friendly CLI.&lt;/p&gt;

&lt;p&gt;By moving away from manual piping and embracing built-in flags and environment variables, you reduce maintenance overhead while significantly improving your daily terminal workflow.&lt;/p&gt;

&lt;p&gt;Whether you’re automating a complex Docker environment or just looking for a faster way to trigger local builds, making your tools interactive by default ensures that your productivity stays as high as your command-line efficiency.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Note&lt;br&gt;
This post was originally published on &lt;a href="https://www.romainlespinasse.dev/posts/interactive-just-recipes/" rel="noopener noreferrer"&gt;my personal blog&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>terminal</category>
      <category>productivity</category>
      <category>just</category>
      <category>fzf</category>
    </item>
    <item>
      <title>Batch Resize Images on macOS via CLI (The Native Way)</title>
      <dc:creator>Romain Lespinasse</dc:creator>
      <pubDate>Fri, 20 Feb 2026 21:59:38 +0000</pubDate>
      <link>https://dev.to/rlespinasse/batch-resize-images-on-macos-via-cli-the-native-way-598p</link>
      <guid>https://dev.to/rlespinasse/batch-resize-images-on-macos-via-cli-the-native-way-598p</guid>
      <description>&lt;p&gt;If you often need to resize dozens of images tucked away in various subdirectories. &lt;br&gt;
While apps like Photoshop or Lightroom are powerful, they are overkill for a simple task: &lt;strong&gt;resizing all &lt;code&gt;png&lt;/code&gt; files to a maximum of 200px.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Forget installing heavy dependencies like ImageMagick. &lt;br&gt;
macOS comes with a built-in "secret weapon" called &lt;strong&gt;Sips&lt;/strong&gt; (Scriptable Image Processing System).&lt;/p&gt;
&lt;h2&gt;
  
  
  The Scenario
&lt;/h2&gt;

&lt;p&gt;You have a project structure like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/assets/products/category-a/item1.png&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/assets/products/category-b/item2.png&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You want to resize these to &lt;strong&gt;200px (max side)&lt;/strong&gt; and save them as &lt;code&gt;_200px.png&lt;/code&gt; in the same folders, keeping the originals intact.&lt;/p&gt;
&lt;h2&gt;
  
  
  The One-Liner Solution
&lt;/h2&gt;

&lt;p&gt;Open your terminal, navigate to your root folder, and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.png"&lt;/span&gt; &lt;span class="nt"&gt;-exec&lt;/span&gt; sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'sips -Z 200 "$1" --out "${1%.png}_200px.png"'&lt;/span&gt; _ &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Breaking Down the Command
&lt;/h3&gt;

&lt;p&gt;To understand what's happening under the hood, let's look at the components:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command Part&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;find .&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Searches the current directory and all subfolders.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-name "*.png"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Filters only the files ending with your specific suffix.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sips -Z 200&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Resizes the image so the largest dimension is 200px (preserving aspect ratio).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--out ...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Specifies the output path so we don't overwrite the original.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;${1%.png}_200px.png&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A shell trick to strip the &lt;code&gt;.png&lt;/code&gt; extension and append our new suffix.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Why Sips?
&lt;/h2&gt;

&lt;p&gt;Sips is remarkably fast because it is optimized for the macOS file system and hardware. &lt;br&gt;
Unlike other tools, it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Respects Color Profiles:&lt;/strong&gt; It uses Apple's ColorSync technology.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zero Install:&lt;/strong&gt; It has been part of macOS for decades.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Smart Scaling:&lt;/strong&gt; Using the &lt;code&gt;-Z&lt;/code&gt; flag ensures your images never look "stretched" as it maintains the original proportions.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro Tip:&lt;/strong&gt; If you want to overwrite the original files instead of creating new ones, simply use:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;find . -name "*.png" -exec sips -Z 200 {} \;
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Next time you're preparing thumbnails for a gallery or optimizing assets for a website, don't reach for a GUI.&lt;br&gt;
The power of the macOS CLI is right at your fingertips.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Note&lt;br&gt;
This post was originally published on &lt;a href="https://www.romainlespinasse.dev/posts/macos-resize-using-sips/" rel="noopener noreferrer"&gt;my personal blog&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>macos</category>
      <category>terminal</category>
      <category>sips</category>
    </item>
    <item>
      <title>How to Add a Photo to an Existing Page in a PDF Using macOS Preview</title>
      <dc:creator>Romain Lespinasse</dc:creator>
      <pubDate>Fri, 20 Feb 2026 21:56:49 +0000</pubDate>
      <link>https://dev.to/rlespinasse/how-to-add-a-photo-to-an-existing-page-in-a-pdf-using-macos-preview-ho9</link>
      <guid>https://dev.to/rlespinasse/how-to-add-a-photo-to-an-existing-page-in-a-pdf-using-macos-preview-ho9</guid>
      <description>&lt;p&gt;If you have ever tried to paste an image into a PDF using the macOS Preview app, you probably ran into a highly frustrating issue. &lt;/p&gt;

&lt;p&gt;Instead of dropping the image onto the page you are currently viewing, Preview insists on pasting the image as a completely new, blank page. &lt;/p&gt;

&lt;p&gt;Preview doesn't have a standard "Insert Image" button. However, there is a hidden workaround that lets you paste a photo as a movable, resizable object directly onto an existing PDF page. &lt;/p&gt;

&lt;h3&gt;
  
  
  The "Paste-Into-Itself" Method
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open the image:&lt;/strong&gt; Double-click your photo to open it in the Preview app.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Copy the image:&lt;/strong&gt; Press &lt;strong&gt;Command + A&lt;/strong&gt; (⌘A) to select the entire image, then press &lt;strong&gt;Command + C&lt;/strong&gt; (⌘C) to copy it to your clipboard.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Paste it into itself:&lt;/strong&gt; Without leaving your image window, press &lt;strong&gt;Command + V&lt;/strong&gt; (⌘V) to paste. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How to know it worked:&lt;/strong&gt; This creates a duplicate "object" layer directly on top of your original image. The new layer will have a bounding box with little blue dots on the corners.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Select and copy the new object:&lt;/strong&gt; This is the most crucial step! Make sure you explicitly click on that newly pasted image layer so that those blue corner dots are actively selected. &lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Once it is selected, press &lt;strong&gt;Command + C&lt;/strong&gt; (⌘C) to copy this specific &lt;em&gt;object&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open your PDF:&lt;/strong&gt; Switch over to the PDF document you want to edit (also opened in Preview).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Select the target page:&lt;/strong&gt; Click directly in the middle of the actual PDF page where you want the image to go. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; Do not click the thumbnail in the sidebar, or Preview will default back to creating a new page.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Paste and adjust:&lt;/strong&gt; Press &lt;strong&gt;Command + V&lt;/strong&gt; (⌘V). &lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Your image should now drop successfully onto your PDF page! &lt;/p&gt;

&lt;p&gt;From there, you can click and drag it into position and use the blue corner dots to resize it to fit perfectly. &lt;/p&gt;

&lt;p&gt;When you are finished, just hit &lt;strong&gt;Command + S&lt;/strong&gt; (⌘S) to save your newly updated PDF.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Note&lt;br&gt;
This post was originally published on &lt;a href="https://www.romainlespinasse.dev/posts/photo-in-pdf-macos-preview/" rel="noopener noreferrer"&gt;my personal blog&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>macos</category>
      <category>preview</category>
      <category>pdf</category>
      <category>apple</category>
    </item>
    <item>
      <title>Optimizing Shared GitLab Pipelines: Flexibility and Maintainability</title>
      <dc:creator>Romain Lespinasse</dc:creator>
      <pubDate>Fri, 20 Feb 2026 21:45:30 +0000</pubDate>
      <link>https://dev.to/rlespinasse/optimizing-shared-gitlab-pipelines-flexibility-and-maintainability-7p8</link>
      <guid>https://dev.to/rlespinasse/optimizing-shared-gitlab-pipelines-flexibility-and-maintainability-7p8</guid>
      <description>&lt;h2&gt;
  
  
  The Challenge
&lt;/h2&gt;

&lt;p&gt;A colleague seeks to modify the script section of a job in a shared GitLab pipeline, facing hardcoded configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# https://gitlab.com/rlespinasse/foobar-shared-ci-templates/-/blob/main/pipeline-with-hardcoded-values.yml&lt;/span&gt;
  &lt;span class="na"&gt;test-branch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
    &lt;span class="na"&gt;before_script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ls&lt;/span&gt;
    &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# it's for the example, the script can be more complex&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ls ./wrong-folder&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This rigid setup causes pipeline failure in their project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# https://gitlab.com/rlespinasse/foobar-project/-/blob/main/.gitlab-ci.yml&lt;/span&gt;
  &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rlespinasse/foobar-shared-ci-templates'&lt;/span&gt;
      &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HEAD&lt;/span&gt;
      &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/pipeline-with-hardcoded-values.yml'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; ./wrong-folder
  &lt;span class="nb"&gt;ls&lt;/span&gt;: cannot access &lt;span class="s1"&gt;'./wrong-folder'&lt;/span&gt;: No such file or directory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Ideal Solution
&lt;/h2&gt;

&lt;p&gt;The optimal approach involves implementing &lt;a href="https://docs.gitlab.com/ee/ci/yaml/includes.html#override-included-configuration-values" rel="noopener noreferrer"&gt;variables as configuration points&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# https://gitlab.com/rlespinasse/foobar-shared-ci-templates/-/blob/main/pipeline-with-variables.yml&lt;/span&gt;
  &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;FOLDER_TO_TEST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wrong-folder&lt;/span&gt;

  &lt;span class="na"&gt;test-branch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
    &lt;span class="na"&gt;before_script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ls&lt;/span&gt;
    &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ls ./${FOLDER_TO_TEST}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method allows for easy customization:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# https://gitlab.com/rlespinasse/foobar-project/-/merge_requests/2&lt;/span&gt;
  &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rlespinasse/foobar-shared-ci-templates'&lt;/span&gt;
      &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HEAD&lt;/span&gt;
      &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/pipeline-with-variables.yml'&lt;/span&gt;

  &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;FOLDER_TO_TEST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;folder&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; ./&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;FOLDER_TO_TEST&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
  some-file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Temporary Workaround
&lt;/h2&gt;

&lt;p&gt;In the meantime, one can override only the &lt;code&gt;script&lt;/code&gt; part:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# https://gitlab.com/rlespinasse/foobar-project/-/merge_requests/1&lt;/span&gt;
  &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rlespinasse/foobar-shared-ci-templates'&lt;/span&gt;
      &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HEAD&lt;/span&gt;
      &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/pipeline-with-hardcoded-values.yml'&lt;/span&gt;

  &lt;span class="na"&gt;test-branch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
    &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ls ./folder&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; ./folder
  some-file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;While functional, this temporary solution may lead to divergences and maintenance issues.&lt;/p&gt;

&lt;p&gt;It's recommended to contribute to open source or innersource projects (especially during &lt;a href="https://hacktoberfest.com/" rel="noopener noreferrer"&gt;Hacktoberfest&lt;/a&gt;) by proposing the addition of variables.&lt;br&gt;
This would allow users to adapt shared pipeline behaviors to their needs while preserving the original intent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Explore the code
&lt;/h3&gt;

&lt;p&gt;You can explore the code on those repositories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gitlab.com/rlespinasse/foobar-shared-ci-templates" rel="noopener noreferrer"&gt;https://gitlab.com/rlespinasse/foobar-shared-ci-templates&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gitlab.com/rlespinasse/foobar-project" rel="noopener noreferrer"&gt;https://gitlab.com/rlespinasse/foobar-project&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Note&lt;br&gt;
This post was originally published on &lt;a href="https://www.romainlespinasse.dev/posts/optimizing-shared-gitlab-pipelines/" rel="noopener noreferrer"&gt;my personal blog&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>gitlab</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Pinning GitHub Actions to Commit SHAs: A Practical Security Step</title>
      <dc:creator>Romain Lespinasse</dc:creator>
      <pubDate>Wed, 04 Feb 2026 10:37:00 +0000</pubDate>
      <link>https://dev.to/rlespinasse/pinning-github-actions-to-commit-shas-a-practical-security-step-mmf</link>
      <guid>https://dev.to/rlespinasse/pinning-github-actions-to-commit-shas-a-practical-security-step-mmf</guid>
      <description>&lt;h2&gt;
  
  
  How a user issue opened my eyes
&lt;/h2&gt;

&lt;p&gt;I maintain &lt;a href="https://github.com/rlespinasse/github-slug-action" rel="noopener noreferrer"&gt;github-slug-action&lt;/a&gt;, and one morning I woke up to &lt;a href="https://github.com/rlespinasse/github-slug-action/issues/174" rel="noopener noreferrer"&gt;issue #174&lt;/a&gt; — users were suddenly blocked because their organisation had enabled GitHub's new policy requiring all actions to be pinned to a full-length commit SHA.&lt;/p&gt;

&lt;p&gt;I already knew that pinning actions to commit SHAs was the right thing to do. Git tags are mutable — they can be deleted, moved, or recreated pointing to an entirely different commit. A compromised repository, a rogue maintainer, or even an honest mistake could silently swap the code your workflows execute, while the logs still show &lt;code&gt;@v4&lt;/code&gt; as if nothing changed. But when you maintain several open source projects on your own, free time goes to the bugs users are hitting right now — not to preventive security work that can always wait until next week.&lt;/p&gt;

&lt;p&gt;That issue, combined with a bit more breathing room in my schedule, gave me the space to finally act on it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxpi6ouhx7qip93fux7bn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxpi6ouhx7qip93fux7bn.png" alt="Tag vs SHA pinning comparison" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What SHA pinning looks like
&lt;/h2&gt;

&lt;p&gt;Instead of referencing an action by tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You reference it by its full commit SHA:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683&lt;/span&gt; &lt;span class="c1"&gt;# v4.2.2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The commit hash is immutable.&lt;br&gt;
Once a commit exists in Git, its SHA cannot change without changing its content.&lt;br&gt;
Pinning to a SHA guarantees that your workflow runs exactly the code you expect, every time.&lt;/p&gt;

&lt;p&gt;The trailing comment (&lt;code&gt;# v4.2.2&lt;/code&gt;) is a convention that keeps the version human-readable.&lt;br&gt;
It has no effect on execution — GitHub Actions resolves the SHA, not the comment.&lt;/p&gt;
&lt;h2&gt;
  
  
  GitHub's immutable release policy
&lt;/h2&gt;

&lt;p&gt;SHA pinning used to be a best practice that teams adopted voluntarily.&lt;br&gt;
That changed when GitHub introduced an &lt;a href="https://github.blog/changelog/2025-08-15-github-actions-policy-now-supports-blocking-and-sha-pinning-actions/" rel="noopener noreferrer"&gt;organisation-level policy&lt;/a&gt; that lets administrators enforce full commit SHA pinning for all actions used in their repositories.&lt;/p&gt;

&lt;p&gt;When this policy is enabled, any workflow that references an action by tag — &lt;code&gt;@v4&lt;/code&gt;, &lt;code&gt;@main&lt;/code&gt;, or any other mutable reference — will fail with an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: The actions example/some-action@v1 are not allowed in your-org/your-repo
because all actions must be pinned to a full-length commit SHA.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a significant shift.&lt;br&gt;
What was once a recommendation is now something organisations can make mandatory across all their repositories.&lt;/p&gt;
&lt;h2&gt;
  
  
  The sub-action catch
&lt;/h2&gt;

&lt;p&gt;There is a subtlety to this policy that caught some users off guard: it applies to &lt;strong&gt;sub-actions&lt;/strong&gt; as well, not just the actions you reference directly in your workflow files.&lt;/p&gt;

&lt;p&gt;This is exactly what happened with &lt;a href="https://github.com/rlespinasse/github-slug-action" rel="noopener noreferrer"&gt;github-slug-action&lt;/a&gt;.&lt;br&gt;
The action internally references two sub-actions — &lt;code&gt;rlespinasse/slugify-value&lt;/code&gt; and &lt;code&gt;rlespinasse/shortify-git-revision&lt;/code&gt; — that were pinned by tag.&lt;br&gt;
Users who enabled the SHA pinning policy in their organisation started seeing failures (&lt;a href="https://github.com/rlespinasse/github-slug-action/issues/174" rel="noopener noreferrer"&gt;#174&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: The actions rlespinasse/slugify-value@v1.4.0 and
rlespinasse/shortify-git-revision@v1.6.0 are not allowed in your-org/your-repo
because all actions must be pinned to a full-length commit SHA.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The users' own workflow files were fine — they had pinned &lt;code&gt;github-slug-action&lt;/code&gt; itself to a SHA.&lt;br&gt;
But the policy checks the entire action dependency tree, including internal references that action consumers do not control.&lt;/p&gt;

&lt;p&gt;This means that &lt;strong&gt;action maintainers&lt;/strong&gt; need to pin their sub-actions too, or they block downstream users from adopting the policy.&lt;/p&gt;
&lt;h2&gt;
  
  
  The fix in practice
&lt;/h2&gt;

&lt;p&gt;In &lt;strong&gt;v5.5.0&lt;/strong&gt; (&lt;a href="https://github.com/rlespinasse/github-slug-action/pull/175" rel="noopener noreferrer"&gt;#175&lt;/a&gt;), all sub-actions referenced within github-slug-action were pinned to full commit SHAs.&lt;/p&gt;

&lt;p&gt;Before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rlespinasse/slugify-value@v1.4.0&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rlespinasse/shortify-git-revision@v1.6.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rlespinasse/slugify-value@750260b26ed3c8e4db9b4833be0a0768a6508e54&lt;/span&gt; &lt;span class="c1"&gt;# v1.4.0&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rlespinasse/shortify-git-revision@14c50a2e4c952a5a9d29a4ee4bb39068af4a1e3d&lt;/span&gt; &lt;span class="c1"&gt;# v1.6.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The workflow behavior is identical.&lt;br&gt;
Organisations with the SHA pinning policy enabled can now use github-slug-action without errors.&lt;/p&gt;
&lt;h2&gt;
  
  
  Keeping SHA pins up to date
&lt;/h2&gt;

&lt;p&gt;The most common objection to SHA pinning is maintenance: "How do I know when a new version is available if I am not using tags?"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.github.com/en/code-security/dependabot" rel="noopener noreferrer"&gt;Dependabot&lt;/a&gt; handles this.&lt;br&gt;
It understands SHA-pinned GitHub Actions and will open pull requests when new versions are released.&lt;br&gt;
The PR updates the SHA and the version comment together, so you get the same update experience as with tag-based references.&lt;/p&gt;

&lt;p&gt;Enable it by adding this to your &lt;code&gt;.github/dependabot.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="na"&gt;updates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;package-ecosystem&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;github-actions"&lt;/span&gt;
    &lt;span class="na"&gt;directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/"&lt;/span&gt;
    &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;weekly"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dependabot will detect your SHA-pinned actions and propose updates with the new commit hash and version comment.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means for action maintainers
&lt;/h2&gt;

&lt;p&gt;If you maintain a GitHub Action that references other actions internally, you should pin those references to full commit SHAs.&lt;br&gt;
Your users may have adopted — or may be required to adopt — the organisation-level policy, and tag-based sub-action references will block them.&lt;/p&gt;

&lt;p&gt;This is a small change on your side that unblocks an entire security posture for your downstream consumers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;SHA pinning is moving from a best practice to an enforced policy.&lt;br&gt;
GitHub's immutable release support means organisations can now mandate it across all repositories, and the policy checks the full dependency tree — including sub-actions that individual users cannot control.&lt;/p&gt;

&lt;p&gt;If you consume third-party actions, pin them to SHAs and let Dependabot handle updates. You can also use the &lt;a href="https://dev.to/posts/pin-github-actions-skill/"&gt;pin-github-actions-skill&lt;/a&gt; to streamline the pinning process.&lt;br&gt;
If you maintain actions, pin your sub-actions too — your users will thank you for it.&lt;/p&gt;

</description>
      <category>github</category>
      <category>cicd</category>
      <category>security</category>
    </item>
    <item>
      <title>Hacktoberfest 2020: Lessons learned as Maintainer</title>
      <dc:creator>Romain Lespinasse</dc:creator>
      <pubDate>Sun, 01 Nov 2020 18:11:06 +0000</pubDate>
      <link>https://dev.to/rlespinasse/hacktoberfest-2020-lessons-learned-57kg</link>
      <guid>https://dev.to/rlespinasse/hacktoberfest-2020-lessons-learned-57kg</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;In addition of my participation for the 4th time in a row, This year report will focus on my activity as Maintainer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  as Creator
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Project ideas come from everywhere, don't limit yourself and create a public repository even when you may be the only user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don't be perfect from the start, you can improve your project during its lifetime.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can choose any name for your project, sometimes a descriptive name, sometimes a play of words.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  as Maintainer
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Learn to say &lt;strong&gt;no&lt;/strong&gt; as Maintainer or to choose your own way to deal with a situation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don't support all releases of your project all the time, you can depreciate version series.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don't be afraid to &lt;code&gt;archived&lt;/code&gt; a project if you unmaintained it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don't put yourself under pressure to respond quickly as possible to issues or pull-requests submissions.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;This post may be edited overtime with new lessons:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't stop learning&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>hacktoberfest</category>
      <category>maintainer</category>
      <category>creator</category>
      <category>lessons</category>
    </item>
    <item>
      <title>Hacktoberfest 2020: github-slug-action Maintainer</title>
      <dc:creator>Romain Lespinasse</dc:creator>
      <pubDate>Sun, 01 Nov 2020 17:49:47 +0000</pubDate>
      <link>https://dev.to/rlespinasse/hacktoberfest-2020-maintainer-of-github-slug-action-49bi</link>
      <guid>https://dev.to/rlespinasse/hacktoberfest-2020-maintainer-of-github-slug-action-49bi</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;In addition of my participation for the 4th time in a row, This year report will focus on my activity as Maintainer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Some projects ideas can start from a colleague tweet.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/rlespinasse" rel="noopener noreferrer"&gt;
        rlespinasse
      &lt;/a&gt; / &lt;a href="https://github.com/rlespinasse/github-slug-action" rel="noopener noreferrer"&gt;
        github-slug-action
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      GitHub Action to expose slug value of GitHub environment variables inside your GitHub workflow
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;This idea behind &lt;code&gt;github-slug-action&lt;/code&gt; is one of them (tweet in French)&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1191827751751299074-278" src="https://platform.twitter.com/embed/Tweet.html?id=1191827751751299074"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1191827751751299074-278');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1191827751751299074&amp;amp;theme=dark"
  }



 &lt;/p&gt;

&lt;p&gt;From this &lt;code&gt;SLUG&lt;/code&gt; variable need, I start to develop my first GitHub Action. Using docker-based container and some bash script with &lt;code&gt;sed&lt;/code&gt; or &lt;code&gt;cut&lt;/code&gt;, I create the first version of this action quickly.&lt;/p&gt;
&lt;h2&gt;
  
  
  master end-of-life
&lt;/h2&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1254456661886066689-635" src="https://platform.twitter.com/embed/Tweet.html?id=1254456661886066689"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1254456661886066689-635');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1254456661886066689&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;After sometimes, &lt;code&gt;github-slug-action&lt;/code&gt; start to be used by multiples projects and some enhancements have been asked.&lt;/p&gt;

&lt;p&gt;This lead to a version bump to &lt;code&gt;2.x&lt;/code&gt; due to a breaking change in April 2020. Due to that breaking change, I take the decision to change my branching strategy to adopt a &lt;code&gt;vX.Y&lt;/code&gt; branch naming to better manage this type of change.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;master&lt;/code&gt; branch have been depreciated&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/rlespinasse/github-slug-action/issues/15" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        github-slug-action - master branch EOL
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#15&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/rlespinasse" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars2.githubusercontent.com%2Fu%2F1280212%3Fv%3D4" alt="rlespinasse avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/rlespinasse" rel="noopener noreferrer"&gt;rlespinasse&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/rlespinasse/github-slug-action/issues/15" rel="noopener noreferrer"&gt;&lt;time&gt;Apr 26, 2020&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Due to changes into the branches management, the &lt;code&gt;master&lt;/code&gt; branch is not longer supported and will be removed in few months (&lt;em&gt;EOL: 2020-10-25&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;After a search, here is the list of projects who use &lt;code&gt;master&lt;/code&gt; branch for this action inside their workflows.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[x] danielr1996/docker-action-multitag#4&lt;/li&gt;
&lt;li&gt;[x] doerfli/feedscraper#93&lt;/li&gt;
&lt;li&gt;[x] patou/liste-envies#97&lt;/li&gt;
&lt;li&gt;[ ] kingkool68/testing-github-actions#1&lt;/li&gt;
&lt;li&gt;[x] TardisBank/TardisBank#48&lt;/li&gt;
&lt;li&gt;[x] feinoujc/node-app#1&lt;/li&gt;
&lt;li&gt;[x] dormdev/dormdev#5&lt;/li&gt;
&lt;li&gt;[x] 7mind/izumi-docker#1&lt;/li&gt;
&lt;li&gt;[x] elmerfdz/rebuild-dndc#31&lt;/li&gt;
&lt;li&gt;[x] VladPodilnyk/d4s-example#2&lt;/li&gt;
&lt;li&gt;[x] LuanaFn/avas-denuncia-backend#12&lt;/li&gt;
&lt;li&gt;[x] time-machine-project/requests-for-comments#9&lt;/li&gt;
&lt;li&gt;[x] chiffre-io/push#44&lt;/li&gt;
&lt;li&gt;[x] elmerfdz/docker-traktarr#8&lt;/li&gt;
&lt;li&gt;[x] elmerfdz/docker-statping#15&lt;/li&gt;
&lt;li&gt;[x] yngwi/requests-for-comments_test#6&lt;/li&gt;
&lt;li&gt;[x] jupitermoney/base-images#2&lt;/li&gt;
&lt;li&gt;[x] elmerfdz/docker-bind#5&lt;/li&gt;
&lt;li&gt;[x] zio/izumi-reflect#21&lt;/li&gt;
&lt;li&gt;[x] PlayQ/d4s#48&lt;/li&gt;
&lt;li&gt;[x] doerfli/rss-mock-server#8&lt;/li&gt;
&lt;li&gt;[x] thecodingmachine/workadventure#58&lt;/li&gt;
&lt;li&gt;[ ] voxeet/voxeet-uxkit-react#2&lt;/li&gt;
&lt;li&gt;[x] Meemaw/Insight#17&lt;/li&gt;
&lt;li&gt;[ ] kingkool68/wordpress-child-themes#25&lt;/li&gt;
&lt;/ul&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/rlespinasse/github-slug-action/issues/15" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;A removal of the &lt;code&gt;master&lt;/code&gt; branch have been plan 6-months later. This work is complete.&lt;br&gt;
Some repositories still used the &lt;code&gt;master&lt;/code&gt; branch and a pull-request to migrate have been created of each of them during October before the &lt;code&gt;master&lt;/code&gt; branch deletion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TIP&lt;/strong&gt;: Use &lt;a href="https://dependabot.com/github-actions/" rel="noopener noreferrer"&gt;&lt;code&gt;Dependabot&lt;/code&gt;&lt;/a&gt; to manage versions of used GitHub Actions in your workflows&lt;/p&gt;
&lt;h2&gt;
  
  
  Docker-based GitHub Action limitation
&lt;/h2&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/rlespinasse/github-slug-action/issues/16" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Other operating systems support
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#16&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/aminya" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars0.githubusercontent.com%2Fu%2F16418197%3Fv%3D4" alt="aminya avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/aminya" rel="noopener noreferrer"&gt;aminya&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/rlespinasse/github-slug-action/issues/16" rel="noopener noreferrer"&gt;&lt;time&gt;Jun 28, 2020&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;What dependency this is using that prevents it from running on other operating systems?&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/rlespinasse/github-slug-action/issues/16" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Currently, a docker-based GitHub Action can only run on Linux-based workflows.&lt;/p&gt;

&lt;p&gt;In order to manage Windows-based and Macos-based workflows, the action need to be rewrite as Javascript-based action. In September 2020, &lt;a href="https://github.com/Ameausoone" rel="noopener noreferrer"&gt;@Ameausoone&lt;/a&gt; have took up the challenge to migrate to Typescript.&lt;/p&gt;

&lt;p&gt;Thanks you.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub Action CVE
&lt;/h2&gt;

&lt;p&gt;During the Hacktoberfest, the GitHub Action have been impacted by a &lt;a href="https://en.wikipedia.org/wiki/Common_Vulnerabilities_and_Exposures" rel="noopener noreferrer"&gt;CVE&lt;/a&gt; on one of the GitHub Action core feature that been in used : &lt;a href="https://github.com/actions/toolkit/security/advisories/GHSA-mfwh-5m23-j46w" rel="noopener noreferrer"&gt;GHSA-mfwh-5m23-j46w&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks you &lt;a href="https://github.com/boolooper" rel="noopener noreferrer"&gt;@boolooper&lt;/a&gt; for the reporting.&lt;/p&gt;

&lt;p&gt;On maintained branches, all impacted versions have been updated to fix this CVE and an advisory have been created on the project : &lt;a href="https://github.com/rlespinasse/github-slug-action/security/advisories/GHSA-7f32-hm4h-w77q" rel="noopener noreferrer"&gt;GHSA-7f32-hm4h-w77q&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before Hacktoberfest 2020
&lt;/h2&gt;

&lt;p&gt;Thanks to &lt;a href="https://github.com/Ameausoone" rel="noopener noreferrer"&gt;@Ameausoone&lt;/a&gt;, &lt;a href="https://github.com/m4rcs" rel="noopener noreferrer"&gt;@m4rcs&lt;/a&gt;, and &lt;a href="https://github.com/php-coder" rel="noopener noreferrer"&gt;@php-coder&lt;/a&gt; for yours contributions before this year event.&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>maintainer</category>
      <category>opensource</category>
      <category>githubaction</category>
    </item>
    <item>
      <title>Hacktoberfest 2020: drawio-cli and drawio-export Maintainer</title>
      <dc:creator>Romain Lespinasse</dc:creator>
      <pubDate>Sun, 01 Nov 2020 17:49:31 +0000</pubDate>
      <link>https://dev.to/rlespinasse/hacktoberfest-2020-maintainer-of-drawio-cli-and-drawio-export-1018</link>
      <guid>https://dev.to/rlespinasse/hacktoberfest-2020-maintainer-of-drawio-cli-and-drawio-export-1018</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;In addition of my participation for the 4th time in a row, This year report will focus on my activity as Maintainer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Earlier this year, I want to be able to automatically export diagrams from a &lt;code&gt;drawio&lt;/code&gt; file. This need lead to the creation of 2 new open-sources projects :&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/rlespinasse" rel="noopener noreferrer"&gt;
        rlespinasse
      &lt;/a&gt; / &lt;a href="https://github.com/rlespinasse/drawio-export" rel="noopener noreferrer"&gt;
        drawio-export
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Export Draw.io diagrams using docker
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/rlespinasse" rel="noopener noreferrer"&gt;
        rlespinasse
      &lt;/a&gt; / &lt;a href="https://github.com/rlespinasse/drawio-cli" rel="noopener noreferrer"&gt;
        drawio-cli
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      CLI for Draw.io
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;drawio-cli&lt;/code&gt; project is responsible to generate a docker image with a &lt;strong&gt;raw&lt;/strong&gt; cli of drawio (thanks &lt;a href="https://github.com/jgraph/drawio-desktop" rel="noopener noreferrer"&gt;drawio-desktop&lt;/a&gt;) for that.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;drawio-export&lt;/code&gt; project use the &lt;code&gt;drawio-cli&lt;/code&gt; project to enhance initial export capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Support latest version of Drawio-desktop
&lt;/h2&gt;

&lt;p&gt;At the beginning of Hacktoberfest, &lt;a href="https://github.com/danquah" rel="noopener noreferrer"&gt;@danquash&lt;/a&gt; start working of this &lt;a href="https://github.com/rlespinasse/drawio-cli/issues/4" rel="noopener noreferrer"&gt;issue&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After an awesome work on debugging the version bump issues, he have create 2 pull-requests (1 on each project)&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/rlespinasse/drawio-cli/pull/5" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Support drawio 13.x
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#5&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/danquah" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars0.githubusercontent.com%2Fu%2F999542%3Fv%3D4" alt="danquah avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/danquah" rel="noopener noreferrer"&gt;danquah&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/rlespinasse/drawio-cli/pull/5" rel="noopener noreferrer"&gt;&lt;time&gt;Oct 02, 2020&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;As discussed in #4
This pull-requests bumps the drawio-version to 13.7.3 (latest according to &lt;a href="https://github.com/jgraph/drawio-desktop/releases/tag/v13.7.3" rel="noopener noreferrer"&gt;https://github.com/jgraph/drawio-desktop/releases/tag/v13.7.3&lt;/a&gt;) and installes a required dependency.&lt;/p&gt;
&lt;p&gt;Apparently the newer version of drawio requires some arguments to come last, without this last change electron simply quits with a&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Error: input file/directory not found
&lt;/code&gt;&lt;/pre&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/rlespinasse/drawio-cli/pull/5" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/rlespinasse/drawio-export/pull/29" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Support draweio 13.x
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#29&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/danquah" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars0.githubusercontent.com%2Fu%2F999542%3Fv%3D4" alt="danquah avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/danquah" rel="noopener noreferrer"&gt;danquah&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/rlespinasse/drawio-export/pull/29" rel="noopener noreferrer"&gt;&lt;time&gt;Oct 02, 2020&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Closely related to &lt;a href="https://github.com/rlespinasse/drawio-cli/pull/5" rel="noopener noreferrer"&gt;https://github.com/rlespinasse/drawio-cli/pull/5&lt;/a&gt; and &lt;a href="https://github.com/rlespinasse/drawio-cli/pull/4" rel="noopener noreferrer"&gt;https://github.com/rlespinasse/drawio-cli/pull/4&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This PR moves an argument to the end of the line as seems to be required by newer versions of drawio.&lt;/p&gt;
&lt;p&gt;Without this we get a "Error: input file/directory not found" error (tested with version 13.7.3 of jgraph/drawio-desktop)&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/rlespinasse/drawio-export/pull/29" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Thanks to him.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enhancements on drawio-export
&lt;/h2&gt;

&lt;p&gt;Some &lt;code&gt;enhancement&lt;/code&gt; issues have been &lt;a href="https://github.com/rlespinasse/drawio-export/contribute" rel="noopener noreferrer"&gt;available for contribution&lt;/a&gt; during this Hacktoberfest 2020.&lt;/p&gt;

&lt;p&gt;This new &lt;code&gt;--on-changes&lt;/code&gt; option, to improve the speed of diagrams generation, have been develop by &lt;a href="https://github.com/Nico385412" rel="noopener noreferrer"&gt;@Nico385412&lt;/a&gt;.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/rlespinasse/drawio-export/pull/34" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        feat(option): add on-changes-option
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#34&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/Nico385412" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars3.githubusercontent.com%2Fu%2F9024389%3Fv%3D4" alt="Nico385412 avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/Nico385412" rel="noopener noreferrer"&gt;Nico385412&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/rlespinasse/drawio-export/pull/34" rel="noopener noreferrer"&gt;&lt;time&gt;Oct 11, 2020&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;resolves #15&lt;/p&gt;
&lt;p&gt;I'm not an expert in shell but this pr do the job, i would like to know your opinion on it :D&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/rlespinasse/drawio-export/pull/34" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Thanks to him.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before Hacktoberfest 2020
&lt;/h2&gt;

&lt;p&gt;Thanks to &lt;a href="https://github.com/bogaertg" rel="noopener noreferrer"&gt;@bogaertg&lt;/a&gt; and &lt;a href="https://github.com/Decat-SimonA" rel="noopener noreferrer"&gt;@Decat-SimonA&lt;/a&gt; for yours contributions before this year event.&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>maintainer</category>
      <category>opensource</category>
      <category>drawio</category>
    </item>
    <item>
      <title>Everybody has a testing environment</title>
      <dc:creator>Romain Lespinasse</dc:creator>
      <pubDate>Sun, 20 Sep 2020 18:42:14 +0000</pubDate>
      <link>https://dev.to/rlespinasse/everybody-has-a-testing-environment-7p</link>
      <guid>https://dev.to/rlespinasse/everybody-has-a-testing-environment-7p</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Everybody has a testing environment.&lt;/strong&gt;&lt;br&gt;
Some people are lucky enough enough to have a totally separate environment to run production in.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From &lt;a href="https://twitter.com/stahnma/status/634849376343429120" rel="noopener noreferrer"&gt;@stahnma&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I love this motto, and you?&lt;/p&gt;

</description>
      <category>quote</category>
      <category>motto</category>
      <category>production</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
