<?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: Jamie Tanna</title>
    <description>The latest articles on DEV Community by Jamie Tanna (@jamietanna).</description>
    <link>https://dev.to/jamietanna</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F75850%2F132c75a8-29b4-40ff-bfaa-52856d0587c5.png</url>
      <title>DEV Community: Jamie Tanna</title>
      <link>https://dev.to/jamietanna</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jamietanna"/>
    <language>en</language>
    <item>
      <title>Why I recommend Renovate over any other dependency update tools</title>
      <dc:creator>Jamie Tanna</dc:creator>
      <pubDate>Fri, 12 Apr 2024 10:06:35 +0000</pubDate>
      <link>https://dev.to/jamietanna/why-i-recommend-renovate-over-any-other-dependency-update-tools-367f</link>
      <guid>https://dev.to/jamietanna/why-i-recommend-renovate-over-any-other-dependency-update-tools-367f</guid>
      <description>&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt; This post was originally posted &lt;a href="https://www.jvt.me/posts/2024/04/12/use-renovate/"&gt;on my blog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've read my blog before, or interacted with me at work or in the Open Source world, you're likely to know that I'm a huge fan of &lt;a href="https://docs.renovatebot.com/"&gt;Renovate&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For those that aren't aware, Renovate is one of the big players in dependency updating tooling, commonly seen in comparisons with Dependabot or Snyk.&lt;/p&gt;

&lt;p&gt;I've been using Renovate for the last ~5 years, alongside a mix of Dependabot and Snyk to keep me grounded. I &lt;em&gt;absolutely love&lt;/em&gt; Renovate, and make a point of making it so I can run Renovate where possible.&lt;/p&gt;

&lt;p&gt;I've also had the experience operating Renovate in self-hosted mode as well as used &lt;a href="https://developer.mend.io"&gt;the hosted Renovate app by Mend&lt;/a&gt; and the Mend Enterprise SAAS, and &lt;a href="https://gitlab.com/tanna.dev/jvt.me/-/issues/1349"&gt;plan to&lt;/a&gt; blog about the lessons learned self-hosting Renovate.&lt;/p&gt;

&lt;p&gt;Renovate has some really key features that set it apart from the competition, and I'm sure in the time it's taken me to write this, they've shipped some new ones 😻&lt;/p&gt;

