Class: SemverVersioning

Inherits:
Object
  • Object
show all
Defined in:
lib/semantic_versioning.rb

Constant Summary collapse

SEMVER =
'semver'

Instance Method Summary collapse

Instance Method Details

#auto_update_local_semverObject

Method invoked to update multiple semvers locally. This will not update single semver. That has to be done manually



166
167
168
169
170
171
172
173
174
175
176
# File 'lib/semantic_versioning.rb', line 166

def auto_update_local_semver
  if(!Dir.exist?(VERSIONING) || File.exist?('.' + SEMVER))
    raise 'Error - local upgrade process only applies to projects with multiple semvers. If you have one semver at root level, please update it manually if needed. Do not invoke auto_update_local_semver task.'
  end
  updated_semver_with_version_state = fetch_updated_semver
  if updated_semver_with_version_state != nil
    update_dependent_semvers PRODUCT, VERSIONING, updated_semver_with_version_state[0], updated_semver_with_version_state[1]
  end

  display_local_changes_to_user
end

#auto_update_semver(project_name, semver_location, semver_file, semver_dimension) ⇒ Object

Method to be used from the upgrade project, to update single or multiple semvers on team city



155
156
157
158
159
160
161
162
163
# File 'lib/semantic_versioning.rb', line 155

def auto_update_semver project_name, semver_location, semver_file, semver_dimension
  Dir.chdir project_name if File.basename(Dir.pwd) != project_name
  if(semver_file.nil? || semver_file.strip == '' || semver_file == '.' + SEMVER)
    increment_version '.' + SEMVER, semver_dimension
  else
    increment_version File.join(semver_location, semver_file), semver_dimension
    update_dependent_semvers project_name, semver_location, semver_file, semver_dimension
  end
end

#create_semver_project_map(product, semver_location) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
# File 'lib/semantic_versioning.rb', line 187

def create_semver_project_map product, semver_location
  semver_project_map = Hash.new

  rake_list = get_file_list semver_location, SEMVER
  rake_list.each{ |rakefile|
    rake = rakefile.gsub "#{semver_location}/", ''
    project_name = rake.gsub '.' + SEMVER, ''
    semver_project_map[rake] = "#{product}.#{project_name}.csproj"
  }
  semver_project_map
end

#display_local_changes_to_userObject



11
12
13
14
15
16
# File 'lib/semantic_versioning.rb', line 11

def display_local_changes_to_user
  git_status = `git status -s`
  if (git_status != nil || git_status != GlobalConstants::EMPTY)
    puts '********** Local semver/s updated. Please commit the change.'
  end
end

#fetch_updated_semverObject



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/semantic_versioning.rb', line 18

def fetch_updated_semver

  updated_semver = get_update_semver_file_with_versions

  #for local run user did not increment any semver
  if updated_semver[3] == 0
    puts '*********** No semver incremented detected. ***********'
    return nil
  end

  version_remote = updated_semver[1].split('.')
  version_local = updated_semver[2].split('.')

  incremented = is_semver_incremented version_remote, version_local

  [updated_semver[0].gsub("#{VERSIONING}/", ''), incremented]
end

#get_branch_nameObject



96
97
98
99
100
101
102
103
# File 'lib/semantic_versioning.rb', line 96

def get_branch_name
  current_branch = ENV['GIT_BRANCH_NAME']
  if current_branch.nil?
    raise '********GIT_BRANCH_NAME environment variable required for local rake run. Cannot continue with build. Exiting..............********'
  else
    current_branch
  end
end

#get_current_version(path, semver) ⇒ Object



128
129
130
131
132
133
# File 'lib/semantic_versioning.rb', line 128

def get_current_version path, semver
  location = File.join path, semver
  content = File.read location
  current_version = get_semver_version content
  current_version
end

#get_file_list(path, extension) ⇒ Object



263
264
265
# File 'lib/semantic_versioning.rb', line 263

def get_file_list path, extension
  return Dir.glob("#{path}/*.#{extension}")
end

#get_project_dependencies(csproj) ⇒ Object

Find a given csproj reference in other projects in the solution



246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/semantic_versioning.rb', line 246

def get_project_dependencies csproj
  proj_files = Dir.glob '**/*.csproj'
  @unique_list = Array.new
  proj_files.each{ |file|
    doc = Nokogiri::XML File.read file
    nodes = doc.search 'ProjectReference'
    nodes.each { |node|
      ref_val = node['Include']
      id = ref_val.split('\\')[2]
      if id.eql? csproj
        @unique_list << file.split('/')[2]
      end
    }
  }
  @unique_list.uniq
end

#get_project_dependencies_semver_files(projects_dependencies, semver_project_map) ⇒ Object

get list of semver files for given project list



233
234
235
236
237
238
239
240
241
242
# File 'lib/semantic_versioning.rb', line 233

def get_project_dependencies_semver_files projects_dependencies, semver_project_map
  project_semver_map = semver_project_map.invert
  @values  = Array.new
  projects_dependencies.each { |dependency|
    if semver_project_map.value?(dependency)
      @values << project_semver_map[dependency]
    end
  }
  @values
end

#get_remote_nameObject



