<?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: Brett Ryan</title>
    <description>The latest articles on DEV Community by Brett Ryan (@brettryan).</description>
    <link>https://dev.to/brettryan</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%2F589713%2F236d611b-9faf-4983-9074-541ebca9a7cc.png</url>
      <title>DEV Community: Brett Ryan</title>
      <link>https://dev.to/brettryan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/brettryan"/>
    <language>en</language>
    <item>
      <title>Keeping Dependencies Current</title>
      <dc:creator>Brett Ryan</dc:creator>
      <pubDate>Fri, 21 Aug 2026 13:50:41 +0000</pubDate>
      <link>https://dev.to/brettryan/keeping-dependencies-current-30la</link>
      <guid>https://dev.to/brettryan/keeping-dependencies-current-30la</guid>
      <description>&lt;p&gt;Working on a project of almost any size will almost always require the use of external dependencies that can often put us in a position of alert fatigue where we might have to chase our projects for CVE's that have been announced where it can feel like constantly plugging a dam. Using a technique to automate this chore which can be reviewed at a later date is extremely helpful.&lt;/p&gt;

&lt;p&gt;There are widely available tools in the ecosystem, however; I'm presenting this as a fun exercise to demonstrate how we can get in touch with the machinery that we can implement to do this.&lt;/p&gt;

&lt;p&gt;What we will do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;a href="https://start.spring.io" rel="noopener noreferrer"&gt;start.spring.io&lt;/a&gt; to create a simple project.&lt;/li&gt;
&lt;li&gt;Configure pom project with specific dependency rules.&lt;/li&gt;
&lt;li&gt;Create &lt;code&gt;dependencies.sh&lt;/code&gt; script.&lt;/li&gt;
&lt;li&gt;Add GitLab CI job to perform automatic dependency checks on a &lt;code&gt;chore/version-updates&lt;/code&gt; branch.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;h4&gt;
  
  
  Full Script
&lt;/h4&gt;

&lt;p&gt;You can obtain a copy of the &lt;a href="https://gitlab.com/-/snippets/5986856" rel="noopener noreferrer"&gt;full script&lt;/a&gt; which has been published as a public GitLab snippet.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Create Your Project
&lt;/h2&gt;

&lt;p&gt;Using the spring starter at &lt;a href="https://start.spring.io" rel="noopener noreferrer"&gt;start.spring.io&lt;/a&gt;, create a maven based project. As we're using the &lt;a href="https://www.mojohaus.org/versions-maven-plugin/" rel="noopener noreferrer"&gt;versions-maven-plugin&lt;/a&gt; we will require this to be a maven project.&lt;/p&gt;

&lt;p&gt;You can use &lt;a href="https://start.spring.io/#!type=maven-project&amp;amp;language=java&amp;amp;platformVersion=4.0.6&amp;amp;packaging=jar&amp;amp;configurationFileFormat=properties&amp;amp;jvmVersion=26&amp;amp;groupId=com.example&amp;amp;artifactId=demo&amp;amp;packageName=com.example.demo&amp;amp;dependencies=" rel="noopener noreferrer"&gt;this template&lt;/a&gt; which is a bookmark of a spring 4.0.6 project using maven and JDK 26.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure Project to Ignore pre-releases
&lt;/h2&gt;