&lt;p&gt;(Aside: I'm largely writing this blog post now, as I've recently been shouting the benefits of Renovate, and instead of writing another internal-only document at work (as I did at Deliveroo), I wanted to &lt;a href="https://www.jvt.me/posts/2017/06/25/blogumentation/"&gt;write it as a form of blogumentation&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Prior art
&lt;/h2&gt;

&lt;p&gt;A few years back, I wrote about &lt;a href="https://www.jvt.me/posts/2021/09/26/whitesource-renovate-tips/"&gt;some tips for using Renovate&lt;/a&gt; to make keeping your software up-to-date easier, which I still stand by.&lt;/p&gt;

&lt;p&gt;Since then, I've worked across a number of different ecosystems, repository sizes, and levels of comfort merging dependency updates, and have learned a few more things about effectively using Renovate - but through it, I'm still very sure of Renovate being the best tool in the ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configurability
&lt;/h2&gt;

&lt;p&gt;Renovate is &lt;em&gt;extremely&lt;/em&gt; configurable, with &lt;a href="https://docs.renovatebot.com/configuration-options/"&gt;dozens of configuration options&lt;/a&gt; to tune your experience. But Renovate doesn't end up being "too" configurable, where you end up spending more time tweaking config than doing the changes, but configurable enough that it's very likely you can do what you need to with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Centralised, shareable presets
&lt;/h2&gt;

&lt;p&gt;This is something that really hit me when we were rolling out Dependabot at Deliveroo, where my team owned ~30 repositories, and so for each of these repos, we needed to hand-craft a &lt;code&gt;dependabot.yml&lt;/code&gt;, as Dependabot needs to be told which directories contain which dependencies, and how often to update them.&lt;/p&gt;

&lt;p&gt;After we'd had about a week of usage, we started needing to tweak the configuration in a few of them to reduce the noise, which then required us to raise PRs across all the repos and get them updated.&lt;/p&gt;

&lt;p&gt;Because Dependabot requires a bit of a snowflake configuration per repository, this wasn't easily automatable, even with &lt;a href="https://www.jvt.me/posts/2023/01/21/bulk-git-repo-changes/"&gt;great tools available to automate some of the bulk updates&lt;/a&gt;, which made this a rather onerous and frustrating process.&lt;/p&gt;

&lt;p&gt;Compare this to Renovate, where there's an excellent first-class support for &lt;a href="https://docs.renovatebot.com/config-presets/"&gt;shareable config presets&lt;/a&gt;, in which you can "extend" multiple configuration(s).&lt;/p&gt;

&lt;p&gt;This allows a team that wants to have consistency (i.e. in how often they receive updates to the AWS and Google Cloud SDKs, or which labels they want on PRs) to create a shared preset for their team that defines this. Then, each of their repositories can "extend" this configuration, as well as defining their own configuration on top of it at a repo-specific level.&lt;/p&gt;

&lt;p&gt;This also makes it possible to provide good guardrails for your organisation, providing a good set of defaults, such as a &lt;code&gt;base.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://docs.renovatebot.com/renovate-schema.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"postUpdateOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"gomodTidy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"gomodUpdateImportPaths"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"regexManagers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"fileMatch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"^Makefile$"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"matchStrings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"curl .*https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- .* (?&amp;lt;currentValue&amp;gt;.*?)&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"depNameTemplate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"github.com/golangci/golangci-lint"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"datasourceTemplate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"go"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This then allows defining a somewhat opinionated good starting point for teams with a &lt;code&gt;default.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://docs.renovatebot.com/renovate-schema.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"local&amp;gt;your-org-here/renovate-config:base"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"config:best-practices"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, teams only need to set the following in their repos' &lt;code&gt;renovate.json&lt;/code&gt;, and they'll have the benefits of onboarding with a lot of the hard work done with starting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://docs.renovatebot.com/renovate-schema.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"local&amp;gt;your-org-here/renovate-config"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it 👏&lt;/p&gt;

&lt;h2&gt;
  
  
  Good defaults
&lt;/h2&gt;

&lt;p&gt;Linking back to the comment about having to hand-craft &lt;code&gt;dependabot.yml&lt;/code&gt;s, the great thing about Renovate is that there's some great defaults, and that it can autodetect the ecosystems your repo uses, and appropriately raises PRs.&lt;/p&gt;

&lt;p&gt;This ease of onboarding is truly excellent, and you can even have &lt;a href="https://docs.renovatebot.com/getting-started/installing-onboarding/#repository-onboarding"&gt;an onboarding PR&lt;/a&gt; raised to your repos to make it even simpler.&lt;/p&gt;

&lt;p&gt;For instance, at Deliveroo, we made it so &lt;a href="https://www.jvt.me/posts/2023/01/30/renovate-global-defaults/"&gt;there was a default set of configuration for all repos&lt;/a&gt; to give us an easy means to update Docker images, but then if teams wanted to manage everything, they could add a &lt;code&gt;renovate.json&lt;/code&gt;, and it'd be more fully featured.&lt;/p&gt;

&lt;p&gt;Additionally, Renovate comes with some great inbuilt configuration in the form of presets, including &lt;a href="https://docs.renovatebot.com/upgrade-best-practices/"&gt;a "best practices" guide&lt;/a&gt; and associated preset, which makes it easier to keep on top of community best practices, without needing to bikeshed about what you think is best.&lt;/p&gt;

&lt;p&gt;If you find that &lt;code&gt;config:best-practices&lt;/code&gt; is a little too much, there's &lt;code&gt;config:recommended&lt;/code&gt; as a starting point, and you can always downgrade or exclude rules you'd prefer not to follow. Or if you &lt;em&gt;really&lt;/em&gt; want to control things &lt;code&gt;config:base&lt;/code&gt; is the minimum you should pull in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Grouping
&lt;/h2&gt;

&lt;p&gt;As suggested above, it's possible to tune how different packages get updated, where you can &lt;a href="https://docs.renovatebot.com/noise-reduction/#package-grouping"&gt;group multiple updates into a single PR&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For instance, let's say that you use 9 different AWS services in your application, and instead of receiving 9 PRs every time there are updates across the SDKs, you want a single one. In this case, you could craft the following Renovate configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://docs.renovatebot.com/renovate-schema.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"packageRules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"groupName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"aws-sdk-go"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"matchPackagePatterns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"^github.com/aws/aws-sdk-go-v2"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What's great about this is that you can also bundle things like all patch updates into a single PR:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"packageRules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"matchPackagePatterns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"matchUpdateTypes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"patch"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"groupName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"all patch dependencies"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"groupSlug"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"all-patch"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is something that's &lt;a href="https://github.blog/2023-08-24-a-faster-way-to-manage-version-updates-with-dependabot/"&gt;recently&lt;/a&gt; been added to Dependabot, which is great, cause Renovate's had it for years 😝&lt;/p&gt;

&lt;h2&gt;
  
  
  Use for one-off bumps
&lt;/h2&gt;

&lt;p&gt;Because Renovate is an Open Source tool you can run on the command-line, it means you can &lt;em&gt;also&lt;/em&gt; get the ability to use &lt;a href="https://www.jvt.me/posts/2022/12/12/renovate-one-off/"&gt;Renovate for one-off executions&lt;/a&gt;, for instance to get everyone in your organisation to a minimum version of a given dependency, or just to do an infrequently performed set of updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Supports more than other tools
&lt;/h2&gt;

&lt;p&gt;Something I always refer back to is the fact that Renovate has a &lt;em&gt;tonne&lt;/em&gt; of supported package managers, package ecosystems and versioning tools.&lt;/p&gt;

&lt;p&gt;Renovate's &lt;a href="https://docs.renovatebot.com/bot-comparison/"&gt;bot comparison guide docs&lt;/a&gt; has a good example which links out to the differences between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.renovatebot.com/modules/manager/"&gt;What platforms Renovate supports&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/about-dependabot-version-updates#supported-repositories-and-ecosystems"&gt;What platforms Dependabot supports&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As Dependabot is more focussed on being used on GitHub's platforms (citation needed?) support for things like CircleCI, GitLab CI or other competitors' tooling doesn't seem to be available.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding support for additional ecosystems
&lt;/h2&gt;

&lt;p&gt;One of the things you'll be used to having from your dependency update tool of choice is your standard package manager support, where it'll update a &lt;code&gt;go.mod&lt;/code&gt; or a &lt;code&gt;pom.xml&lt;/code&gt; in your repositories.&lt;/p&gt;

&lt;p&gt;But one thing that's quite important to understand is that there are &lt;em&gt;many more&lt;/em&gt; dependencies in your project than those installed in your package manager. Something I find great about Renovate is that, as well as managing &lt;code&gt;Dockerfile&lt;/code&gt;s, &lt;code&gt;build.gradle&lt;/code&gt;s, &lt;code&gt;.gitlab-ci.yml&lt;/code&gt;, etc, it will &lt;em&gt;also&lt;/em&gt; manage things your &lt;code&gt;.ruby-version&lt;/code&gt; or configuration for the ASDF version manager.&lt;/p&gt;

&lt;p&gt;But what about some of the non-standard, or organisation-specific means for tracking versions?&lt;/p&gt;

&lt;p&gt;For instance, installing the &lt;code&gt;golangci-lint&lt;/code&gt; linting tool recommends using &lt;code&gt;curl | sh&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;$(GOBIN)/golangci-lint&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="nl"&gt;curl -sSfL https&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;//raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOBIN) v1.57.2&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it's common for &lt;code&gt;Dockerfile&lt;/code&gt;s to have a definition of the version of dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; MONGODB_VERSION=6.0.4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or what if you have a custom deployment configuration like:&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;# this is an (imaginary) company specific deployment configuration file&lt;/span&gt;
&lt;span class="na"&gt;application&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;lb&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;uk-tooling/load-balancer@v3.0.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's very unlikely that you have these supported by other tools out-of-the-box, and Renovate is the same.&lt;/p&gt;

&lt;p&gt;But Renovate &lt;em&gt;does&lt;/em&gt; give you the ability to manage these versions yourself.&lt;/p&gt;

&lt;p&gt;Using Renovate's &lt;a href="https://docs.renovatebot.com/modules/manager/regex/"&gt;custom managers&lt;/a&gt; we can craft a configuration file such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://docs.renovatebot.com/renovate-schema.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"regexManagers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"fileMatch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"^Makefile$"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"matchStrings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"curl .*https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- .* (?&amp;lt;currentValue&amp;gt;.*?)&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"depNameTemplate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"github.com/golangci/golangci-lint"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"datasourceTemplate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"go"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this will allow us to manage the &lt;code&gt;golangci-lint&lt;/code&gt; installation.&lt;/p&gt;

&lt;p&gt;Ideally, this sort of configuration may make it upstream so Renovate can do it out-of-the-box, but as we can see from the above example, there may be things that are organisation- or repo-specific, and so having it upstream'd doesn't make sense.&lt;/p&gt;

&lt;h2&gt;
  
  
  Because you can do more with it
&lt;/h2&gt;

&lt;p&gt;And you can do even more with it - I've mentioned you can use it for one-off updates on the command-line, but for instance I've also written a tool &lt;a href="https://gitlab.com/tanna.dev/renovate-graph"&gt;renovate-graph&lt;/a&gt; which takes the detected dependency data from Renovate and gives you a JSON blob you can consume.&lt;/p&gt;

&lt;p&gt;This underpins a large swathe of the power behind &lt;a href="https://dmd.tanna.dev"&gt;dependency-management-data&lt;/a&gt; and can be used for other means, such as &lt;a href="https://www.jvt.me/posts/2023/11/03/renovate-to-sbom/"&gt;converting Renovate data exports to a Software Bill of Materials (SBOM)&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependency Dashboard
&lt;/h2&gt;

&lt;p&gt;One thing I love about Renovate is that you can enable the &lt;a href="https://docs.renovatebot.com/key-concepts/dashboard/"&gt;Dependency Dashboard&lt;/a&gt;, which gives you an overview of the detected dependencies, open PRs, as well s anything that may be waiting, or has failed to update.&lt;/p&gt;

&lt;p&gt;This is a hugely useful insight into the at-a-glance how far behind are we on updates, giving a view of whether you maybe want to spend a bit more time focussing on updates, or looking at ways to cut through the noise.&lt;/p&gt;

&lt;p&gt;When you merge a PR into your default branch, Renovate will rebase open PRs, so they're easier to review, and are guaranteed to run against the latest changes. However, if you're not getting to your updates as often as changes are going in, you may have a tonne of PRs constantly building, which is a waste of energy and CI minutes.&lt;/p&gt;

&lt;p&gt;Instead, you can use the Dependency Dashboard for its ability to i.e. &lt;a href="https://docs.renovatebot.com/key-concepts/dashboard/#require-approval-for-major-updates"&gt;require major bumps be gated behind a manual approval&lt;/a&gt;, as it's likely you'll need some human interaction for that PR, and can then only raise it when you're actually ready to deal with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open Source
&lt;/h2&gt;

&lt;p&gt;A very important factor to me is that Renovate is Open Source, and open to community contributions.&lt;/p&gt;

&lt;p&gt;Although it's probably best to be split into another article, I love the AGPL3, and it's a great way of making sure that anyone hosting Renovate as a platform makes sure that their users get the access to the source code.&lt;/p&gt;

&lt;p&gt;Alternatively, Snyk is proprietary, and Dependabot is source available (or at a stretch "open source" not "Open Source") with &lt;a href="https://github.com/dependabot/dependabot-core?tab=readme-ov-file#license"&gt;a license&lt;/a&gt; that doesn't even appear on the SPDX license list.&lt;/p&gt;

&lt;p&gt;Renovate is also brilliantly set up as a community project, where they're shipping hundreds of PRs a month, alongside managing the community really well. I've seen a few things change in the last few years I've been more actively contributing, and it's a really well run project and an indication of something I'd love to be able to replicate at some point!&lt;/p&gt;

&lt;p&gt;It also helps that &lt;a href="https://mend.io"&gt;Mend&lt;/a&gt;, the company behind Renovate, invests a fair bit of time and money into development of the project, as well as their commercial offerings on top of it, which continue to make the project sustainable and remain Free and Open.&lt;/p&gt;

&lt;h2&gt;
  
  
  Great documentation
&lt;/h2&gt;

&lt;p&gt;Following on from the excellent community and maintainer contributions alike, there's also some really excellent work on a technical writing and documentation point of view, which makes a lot of tasks straightforward to solve.&lt;/p&gt;

&lt;p&gt;If there's something a little more complex or custom than the docs can offer, it's usually something that can be answered by the community in a GitHub Discussion, and likely could turn into a docs improvement, if necessary.&lt;/p&gt;

&lt;p&gt;There's even a great &lt;a href="https://docs.renovatebot.com/bot-comparison/"&gt;comparison table between Renovate and other dependency update bots&lt;/a&gt;, as well as &lt;a href="https://docs.renovatebot.com/upgrade-best-practices/"&gt;tips on how best to update your projects&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I've recently discovered a few pages and features that I wasn't aware, just by going through the docs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overall
&lt;/h2&gt;

&lt;p&gt;In summary, there's just so much that makes Renovate a greater choice than any of the alternatives, and I'm sure I could talk about more things that make it great.&lt;/p&gt;

&lt;p&gt;Whether you self-host it for maximum control (such as being able to access internal artifact registries), or run the hosted app for ease of operations, or just run it from the command-line once in a while, it can be hugely useful to your experience as an engineer.&lt;/p&gt;

&lt;p&gt;I hope you'll check it out!&lt;/p&gt;

</description>
      <category>renovate</category>
      <category>dependabot</category>
      <category>blogumentation</category>
      <category>snyk</category>
    </item>
    <item>
      <title>Lessons learned since posting my salary history publicly</title>
      <dc:creator>Jamie Tanna</dc:creator>
      <pubDate>Thu, 19 Jan 2023 11:45:57 +0000</pubDate>
      <link>https://dev.to/jamietanna/lessons-learned-since-posting-my-salary-history-publicly-5055</link>
      <guid>https://dev.to/jamietanna/lessons-learned-since-posting-my-salary-history-publicly-5055</guid>
      <description>&lt;p&gt;This post originally appeared &lt;a href="https://www.jvt.me/posts/2022/09/21/year-later-salary-history/"&gt;on my personal website&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Just over a year ago, I did something quite "out there", even for me, and I posted my &lt;a href="https://www.jvt.me/salary/"&gt;salary history publicly&lt;/a&gt;. This was accompanied by &lt;a href="https://www.jvt.me/posts/2021/09/09/public-salary-history/"&gt;a blog post&lt;/a&gt; to explain why I was doing it, and it's certainly been popular.&lt;/p&gt;

&lt;p&gt;When I first posted it, I made a note to myself to come back in a year, and see whether anything had changed, as well as to look back on some of the events that happened immediately after my posting, as it certainly made life interesting in the month or so following the post. I &lt;a href="https://www.jvt.me/posts/2021/10/13/what-learned-sharing-salary-publicly/"&gt;wrote up&lt;/a&gt; a lightning talk I did the month after, but this should give a bit more insight on further reflection.&lt;/p&gt;

&lt;p&gt;The usual caveats apply of the fact that this is a personal post, detailing personal experiences, and doesn't represent the views of any employers. I have also made efforts to remove a number of key details, which would tell a more realistic story, but are probably best told in person, rather than on the Internet.&lt;/p&gt;

&lt;h1&gt;
  
  
  How many people have seen it?*
&lt;/h1&gt;

&lt;p&gt;Probably one of the key things you, dear reader, want to know is how many people have seen the page?&lt;/p&gt;

&lt;p&gt;I love the dopamine rush of watching my analytics climb up after posting a new post, or trying to work out where referrers are coming from when I see a sudden spike in hits, and I will always have my analytics open in a window on my desktop, so I can see what's going on at the moment.&lt;/p&gt;

&lt;p&gt;So how many people have seen this? My first caveat for these numbers is that privacy-protecting browsers and extensions often block it (which is absolutely fine, by the way!) so these numbers are definitely not as many as it's actually gotten, it's just based on how many people don't block my analytics.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;tr&gt;
    &lt;th&gt;Page&lt;/th&gt;
    &lt;th&gt;Number of views&lt;/th&gt;
    &lt;th&gt;% of overall site views (between 2021-09-09 and 2022-09-21)&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;a href="https://www.jvt.me/salary/"&gt;Salary page&lt;/a&gt;&lt;/td&gt;
    &lt;td&gt;11818&lt;/td&gt;
    &lt;td&gt;4.1&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;a href="https://www.jvt.me/posts/2021/09/09/public-salary-history/"&gt;Salary blog post&lt;/a&gt;&lt;/td&gt;
    &lt;td&gt;3035&lt;/td&gt;
    &lt;td&gt;1.1&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One of the most interesting things is how many direct hits I get on the page - it's often not discovered on my site's header, or via the feed, but it's by someone either arriving through a privacy-preserving referrer, or they're here by a direct link someone else has sent them. Probably the most organic way of building traffic I've ever had, including being featured on a podcast, and in several newsletters!&lt;/p&gt;

&lt;h1&gt;
  
  
  I got a lot of (private) thanks
&lt;/h1&gt;

&lt;p&gt;In the days after posting it, I received loads of private messages from folks, a good number from underrepresented backgrounds, to say thank you for posting it, and that it's really been helpful for them. I also know of &lt;em&gt;at least&lt;/em&gt; 3 people who've used it to get a considerably better paying job, which is really amazing.&lt;/p&gt;

&lt;p&gt;I'd love to hear if it's been great for you, too.&lt;/p&gt;

&lt;h1&gt;
  
  
  It's got more people sharing theirs
&lt;/h1&gt;

&lt;p&gt;Something really awesome is that since I posted my blog post, I've had a number of other people in the tech community sharing their own salaries. I know of at least 5 people who've done it off the back of my post, which to be honest is really quite cool. It's nice to have been able to nudge a bit of change.&lt;/p&gt;

&lt;p&gt;I'm capturing them &lt;a href="https://www.jvt.me/tags/salary/"&gt;by tagging them with my &lt;code&gt;salary&lt;/code&gt; tag&lt;/a&gt; (although I will caveat that it is included with a lot of other posts, sorry it's not as discoverable!) and hope to have pages of these in the future!&lt;/p&gt;

