firespring_dev_commands 2.1.10.pre.alpha.1 → 2.1.10.pre.alpha.2
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 +4 -4
- data/lib/firespring_dev_commands/git.rb +12 -0
- data/lib/firespring_dev_commands/jira/histories.rb +2 -0
- data/lib/firespring_dev_commands/jira/history.rb +1 -0
- data/lib/firespring_dev_commands/jira/issue.rb +6 -0
- data/lib/firespring_dev_commands/platform.rb +6 -2
- data/lib/firespring_dev_commands/target_process/project.rb +1 -0
- data/lib/firespring_dev_commands/target_process/query.rb +12 -0
- data/lib/firespring_dev_commands/target_process/release.rb +1 -0
- data/lib/firespring_dev_commands/target_process/team.rb +1 -0
- data/lib/firespring_dev_commands/target_process/user.rb +1 -0
- data/lib/firespring_dev_commands/target_process/user_story.rb +3 -0
- data/lib/firespring_dev_commands/target_process.rb +13 -9
- data/lib/firespring_dev_commands/version.rb +1 -1
- metadata +1 -1
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: c75f83066598edad92a8d34dd12d898d9f5229cf80bd8eeba166cd7e5451296e
         | 
| 4 | 
            +
              data.tar.gz: 832006c6ec28b9b8a288e3a0d510f628f3c468b3c0cb8614d1eae5927f25184a
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: f3ea07c7f9be119c8ec47914c213560069ee1c17b6a0e8dcbe43b41cb246febd258079b12843d2819cdd4b1cc7aa180e3515fd8edeaca8fea9a5866758614a33
         | 
| 7 | 
            +
              data.tar.gz: b395757808d58b999546d5df762ef46caf59ebf670599ec77d0b1c91098381c9f6da96e102141050f1a638ea83972c2757d795016e90cff1bb0474d0865b5db0
         | 
| @@ -203,6 +203,7 @@ module Dev | |
| 203 203 |  | 
| 204 204 | 
             
                # Checks out the given branch in the given repo
         | 
| 205 205 | 
             
                # Defaults to the current directory
         | 
| 206 | 
            +
                # optionally raise errors
         | 
| 206 207 | 
             
                def checkout(branch, dir: default_project_dir, raise_errors: false)
         | 
| 207 208 | 
             
                  raise 'branch is required' if branch.to_s.strip.empty?
         | 
| 208 209 | 
             
                  return unless File.exist?(dir)
         | 
| @@ -231,6 +232,8 @@ module Dev | |
| 231 232 | 
             
                end
         | 
| 232 233 |  | 
| 233 234 | 
             
                # Create the given branch in the given repo
         | 
| 235 | 
            +
                # Defaults to the current directory
         | 
| 236 | 
            +
                # optionally raise errors
         | 
| 234 237 | 
             
                def create_branch(branch, dir: default_project_dir, raise_errors: false)
         | 
| 235 238 | 
             
                  raise 'branch is required' if branch.to_s.strip.empty?
         | 
| 236 239 | 
             
                  raise "refusing to create protected branch '#{branch}'" if %w(master develop).any?(branch.to_s.strip)
         | 
| @@ -259,6 +262,9 @@ module Dev | |
| 259 262 | 
             
                  false
         | 
| 260 263 | 
             
                end
         | 
| 261 264 |  | 
| 265 | 
            +
                # Add the given paths to git
         | 
| 266 | 
            +
                # Defaults to the current directory
         | 
| 267 | 
            +
                # optionally raise errors
         | 
| 262 268 | 
             
                def add(*paths, dir: default_project_dir, raise_errors: false)
         | 
| 263 269 | 
             
                  g = ::Git.open(dir)
         | 
| 264 270 | 
             
                  indent g.add(paths)
         | 
| @@ -292,6 +298,8 @@ module Dev | |
| 292 298 | 
             
                end
         | 
| 293 299 |  | 
| 294 300 | 
             
                # Merge the given branch into the given repo
         | 
| 301 | 
            +
                # Defaults to the current directory
         | 
| 302 | 
            +
                # optionally raise errors
         | 
| 295 303 | 
             
                def merge(branch, dir: default_project_dir, raise_errors: false)
         | 
| 296 304 | 
             
                  raise 'branch is required' if branch.to_s.strip.empty?
         | 
