firespring_dev_commands 2.2.6 → 2.5.0.pre.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/firespring_dev_commands/audit/report.rb +2 -9
  4. data/lib/firespring_dev_commands/aws/cloudformation.rb +3 -10
  5. data/lib/firespring_dev_commands/common.rb +2 -22
  6. data/lib/firespring_dev_commands/docker/status.rb +0 -20
  7. data/lib/firespring_dev_commands/docker.rb +16 -86
  8. data/lib/firespring_dev_commands/eol/aws.rb +2 -10
  9. data/lib/firespring_dev_commands/eol.rb +2 -22
  10. data/lib/firespring_dev_commands/git.rb +24 -37
  11. data/lib/firespring_dev_commands/jira/issue.rb +1 -3
  12. data/lib/firespring_dev_commands/node.rb +1 -1
  13. data/lib/firespring_dev_commands/php/audit.rb +0 -4
  14. data/lib/firespring_dev_commands/php.rb +12 -28
  15. data/lib/firespring_dev_commands/platform.rb +31 -38
  16. data/lib/firespring_dev_commands/ruby.rb +3 -6
  17. data/lib/firespring_dev_commands/target_process/query.rb +4 -30
  18. data/lib/firespring_dev_commands/target_process/release.rb +1 -1
  19. data/lib/firespring_dev_commands/target_process/team_assignment.rb +1 -1
  20. data/lib/firespring_dev_commands/target_process/user.rb +1 -13
  21. data/lib/firespring_dev_commands/target_process/user_story.rb +1 -1
  22. data/lib/firespring_dev_commands/target_process/user_story_history.rb +1 -1
  23. data/lib/firespring_dev_commands/target_process.rb +7 -24
  24. data/lib/firespring_dev_commands/templates/aws.rb +6 -33
  25. data/lib/firespring_dev_commands/templates/base_interface.rb +2 -2
  26. data/lib/firespring_dev_commands/templates/ci.rb +11 -16
  27. data/lib/firespring_dev_commands/templates/docker/application.rb +2 -2
  28. data/lib/firespring_dev_commands/templates/docker/node/application.rb +5 -55
  29. data/lib/firespring_dev_commands/templates/docker/php/application.rb +16 -58
  30. data/lib/firespring_dev_commands/templates/docker/ruby/application.rb +5 -54
  31. data/lib/firespring_dev_commands/templates/eol.rb +2 -9
  32. data/lib/firespring_dev_commands/templates/git.rb +0 -165
  33. data/lib/firespring_dev_commands/version.rb +1 -1
  34. data/lib/firespring_dev_commands.rb +1 -1
  35. metadata +37 -113
  36. data/lib/firespring_dev_commands/aws/route53.rb +0 -139
  37. data/lib/firespring_dev_commands/bloom_growth/rock.rb +0 -34
  38. data/lib/firespring_dev_commands/bloom_growth/seat.rb +0 -16
  39. data/lib/firespring_dev_commands/bloom_growth/user.rb +0 -43
  40. data/lib/firespring_dev_commands/bloom_growth.rb +0 -132
  41. data/lib/firespring_dev_commands/certificate.rb +0 -59
  42. data/lib/firespring_dev_commands/coverage/base.rb +0 -16
  43. data/lib/firespring_dev_commands/coverage/cobertura.rb +0 -86
  44. data/lib/firespring_dev_commands/coverage/none.rb +0 -21
  45. data/lib/firespring_dev_commands/dns/resource.rb +0 -83
  46. data/lib/firespring_dev_commands/docker/desktop.rb +0 -61
  47. data/lib/firespring_dev_commands/eol/node.rb +0 -42
  48. data/lib/firespring_dev_commands/eol/php.rb +0 -50
  49. data/lib/firespring_dev_commands/eol/ruby.rb +0 -42
  50. data/lib/firespring_dev_commands/jira/parent.rb +0 -19
  51. data/lib/firespring_dev_commands/os.rb +0 -35
  52. data/lib/firespring_dev_commands/port.rb +0 -24
  53. data/lib/firespring_dev_commands/target_process/time.rb +0 -32
  54. data/lib/firespring_dev_commands/templates/aws/services/route53.rb +0 -111
  55. data/lib/firespring_dev_commands/templates/certificate.rb +0 -41