&lt;h1&gt;
  
  
  Didn't check legality
&lt;/h1&gt;

&lt;p&gt;In my usual way of living my life, I didn't quite consider the consequences of what I was doing, I'd just got it in my head that I wanted to do it, so I did it.&lt;/p&gt;

&lt;p&gt;It wasn't until it was being actively discussed on the Tech Nottingham Slack that I realised it &lt;em&gt;could&lt;/em&gt; have been illegal to talk about 😅 Fortunately, it was all OK - and I double checked in my contract - but not ideal to be finding that out after it's already been read by quite a few folks.&lt;/p&gt;

&lt;h1&gt;
  
  
  People are more comfortable sharing privately than publicly
&lt;/h1&gt;

&lt;p&gt;Something I completely appreciate, and massively applaud, is that people &lt;em&gt;are&lt;/em&gt; still talking salary, just not publicly. Talking about topics like this is hard even with friends, let alone putting it out for the whole world to see.&lt;/p&gt;

&lt;p&gt;I know a few people who've said that they're worried it comes off as if they're "showing off", or that they'll be devalued as a person because their salary is lower than someone else's.&lt;/p&gt;

&lt;p&gt;It's absolutely a difficult one to deal with, and I guess if you can get yourself over that, it's great but if not, that's also OK. But it's still awesome that a lot of people are talking about salaries with friends, and hopefully it's helping more people bridge the topic.&lt;/p&gt;