| 297 305 | 
             
                  return unless File.exist?(dir)
         | 
| @@ -337,6 +345,8 @@ module Dev | |
| 337 345 | 
             
                end
         | 
| 338 346 |  | 
| 339 347 | 
             
                # Pull the given repo
         | 
| 348 | 
            +
                # Defaults to the current directory
         | 
| 349 | 
            +
                # optionally raise errors
         | 
| 340 350 | 
             
                def pull(dir: default_project_dir, raise_errors: false)
         | 
| 341 351 | 
             
                  return unless File.exist?(dir)
         | 
| 342 352 |  | 
| @@ -374,6 +384,8 @@ module Dev | |
| 374 384 | 
             
                end
         | 
| 375 385 |  | 
| 376 386 | 
             
                # Push the given repo
         | 
| 387 | 
            +
                # Defaults to the current directory
         | 
| 388 | 
            +
                # optionally raise errors
         | 
| 377 389 | 
             
                def push(dir: default_project_dir, raise_errors: false)
         | 
| 378 390 | 
             
                  return unless File.exist?(dir)
         | 
| 379 391 |  | 
| @@ -1,6 +1,8 @@ | |
| 1 1 | 
             
            module Dev
         | 
| 2 2 | 
             
              class Jira
         | 
| 3 | 
            +
                # Class which provides a helper method for converting the changelog data to history objects
         | 
| 3 4 | 
             
                class Histories
         | 
| 5 | 
            +
                  # If changelog is present in the given data, return an array of history objects for each changelog entry
         | 
| 4 6 | 
             
                  def self.populate(data)
         | 
| 5 7 | 
             
                    return nil unless data.attrs.key?('changelog')
         | 
| 6 8 |  | 
| @@ -21,21 +21,25 @@ module Dev | |
| 21 21 | 
             
                    @last_closed_history = nil
         | 
| 22 22 | 
             
                  end
         | 
| 23 23 |  | 
| 24 | 
            +
                  # Returns the cycle time of the issue (time between in progress and closed states)
         | 
| 24 25 | 
             
                  def cycle_time
         | 
| 25 26 | 
             
                    # Calculate the difference and convert to days
         | 
| 26 27 | 
             
                    ((last_closed_history.created - last_in_progress_history.created) / 60 / 60 / 24).round(2)
         | 
| 27 28 | 
             
                  end
         | 
| 28 29 |  | 
| 30 | 
            +
                  # Returns the time the issue was in progress (time between in progress and in review states)
         | 
| 29 31 | 
             
                  def in_progress_cycle_time
         | 
| 30 32 | 
             
                    # Calculate the difference and convert to days
         | 
| 31 33 | 
             
                    ((first_in_review_history.created - last_in_progress_history.created) / 60 / 60 / 24).round(2)
         | 
| 32 34 | 
             
                  end
         | 
| 33 35 |  | 
| 36 | 
            +
                  # Returns the time the issue was in review (time between in review and closed states)
         | 
| 34 37 | 
             
                  def in_review_cycle_time
         | 
| 35 38 | 
             
                    # Calculate the difference and convert to days
         | 
| 36 39 | 
             
                    ((last_closed_history.created - first_in_review_history.created) / 60 / 60 / 24).round(2)
         | 
| 37 40 | 
             
                  end
         | 
| 38 41 |  | 
| 42 | 
            +
                  # Loop through the issue history and find the most recent state change from Open to In Progress
         | 
| 39 43 | 
             
                  private def last_in_progress_history
         | 
| 40 44 | 
             
                    raise 'you must expand the changelog field to calculate cycle time' if histories.nil?
         | 
| 41 45 |  | 
| @@ -50,6 +54,7 @@ module Dev | |
| 50 54 | 
             
                    @last_in_progress_history
         | 
| 51 55 | 
             
                  end
         | 
| 52 56 |  | 
| 57 | 
            +
                  # Loop through the issue history and find the oldest state change to In Review
         | 
| 53 58 | 
             
                  private def first_in_review_history
         | 
| 54 59 | 
             
                    raise 'you must expand the changelog field to calculate cycle time' if histories.nil?
         | 
| 55 60 |  | 
| @@ -64,6 +69,7 @@ module Dev | |
| 64 69 | 
             
                    @first_in_review_history
         | 
| 65 70 | 
             
                  end
         | 