&lt;p&gt;I've found that in maven central, some projects will release release candidates, milestones, alpha and other releases that I do not want to have my dependency management script to try an upgrade to. My original approach to solve this was to set the &lt;code&gt;maven.version.ignore&lt;/code&gt; maven property to ignore these&lt;br&gt;
patterns, like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;properties&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;maven.version.ignore&amp;gt;&lt;/span&gt;(?i).*[\-\.](m|rc|dev|alpha|beta)[\-\.]?[0-9]*&lt;span class="nt"&gt;&amp;lt;/maven.version.ignore&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;processDependencyManagementTransitive&amp;gt;&lt;/span&gt;${processDependencyManagementTransitive}&lt;span class="nt"&gt;&amp;lt;/processDependencyManagementTransitive&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/properties&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works well, however; if you want to have rules where you may want to be using pre-releases or milestones from specific vendors, i.e. you may be testing the newest spring milestones, you will need to extend this by adding a &lt;code&gt;ruleSet&lt;/code&gt; to the &lt;code&gt;build/plugins&lt;/code&gt; section of your pom.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;build&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;plugins&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.codehaus.mojo&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;versions-maven-plugin&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ruleSet&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;rules&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;rule&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;ignoreVersions&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;ignoreVersion&amp;gt;&lt;/span&gt;
                  &lt;span class="nt"&gt;&amp;lt;type&amp;gt;&lt;/span&gt;regex&lt;span class="nt"&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
                  &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;(?i).*&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"m|rc|dev|alpha|beta"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;\-\.&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;[\-\.]?[0-9]*&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/ignoreVersion&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;/ignoreVersions&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/rule&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;rule&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.boot&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-boot-starter-parent&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/rule&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;rule&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.modulith&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-modulith-bom&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/rule&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/rules&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/ruleSet&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;processDependencyManagementTransitive&amp;gt;&lt;/span&gt;${processDependencyManagementTransitive}&lt;span class="nt"&gt;&amp;lt;/processDependencyManagementTransitive&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/plugins&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/build&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that I've also set the property &lt;code&gt;processDependencyManagementTransitive&lt;/code&gt;, keep this in your &lt;code&gt;properties&lt;/code&gt; section as our script will set this later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependency Update Script
&lt;/h2&gt;

&lt;p&gt;We will now create a script that will perform the dependency update check and optionally perform a &lt;code&gt;git commit&lt;/code&gt; if updates were found.&lt;/p&gt;

&lt;p&gt;There are two sets of maven goals we could use&lt;/p&gt;

&lt;p&gt;To show only:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;versions:display-dependency-updates&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;versions:display-plugin-updates&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;versions:display-property-updates&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or, to perform the updates my modifying the pom.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;versions:update-parent&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;versions:update-properties&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;versions:use-latest-versions&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Refer to the &lt;a href="https://www.mojohaus.org/versions/versions-maven-plugin/index.html" rel="noopener noreferrer"&gt;versions-maven-plugin&lt;/a&gt; documentation for more on what these goals do.&lt;/p&gt;

&lt;p&gt;We will write a script that gives us the following capabilities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Usage: dependencies.sh [-cCsStu]

-c  : Perform git commit opening editor for review
-C  : Perform git commit
-s  : Don't perform snapshot updates
-S  : Force update snapshot updates
-t  : Process transitive dependencies
-u  : Perform update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this script, we will begin with the setup and a &lt;code&gt;getopts&lt;/code&gt; block that takes these command line arguments.&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;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class="nv"&gt;goals&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"
  versions:display-dependency-updates
  versions:display-plugin-updates
  versions:display-property-updates
"&lt;/span&gt;

&lt;span class="nv"&gt;snaps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nv"&gt;margs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;

&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;getopts &lt;/span&gt;cChsStu OPTION&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  case&lt;/span&gt; &lt;span class="nv"&gt;$OPTION&lt;/span&gt; &lt;span class="k"&gt;in
    &lt;/span&gt;h&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"
Usage: &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt; [-cCsStu]

-c  : Perform git commit opening editor for review
-C  : Perform git commit
-s  : Don't perform snapshot updates
-S  : Force update snapshot updates
-t  : Process transitive dependencies
-u  : Perform update
"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
        &lt;span class="nb"&gt;exit &lt;/span&gt;1
        &lt;span class="p"&gt;;;&lt;/span&gt;
    c&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="nv"&gt;commit_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;edit &lt;span class="p"&gt;;;&lt;/span&gt;
    C&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="nv"&gt;commit_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;perform &lt;span class="p"&gt;;;&lt;/span&gt;
    s&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="nv"&gt;snaps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-nsu"&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
    S&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="nv"&gt;snaps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-U"&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
    t&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="nv"&gt;margs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;margs&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; -DprocessDependencyManagementTransitive=true"&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
    u&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="nv"&gt;goals&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"
          versions:update-parent
          versions:update-properties
          versions:use-latest-versions
        "&lt;/span&gt;
        &lt;span class="p"&gt;;;&lt;/span&gt;
  &lt;span class="k"&gt;esac&lt;/span&gt;