&lt;h1&gt;
  
  
  Probably(?) not been bad for me
&lt;/h1&gt;

&lt;p&gt;So far, I don't think I've been negatively affected by the move. It didn't seem to block me moving jobs, and I've not had anything explicitly saying it's bad, but it may have been causing people to look down on me behind-the-scenes, and I wouldn't know.&lt;/p&gt;

&lt;p&gt;I asked companies about whether they were comfortable with me sharing salary details when applying - if they'd not already done their background research on me -  and they were happy with it.&lt;/p&gt;

&lt;p&gt;I would say that one thing I as an employee bring to the table is a level of transparency, both internally and externally, and it's nice to be in companies that value this, whether it's my salary or talking about what I'm working on.&lt;/p&gt;

&lt;h1&gt;
  
  
  Wider impact
&lt;/h1&gt;

&lt;p&gt;Unfortunately I can't take the credit for California deciding to require salary ranges on job applications, but I can definitely take some wins closer to home.&lt;/p&gt;

&lt;p&gt;I know that the Nottingham job market was affected by my post, as suddenly a lot of recruiters knew exactly what salary and progression looked like elsewhere, as well as people looking at moving elsewhere having more of an idea about what that would be like.&lt;/p&gt;

&lt;p&gt;There's definitely a company in Nottingham that started to discuss their salary ranges being put publicly on job posts after my post, but I've not had a chance to check if it was done.&lt;/p&gt;