@@ -1,132 +0,0 @@
1
- require 'net/http'
2
-
3
- module Dev
4
- # Class for interacting with the Bloom Growth api
5
- class BloomGrowth
6
- # The config file to try to load credentials from
7
- CONFIG_FILE = "#{Dir.home}/.env.bloom".freeze
8
-
9
- # The text of the username variable key
10
- BLOOM_USERNAME = 'BLOOM_USERNAME'.freeze
11
-
12
- # The text of the password variable key
13
- BLOOM_PASSWORD = 'BLOOM_PASSWORD'.freeze
14
-
15
- # The text of the token variable key
16
- BLOOM_TOKEN = 'BLOOM_TOKEN'.freeze
17
-
18
- # The text of the url variable key
19
- BLOOM_URL = 'BLOOM_URL'.freeze
20
-
21
- # Config object for setting top level bloom growth config options
22
- Config = Struct.new(:username, :password, :url, :http_debug) do
23
- def initialize
24
- Dotenv.load(CONFIG_FILE) if File.exist?(CONFIG_FILE)
25
-
26
- self.username = ENV.fetch(BLOOM_USERNAME, nil)
27
- self.password = ENV.fetch(BLOOM_PASSWORD, nil)
28
- self.url = ENV.fetch(BLOOM_URL, 'https://app.bloomgrowth.com')
29
- self.http_debug = false
30
- end
31
- end
32
-
33
- class << self
34
- # Instantiates a new top level config object if one hasn't already been created
35
- # Yields that config object to any given block
36
- # Returns the resulting config object
37
- def config
38
- @config ||= Config.new
39
- yield(@config) if block_given?
40
- @config
41
- end
42
-
43
- # Alias the config method to configure for a slightly clearer access syntax
44
- alias_method :configure, :config
45
- end
46
-
47
- attr_accessor :username, :password, :url, :token, :client, :default_headers
48
-
49
- # Initialize a new target process client using the given inputs
50
- def initialize(username: self.class.config.username, password: self.class.config.password, url: self.class.config.url)
51
- raise 'username is required' if username.to_s.strip.empty?
52
- raise 'password is required' if password.to_s.strip.empty?
53
- raise 'url is required' if url.to_s.strip.empty?
54
-
55
- @username = username
56
- @password = password
57
- @url = url
58
- uri = URI.parse(@url)
59
- @client = Net::HTTP.new(uri.host, uri.port)
60
- @client.use_ssl = true
61
- @client.verify_mode = OpenSSL::SSL::VERIFY_PEER
62
- @client.set_debug_output(LOG) if self.class.config.http_debug
63
- @default_headers = {
64
- 'authorization' => "Bearer #{token}",
65
- 'content-type' => 'application/json',
66
- 'accept' => 'application/json'
67
- }
68
- end
69
-
70
- # Method for getting a bearer token for the bloom growth api. There are a couple of possible logic paths
71
- # - If a token has already been defined, use it
72
- # - If a token is found in the ENV, use it
73
- # - Otherwise, use the username and passowrd that has been configured to request a new token from bloom
74
- def token
75
- @token ||= ENV.fetch(BLOOM_TOKEN, nil)
76
-
77
- unless @token
78
- response = post(
79
- '/Token',
80
- {
81
- grant_type: 'password',
82
- userName: username,
83
- password:
84
- },
85
- headers: {
86
- 'content-type' => 'application/json',
87
- 'accept' => 'application/json'
88
- }
89
- )
90
- # TODO: Should we look at https://github.com/DannyBen/lightly for caching the token?
91
- @token = ENV[BLOOM_TOKEN] = response['access_token']
92
- LOG.info("Retrieved BloomGrowth token. Expires on #{Time.now + response['expires_in']}")
93
- end
94
-
95
- @token
96
- end
97
-
98
- # Return all user objects visible to the logged in user
99
- def visible_users(&)
100
- [].tap do |ary|
101
- get('/api/v1/users/mineviewable') do |user_data|
102
- ary << User.new(user_data)
103
- end
104
- ary.each(&)
105
- end
106
- end
107
-
108
- # Perform a get request to the given path using the given query
109
- # Call the given block (if present) with each piece of data
110
- # Return all pieces of data
111
- def get(path, query_string: nil, headers: default_headers, &)
112
- url = path
113
- url << "?#{URI.encode_www_form(query_string)}" unless query_string.to_s.strip.empty?
114
-
115
- response = client.request_get(url, headers)
116
- raise "Error querying #{url} [#{query_string}]: #{response.inspect}" unless response.response.is_a?(Net::HTTPSuccess)
117
-
118
- JSON.parse(response.body).each(&)
119
- nil
120
- end
121
-
122
- # Perform a post request to the given path using the gien data
123
- # Return the parsed json body
124
- def post(path, data, headers: default_headers)
125
- data = data.to_json unless data.is_a?(String)
126
- response = client.request_post(path, data, headers)
127
- raise "Error querying #{url}/#{path}: #{response.inspect}" unless response.response.is_a?(Net::HTTPSuccess)
128
-
129
- JSON.parse(response.body)
130
- end
131
- end
132
- end
@@ -1,59 +0,0 @@
1
- module Dev
2
- # Class contains methods for requesting a certificate from route53.
3
- # You must have a hosted zone defined for the desired domain
4
- class Certificate
5
- attr_accessor :domains, :email
6
-
7
- def initialize(domains, email)
8
- @domains = Array(domains)
9
- @email = email
10
- raise 'No certificate domains specified' if domains.empty?
11
- end
12
-
13
- # Request the certificate using the route53 docker image
14
- # Certificate is stored in /etc/letsencrypt
15
- def request
16
- puts
17
- puts 'Getting SSL Certs For:'
18
- puts domains.join("\n")
19
- puts
20
- puts 'This process can take up to 10 minutes'
21
- puts
22
- puts Time.now
23
-
24
- # TODO: Really should use the docker api for this
25
- cmd = %w(docker run -it --rm --name certbot)
26
- cmd << '-e' << 'AWS_ACCESS_KEY_ID'
27
- cmd << '-e' << 'AWS_SECRET_ACCESS_KEY'
28
- cmd << '-e' << 'AWS_SESSION_TOKEN'
29
- cmd << '-v' << '/etc/letsencrypt:/etc/letsencrypt'
30
- cmd << 'certbot/dns-route53:latest'
31
- cmd << 'certonly'
32
- cmd << '-n'
33
- cmd << '--agree-tos'
34
- cmd << '--dns-route53'
35
- cmd << '-d' << domains.join(',')
36
- cmd << '--email' << email
37
- cmd << '--server' << 'https://acme-v02.api.letsencrypt.org/directory'
38
- puts cmd.join(' ')
39
- Dev::Common.new.run_command(cmd)
40
- end
41
-
42
- # Saves the latest version of the certificate into the given dest_dir
43
- def save(dest_dir)
44
- raise "directory #{dest_dir} must be an existing directory" unless File.directory?(dest_dir)
45
-
46
- domain = domains.first.sub(/^\*\./, '') # Need to strip off the '*.' if this is a wildcard cert
47
- directories = Dir.glob("/etc/letsencrypt/live/#{domain}*/")
48
- no_suffix = directories.delete("/etc/letsencrypt/live/#{domain}/")
49
- biggest_suffix = directories.max
50
- source_dir = biggest_suffix || no_suffix
51
- raise "unable to determine certificate directory for #{domain}" unless source_dir
52
-
53
- FileUtils.cp("#{source_dir}privkey.pem", dest_dir, verbose: true)
54
- FileUtils.cp("#{source_dir}cert.pem", dest_dir, verbose: true)
55
- FileUtils.cp("#{source_dir}chain.pem", dest_dir, verbose: true)
56
- FileUtils.cp("#{source_dir}fullchain.pem", dest_dir, verbose: true)
57
- end
58
- end
59
- end
@@ -1,16 +0,0 @@
1
- module Dev
2
- module Coverage
3
- # Class which defines the methods which must be implemented to function as a coverage class
4
- class Base
5
- # Raises not implemented
6
- def php_options
7
- raise 'not implemented'
8
- end
9
-
10
- # Raises not implemented
11
- def check(*)
12
- raise 'not implemented'
13
- end
14
- end
15
- end
16
- end
@@ -1,86 +0,0 @@
1
- module Dev
2
- # Module containing different classes for interfacing with coverage files
3
- module Coverage
4
- # Class for checking code coverage using cobertura
5
- class Cobertura < Base
6
- attr_reader :local_filename, :container_filename, :filename, :threshold, :exclude
7
-
8
- def initialize(filename: File.join('coverage', 'cobertura.xml'), threshold: nil, container_path: nil, local_path: nil, exclude: nil)
9
- super()
10
-
11
- @filename = filename
12
- @local_filename = File.join(local_path || '.', @filename)
13
- @container_filename = File.join(container_path || '.', @filename)
14
- @threshold = threshold
15
- @exclude = (exclude || []).map do |it|
16
- next it if it.is_a?(Regex)
17
-
18
- Regex.new(it)
19
- end
20
- end
21
-
22
- # Remove any previous versions of the local file that will be output
23
- # return the phpunit options needed to regenerate the cobertura xml file
24
- def php_options
25
- # Remove any previous coverage info
26
- FileUtils.rm_f(local_filename, verbose: true)
27
-
28
- # Return the needed php commands to generate the cobertura report
29
- %W(--coverage-cobertura #{container_filename})
30
- end
31
-
32
- # Parse the cobertura file and check the lines missed against the desired threshold
33
- def check(application: nil)
34
- # If an application has been specified and the file does not exist locally, attempt to copy it back from the docker container
35
- if application && !File.exist?(local_filename)
36
- container = Dev::Docker::Compose.new.container_by_name(application)
37
- Dev::Docker.new.copy_from_container(container, container_filename, local_filename, required: true)
38
- end
39
-
40
- report = Ox.load(File.read(local_filename))
41
- total_missed = report.coverage.locate('packages/package').sum { |package| parse_package_missed(package) }
42
- puts "Lines missing coverage was #{total_missed}"
43
- puts "Configured threshold was #{threshold}" if threshold
44
- raise 'Code coverage not met' if threshold && total_missed > threshold
45
- end
46
-
47
- # Go through the package and add up all of the lines that were missed
48
- # Ignore if the file was in the exlude list
49
- private def parse_package_missed(package)
50
- filename = package.attributes[:name]
51
- return if exclude.any? { |it| it.match(filename) }
52
-
53
- missed = 0
54
- lines_processed = Set.new
55
- package.locate('classes/class/lines/line').each do |line|
56
- # Don't count lines multiple times
57
- line_number = line.attributes[:number]
58
- next if lines_processed.include?(line_number)
59
-
60
- lines_processed << line_number
61
- missed += 1 unless line.attributes[:hits].to_i.positive?
62
- end
63
- total = lines_processed.length
64
-
65
- sanity_check_coverage_against_cobertura_values(package, missed, total)
66
- missed
67
- end
68
-
69
- # Calculate the coverage percent based off the numbers we got and compare to the
70
- # value cobertura reported. This is meant as a sanity check that we are reading the data correctly
71
- # TODO: This should be removed after the above logic has been vetted
72
- private def sanity_check_coverage_against_cobertura_values(package, missed, total)
73
- line_rate = package.attributes[:'line-rate']
74
- cobertura_reported_coverage = line_rate.to_f
75
- cobertura_reported_precision = line_rate.split('.').last.length
76
-
77
- file_coverage = 0.0
78
- file_coverage = ((total - missed).to_f / total).round(cobertura_reported_precision) if total.positive?
79
- return if file_coverage == cobertura_reported_coverage
80
-
81
- filename = package.attributes[:name]
82
- puts "WARNINNG: #{filename} coverage (#{file_coverage}) differed from what cobertura reported (#{cobertura_reported_coverage})"
83
- end
84
- end
85
- end
86
- end
@@ -1,21 +0,0 @@
1
- module Dev
2
- # Module with a variety of coverage methods for different languages
3
- module Coverage
4
- # Class which provides methods to effectvely skip coverage
5
- class None < Base
6
- def initialize(*)
7
- super()
8
- end
9
-
10
- # Returns the php options for generating code coverage file
11
- def php_options
12
- []
13
- end
14
-
15
- # Checks the code coverage against the defined threshold
16
- def check(*)
17
- puts 'Coverage not configured'
18
- end
19
- end
20
- end
21
- end
@@ -1,83 +0,0 @@
1
- module Dev
2
- class Dns
3
- class Resource
4
- attr_reader :domain
5
-
6
- def initialize(domain)
7
- @domain = domain
8
- end
9
-
10
- # Returns whether or not the given value is a valid IPv4 or IPv6 address
11
- def self.ip?(value)
12
- ipv4?(value) || ipv6?(value)
13
- end
14
-
15
- # Returns whether or not the given value is a valid IPv4 address
16
- def self.ipv4?(value)
17
- value.match?(Resolv::IPv4::Regex)
18
- end
19
-
20
- # Returns whether or not the given value is a valid IPv6 address
21
- def self.ipv6?(value)
22
- value.match?(Resolv::IPv6::Regex)
23
- end
24
-
25
- # Recursively determine the correct nameservers for the given domain.
26
- # If nameservers are not found, strip subdomains off until we've reached the TLD
27
- def recursive_nameserver_lookup(name = domain)
28
- records = lookup(name, type: Resolv::DNS::Resource::IN::NS)
29
-
30
- # Strip the subdomain and try again if we didn't find any nameservers (this can happen with wildcards)
31
- return recursive_nameserver_lookup(name.split('.', 2).last) if records.empty?
32
-
33
- # Look up the IPs for the nameservers
34
- records
35
- end
36
-
37
- # Recursively attempt to find an A record for the given domain.
38
- # If one isn't found, also check for CNAMEs continually until we have either found an IP or run out of things to check
39
- def recursive_a_lookup(name = domain)
40
- # Try looking up an A record first. If we find one, we are done.
41
- records = lookup(name, type: Resolv::DNS::Resource::IN::A)
42
- return records unless records.empty?
43
-
44
- # Try looking up a CNAME record
45
- records = lookup(name, type: Resolv::DNS::Resource::IN::CNAME)
46
-
47
- # If we didn't find an A record _or_ a CNAME, just return empty
48
- return records if records.empty?
49
-
50
- # If we found more than one CNAME that is a DNS error
51
- raise "Found more than one CNAME entry for #{name}. This is not allowed by DNS" if records.length > 1
52
-
53
- recursive_a_lookup(records.first)
54
- end
55
-
56
- # Lookup the given name using the record type provided.
57
- def lookup(name = domain, type: Resolv::DNS::Resource::IN::A)
58
- # Validate the type
59
- raise 'lookup type must be a Resolv::DNS::Resource' unless type.ancestors.include?(Resolv::DNS::Resource)
60
-
61
- # If we were given a tld, return empty
62
- return [] unless name.include?('.')
63
-
64
- # Look up NS records for the given host
65
- records = Resolv::DNS.new.getresources(name, type)
66
-
67
- # Return the record names
68
- records.map do |record|
69
- if record.respond_to?(:address)
70
- record.address.to_s
71
- elsif record.respond_to?(:name)
72
- record.name.to_s
73
- else
74
- ''
75
- end
76
- end
77
- rescue
78
- sleep(1)
79
- retry
80
- end
81
- end
82
- end
83
- end
@@ -1,61 +0,0 @@
1
- module Dev
2
- class Docker
3
- # Class for configuring docker desktop
4
- # This is mostly around configuring the docker URL correctly
5
- class Desktop
6
- # A snippet of a docker compose file which forwards a socket to a local port so that we can read it in the docker library
7
- WIN_TCP_COMPOSE_CONTENT = "
8
- ---
9
- version: '3.8'
10
- services:
11
- windows_tcp:
12
- image: alpine/socat
13
- network_mode: bridge
14
- ports:
15
- - 127.0.0.1:23750:2375
16
- volumes:
17
- - /var/run/docker.sock:/var/run/docker.sock
18
- command: tcp-listen:2375,reuseaddr,fork unix-connect:/var/run/docker.sock
19
- restart: always".freeze
20
-
21
- # Set up the local ports/sockets correctly based off of the os type
22
- def configure
23
- if Dev::Os.new.windows?
24
- # Start up a small proxy container if running Docker Desktop on windows
25
- # This is needed because the docker api library cannot connect to the windows socket
26
- unless Dev::Port.new('127.0.0.1', 23_750).open?
27
- LOG.info('Starting local proxy port for docker')
28
-
29
- # Write the compose data to a tmp file
30
- tmp_compose_file = Tempfile.new('windows_tcp')
31
- tmp_compose_file.write(WIN_TCP_COMPOSE_CONTENT)
32
- tmp_compose_file.close
33
-
34
- # Start up the container
35
- Dev::Docker::Compose.new(
36
- compose_files: tmp_compose_file.path,
37
- options: ['--detach'],
38
- project_name: 'proxy'
39
- ).up
40
-
41
- # Wait 1 second before we continue
42
- sleep 1
43
- end
44
-
45
- # Configure the docker url to use 23750 on windows
46
- ::Docker.url = 'tcp://127.0.0.1:23750'
47
-
48
- else
49
- context = Dev::Common.new.run_command(
50
- "docker context inspect --format '{{.Endpoints.docker.Host}}'",
51
- capture: true
52
- ).to_s.strip
53
- raise 'context is empty' unless context
54
-
55
- # If a user based socket has been defined, default to that
56
- ::Docker.url = context
57
- end
58
- end
59
- end
60
- end
61
- end
@@ -1,42 +0,0 @@
1
- module Dev
2
- class EndOfLife
3
- # Class which checks for eol packges referenced by the node package manager
4
- class Node
5
- attr_reader :node, :lockfile
6
-
7
- def initialize(node = Dev::Node.new)
8
- @node = node
9
- @lockfile = File.join(node.local_path, "#{node.package_file.reverse.split('.')[-1].reverse}-lock.json")
10
- end
11
-
12
- # Default to NPM products
13
- def default_products
14
- npm_products
15
- end
16
-
17
- # 1.) Parse the npm lock file
18
- # 2.) Do some package name and version manipulation
19
- # 3.) Return the product if it looks like something that the EOL library tracks
20
- def npm_products
21
- eol = Dev::EndOfLife.new
22
- major_version_only_products = %w(ckeditor jquery)
23
-
24
- [].tap do |ary|
25
- packages = JSON.parse(File.read(lockfile))&.fetch('packages', [])
26
- packages.each do |key, info|
27
- name = key.split('node_modules/').last
28
- product = name
29
-
30
- # Make sure what we found is supported by the EOL library
31
- next unless eol.product?(product)
32
-
33
- version = info['version'].reverse.split('.')[-2..].join('.').reverse.tr('v', '')
34
- version = version.split('.').first if major_version_only_products.include?(product)
35
- version.chop! if version.end_with?('.00')
36
- ary << Dev::EndOfLife::ProductVersion.new(product, version, name)
37
- end
38
- end
39
- end
40
- end
41
- end
42
- end
@@ -1,50 +0,0 @@
1
- module Dev
2
- class EndOfLife
3
- # Class which checks for eol packges referenced by the php package manager
4
- class Php
5
- attr_reader :php, :lockfile
6
-
7
- def initialize(php = Dev::Php.new)
8
- @php = php
9
- @lockfile = File.join(php.local_path, "#{php.package_file.reverse.split('.')[-1].reverse}.lock")
10
- end
11
-
12
- # Default to Composer products
13
- def default_products
14
- composer_products
15
- end
16
-
17
- # 1.) Parse the composer lock file
18
- # 2.) Do some package name and version manipulation
19
- # 3.) Return the product if it looks like something that the EOL library tracks
20
- def composer_products
21
- eol = Dev::EndOfLife.new
22
- major_version_only_products = ['laravel']
23
- laravel_products = ['laravel/framework']
24
- symfony_products = ['symfony/http-client', 'symfony/mailer', 'symfony/mailchimp-mailer']
25
-
26
- [].tap do |ary|
27
- packages = JSON.parse(File.read(lockfile))&.fetch('packages', [])
28
- packages&.each do |package|
29
- name = package['name']
30
- product = if laravel_products.include?(name)
31
- 'laravel'
32
- elsif symfony_products.include?(name)
33
- 'symfony'
34
- else
35
- name
36
- end
37
-
38
- # Make sure what we found is supported by the EOL library
39
- next unless eol.product?(product)
40
-
41
- version = package['version'].reverse.split('.')[-2..].join('.').reverse.tr('v', '')
42
- version = version.split('.').first if major_version_only_products.include?(product)
43
- version.chop! if version.end_with?('.00')
44
- ary << Dev::EndOfLife::ProductVersion.new(product, version, name)
45
- end
46
- end
47
- end
48
- end
49
- end
50
- end
@@ -1,42 +0,0 @@
1
- module Dev
2
- class EndOfLife
3
- # Class which checks for eol packges referenced by the ruby package manager
4
- class Ruby
5
- attr_reader :ruby, :lockfile
6
-
7
- def initialize(ruby = Dev::Ruby.new)
8
- @ruby = ruby
9
- @lockfile = File.join(ruby.local_path, "#{ruby.package_file.reverse.split('.')[-1].reverse}.lock")
10
- end
11
-
12
- # Default to Rubygems products
13
- def default_products
14
- rubygems_products
15
- end
16
-
17
- # 1.) Parse the rubygems lock file
18
- # 2.) Do some package name and version manipulation
19
- # 3.) Return the product if it looks like something that the EOL library tracks
20
- def rubygems_products
21
- eol = Dev::EndOfLife.new
22
- major_version_only_products = []
23
-
24
- [].tap do |ary|
25
- packages = Bundler::LockfileParser.new(Bundler.read_file(lockfile)).specs
26
- packages.each do |package|
27
- name = package.name
28
- product = name
29
-
30
- # Make sure what we found is supported by the EOL library
31
- next unless eol.product?(product)
32
-
33
- version = package.version.to_s.reverse.split('.')[-2..].join('.').reverse.tr('v', '')
34
- version = version.split('.').first if major_version_only_products.include?(product)
35
- version.chop! if version.end_with?('.00')
36
- ary << Dev::EndOfLife::ProductVersion.new(product, version, name)
37
- end
38
- end
39
- end
40
- end
41
- end
42
- end
@@ -1,19 +0,0 @@
1
- module Dev
2
- class Jira
3
- # Contains information on the Jira parent issue
4
- class Parent
5
- attr_accessor :data, :id, :title
6
-
7
- def initialize(data)
8
- @data = data.parent
9
- @id = data.parent['key']
10
- @title = data.parent['fields']['summary']
11
- end
12
-
13
- # Converts the jira parent object to a string representation
14
- def to_s
15
- "[#{id}] #{title}"
16
- end
17
- end
18
- end
19
- end
@@ -1,35 +0,0 @@
1
- module Dev
2
- # Class containing methods for determining operating system information
3
- class Os
4
- attr_accessor :os
5
-
6
- def initialize
7
- @os = ::RbConfig::CONFIG['host_os']
8
- end
9
-
10
- # Returns true if the host_os contains windowsy text
11
- def windows?
12
- os.match?(/(mingw|mswin|windows)/i)
13
- end
14
-
15
- # Returns true if the host_os contains darwinsy text
16
- def darwin?
17
- os.match?(/(darwin|mac os)/i)
18
- end
19
-
20
- # Returns true if the host_os contains macsy text
21
- def mac?
22
- darwin?
23
- end
24
-
25
- # Returns true if the host_os contains nixy text
26
- def nix?
27
- os.match?(/(linux|bsd|aix|solaris)/i)
28
- end
29
-
30
- # Returns true if the host_os contains cygwiny text
31
- def cygwin?
32
- os.match?(/(cygwin)/i)
33
- end
34
- end
35
- end
@@ -1,24 +0,0 @@
1
- module Dev
2
- # Class containing methods for actions to be taken on ports
3
- class Port
4
- attr_accessor :ip_address, :port
5
-
6
- def initialize(ip_address, port)
7
- @ip_address = ip_address
8
- @port = port
9
- end
10
-
11
- # Returns true if the port is open
12
- # Returns false otherwise
13
- def open?(timeout = 1)
14
- Timeout.timeout(timeout) do
15
- TCPSocket.new(ip_address, port).close
16
- return true
17
- end
18
-
19
- false
20
- rescue Timeout::Error, Errno::ECONNREFUSED, Errno::EHOSTUNREACH
21
- false
22
- end
23
- end
24
- end