a2zdeploy 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d26ef64a5e56fba85aad32a6716bc11d04edd861
4
- data.tar.gz: c846d6a9030f00ab41d8ba47cbf606a3c04bbec5
3
+ metadata.gz: 7ed53192adb1971f268124fc20fb11510ee31e06
4
+ data.tar.gz: b49b25d81f158ae3ad8420761aa5559fd6d2c2bf
5
5
  SHA512:
6
- metadata.gz: 5d5e93a79e70af4176b95434edfcc1fb5d83df3c9f8a8b6060a8f32065780f6461e79c551880f6b0a909aca305fb8a8616b1bc940c1e7acb2fecad1a487ed4fb
7
- data.tar.gz: 3c95f5c78ed0915dbfe811b57f316d0a87dee466e2e197d810756edbfe9e5e2e7380c5e22a0052a1ed32a0d0d7cebbbff39a037debed93cd2f4c01fa256cacbb
6
+ metadata.gz: cc2e1fdf5f6d4681709a6c9b6c3d34b4e137708acd381b4317ba168609379c5ad41a1379a0604060644924d73491503258aafe29ef487c56bf804088712550a1
7
+ data.tar.gz: f83acdd75516f2c3c373b8c5bb26c8cd74bb51a8f2ffdb903c84bb2a55de864d87c97a4a081fe8af86c373796f85634aa7ef6964f4884d5fb5fb90223cfa3adb
@@ -1,12 +1,12 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'a2zdeploy'
3
- s.version = '1.0.2'
4
- s.date = '2015-12-30'
3
+ s.version = '1.0.3'
4
+ s.date = '2016-01-19'
5
5
  s.summary = 'Given a project dependency chain, updates versions, builds, tests, manages service and cloud settings as well as build environment configuration'
6
6
  s.description = 'Automated Upgrades Gem. Provides version upgrades, build and deployment configuration management'
7
7
  s.authors = ['Suresh Batta']
8
8
  s.email = 'subatta@hotmail.com'
9
- s.files = Dir['{lib}/**/*'] + ['a2zdeploy.gemspec', 'ReadMe.md']
9
+ s.files = Dir['{test,lib,rakefile.rb}/**/*'] + ['a2zdeploy.gemspec', 'ReadMe.md']
10
10
  s.homepage = 'http://rubygems.org/gems/a2zdeploy'
11
11
  s.license = 'MIT'
12
12
  end
@@ -1,5 +1,5 @@
1
1
  require_relative 'dependency_tree'
2
- require_relative 'globalconstants'
2
+ require_relative 'global_constants'
3
3
  require_relative 'proget_api.rb'
4
4
  require_relative 'teamcity_api.rb'
5
5
  require_relative 'github_api.rb'
@@ -7,15 +7,15 @@ require_relative 'upgrade.rb'
7
7
  require_relative 'upgradeall.rb'
8
8
  require_relative 'github_api'
9
9
  require_relative 'version_map'
10
+ require_relative 'hash_extensions'
11
+ require_relative 'input_validator'
10
12
 
11
13
  require 'addressable/uri'
12
- require 'pathname'
14
+ require 'azdeploy'
15
+ require 'builder'
13
16
  require 'fileutils'
17
+ require 'json'
14
18
  require 'net/http'
15
-
16
19
  require 'nokogiri'
17
- require 'net/http'
18
- require 'builder'
19
- require 'json'
20
- require 'azdeploy'
20
+ require 'pathname'
21
21
  require 'semver'
@@ -1,16 +1,16 @@
1
1
  =begin
2
2
  Defines a simple dependency tree in a has map and allows accessing top and GlobalConstants::NEXT item in the tree.
3
- - The keys 'GlobalConstants::ROOT, GlobalConstants::NEXT, GlobalConstants::PREVIOUS and GlobalConstants::PROJECT' are self-descriptive and symbols
3
+ - The keys 'GlobalConstants::ROOT, GlobalConstants::NEXT, GlobalConstants::PREVIOUS and GlobalConstants::PROJECTNAME_NAME' are self-descriptive and symbols
4
4
  - GlobalConstants::ROOT's GlobalConstants::PREVIOUS is always nil, so are all leaf node GlobalConstants::NEXT