&lt;h1&gt;
  
  
  Great for current employers
&lt;/h1&gt;

&lt;p&gt;I would also say that generally his has been positive for my employers.&lt;/p&gt;

&lt;p&gt;When I worked in the government, our salary ranges are public and transparent, and it's really great to make things fair for candidates and employees alike. Putting my individual salary on top of that didn't help too much, because people could guess where in the salary band I'd be landing, but in a private company, it makes a lot more of a difference.&lt;/p&gt;

&lt;p&gt;At Deliveroo, we compensate exceptionally well in terms of salary, so having that extremely public, as well as the submitted salary information on sites like Glassdoor, has been - from what I've been told - positive for the company, and convincing more folks to come work for us. It also helps that we've got some great tech, great problems, and you can spend most of your days delivering value to customers 🤓&lt;/p&gt;

&lt;p&gt;There are things like &lt;code&gt;levels.fyi&lt;/code&gt;, Glassdoor and Google Sheet of (mostly US-based) salaries going around, but it's nice to have other options, to see what you could get compensation wise.&lt;/p&gt;

&lt;h1&gt;
  
  
  Does it make negotiation harder?
&lt;/h1&gt;

&lt;p&gt;One concern people have is that if they've got their current salary, they believe that negotiating for a raise/new job is harder.&lt;/p&gt;