| 66 71 |  | 
| 72 | 
            +
                  # Loop through the issue history and find the most recent state change to closed
         | 
| 67 73 | 
             
                  private def last_closed_history
         | 
| 68 74 | 
             
                    raise 'you must expand the changelog field to calculate cycle time' if histories.nil?
         | 
| 69 75 |  | 
| @@ -1,8 +1,11 @@ | |
| 1 1 | 
             
            module Dev
         | 
| 2 2 | 
             
              class Common
         | 
| 3 | 
            +
                # Class which returns information about the current platform
         | 
| 3 4 | 
             
                class Platform
         | 
| 5 | 
            +
                  # Constant containing all supported architectures
         | 
| 4 6 | 
             
                  ALLOWED_ARCHITECTURES = %w(arm64 amd64).freeze
         | 
| 5 7 |  | 
| 8 | 
            +
                  # Normalize the ruby platform to return a docker platform architecture format
         | 
| 6 9 | 
             
                  def determine_compute_architecture
         | 
| 7 10 | 
             
                    case RUBY_PLATFORM
         | 
| 8 11 | 
             
                    when /x86_64|amd64/
         | 
| @@ -14,6 +17,9 @@ module Dev | |
| 14 17 | 
             
                    end
         | 
| 15 18 | 
             
                  end
         | 
| 16 19 |  | 
| 20 | 
            +
                  # Determine the platform architecture
         | 
| 21 | 
            +
                  # If one was specified in the DOCKER_ARCHITECTURE variable, use it
         | 
| 22 | 
            +
                  # Otherwise, use the RUBY_PLATFORM built-in to auto-detect and architecture
         | 
| 17 23 | 
             
                  def architecture
         | 
| 18 24 | 
             
                    docker_architecture = ENV['DOCKER_ARCHITECTURE'].to_s.strip.downcase
         | 
| 19 25 | 
             
                    if docker_architecture.empty?
         | 
| @@ -22,13 +28,11 @@ module Dev | |
| 22 28 | 
             
                      raise "Missing 'linux/' prefix in DOCKER_ARCHITECTURE: #{docker_architecture}" unless docker_architecture.start_with?('linux/')
         | 
| 23 29 |  | 
| 24 30 | 
             
                      architecture_name = docker_architecture.split('/')[1]
         | 
| 25 | 
            -
             | 
| 26 31 | 
             
                      unless ALLOWED_ARCHITECTURES.include?(architecture_name)
         | 
| 27 32 | 
             
                        raise "Invalid DOCKER_ARCHITECTURE: #{architecture_name}. Allowed architectures are #{ALLOWED_ARCHITECTURES.join(', ')}"
         | 
| 28 33 | 
             
                      end
         | 
| 29 34 |  | 
| 30 35 | 
             
                      docker_architecture
         | 
| 31 | 
            -
             | 
| 32 36 | 
             
                    end
         | 
| 33 37 | 
             
                  end
         | 
| 34 38 | 
             
                end
         | 
| @@ -1,5 +1,6 @@ | |
| 1 1 | 
             
            module Dev
         | 
| 2 2 | 
             
              class TargetProcess
         | 
| 3 | 
            +
                # Class for writing target process query statements
         | 
| 3 4 | 
             
                class Query
         | 
| 4 5 | 
             
                  attr_accessor :where, :incl, :take
         | 
| 5 6 |  | 
| @@ -9,10 +10,12 @@ module Dev | |
| 9 10 | 
             
                    @take = 250
         | 
| 10 11 | 
             
                  end
         | 
| 11 12 |  | 
| 13 | 
            +
                  # Add a new query clause
         | 
| 12 14 | 
             
                  def <<(item)
         | 
| 13 15 | 
             
                    where << item
         | 
| 14 16 | 
             
                  end
         | 
| 15 17 |  | 
| 18 | 
            +
                  # Add the item to the where clause
         | 
| 16 19 | 
             
                  def where=(item)
         | 
| 17 20 | 
             
                    if item.is_a?(Array)
         | 
| 18 21 | 
             
                      where.concat(item)
         | 
| @@ -21,6 +24,7 @@ module Dev | |
| 21 24 | 
             
                    end
         | 
| 22 25 | 
             
                  end
         | 
| 23 26 |  | 
| 27 | 
            +
                  # Add the item to the include clause
         | 