5
5
  {
6
6
  "GlobalConstants::ROOT" => {
7
- "GlobalConstants::PROJECT" => "Ontology",
7
+ "GlobalConstants::PROJECTNAME" => "Ontology",
8
8
  "GlobalConstants::NEXT" => "FhirWalker",
9
9
  "GlobalConstants::PREVIOUS" => nil,
10
10
  "metadata" => "[json or another hash]"
11
11
  },
12
12
  "FhirWalker" => {
13
- "GlobalConstants::PROJECT" => "Portal",
13
+ "GlobalConstants::PROJECTNAME" => "Portal",
14
14
  "GlobalConstants::NEXT" => "EventTracking",
15
15
  "GlobalConstants::PREVIOUS" => "Ontology",
16
16
  "metadata" => "[json or another hash]"
@@ -26,40 +26,59 @@ class DependencyTree
26
26
  end
27
27
 
28
28
  def root
29
- return nil if (@dependency_map.nil? || @dependency_map.class.to_s != GlobalConstants::HASH)
29
+ return nil if @dependency_map.nil? || @dependency_map.class.to_s != GlobalConstants::HASH || @dependency_map.empty?
30
30
 
31
31
  if @dependency_map.has_key?(GlobalConstants::ROOT)
32
- if @dependency_map[GlobalConstants::ROOT].has_key? GlobalConstants::PROJECT
33
- @dependency_map[GlobalConstants::ROOT][GlobalConstants::PROJECT]
32
+ if @dependency_map[GlobalConstants::ROOT].has_key? GlobalConstants::PROJECTNAME
33
+ root_node = Hashit.new @dependency_map[GlobalConstants::ROOT]
34
+ root_node
34
35
  end
35
36
  end
36
37
  end
37
38
 
38
39
  def next_node current
39
40
  return nil if current.to_s.strip.length == 0
40
- return nil if @dependency_map.nil? || @dependency_map.class.to_s != GlobalConstants::HASH
41
- return nil if @dependency_map[current] == nil
41
+ return nil if @dependency_map.nil? || @dependency_map.class.to_s != GlobalConstants::HASH || @dependency_map.empty?
42
42
 
43
+ current = GlobalConstants::ROOT if @dependency_map[GlobalConstants::ROOT][GlobalConstants::PROJECTNAME] == current
43
44
  if @dependency_map[current].has_key? GlobalConstants::NEXT
44
- @dependency_map[current][GlobalConstants::NEXT]
45
+ next_node = @dependency_map[current][GlobalConstants::NEXT]
46
+ next_node = @dependency_map[next_node]
47
+ if !next_node.nil?
48
+ next_node = Hashit.new next_node
49
+ end
45
50
  end
46
51
  end
47
52
 
48
53
  def previous_node current
49
54
  return nil if current.to_s.strip.length == 0
50
- return nil if (@dependency_map.nil? || @dependency_map.class.to_s != GlobalConstants::HASH)
55
+ return nil if @dependency_map.nil? || @dependency_map.class.to_s != GlobalConstants::HASH || @dependency_map.empty?
51
56
 
52
57
  if @dependency_map[current].has_key? GlobalConstants::PREVIOUS
53
- @dependency_map[current][GlobalConstants::PREVIOUS]
58
+ prev_node = @dependency_map[current][GlobalConstants::PREVIOUS]
59
+ if @dependency_map[GlobalConstants::ROOT][GlobalConstants::PROJECTNAME] == prev_node
60
+ prev_node = @dependency_map[GlobalConstants::ROOT]
61
+ else
62
+ prev_node = @dependency_map[prev_node]
63
+ end
64
+ return nil if prev_node.nil?
65
+ return Hashit.new prev_node
54
66
  end
55
67
  end
56
68
 
57
69
  def traverse
58
70
  current = GlobalConstants::ROOT
59
- yield @dependency_map[current][GlobalConstants::PROJECT] if @dependency_map.has_key?(current) && @dependency_map[current].has_key?(GlobalConstants::PROJECT)
71
+ current = @dependency_map[current]
72
+ current = Hashit.new current
73
+ yield current
60
74
  while current != nil
61
- current = next_node(current)
62
- yield @dependency_map[current][GlobalConstants::PROJECT] if @dependency_map.has_key?(current) && @dependency_map[current].has_key?(GlobalConstants::PROJECT)
75
+ begin
76
+ current = next_node current.project_name
77
+ rescue
78
+ #puts $!
79
+ current = nil
80
+ end
81
+ yield current if !current.nil?
63
82
  end
64
83
  end
65
84
 
@@ -59,18 +59,20 @@ module GithubApi
59
59
  `git pull --rebase #{@repo_url} #{@branch}`
60
60
  end
61
61
 
62
- def GithubApi.CommitChanges comment, git_status
63
- val = git_status.split("\n")
64
- val.each { |x|
65
- value = x.split(' M ').last
62
+ def GithubApi.CommitChanges comment, git_status = ''
63
+ if git_status != GlobalConstants::EMPTY
64
+ val = git_status.split("\n")
65
+ val.each { |x|
66
+ value = x.split(' M ').last || x.split('?? ').last
66
67
  if (/.csproj/.match(value) || /packages.config/.match(value))
67
- status = `git add #{value}`
68
- if status != GlobalConstants::EMPTY
69
- return false
70
- end
68
+ status = `git add #{value}`
69
+ if status != GlobalConstants::EMPTY
70
+ return false
71
+ end
71
72
  end
72
- }
73
-
73
+ }
74
+ end
75
+
74
76
  status = `git commit -m "#{comment}"`
75
77
  return status != GlobalConstants::EMPTY
76
78
  end
@@ -114,6 +116,7 @@ module GithubApi
114
116
  begin
115
117
  uri = Addressable::URI.parse repo_url
116
118
  rescue
119
+ puts $!
117
120
  puts "repo_url: #{repo_url} parse failed"
118
121
  return repo
119
122
  end
@@ -0,0 +1,22 @@
1
+ module GlobalConstants
2
+
3
+ HASH = 'Hash'
4
+
5
+ SPEC = 'spec'
6
+
7
+ ROOT = 'root'
8
+ PREVIOUS = 'previous'
9
+ NEXT = 'next'
10
+ PROJECTNAME = 'project_name'
11
+ DPREPO = 'http://ndhaxpgit01.mckesson.com/Carnegie/RelayHealth.DataPlatform.git'
12
+
13
+ UNPROCESSED = 'unprocessed'
14
+ FAILED = 'failed'
15
+ SUCCESS = 'success'
16
+ UPGRADE_PROGRESS = '***Upgrade progress: '
17
+
18
+ EMPTY = ''
19
+ PARENTDIR = '..'
20
+ DOT = '.'
21
+
22
+ end
@@ -0,0 +1,9 @@
1
+ class Hashit
2
+ def initialize(hash)
3
+ hash.each do |k,v|
4
+ self.instance_variable_set("@#{k}", v.is_a?(Hash) ? Hashit.new(v) : v)
5
+ self.class.send(:define_method, k, proc{self.instance_variable_get("@#{k}")})
6
+ self.class.send(:define_method, "#{k}=", proc{|v| self.instance_variable_set("@#{k}", v)})
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,159 @@
1
+ class InputValidator
2
+
3
+ def initialize
4
+ @simple_validator = SimpleValidator.new
5
+ end
6
+
7
+ def test_mode
8
+ @test_mode = true
9
+ end
10
+
11
+ # We should do more specific test of which environment variables are we expecting or which metatdata are we expecting
12
+ #if project publishes nuget we need to check if major /minor/patch incrmeented but not all 3
13
+
14
+ def validate_version_map version_map
15
+ if version_map.nil? || version_map.class.to_s != GlobalConstants::HASH
16
+ yield 'Version map must be a non-empty ' + GlobalConstants::HASH
17
+ end
18
+ end
19
+
20
+ def validate_manifest m
21
+
22
+ manifest = Hashit.new m
23
+ puts 'Validating upgrade manifest...'
24
+
25
+ if manifest.nil? || manifest.class.to_s != 'Hashit'
26
+ yield 'Config map must be a non-nil class of type Hashit'
27
+ end
28
+
29
+ node_name = 'manifest'
30
+ yield @simple_validator.method_exists manifest, 'version_source', node_name
31
+ yield @simple_validator.method_value_not_nil manifest, 'version_source', node_name
32
+ yield @simple_validator.method_exists manifest.version_source, 'repo_url', node_name
33
+ yield @simple_validator.method_value_not_nil_or_empty manifest.version_source, 'repo_url', node_name
34
+ yield @simple_validator.method_exists manifest.version_source, 'branch', node_name
35
+ yield @simple_validator.method_value_not_nil_or_empty manifest.version_source, 'branch', node_name
36
+ yield @simple_validator.method_exists manifest, 'projects', node_name
37
+ yield @simple_validator.method_value_not_nil manifest, 'projects', node_name
38
+ end
39
+
40
+ def validate_project_node project
41
+
42
+ node_name = 'project'
43
+
44
+ yield @simple_validator.method_exists project, 'next', node_name
45
+ #yield @simple_validator.method_value_not_nil_or_empty project, 'next', node_name
46
+
47
+ yield @simple_validator.method_exists project, 'previous', node_name
48
+ #yield @simple_validator.method_value_not_nil_or_empty project, 'previous', node_name
49
+
50
+ node_name = 'project.metadata'
51
+ yield @simple_validator.method_exists project.metadata, 'repo_url', node_name
52
+ yield @simple_validator.method_value_not_nil_or_empty project.metadata, 'repo_url', node_name
53
+
54
+ yield @simple_validator.method_exists project.metadata, 'branch', node_name
55
+ yield @simple_validator.method_value_not_nil_or_empty project.metadata, 'branch', node_name
56
+
57
+ yield @simple_validator.method_exists project.metadata, 'should_upgrade', node_name
58
+ yield @simple_validator.method_value_not_nil_or_empty project.metadata, 'should_upgrade', node_name
59
+
60
+ yield @simple_validator.method_exists project.metadata, 'is_package_builder', node_name
61
+ yield @simple_validator.method_value_not_nil_or_empty project.metadata, 'is_package_builder', node_name
62
+
63
+ yield @simple_validator.method_exists project.metadata, 'should_publish_nuget', node_name
64
+ yield @simple_validator.method_value_not_nil_or_empty project.metadata, 'should_publish_nuget', node_name
65
+
66
+ yield @simple_validator.method_exists project.metadata, 'env_vars', node_name
67
+ yield @simple_validator.method_value_not_nil project.metadata, 'env_vars', node_name
68
+
69
+ yield @simple_validator.method_exists project.metadata, 'status', node_name
70
+ yield @simple_validator.method_value_not_nil_or_empty project.metadata, 'status', node_name
71
+
72
+ yield @simple_validator.method_exists project.metadata, 'build_configuration_id', node_name
73
+
74
+ node_name = 'project.metadata.env_vars'
75
+ yield @simple_validator.method_exists project.metadata.env_vars, 'env', node_name
76
+ yield @simple_validator.method_value_not_nil_or_empty project.metadata.env_vars, 'env', node_name
77
+
78
+ yield @simple_validator.method_exists project.metadata.env_vars, 'service_name', node_name
79
+ yield @simple_validator.method_value_not_nil_or_empty project.metadata.env_vars, 'service_name', node_name
80
+
81
+ if !@test_mode
82
+ yield @simple_validator.method_exists project.metadata.env_vars, 'AI_InstrumentationKey', node_name
83
+ yield @simple_validator.method_value_not_nil_or_empty project.metadata.env_vars, 'AI_InstrumentationKey', node_name
84
+
85
+ yield @simple_validator.method_exists project.metadata.env_vars, 'AppClientId', node_name
86
+ yield @simple_validator.method_value_not_nil_or_empty project.metadata.env_vars, 'AppClientId', node_name
87
+
88
+ yield @simple_validator.method_exists project.metadata.env_vars, 'RuntimePath', node_name
89
+ yield @simple_validator.method_value_not_nil_or_empty project.metadata.env_vars, 'RuntimePath', node_name
90
+
91
+ yield @simple_validator.method_exists project.metadata.env_vars, 'SettingsAccount', node_name
92
+ yield @simple_validator.method_value_not_nil_or_empty project.metadata.env_vars, 'SettingsAccount', node_name
93
+
94
+ yield @simple_validator.method_exists project.metadata.env_vars, 'SettingsAccountKey', node_name
95
+ yield @simple_validator.method_value_not_nil_or_empty project.metadata.env_vars, 'SettingsAccountKey', node_name
96
+
97
+ yield @simple_validator.method_exists project.metadata.env_vars, 'unitestconnectionString', node_name
98
+ yield @simple_validator.method_value_not_nil_or_empty project.metadata.env_vars, 'unitestconnectionString', node_name
99
+
100
+ yield @simple_validator.method_exists project.metadata.env_vars, 'should_update_settings_connstr', node_name
101
+ yield @simple_validator.method_value_not_nil_or_empty project.metadata.env_vars, 'should_update_settings_connstr', node_name
102
+ end
103
+
104
+ node_name = 'project.metadata.semver'
105
+ yield @simple_validator.method_exists project.metadata, 'semver', node_name
106
+ yield @simple_validator.method_value_not_nil project.metadata, 'semver', node_name
107
+ yield @simple_validator.method_exists project.metadata.semver, 'file', node_name
108
+ yield @simple_validator.method_value_not_nil_or_empty project.metadata.semver, 'file', node_name
109
+
110
+ yield @simple_validator.method_exists project.metadata.semver, 'dimension', node_name
111
+ yield @simple_validator.method_value_not_nil_or_empty project.metadata.semver, 'dimension', node_name
112
+
113
+ yield @simple_validator.method_exists project.metadata.semver, 'location', node_name
114
+ #yield @simple_validator.method_value_not_nil_or_empty project.metadata.semver, 'location', node_name
115
+
116
+ end
117
+
118
+ end
119
+
120
+
121
+
122
+ # nil return is treated as no error
123
+ class SimpleValidator
124
+
125
+ CANNOT_CONTINUE = '. Cannot continue!'
126
+ IS_MISSING = ' is missing'
127
+
128
+ def method_exists object, method, name
129
+ begin
130
+ if !object.respond_to? method
131
+ "#{name}\'s method: *#{method}*" + IS_MISSING
132
+ end
133
+ rescue
134
+ nil
135
+ end
136
+ end
137
+
138
+ def method_value_not_nil_or_empty object, method, name
139
+ begin
140
+ value = object.send method
141
+ if value == nil || value.to_s.strip.length == 0
142
+ "#{name}\'s *#{method}* value is empty or" + IS_MISSING
143
+ end
144
+ rescue
145
+ nil
146
+ end
147
+ end
148
+
149
+ def method_value_not_nil object, method, name
150
+ begin
151
+ value = object.send method
152
+ if value == nil
153
+ "#{name}\'s *#{method}* value" + IS_MISSING
154
+ end
155
+ rescue
156
+ nil
157
+ end
158
+ end
159
+ end
@@ -19,7 +19,6 @@ module TeamCityApi
19
19
  http.request request
20
20
  end
21
21
 
22
-
23
22
  def TeamCityApi.create_build_trigger_config buildConfigurationId
24
23
  xml = Builder::XmlMarkup.new :indent => 2
25
24
  xml.build{
@@ -27,24 +26,24 @@ module TeamCityApi
27
26
  xml.buildType "id" => "#{buildConfigurationId}"
28
27
  }
29
28
  end
30
-
29
+
31
30
  #Project Get/Create API
32
31
  def TeamCityApi.get_project_by_id projectId, username, password
33
32
  uri = URI.parse "http://teamcity.relayhealth.com"
34
33
  http = Net::HTTP.new uri.host, uri.port
35
34
  request = Net::HTTP::Get.new "/app/rest/projects/id:#{projectId}", {'Accept' => 'application/json'}
36
35
  request.basic_auth username, password
37
- response = http.request request
38
- # File handling will be removed and instead use Tempfile for better security
39
- target = open("../spec/ProjectConfigByProjectId", 'w')
36
+ response = http.request request
37
+ # File handling will be removed and instead use Tempfile for better security
38
+ target = open("../spec/ProjectConfigByProjectId", 'w')
40
39
  target.truncate(0)
41
40
  target.write(response.body)
42
41
  target.close
43
42
  end
44
-
43
+
45
44
  def TeamCityApi.create_new_project inputFile, username, password
46
45
  file = File.open("../spec/#{inputFile}", "r")
47
- requestContent = file.read
46
+ requestContent = file.read
48
47
  uri = URI.parse "http://localhost:9999/"
49
48
  http = Net::HTTP.new uri.host, uri.port
50
49
  request = Net::HTTP::Post.new "/httpAuth/app/rest/projects", {'Accept' => 'application/json'}
@@ -52,26 +51,26 @@ module TeamCityApi
52
51
  request.content_type = 'application/json'
53
52
  request.basic_auth username, password
54
53
  response = http.request request
55
- puts response.body
54
+ puts response.body
56
55
  end
57
-
56
+
58
57
  #VCS-Root Get/Create API
59
58
  def TeamCityApi.get_vcs_roots_by_id vcsRootId, username, password
60
59
  uri = URI.parse "http://teamcity.relayhealth.com"
61
60
  http = Net::HTTP.new uri.host, uri.port
62
61
  request = Net::HTTP::Get.new "/httpAuth/app/rest/vcs-roots/id:#{vcsRootId}", {'Accept' => 'application/json'}
63
62
  request.basic_auth username, password
64
- response = http.request request
65
- # File handling will be removed and instead use Tempfile for better security
66
- target = open("../spec/VcsRootConfigByVcsRootId", 'w')
63
+ response = http.request request
64
+ # File handling will be removed and instead use Tempfile for better security
65
+ target = open("../spec/VcsRootConfigByVcsRootId", 'w')
67
66
  target.truncate(0)
68
67
  target.write(response.body)
69
68
  target.close
70
69
  end
71
-
70
+
72
71
  def TeamCityApi.create_new_vcs_root inputFile, username, password
73
72
  file = File.open("../spec/#{inputFile}", "r")
74
- requestContent = file.read
73
+ requestContent = file.read
75
74
  uri = URI.parse "http://localhost:9999/"
76
75
  http = Net::HTTP.new uri.host, uri.port
77
76
  request = Net::HTTP::Post.new "/httpAuth/app/rest/vcs-roots", {'Accept' => 'application/json'}
@@ -79,43 +78,39 @@ module TeamCityApi
79
78
  request.content_type = 'application/json'
80
79
  request.basic_auth username, password
81
80
  response = http.request request
82
- puts response.body
81
+ puts response.body
83
82
  end
84
-
83
+
85
84
  #Build Config Get/Create API
86
- def TeamCityApi.get_build_configs_by_projectId projectId, username, password
85
+ def TeamCityApi.get_build_configs_by_projectId projectId, username, password
87
86
  uri = URI.parse "http://teamcity.relayhealth.com"
88
87
  http = Net::HTTP.new uri.host, uri.port
89
88
  request = Net::HTTP::Get.new "/app/rest/projects/id:#{projectId}/buildTypes", {'Accept' => 'application/json'}
90
89
  request.basic_auth username, password
91
- response = http.request request
92
- # File handling will be removed and instead use Tempfile for better security
93
- target = open("../spec/BuildConfigsByProjectId", 'w')
90
+ response = http.request request
91
+ # File handling will be removed and instead use Tempfile for better security
92
+ target = open("../spec/BuildConfigsByProjectId", 'w')
94
93
  target.truncate(0)
95
94
  target.write(response.body)
96
95
  target.close
97
96
  end
98
-
97
+
99
98
  def TeamCityApi.get_build_configs_by_projectId_and_build_configurationId projectId, buildConfigurationId, username, password
100
99
  uri = URI.parse "http://teamcity.relayhealth.com"
101
100
  http = Net::HTTP.new uri.host, uri.port
102
101
  request = Net::HTTP::Get.new "/app/rest/projects/id:#{projectId}/buildTypes/id:#{buildConfigurationId}", {'Accept' => 'application/json'}
103
102
  request.basic_auth username, password
104
- response = http.request request
105
- # File handling will be removed and instead use Tempfile for better security
103
+ response = http.request request
104
+ # File handling will be removed and instead use Tempfile for better security
106
105
  target = open("../spec/BuildConfigByProjectAndBuildConfigurationId", 'w')
107
106
  target.truncate(0)
108
107
  target.write(response.body)
109
108
  target.close
110
109
  end
111
110
 
112
-
113
-
114
-
115
-
116
111
  def TeamCityApi.create_new_build_configuration projectId, inputFile, username, password
117
112
  file = File.open("../spec/#{inputFile}", "r")
118
- requestContent = file.read
113
+ requestContent = file.read
119
114
  uri = URI.parse "http://localhost:9999/"
120
115
  http = Net::HTTP.new uri.host, uri.port
121
116
 
@@ -125,13 +120,13 @@ module TeamCityApi
125
120
  request.content_type = 'application/json'
126
121
  request.basic_auth username, password
127
122
  response = http.request request
128
- # File handling will be removed and instead use Tempfile for better security
123
+ # File handling will be removed and instead use Tempfile for better security
129
124
  target = open("../spec/CreateNewBuildConfigurationResponse", 'w')
130
125
  target.truncate(0)
131
126
  target.write(response.body)
132
127
  target.close
133
128
  end
134
-
129
+
135
130
  # Setup build configuration settings
136
131
  def TeamCityApi.set_build_configuration_setting buildConfigurationId, settingName, settingValue, username, password
137
132
  uri = URI.parse "http://localhost:9999/"
@@ -142,7 +137,7 @@ module TeamCityApi
142
137
  request.basic_auth username, password
143
138
  response = http.request request
144
139
  end
145
-
140
+
146
141
  # Setup build configuration parameters
147
142
  def TeamCityApi.set_build_configuration_parameter buildConfigurationId, parameterName, parameterValue, username, password
148
143
  uri = URI.parse "http://localhost:9999/"
@@ -153,74 +148,65 @@ module TeamCityApi
153
148
  request.basic_auth username, password
154
149
  response = http.request request
155
150
  end
156
-
151
+
157
152
  # Setup build configuration Vcs-Root
158
153
  def TeamCityApi.set_build_configuration_vcs_root buildConfigurationId, vcsRootId, username, password
159
- uri = URI.parse "http://localhost:9999/"
154
+ uri = URI.parse "http://localhost:9999/"
160
155
  http = Net::HTTP.new uri.host, uri.port
161
156
  request = Net::HTTP::Post.new "/httpAuth/app/rest/buildTypes/id:#{buildConfigurationId}/vcs-root-entries/"
162
- request.body = create_build_config_vcs_root_config vcsRootId
157
+ request.body = create_build_config_vcs_root_config vcsRootId
163
158
  request.content_type = 'application/xml'
164
159
  request.basic_auth username, password
165
160
 
166
161
  response = http.request request
167
162
  end
168
163
 
169
-
170
-
171
-
172
164
  def TeamCityApi.create_build_config_vcs_root_config vcsRootId
173
165
  xml = Builder::XmlMarkup.new :indent => 2
174
-
175
-
176
-
177
166
  xml.tag!("vcs-root-entry"){
178
167
  xml.tag!("vcs-root", "id" => "#{vcsRootId}")
179
168
  }
180
169
  end
181
-
182
-
183
170
 
184
171
  # Setup build configuration step
185
172
  def TeamCityApi.set_build_configuration_build_step buildConfigurationId, inputFile, username, password
186
173
  file = File.open("../spec/#{inputFile}", "r")
187
- requestContent = file.read
174
+ requestContent = file.read
188
175
  uri = URI.parse "http://localhost:9999/"
189
176
  http = Net::HTTP.new uri.host, uri.port
190
177
  request = Net::HTTP::Post.new "/httpAuth/app/rest/buildTypes/id:#{buildConfigurationId}/steps/"
191
- request.body = requestContent
178
+ request.body = requestContent
192
179
  request.content_type = 'application/xml'
193
180
  request.basic_auth username, password
194
181
  response = http.request request
195
182
  end
196
-
197
183
 
198
184
  # Setup build feature step
199
185
  def TeamCityApi.set_build_configuration_feature buildConfigurationId, inputFile, username, password
200
186
  file = File.open("../spec/#{inputFile}", "r")
201
- requestContent = file.read
187
+ requestContent = file.read
202
188
  uri = URI.parse "http://localhost:9999/"
203
189
  http = Net::HTTP.new uri.host, uri.port
204
190
  request = Net::HTTP::Post.new "/httpAuth/app/rest/buildTypes/id:#{buildConfigurationId}/features/"
205
- request.body = requestContent
191
+ request.body = requestContent
206
192
  request.content_type = 'application/xml'
207
193
  request.basic_auth username, password
208
194
  response = http.request request
209
195
  end
210
-
196
+
211
197
  # Setup build trigger step
212
198
  def TeamCityApi.set_build_configuration_trigger buildConfigurationId, inputFile, username, password
213
199
  file = File.open("../spec/#{inputFile}", "r")
214
- requestContent = file.read
200
+ requestContent = file.read
215
201
  uri = URI.parse "http://localhost:9999/"
216
202
  http = Net::HTTP.new uri.host, uri.port
217
203
  request = Net::HTTP::Post.new "/httpAuth/app/rest/buildTypes/id:#{buildConfigurationId}/triggers/"
218
- request.body = requestContent
204
+ request.body = requestContent
219
205
  request.content_type = 'application/xml'
220
206
  request.basic_auth username, password
221
207
  response = http.request request
222
208
  end
223
-
209
+
224
210
  end
225
211
 
226
212
 
@@ -242,4 +228,4 @@ end
242
228
  #TeamCityApi.set_build_configuration_build_step "DataPlatform_DataPlatformOntology_DevelopBuild", "RakeBuildStep", "username", "password"
243
229
  #TeamCityApi.set_build_configuration_feature "DataPlatform_DataPlatformOntology_DevelopBuild", "BuildConfigurationFeature", "username", "password"
244
230
  #TeamCityApi.set_build_configuration_feature "DataPlatform_DataPlatformOntology_DevelopBuild", "BuildConfigurationFeatureForFailureCondition", "username", "password"
245
- #TeamCityApi.set_build_configuration_trigger "DataPlatform_DataPlatformOntology_DevelopBuild", "SetupTriggerForBuildStep", "username", "password"
231
+ #TeamCityApi.set_build_configuration_trigger "DataPlatform_DataPlatformOntology_DevelopBuild", "SetupTriggerForBuildStep", "username", "password"
@@ -1,68 +1,20 @@
1
1
  =begin
2
2
 
3
- Processes upgrade for a repository that is deployed as a cloud service.
4
-
5
- Inputs:
6
- 1. Project Manifest that describes repo/project to be processed
7
- a. repo name, repo url, branch name
8
- b.
9
- 2. Change Manifest that describes what references have been upgraded due to framework upgrade.
10
- Can be as simple as dictionary<string, string> of 'Package:[new version]'
11
- example: When TestService is upgraded, we'll know what references have changed.
12
- These can be used to replace packages.config and project references
13
- =end
14
-
15
- require 'nokogiri'
16
- require 'json'
17
- require 'azdeploy'
3
+ Processes upgrade for a C# code repositoryy
18
4
 
19
- require_relative 'github_api'
20
- require_relative 'globalconstants'
5
+ =end
21
6
 
22
7
  class UpgradePackages
23
8
 
24
9
  UPGRADE_BRANCH = 'upgrade'
25
10
 
26
- # versions need to be passed in as they are based on a repo_url and branch that's source, likely DP solution
27
- def initialize repo_url, branch, versions, config_map
28
- @repo_url = repo_url
29
- @branch = branch
11
+ def initialize versions
30
12
  @versions = versions
31
- @config_map = config_map
32
- end
33
-
34
- def validate_inputs
35
- return false if @repo_url.to_s.strip.length == 0
36
- return false if @branch.to_s.strip.length == 0
37
- if (@versions.nil? || @versions.class.to_s != GlobalConstants::HASH)
38
- puts 'Version map must be a ' + GlobalConstants::HASH
39
- return false
40
- end
41
- if (@config_map.nil? || @config_map.class.to_s != GlobalConstants::HASH)
42
- puts 'Config map must be a ' + GlobalConstants::HASH
43
- return false
44
- end
45
-
46
- # fail if env vars were not supplied
47
- if (!@config_map.has_key? 'env_vars')
48
- puts 'Environment variables not supplied. Cannot continue!'
49
- return false
50
- end
51
-
52
- # fail if metadata was not supplied
53
- if (!@config_map.has_key? 'metadata')
54
- puts 'Metadata variables not supplied. Cannot continue!'
55
- return false
56
- end
57
-
58
- # We should do more specific test of which environment variables are we expecting or which metatdata are we expecting
59
- #if project publishes nuget we need to check if major /minor/patch incrmeented but not all 3
60
- return true
61
13
  end
62
14
 
63
15
  def checkout_upgrade_branch
16
+
64
17
  # obtain an upgrade branch
65
- puts 'Getting upgrade branch...'
66
18
  if (GithubApi.DoesBranchExist('origin', UPGRADE_BRANCH) != GlobalConstants::EMPTY)
67
19
  puts 'Checking out existing upgrade branch...'
68
20
  return false if !GithubApi.CheckoutExistingBranch(UPGRADE_BRANCH) == GlobalConstants::EMPTY
@@ -74,54 +26,99 @@ class UpgradePackages
74
26
  return true
75
27
  end
76
28
 
77
- def Do
78
- return false if !validate_inputs
29
+ def Do config_map, nuget_targets, is_local_run=false
30
+
31
+ @config_map = config_map
32
+ @repo_url = @config_map.metadata.repo_url
33
+ @branch = @config_map.metadata.branch
79
34
 
80
35
  # checkout repo and branch
81
36
  return false if !GithubApi.CheckoutRepoAfresh @repo_url, @branch
82
37
 
38
+ # make upgrade branch
83
39
  return false if !checkout_upgrade_branch
84
40
 
41
+ # use local nuget path for restore if provided
42
+ set_local_nuget_target nuget_targets if is_local_run
43
+
85
44
  # replace versions in package config files
45
+ puts GlobalConstants::UPGRADE_PROGRESS + 'Replacing package versions...'
86
46
  pkg_files = Dir.glob '**/packages.config'
87
- if (replace_package_versions(pkg_files) == false)
88
- puts "Package version replacement failed."
47
+ if !replace_package_versions(pkg_files)
48
+ puts GlobalConstants::UPGRADE_PROGRESS + 'Package version replacement failed.'
89
49
  return false
90
50
  end
91
51
 
92
52
  # replace versions in project references
53
+ puts GlobalConstants::UPGRADE_PROGRESS + 'Replacing project versions...'
93
54
  proj_files = Dir.glob '**/*.csproj'
94
- if (replace_project_versions(proj_files) == false)
95
- puts "Project version replacement failed."
55
+ if !replace_project_versions(proj_files)
56
+ puts GlobalConstants::UPGRADE_PROGRESS + 'Project version replacement failed.'
96
57
  return false
97
58
  end
98
59
 
99
60
  # Check in manifest if project publish nuget? If yes, increment .semver
100
61
  # QUESTION: Should this method increment semver even if there is no nuget published?
101
- increment_semver_if_publish
62
+ puts GlobalConstants::UPGRADE_PROGRESS + 'Upgrading semver...'
63
+ semver_inc_done = increment_semver_if_publish is_local_run
64
+ if @config_map.metadata.should_publish_nuget.downcase == 'y'
65
+ nuget_targets << Dir.pwd + '/build_artifacts'
66
+ end
102
67
 
103
68
  # do rake build to test for compilation errors. This needs ENV vars set, passed in via config
104
- set_project_env_vars @config_map['env_vars']
69
+ set_project_env_vars @config_map.metadata.env_vars
105
70
  output = system 'rake'
106
-
107
- commit_msg = 'Versions updated'
108
71
  if output.to_s == 'false'
109
- puts '~~/\~~\/~~ Rake Error: There were errors during rake run. ~~\/~~/\~~'
110
- # save state
111
- commit_msg = 'Versions updated, build failed'
72
+ puts GlobalConstants::UPGRADE_PROGRESS + ' Rake Error: There were errors during rake run.'
73
+ # save state
74
+ GithubApi.CommitChanges( 'Versions updated, build failed')
75
+
76
+ return false
77
+ end
78
+
79
+ # update version map with nuget versions after build success
80
+ if semver_inc_done
81
+ update_version_map
82
+ puts GlobalConstants::UPGRADE_PROGRESS + 'Semver upgraded. Version map updated.'
112
83
  end
113
84
 
85
+ if is_local_run
86
+ puts GlobalConstants::UPGRADE_PROGRESS + 'Local run. No branch update or teamcity build triggered'
87
+ else
88
+ return false if !update_branch
89
+ # kick off teamcity build
90
+ TeamCityApi.trigger_build @config_map.build_configuration_id, @config_map.tc_un, @config_map.tc_pwd
91
+ end
92
+
93
+ true
94
+ end
95
+
96
+ def set_local_nuget_target nuget_targets
97
+ num_paths = 1;
98
+ nuget_targets.each { |target|
99
+ nuget_targets_file = Dir.pwd + '/src/.nuget/Nuget.Config'
100
+ doc = Nokogiri::XML(File.read nuget_targets_file)
101
+ node_parent = doc.at_css 'packageSources'
102
+ node = Nokogiri::XML::Node.new('add', doc)
103
+ node['key'] = "local_nuget_source#{num_paths}"
104
+ node['value'] = target
105
+ node_parent.add_child node
106
+ File.write nuget_targets_file, doc.to_xml
107
+ num_paths += 1
108
+ }
109
+ end
110
+
111
+ def update_branch
112
+
114
113
  # see if any files changed and commit
115
114
  git_status = GithubApi.HaveLocalChanges
116
- if (git_status != nil || git_status != GlobalConstants::EMPTY)
117
- puts 'Local version changes have been committed'
118
- return false if !GithubApi.CommitChanges commit_msg, git_status
119
- else
120
- puts 'No local changes exist. Nothing to commit'
115
+ if git_status != nil || git_status != GlobalConstants::EMPTY
116
+ puts GlobalConstants::UPGRADE_PROGRESS + 'Local version changes have been committed'
117
+ return false if !GithubApi.CommitChanges( 'Versions updated')
121
118
  end
122
119
 
123
120
  # rebase and push the branch
124
- puts 'Rebasing and pushing...'
121
+ puts GlobalConstants::UPGRADE_PROGRESS + 'Rebasing and pushing update branch...'
125
122
  GithubApi.CheckoutLocal @branch
126
123
  GithubApi.RebaseLocal UPGRADE_BRANCH
127
124
 
@@ -130,11 +127,11 @@ class UpgradePackages
130
127
  # Build failure email will inform concerned team
131
128
  git_status = GithubApi.PushBranch(@repo_url, @branch) == GlobalConstants::EMPTY
132
129
  if git_status
133
- puts "Version upgrade changes have been rebased with #{@repo_url}/#{@branch} and pushed"
130
+ puts GlobalConstants::UPGRADE_PROGRESS + "Version upgrade changes have been rebased with #{@repo_url}/#{@branch} and pushed"
134
131
  else
135
132
  GithubApi.PullWithRebase @repo_url, @branch
136
133
  GithubApi.PushBranch @repo_url, @branch
137
- puts "Push after version upgrade failed for #{@repo_url}/#{@branch}. Pull with rebase done and pushed"
134
+ puts GlobalConstants::UPGRADE_PROGRESS + "Push after version upgrade failed for #{@repo_url}/#{@branch}. Pull with rebase done and pushed"
138
135
  return false
139
136
  end
140
137
 
@@ -142,12 +139,11 @@ class UpgradePackages
142
139
  GithubApi.DeleteLocalBranch UPGRADE_BRANCH
143
140
  GithubApi.DeleteRemoteBranch @repo_url, UPGRADE_BRANCH
144
141
 
145
- # handle configuration changes. The settings file, update hash or TeamCity Params list is passed in through Ctor
146
-
147
142
  true
148
143
  end
149
144
 
150
145
  def replace_package_versions pkg_files
146
+
151
147
  begin
152
148
  # iterate each package file, replace version numbers and save
153
149
  pkg_files.each{ |file|
@@ -155,19 +151,17 @@ class UpgradePackages
155
151
  doc = Nokogiri::XML File.read(file)
156
152
  nodes = doc.xpath "//*[@id]"
157
153
  nodes.each { |node|
158
- if (@versions.has_key?(node['id']))
159
- node['version'] = @versions[node['id']]
160
- #puts "#{node['id']} #{node['version']} -- #{@versions[node['id']]}"
161
- end
154
+ node['version'] = @versions[node['id']] if (@versions.has_key?(node['id']))
162
155
  }
163
-
164
156
  File.write file, doc.to_xml
165
157
  }
166
158
  rescue
167
159
  puts $!
168
160
  return false
169
161
  end
162
+
170
163
  return true
164
+
171
165
  end
172
166
 
173
167
  =begin
@@ -184,6 +178,7 @@ class UpgradePackages
184
178
  </Reference>
185
179
  =end
186
180
  def replace_project_versions proj_files
181
+
187
182
  begin
188
183
  # iterate each package file, replace version numbers and save
189
184
  proj_files.each{ |file|
@@ -206,7 +201,7 @@ class UpgradePackages
206
201
  hint_path_id = id_from_hint_path hint_path_value
207
202
  if @versions.has_key? hint_path_id
208
203
  hint_path_parts = hint_path_value.split '\\'
209
- hint_path_parts[2] = hint_path_id + '.' + @versions[hint_path_id]
204
+ hint_path_parts[2] = hint_path_id + GlobalConstants::DOT + @versions[hint_path_id]
210
205
  hint_path[0].children = hint_path_parts.join '\\'
211
206
  end
212
207
  end
@@ -217,42 +212,68 @@ class UpgradePackages
217
212
  puts $!
218
213
  return false
219
214
  end
215
+
220
216
  return true
217
+
221
218
  end
222
219
 
223
220
  def id_from_hint_path path
224
- name = path.split('\\')[2].split '.'
221
+ name = path.split('\\')[2].split GlobalConstants::DOT
225
222
  name_without_ver = GlobalConstants::EMPTY
226
223
  name.all? {|i|
227
224
  if i.to_i == 0
228
- name_without_ver += i.to_s + '.'
225
+ name_without_ver += i.to_s + GlobalConstants::DOT
229
226
  end
230
227
  }
231
- name_without_ver.chomp '.'
228
+ name_without_ver.chomp GlobalConstants::DOT
232
229
  end
233
230
 
234
231
  def set_project_env_vars envs
235
- envs.keys.each { | key |
236
- ENV[key] = envs[key]
237
- }
232
+ ENV['AI_InstrumentationKey'] = envs.AI_InstrumentationKey if envs.respond_to? 'AI_InstrumentationKey'
233
+ ENV['AppClientId'] = envs.AppClientId if envs.respond_to? 'AppClientId'
234
+ ENV['ConfigSettingsTable'] = envs.ConfigSettingsTable if envs.respond_to? 'ConfigSettingsTable'
235
+ ENV['env'] = envs.env if envs.respond_to? 'env'
236
+ ENV['RuntimePath'] = envs.RuntimePath if envs.respond_to? 'RuntimePath'
237
+ ENV['ServiceName'] = envs.ServiceName if envs.respond_to? 'ServiceName'
238
+ ENV['SettingsAccount'] = envs.SettingsAccount if envs.respond_to? 'SettingsAccount'
239
+ ENV['SettingsAccountKey'] = envs.SettingsAccountKey if envs.respond_to? 'SettingsAccountKey'
240
+ ENV['should_update_settings_connstr'] = envs.should_update_settings_connstr if envs.respond_to? 'should_update_settings_connstr'
241
+ ENV['unitestconnectionString'] = envs.unitestconnectionString if envs.respond_to? 'unitestconnectionString'
238
242
  end
239
243
 
240
- def increment_semver_if_publish
241
- if !is_team_city_run
242
- # local run
243
- auto_update_local_semver
244
+ def increment_semver_if_publish is_local_run
245
+
246
+ if is_local_run
247
+ auto_update_semver @config_map.project_name, @config_map.metadata.semver.location, @config_map.metadata.semver.file, @config_map.metadata.semver.dimension
248
+ return true
244
249
  else
245
- should_publish_nuget = @config_map['metadata']['ShouldPublishNuget'].downcase
250
+ should_publish_nuget = @config_map.metadata.should_publish_nuget.downcase
246
251
  if should_publish_nuget.eql? 'y'
247
- semver_file = @config_map['metadata']['SemverFile']
252
+ semver_file = @config_map.metadata.semver.file
248
253
  if (semver_file != nil && semver_file != GlobalConstants::EMPTY)
249
254
  semver_file.capitalize
250
255
  end
251
- semver_dimension = @config_map['metadata']['SemverDimension']
252
- auto_update_semver @config_map['project'], @config_map['metadata']['SemverLocation'], semver_file, semver_dimension
256
+ auto_update_semver @config_map.project_name, @config_map.metadata.semver.location, semver_file, @config_map.metadata.semver.dimension
257
+ return true
253
258
  else
254
- puts '******** Project does not publish nuget.**********'
259
+ puts GlobalConstants::UPGRADE_PROGRESS + 'Project does not publish nuget.'
255
260
  end
256
261
  end
262
+
263
+ false
264
+ end
265
+
266
+ def update_version_map
267
+ path = File.join(Dir.pwd, '/build_artifacts/*.nupkg')
268
+ nugets = Dir.glob path
269
+ nugets.each { |nuget|
270
+ full_name = File.basename nuget
271
+ full_name = full_name.sub! '.nupkg', ''
272
+ full_name = full_name.sub! '.symbols', '' if full_name.include? '.symbols'
273
+ dot_pos = full_name.index GlobalConstants::DOT
274
+ nuget_name = full_name[0..dot_pos-1]
275
+ nuget_version = full_name[dot_pos+1..full_name.length]
276
+ @versions[nuget_name] = nuget_version
277
+ }
257
278
  end
258
279
  end
@@ -12,11 +12,21 @@ class UpgradeAll
12
12
  MANIFEST_FILE = 'manifest.json'
13
13
 
14
14
  # repo_url is where the last known version map and manifest are checked-in
15
- def initialize repo_url, branch
15
+ def initialize repo_url, branch, manifest_path = MANIFEST_FILE
16
16
 
17
17
  @repo_url = repo_url
18
18
  @branch = branch
19
+ @manifest_path = manifest_path
19
20
 
21
+ @manifest = JSON.parse File.read(@manifest_path) if File.exist? @manifest_path
22
+ end
23
+
24
+ def manifest
25
+ @manifest
26
+ end
27
+
28
+ def version_map
29
+ @remote_version_map
20
30
  end
21
31
 
22
32
  def retrieve_artifacts
@@ -24,44 +34,99 @@ class UpgradeAll
24
34
  return if !GithubApi.CheckoutRepoAfresh @repo_url, @branch
25
35
 
26
36
  # JSON files converted to hash
27
- if File.exist? VERSION_MAP_FILE
28
- @remote_version_map = JSON.parse File.read(VERSION_MAP_FILE)
29
- end
30
-
31
- if File.exist? MANIFEST_FILE
32
- @manifest = JSON.parse File.read(MANIFEST_FILE)
33
- end
37
+ @remote_version_map = JSON.parse File.read(VERSION_MAP_FILE) if File.exist? VERSION_MAP_FILE
38
+ @manifest = JSON.parse File.read(@manifest_path) if File.exist? @manifest_path
34
39
 
40
+ Dir.chdir GlobalConstants::PARENTDIR
35
41
  end
36
42
 
37
- def Do
43
+ def Do input_validator, is_local_run=false
44
+
45
+ puts "\n"
46
+ puts GlobalConstants::UPGRADE_PROGRESS + 'Upgrade All has begun..'
38
47
 
39
48
  # retrieve version map and upgrade manifest
49
+ puts GlobalConstants::UPGRADE_PROGRESS + 'Retrieving artifacts...'
40
50
  retrieve_artifacts
41
51
 
42
52
  return false if @remote_version_map.nil? || @manifest.nil?
43
53
 
44
54
  #find version diff. If no changes exist, kick off deploy cycle only
45
- puts 'Calculating version diff...'
55
+ puts GlobalConstants::UPGRADE_PROGRESS + 'Calculating version diff...'
46
56
  versions_to_update = version_diff
47
57
 
58
+ # nothing to update
59
+ if versions_to_update.nil? || versions_to_update.length == 0
60
+ puts 'No version diff, nothing to upgrade!'
61
+ return false
62
+ end
63
+
64
+ # validate manifest
65
+ puts GlobalConstants::UPGRADE_PROGRESS + 'Validating manifest...'
66
+ validation_errors = []
67
+ input_validator.validate_manifest(@manifest) do |error|
68
+ validation_errors << error if !error.nil?
69
+ end
70
+ raise StandardError, validation_error_message(validation_errors) if validation_errors.length > 0
71
+
72
+ nuget_targets = []
73
+ upgrader = UpgradePackages.new versions_to_update
74
+
48
75
  # if changes exist, cycle through dependency tree and kick off upgrades
49
- projects = @manifest['projects']
50
- projects.each { | proj |
51
- p proj
52
- if proj['ShouldUpgrade'].downcase != 'n'
53
- p proj
54
- puts "================="
76
+ puts GlobalConstants::UPGRADE_PROGRESS + 'Navigating projects...'
77
+ dep_tree = DependencyTree.new(@manifest['projects'])
78
+ dep_tree.traverse do |node|
79
+
80
+ if node.metadata.should_upgrade.downcase == 'y'
81
+ puts "#{GlobalConstants::UPGRADE_PROGRESS} Processing project #{node.project_name}..."
82
+
83
+ # validate project node
84
+ puts GlobalConstants::UPGRADE_PROGRESS + 'Validating project node...'
85
+ input_validator.validate_project_node(node) do |error|
86
+ validation_errors << error if !error.nil?
87
+ end
88
+ raise StandardError, validation_error_message(validation_errors) if validation_errors.length > 0
89
+
90
+ # the upgrade
91
+ puts "#{GlobalConstants::UPGRADE_PROGRESS} Upgrading project #{node.project_name}..."
92
+ upgrade_status = upgrader.Do node, nuget_targets, is_local_run
93
+
94
+ # save node name to use for status update
95
+ node_name = node.project_name
96
+ if (node.respond_to?('is_root') && node.is_root == 'true')
97
+ node_name = GlobalConstants::ROOT
98
+ end
99
+
100
+ # project status set in json
101
+ if upgrade_status
102
+ puts "#{GlobalConstants::UPGRADE_PROGRESS} Upgrade of #{node.project_name} succeeded"
103
+ @manifest['projects'][node_name]['metadata']['status'] = GlobalConstants::SUCCESS
104
+ Dir.chdir GlobalConstants::PARENTDIR
105
+ else
106
+ # either cycle was unterrupted, a step in upgrade failed or full cycle successfully completed
107
+ # save the version map and manifest
108
+ puts "#{GlobalConstants::UPGRADE_PROGRESS} Upgrade of #{node.project_name} failed"
109
+ @manifest['projects'][node_name]['metadata']['status'] = GlobalConstants::FAILED
110
+ # no more processing after failure
111
+ return false
112
+ end
113
+
114
+ else
115
+ puts "#{GlobalConstants::UPGRADE_PROGRESS} Skipping upgrade for project #{node.project_name}..."
55
116
  end
56
- }
117
+ end
57
118
 
58
- # either cycle was unterrupted, a step in upgrade failed or full cycle successfully completed
119
+ # upgrade completed successfully, update status as unprocessed and save version map and manifest, push
120
+ reset_status_unprocessed
59
121
 
60
- # save the version map and manifest
61
122
 
62
123
  true
63
124
  end
64
125
 
126
+ def save version_manifest
127
+
128
+ end
129
+
65
130
  def version_diff
66
131
 
67
132
  # create version map afresh to compare
@@ -77,15 +142,24 @@ class UpgradeAll
77
142
  return hash
78
143
  end
79
144
 
80
- #p @remote_version_map
81
- #p versions
82
-
83
145
  # compare current and remote versions, obtain changeset
84
146
  hash = Hash[*(versions.to_a - @remote_version_map.to_a).flatten]
85
147
 
86
148
  # return changeset hash
87
149
  hash
150
+ end
151
+
152
+ def reset_status_unprocessed
153
+ @manifest['projects'].each { |proj|
154
+ proj.each { |item|
155
+ item['metadata']['status'] = GlobalConstants::UNPROCESSED if item.class.to_s != 'String'
156
+ }
157
+ }
158
+ @manifest
159
+ end
88
160
 
161
+ def validation_error_message validation_errors
162
+ "One or more validation errors have occurred: #{validation_errors.join(' ')}"
89
163
  end
90
164
 
91
165
  end
@@ -33,7 +33,7 @@ class VersionMap
33
33
 
34
34
  # load old versions
35
35
  old_versions = {}
36
- if (File.exists? VERSIONMAPFILE)
36
+ if File.exists? VERSIONMAPFILE
37
37
  old_versions = JSON.parse File.read(VERSIONMAPFILE)
38
38
  end
39
39
 
@@ -41,24 +41,25 @@ class VersionMap
41
41
  versions = {}
42
42
  pkg_files = Dir.glob '**/packages.config'
43
43
  pkg_files.each{ |file|
44
- puts "Finding packages in: #{file}"
44
+ #puts "Finding packages in: #{file}"
45
45
  doc = Nokogiri::XML File.read(file)
46
46
  nodes = doc.xpath "//*[@id]"
47
47
  nodes.each { |node|
48
- if (!versions[node['id']].nil? && node['version'] != versions[node['id']]['version'])
48
+
49
+ if (!versions[node['id']].nil? && node['version'] != versions[node['id']])
49
50
  puts "======Error: Package #{node['id']} with version #{node['version']} has a different pre-exisiting version: #{versions[node['id']]}"
50
51
  end
51
52
  versions[node['id']] = node['version']
52
53
  }
53
54
  }
54
-
55
+
55
56
  if Dir.exist?('versioning')
56
- update_platform_multiple_semver_package_versions versions
57
- else
58
- update_platform_single_semver_package_versions versions
59
- end
57
+ update_platform_multiple_semver_package_versions versions
58
+ else
59
+ update_platform_single_semver_package_versions versions
60
+ end
60
61
 
61
- Dir.chdir '..'
62
+ Dir.chdir GlobalConstants::PARENTDIR
62
63
  File.write VERSIONMAPFILE, versions.to_json
63
64
 
64
65
  versions
@@ -81,7 +82,7 @@ class VersionMap
81
82
 
82
83
  versions
83
84
  end
84
-
85
+
85
86
  def update_platform_multiple_semver_package_versions versions
86
87
  versions['RelayHealth.DataPlatform.Contracts'] = get_semver 'Contracts.semver'
87
88
  versions['RelayHealth.DataPlatform.Framework'] = get_semver 'Framework.semver'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: a2zdeploy
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Suresh Batta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-30 00:00:00.000000000 Z
11
+ date: 2016-01-19 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Automated Upgrades Gem. Provides version upgrades, build and deployment
14
14
  configuration management
@@ -20,7 +20,9 @@ files:
20
20
  - lib/a2zdeploy.rb
21
21
  - lib/dependency_tree.rb
22
22
  - lib/github_api.rb
23
- - lib/globalconstants.rb
23
+ - lib/global_constants.rb
24
+ - lib/hash_extensions.rb
25
+ - lib/input_validator.rb
24
26
  - lib/proget_api.rb
25
27
  - lib/teamcity_api.rb
26
28
  - lib/upgrade.rb
@@ -1,9 +0,0 @@
1
- module GlobalConstants
2
- HASH = 'Hash'
3
- EMPTY = ''
4
- SPEC = 'spec'
5
- ROOT = 'root'
6
- PREVIOUS = 'previous'
7
- NEXT = 'next'
8
- PROJECT = 'project'
9
- end