&lt;p&gt;I'll definitely defer to someone who's well versed in negotiation - there are some great workshops out there! - but I'll say for me, I'm privileged and comfortable being a bit more entitled in the world.&lt;/p&gt;

&lt;p&gt;I did find it difficult at first going into a couple of job applications, where they requested a range that you'd be interested in getting, but I increased the numbers a good chunk from what I was currently getting, and that worked out well 😁&lt;/p&gt;

&lt;p&gt;But remember that just because they know what you're currently being paid, doesn't make it like they have any more power over you - if, before you've even started, they want to knock your salary down as much as possible, it's unlikely to get better the longer you work there.&lt;/p&gt;

&lt;h1&gt;
  
  
  The "counter offer"
&lt;/h1&gt;

&lt;p&gt;One thing that I found out in my exit interview at Capital One is that the mistake I made while posting this was to call something a "counter offer" from Capital One. It was noted that this wasn't a counter offer, it was a "your salary is being updated anyway for competitiveness", but I'd misinterpreted the exact wording, as it sounded like a counter at the time.&lt;/p&gt;

&lt;p&gt;Unfortunately by the time I'd been told, the damage had been done, and I'd caused some awkward conversations internally about counter offers. I've now removed the reference to this "counter offer", but thought it should be talked about.&lt;/p&gt;