| 24 28 | 
             
                  def include=(item)
         | 
| 25 29 | 
             
                    if item.is_a?(Array)
         | 
| 26 30 | 
             
                      incl.concat(item)
         | 
| @@ -29,6 +33,7 @@ module Dev | |
| 29 33 | 
             
                    end
         | 
| 30 34 | 
             
                  end
         | 
| 31 35 |  | 
| 36 | 
            +
                  # Generate the string representation for this query
         | 
| 32 37 | 
             
                  def generate
         | 
| 33 38 | 
             
                    {}.tap do |clause|
         | 
| 34 39 | 
             
                      clause[:where] = where.join(' and ') unless where.nil? || where.empty?
         | 
| @@ -37,31 +42,38 @@ module Dev | |
| 37 42 | 
             
                    end
         | 
| 38 43 | 
             
                  end
         | 
| 39 44 |  | 
| 45 | 
            +
                  # Generate the string representation for this query
         | 
| 40 46 | 
             
                  def to_s
         | 
| 41 47 | 
             
                    generate
         | 
| 42 48 | 
             
                  end
         | 
| 43 49 |  | 
| 50 | 
            +
                  # Add a filter that looks for stories whose id is contained in the list of ids given
         | 
| 44 51 | 
             
                  def filter_by_user_story_ids(user_story_ids)
         | 
| 45 52 | 
             
                    self << "(Id in ('#{user_story_ids.join("', '")}'))"
         | 
| 46 53 | 
             
                  end
         | 
| 47 54 |  | 
| 55 | 
            +
                  # Add a filter that looks for stories whose project id is contained in the list of ids given
         | 
| 48 56 | 
             
                  def filter_by_project(projects)
         | 
| 49 57 | 
             
                    self << "(Project.Name in ('#{projects.join("', '")}'))"
         | 
| 50 58 | 
             
                  end
         | 
| 51 59 |  | 
| 60 | 
            +
                  # Add a filter that looks for stories whose state is contained in the list of states given
         | 
| 52 61 | 
             
                  def filter_by_states(states)
         | 
| 53 62 | 
             
                    self << "(EntityState.Name in ('#{states.join("', '")}'))" unless states.nil? || states.empty?
         | 
| 54 63 | 
             
                  end
         | 
| 55 64 |  | 
| 65 | 
            +
                  # Add a filter that looks for stories whose state is set to final
         | 
| 56 66 | 
             
                  def filter_by_final
         | 
| 57 67 | 
             
                    self << "(EntityState.IsFinal eq 'true')"
         | 
| 58 68 | 
             
                  end
         | 
| 59 69 |  | 
| 70 | 
            +
                  # Add a filter that looks for stories whose end date is between the given dates
         | 
| 60 71 | 
             
                  def filter_by_end_dates(start_date, end_date)
         | 
| 61 72 | 
             
                    self << "(EndDate gt '#{start_date}')" if start_date
         | 
| 62 73 | 
             
                    self << "(EndDate lt '#{end_date}')" if end_date
         | 
| 63 74 | 
             
                  end
         | 
| 64 75 |  | 
| 76 | 
            +
                  # Add a filter that looks for stories which do not have a linked test plan
         | 
| 65 77 | 
             
                  def filter_by_missing_tests
         | 
| 66 78 | 
             
                    self << '(LinkedTestPlan is nil)'
         | 
| 67 79 | 
             
                  end
         | 
| @@ -1,6 +1,8 @@ | |
| 1 1 | 
             
            module Dev
         | 
| 2 2 | 
             
              class TargetProcess
         | 
| 3 | 
            +
                # Class containing user story information
         | 
| 3 4 | 
             
                class UserStory
         | 
| 5 | 
            +
                  # The api path for user story requests
         | 
| 4 6 | 
             
                  PATH = '/UserStories'.freeze
         | 
| 5 7 |  | 
| 6 8 | 
             
                  attr_accessor :type, :id, :name, :description, :start_date, :end_date, :create_date, :modify_date, :tags, :effort, :time_spent, :last_state_change_date, :project,
         | 
| @@ -35,6 +37,7 @@ module Dev | |
| 35 37 | 
             
                    Time.at(string.slice(6, 10).to_i)
         | 
| 36 38 | 
             
                  end
         | 