105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/semantic_versioning.rb', line 105

def get_remote_name
  remote_name = ENV['GIT_REMOTE_NAME']
  if remote_name.nil?
    raise '********GIT_REMOTE_NAME environment variable required for local rake run. Cannot continue with build. Exiting..............********'
  else
    @remote = `git remote -v`.split("\n")
    @remote.each { |val|
      if val =~ /#{remote_name}/
        return val.split(" ")[1].sub('.git', '')
      end
    }
  end
end

#get_repo_version(semver) ⇒ Object



119
120
121
122
123
124
125
126
# File 'lib/semantic_versioning.rb', line 119

def get_repo_version semver
  remote_name = get_remote_name
  branch_name = get_branch_name
  url = URLTEMPLATE % [remote_name, branch_name, semver]
  page_content = open url
  repo_version = get_semver_version page_content
  repo_version
end

#get_semver_version(content) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/semantic_versioning.rb', line 135

def get_semver_version content
  s = content.split("\n")
  val = ''
  s.each{ |i|
    if i.start_with?(':')
      x = i.split(': ')[1].strip
      x.gsub! "'", ''
      if x.length != 0
        val = val + x.to_s + '.'
      end
    end
  }
  val.chomp '.'
end

#get_update_semver_file_with_versionsObject



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/semantic_versioning.rb', line 36

def get_update_semver_file_with_versions
  count = 0
  semver_file = ''
  version_remote = ''
  version_local = ''

  semvers = get_file_list VERSIONING, SEMVER
  if semvers.empty?
    raise "************Error - no semver files found at #{VERSIONING}********"
  end

  semvers.each { |semver|
    v1 = get_repo_version semver
    v2 = get_current_version VERSIONING, semver.gsub("#{VERSIONING}/", '')
    if (!same_versions v1, v2)
      puts "#{semver} version changed"
      semver_file = semver
      version_remote = v1
      version_local = v2
      count = count + 1
    end
  }
  if count > 1
    raise '*********** Error - Version increment is expected in a single semver file and can be only one of major|minor|patch ************'
    return
  end

  [semver_file, version_remote, version_local, count]
end

#increment_version(semver_file, dimension) ⇒ Object

Increment the major, minor, or patch of the .semver file.



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/semantic_versioning.rb', line 200

def increment_version semver_file, dimension
  if dimension.nil?
    raise 'The parameter dimension is required to be one of : major | minor | patch'
  end
  semver = load_semver semver_file

  case dimension
  when 'major'
    semver.major += 1
    semver.minor =  0
    semver.patch =  0
  when 'minor'
    semver.minor += 1
    semver.patch =  0
  when 'patch'
    semver.patch += 1
  else
    raise "The parameter #{dimension} is invalid: major | minor | patch"
  end

  hash = "---\n:major: %s\n:minor: %s\n:patch: %s\n:special: '%s'\n:metadata: '%s'"
  value = hash % [semver.major, semver.minor, semver.patch, semver.special, semver.]
  File.write semver_file, value
end

#is_semver_incremented(version_remote, version_local) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/semantic_versioning.rb', line 66

def is_semver_incremented version_remote, version_local
  is_incremented = [version_local[0].to_i - version_remote[0].to_i > 0, version_local[1].to_i - version_remote[1].to_i > 0, version_local[2].to_i - version_remote[2].to_i > 0]

  if is_incremented[0]
    if (version_local[1] != 0 || version_local[2] != 0)
      raise 'Error - major version is incremented. Minor and Patch should be 0. Cannot continue build. Exiting....'
    end
  end

  if is_incremented[1]
    if is_incremented[0]
      raise 'Error - cannot increment both major and minor version. . Exiting....'
    end
  end

  if is_incremented[2]
    if(is_incremented[0] || is_incremented[1])
      raise 'Error - cannot increment major, minor and patch together. . Exiting....'
    end
  end

  if is_incremented[0]
    'major'
  elsif is_incremented[1]
    'minor'
  elsif is_incremented[2]
    'patch'
  end
end

#load_semver(path) ⇒ Object

load a sepcific semver (rather than generic .semver file



226
227
228
229
230
# File 'lib/semantic_versioning.rb', line 226

def load_semver path
  v = SemVer.new
  v.load path
  v
end

#open(url) ⇒ Object



7
8
9
# File 'lib/semantic_versioning.rb', line 7

def open url
  Net::HTTP.get(URI.parse url)
end

#same_versions(version1, version2) ⇒ Object



150
151
152
# File 'lib/semantic_versioning.rb', line 150

def same_versions version1, version2
  version1 == version2
end

#update_dependent_semvers(product, semver_location, semver_file, dimension) ⇒ Object



178
179
180
181
182
183
184
185
# File 'lib/semantic_versioning.rb', line 178

def update_dependent_semvers product, semver_location, semver_file, dimension
  semver_project_map = create_semver_project_map product, semver_location
  projects_dependencies =  get_project_dependencies semver_project_map[semver_file]
  semver_files = get_project_dependencies_semver_files projects_dependencies, semver_project_map
  semver_files.each { |semver|
    increment_version File.join(semver_location, semver), dimension
  }
end