&lt;h1&gt;
  
  
  Take it with a pinch of salt
&lt;/h1&gt;

&lt;p&gt;As often comes up in conversations about salary - take the numbers with a pinch of salt. I've had a number of US-based folks call me woefully underpaid at £90k fully remote in Nottingham, whereas looking at that compared to folks who are also Senior Engineers at Nottingham-based companies, it ain't me being underpaid 🤑&lt;/p&gt;

&lt;p&gt;Also remember that the salary doesn't necessarily take into account things like workload, personal development time, and benefits - use it as a guiding factor, not the be-all-and-end-all!&lt;/p&gt;

&lt;h1&gt;
  
  
  Regrets
&lt;/h1&gt;

&lt;p&gt;Hah, tricked you - I don't have any! I've found it to be a really good experience, and am really glad that I've been able to enact some change.&lt;/p&gt;

&lt;p&gt;There's some interesting conversations &lt;a href="https://lobste.rs/s/bf54tf/thoughts_on_job_pay_history_page_on"&gt;on Lobsters&lt;/a&gt; about salary history pages that may be good as some further reading.&lt;/p&gt;

&lt;p&gt;Here's to the rest of my career being as transparent!&lt;/p&gt;

</description>
      <category>salary</category>
      <category>career</category>
    </item>
    <item>
      <title>Deploying a Branch to Netlify on the Command-Line</title>
      <dc:creator>Jamie Tanna</dc:creator>
      <pubDate>Wed, 03 Jun 2020 20:02:15 +0000</pubDate>
      <link>https://dev.to/jamietanna/deploying-a-branch-to-netlify-on-the-command-line-44pg</link>
      <guid>https://dev.to/jamietanna/deploying-a-branch-to-netlify-on-the-command-line-44pg</guid>
      <description>&lt;p&gt;This post originally appeared &lt;a href="https://www.jvt.me/posts/2020/06/03/netlify-cli-branch/"&gt;on my personal website&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'm very excited to say that the Netlify CLI tool (&lt;a href="https://github.com/netlify/cli"&gt; netlify/cli&lt;/a&gt;) &lt;a href="https://github.com/netlify/cli/pull/907"&gt;now&lt;/a&gt; has the ability to deploy a branch on the command-line.&lt;/p&gt;