| 37 39 |  | 
| 40 | 
            +
                  # Calculate the cycle time as the amount of time the story was open
         | 
| 38 41 | 
             
                  def cycle_time
         | 
| 39 42 | 
             
                    return 1.0 unless start_date && end_date
         | 
| 40 43 |  | 
| @@ -1,15 +1,21 @@ | |
| 1 1 | 
             
            require 'net/http'
         | 
| 2 2 |  | 
| 3 3 | 
             
            module Dev
         | 
| 4 | 
            +
              # Class for querying target process data from their api
         | 
| 4 5 | 
             
              class TargetProcess
         | 
| 6 | 
            +
                # The config file to try to load credentials from
         | 
| 5 7 | 
             
                CONFIG_FILE = "#{Dir.home}/.env.tp".freeze
         | 
| 6 8 |  | 
| 9 | 
            +
                # The text of the username variable key
         | 
| 7 10 | 
             
                TP_USERNAME = 'TP_USERNAME'.freeze
         | 
| 8 11 |  | 
| 12 | 
            +
                # The text of the password variable key
         | 
| 9 13 | 
             
                TP_PASSWORD = 'TP_PASSWORD'.freeze
         | 
| 10 14 |  | 
| 15 | 
            +
                # The text of the url variable key
         | 
| 11 16 | 
             
                TP_URL = 'TP_URL'.freeze
         | 
| 12 17 |  | 
| 18 | 
            +
                # Config object for setting top level jira config options
         | 
| 13 19 | 
             
                Config = Struct.new(:username, :password, :url, :http_debug) do
         | 
| 14 20 | 
             
                  def initialize
         | 
| 15 21 | 
             
                    Dotenv.load(CONFIG_FILE) if File.exist?(CONFIG_FILE)
         | 
| @@ -37,7 +43,7 @@ module Dev | |
| 37 43 |  | 
| 38 44 | 
             
                attr_accessor :username, :password, :url, :auth, :client, :headers
         | 
| 39 45 |  | 
| 40 | 
            -
                # Initialize a new  | 
| 46 | 
            +
                # Initialize a new target process client using the given inputs
         | 
| 41 47 | 
             
                def initialize(username: self.class.config.username, password: self.class.config.password, url: self.class.config.url)
         | 
| 42 48 | 
             
                  @username = username
         | 
| 43 49 | 
             
                  @password = password
         | 
| @@ -55,6 +61,9 @@ module Dev | |
| 55 61 | 
             
                  }
         | 
| 56 62 | 
             
                end
         | 
| 57 63 |  | 
| 64 | 
            +
                # Perform a query to the user story api path
         | 
| 65 | 
            +
                # Call the given block (if present) with each user story
         | 
| 66 | 
            +
                # Return all user stories
         | 
| 58 67 | 
             
                def user_stories(query, &)
         | 
| 59 68 | 
             
                  [].tap do |ary|
         | 
| 60 69 | 
             
                    get(UserStory::PATH, query) do |result|
         | 
| @@ -64,6 +73,9 @@ module Dev | |
| 64 73 | 
             
                  end
         | 
| 65 74 | 
             
                end
         | 
| 66 75 |  | 
| 76 | 
            +
                # Perform a get request to the given path using the given query
         | 
| 77 | 
            +
                # Call the given block (if present) with each piece of data
         | 
| 78 | 
            +
                # Return all pieces of data
         | 
| 67 79 | 
             
                def get(path, query, &)
         | 
| 68 80 | 
             
                  query_string = query.generate
         | 
| 69 81 | 
             
                  url = "/api/v1/#{path}"
         | 
| @@ -89,13 +101,5 @@ module Dev | |
| 89 101 |  | 
| 90 102 | 
             
                  nil
         | 
| 91 103 | 
             
                end
         | 
| 92 | 
            -
             | 
| 93 | 
            -
                def self.parse_dot_net_time(string)
         | 
| 94 | 
            -
                  Time.at(string.slice(6, 10).to_i)
         | 
| 95 | 
            -
                end
         | 
| 96 | 
            -
             | 
| 97 | 
            -
                def self.parse_dot_net_date(string)
         | 
| 98 | 
            -
                  parse_dot_net_time(string).to_date
         | 
| 99 | 
            -
                end
         | 
| 100 104 | 
             
              end
         | 
| 101 105 | 
             
            end
         |