In our applications we have a version file that has three variables that are then joined to create a string that can be used for the semantic version.
The file looks like:
# frozen_string_literal: true
major = 0
minor = 1
patch = 0
PORTAL_VERSION = [major, minor, patch].join('.')
And then we update it using the following from our CI server:
@version = '0.1.1' # this is passed from somewhere
puts 'updating version'
version_file = File.open("version.rb").read
version = @version.split('.')
version_file = version_file.gsub(/(major = \w)/, "major = #{version[0]}")
version_file = version_file.gsub(/(minor = \w)/, "minor = #{version[1]}")
version_file = version_file.gsub(/(patch = \w)/, "patch = #{version[2]}")
File.open('version.rb', 'wb') { |file| file.write(version_file) }
puts "updated version to #{@version}"
Is there a better way to do the replacement using the regex? As by having to find each line and then replace it feels a little dirty, plus if there was or wasn't spaces between the variable name and value it wouldn't work. So it feels a little fragile.
1 Answer 1
There might be two easier options:
Generate the file using a template file something like the following
major = {{major}} minor = {{minor}} patch = {{patch}}
that has strings that are easy to search for. You could also use ERB to generate the file.
Put the logic in your
version.rb
file something like:PORTAL_VERSION = '1.2.3' major, minor, path = PORTAL_VERSION.split('.').map(&:to_i)
This way you would just have to replace the first line.
If you want to do it using your logic I would change the regex from
/(patch = \w)/
to/(patch\s*=\s*\w+)/
this would handle extra whitespace and version numbers bigger than 9Note you can also do variable substitution in Regexes so you could write your code as:
['major', 'minor', 'patch'].each.with_index do |key, i| version_file.sub!(/(#{key}\s*=\s*\w+)/, "#{key} = #{version[i]}") end
Note that gsub
isn't necessary as you only expect one occurrence.
version.rb
from scratch instead of trying to edit it? \$\endgroup\$