&lt;p&gt;This has been a feature request since &lt;a href="https://github.com/netlify/cli/issues/44"&gt;at least 2018&lt;/a&gt; and has been greatly anticipated from the community, and I've been wanting to use it for some time when using &lt;a href="https://dev.to%7B%7B&amp;lt;%20ref%202018-04-12-gitlab-ci-netlify%20&amp;gt;%7D%7D"&gt;GitLab CI&lt;/a&gt; pipelines.&lt;/p&gt;

&lt;p&gt;As of &lt;a href="https://www.npmjs.com/package/netlify-cli/v/2.53.0"&gt;netlify-cli@2.53.0&lt;/a&gt;, it's now possible to deploy using the &lt;code&gt;-b $branchName&lt;/code&gt; flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;% netlify deploy -b wibble
Deploy path:        /home/jamie/workspaces/talks/public
Configuration path: /home/jamie/workspaces/talks/netlify.toml
Deploying to draft URL...
✔ Finished hashing 286 files
✔ CDN requesting 0 files
✔ Finished uploading 0 assets
✔ Deploy is live!

Logs:              https://app.netlify.com/sites/epic-wozniak-9aa019/deploys/5ed7eaedb88cedbb42a9d341
Website Draft URL: https://wibble--epic-wozniak-9aa019.netlify.app

If everything looks good on your draft URL, deploy it to your main site URL with the --prod flag.
netlify deploy --prod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is super exciting, and will help help folks deploying from Continuous Integration platforms, or with use cases where they don't want to use Netlify's Webhook integrations.&lt;/p&gt;

</description>
      <category>netlify</category>
    </item>
    <item>
      <title>Generating HMAC Signatures on the Command Line with OpenSSL</title>
      <dc:creator>Jamie Tanna</dc:creator>
      <pubDate>Fri, 21 Feb 2020 09:46:46 +0000</pubDate>
      <link>https://dev.to/jamietanna/generating-hmac-signatures-on-the-command-line-with-openssl-1h1l</link>
      <guid>https://dev.to/jamietanna/generating-hmac-signatures-on-the-command-line-with-openssl-1h1l</guid>
      <description>&lt;p&gt;This post originally appeared &lt;a href="https://www.jvt.me/posts/2020/02/21/openssl-hmac/"&gt;on my personal website&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Proving authenticity of a message is important, even over transport methods such as HTTPS, as we may not be able to require full end-to-end encryption. One such method of producing a signature is using HMAC with a shared secret.&lt;/p&gt;

&lt;p&gt;For instance, let us say that we want to use SHA256 as the hashing algorithm.&lt;/p&gt;

&lt;p&gt;If using Java, we could write code similar to the below, leveraging the &lt;a href="https://mvnrepository.com/artifact/commons-codec/commons-codec"&gt;commons-codec&lt;/a&gt; project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.apache.commons.codec.binary.Base64&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.apache.commons.codec.digest.HmacAlgorithms&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.apache.commons.codec.digest.HmacUtils&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;digest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;Base64&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;encodeBase64String&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;HmacUtils&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HmacAlgorithms&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HMAC_SHA_256&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"secret-key-here"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hmac&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"value-to-digest"&lt;/span&gt;&lt;span class="o"&gt;)));&lt;/span&gt;
&lt;span class="c1"&gt;// G73zFnFYggHRpmwuRFPgch6ctqEfyhZu33j5PQWYm+4=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, this doesn't help when we want to script this from the command-line, and isn't as portable.&lt;/p&gt;

&lt;p&gt;To do this we can utilise &lt;code&gt;openssl&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"value-to-digest"&lt;/span&gt; | openssl dgst &lt;span class="nt"&gt;-sha256&lt;/span&gt; &lt;span class="nt"&gt;-hmac&lt;/span&gt; &lt;span class="s2"&gt;"secret-key-here"&lt;/span&gt; &lt;span class="nt"&gt;-binary&lt;/span&gt; | openssl enc &lt;span class="nt"&gt;-base64&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt;
// G73zFnFYggHRpmwuRFPgch6ctqEfyhZu33j5PQWYm+4&lt;span class="o"&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
  </channel>
</rss>
