module CC module Analyzer # The shared interface, invoked by Builder or CLI::Analyze # # Input: # - config # - engines # - exclude_patterns # - development? # - analysis_paths # - formatter # - started # - engine_running # - finished # - close # - listener # - started(engine, details) # - finished(engine, details, result) # - registry # # Only raises if Listener raises # class Bridge def initialize(config:, formatter:, listener:, registry:) @config = config @formatter = formatter @listener = listener @registry = registry end def run formatter.started config.engines.each do |engine| next unless engine.enabled? formatter.engine_running(engine) do result = nil engine_details = nil begin engine_details = registry.fetch_engine_details( engine, development: config.development?, ) listener.started(engine, engine_details) result = run_engine(engine, engine_details) rescue CC::EngineRegistry::EngineDetailsNotFoundError => ex result = Container::Result.skipped(ex) end listener.finished(engine, engine_details, result) result end end formatter.finished ensure formatter.close end private attr_reader :config, :formatter, :listener, :registry def run_engine(engine, engine_details) # Analyzer::Engine doesn't have the best interface, but we're limiting # our refactors for now. Engine.new( engine.name, { "image" => engine_details.image, "command" => engine_details.command, "memory" => engine_details.memory, }, engine.config.merge( "channel" => engine.channel, "include_paths" => engine_workspace(engine).paths, ), engine.container_label, ).run(formatter) end def engine_workspace(engine) if engine.exclude_patterns.any? workspace.clone.tap do |engine_workspace| engine_workspace.remove(engine.exclude_patterns) end else workspace end end def workspace @workspace ||= Workspace.new.tap do |workspace| workspace.add(config.analysis_paths) unless config.analysis_paths.any? workspace.remove([".git"]) workspace.remove(config.exclude_patterns) end end end end end end