&lt;span class="k"&gt;done
&lt;/span&gt;&lt;span class="nb"&gt;shift&lt;/span&gt; &lt;span class="k"&gt;$((&lt;/span&gt;OPTIND &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows the user to either view (default) or update (-u). When viewing the caller can test for transitive dependency updates with &lt;code&gt;-t&lt;/code&gt;. We can also commit changes automatically with &lt;code&gt;-c&lt;/code&gt; to open an editor or have &lt;code&gt;-C&lt;/code&gt; perform the commit.&lt;/p&gt;

&lt;p&gt;In order to capture the dependencies that were updated, we will &lt;code&gt;tee&lt;/code&gt; the output from maven (using &lt;code&gt;./mvnw&lt;/code&gt; here) to allow us to parse the content when complete.&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;mvn_log&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;mktemp&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Couldn't create temp file"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;trap&lt;/span&gt; &lt;span class="s1"&gt;'rm -f "$mvn_log"'&lt;/span&gt; EXIT

&lt;span class="nb"&gt;echo&lt;/span&gt; ./mvnw &lt;span class="nv"&gt;$snaps&lt;/span&gt; &lt;span class="nv"&gt;$margs&lt;/span&gt; &lt;span class="nv"&gt;$goals&lt;/span&gt;
./mvnw &lt;span class="nv"&gt;$snaps&lt;/span&gt; &lt;span class="nv"&gt;$margs&lt;/span&gt; &lt;span class="nv"&gt;$goals&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nv"&gt;$mvn_log&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we will parse the output file to list off all our changes. A regular expression here formats the content into the following form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;- &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;DEPENDENCY&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;: &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;FROM&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt; -&amp;gt; &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;TO&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This format will strip out property managed versions such as &lt;code&gt;${spring-modulith.version}&lt;/code&gt; and replace it with &lt;code&gt;spring-modulith&lt;/code&gt; to make our git commit more readable.&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;changes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;
  &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"Updated "&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$mvn_log&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;|&lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'s/^.* Updated (\$\{)?([^.}]*)(.version)?\}? from (.*) to (.*)$/- \2: \4 -&amp;gt; \5/'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;h4&gt;
  
  
  Regular Expression Deep Dive
&lt;/h4&gt;

&lt;p&gt;We're creating an expression that looks for lines that have the following core pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;^.* Updated&lt;/code&gt;: Looks from the start of line until we reach the word &lt;code&gt;Updated&lt;/code&gt; with a leading and trailing space.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(\$\{)?&lt;/code&gt;: May contain the sequence &lt;code&gt;${&lt;/code&gt; which we want to ignore so must remember to skip this capture group.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;([^.}])&lt;/code&gt;: Capture all characters that are not &lt;code&gt;'.'&lt;/code&gt; or &lt;code&gt;'}'&lt;/code&gt;, there is a slight issue with this in that if you use a property that doesn't end in &lt;code&gt;.version&lt;/code&gt; but does have a dot &lt;code&gt;'.'&lt;/code&gt; in it's name, it might not be processed correctly.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(.version)?\}?&lt;/code&gt;: skip the optional phrase &lt;code&gt;.version&lt;/code&gt; and the optional &lt;code&gt;}&lt;/code&gt; character.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;from (.*) to (.*)$&lt;/code&gt; capture the from and to versions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If all these sequences match the line, it will be replaced with the capture groups we are interested in &lt;code&gt;- \2: \4 -&amp;gt; \5&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can now test for this to see if there were any changes detected, if there are, we can then perform the determined git commit option chosen by the caller.&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="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$changes&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"No changes detected to commit."&lt;/span&gt;
&lt;span class="k"&gt;else
  &lt;/span&gt;&lt;span class="nv"&gt;commit_msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"[chore] Dependency and plugin updates

&lt;/span&gt;&lt;span class="nv"&gt;$changes&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$commit_msg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .git/COMMIT_EDITMSG
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$commit_mode&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; --- Changes staged for commit ---"&lt;/span&gt;
  &lt;span class="k"&gt;else
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;--- Committing Changes ---"&lt;/span&gt;
    git add pom.xml &lt;span class="k"&gt;**&lt;/span&gt;/pom.xml 2&amp;gt;/dev/null
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$commit_mode&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"edit"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
      &lt;/span&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$commit_msg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;
    &lt;span class="k"&gt;else
      &lt;/span&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$commit_msg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;fi
  fi
fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setup GitLab Automation
&lt;/h2&gt;

&lt;p&gt;This could now be setup on an automated &lt;code&gt;chore/version-updates&lt;/code&gt; branch to be performed once a week or on a schedule of your choosing.&lt;/p&gt;

&lt;p&gt;Configure your &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; with blocks similar to the following, your configuration may look different, however; in my case I use GraalVM CE edition for my use-cases.&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;.maven-base&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="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io/graalvm/jdk-community:25&lt;/span&gt;
    &lt;span class="na"&gt;entrypoint&lt;/span&gt;&lt;span class="pi"&gt;:&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="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;maven-shared-cache"&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.m2/repository&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.sonar/cache&lt;/span&gt;

&lt;span class="na"&gt;version_updates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.maven-base&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;microdnf install -y git&lt;/span&gt;

    &lt;span class="s"&gt;git config --global user.name "GitLab CI Bot"&lt;/span&gt;
    &lt;span class="s"&gt;git config --global user.email "brett.ryan+gitlab-bot@gmail.com"&lt;/span&gt;
    &lt;span class="s"&gt;git remote set-url origin https://oauth2:${GITLAB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git&lt;/span&gt;

    &lt;span class="s"&gt;./dependencies.sh -u -C&lt;/span&gt;
    &lt;span class="s"&gt;if [[ "$(git rev-list --count @{u}..HEAD)" != "0" ]]; then&lt;/span&gt;
      &lt;span class="s"&gt;git pull origin ${CI_COMMIT_REF_NAME} --rebase&lt;/span&gt;
      &lt;span class="s"&gt;git push origin HEAD:${CI_COMMIT_REF_NAME}&lt;/span&gt;
    &lt;span class="s"&gt;fi&lt;/span&gt;

  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$CI_PIPELINE_SOURCE&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;==&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"schedule"&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$CI_COMMIT_BRANCH&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;==&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"chore/version-updates"'&lt;/span&gt;
      &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;never&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;h4&gt;
  
  
  GITLAB_TOKEN Best Practices
&lt;/h4&gt;

&lt;p&gt;Ensure that you create a masked Group Access Token or Project Access Token for &lt;code&gt;GITLAB_TOKEN&lt;/code&gt;. This token will need to have &lt;code&gt;write_repository&lt;/code&gt; access.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this script we take advantage of the script using the &lt;code&gt;-C&lt;/code&gt; option to perform the automated commit, which; can then be detected with &lt;code&gt;git rev-list --count @{u}..HEAD&lt;/code&gt; to detect if changes were made. If they were, then we can then push the commits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;There are several ways you could progress this by having full regression tests performed, notifications to slack or teams to notify the development team when the branch has been updated.&lt;/p&gt;

&lt;p&gt;You could now integrate this into a release cycle where a QA manager performs validation and owns the &lt;code&gt;chore&lt;/code&gt; branch, and; what should be done in the negative scenario where there may be versions that are not desired? Would you make it a practice to include them into the &lt;code&gt;ruleSet&lt;/code&gt;? This could even be automated based on build failures.&lt;/p&gt;

</description>
      <category>java</category>
      <category>maven</category>
      <category>gitlabci</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
