a2zdeploy 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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