Class: Aidp::Setup::Devcontainer::Parser
- Inherits:
-
Object
- Object
- Aidp::Setup::Devcontainer::Parser
- Defined in:
- lib/aidp/setup/devcontainer/parser.rb
Overview
Parses existing devcontainer.json files and extracts configuration for pre-filling wizard defaults.
Defined Under Namespace
Classes: DevcontainerNotFoundError, InvalidDevcontainerError
Constant Summary collapse
- STANDARD_LOCATIONS =
[ ".devcontainer/devcontainer.json", ".devcontainer.json", "devcontainer.json" ].freeze
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#devcontainer_path ⇒ Object
readonly
Returns the value of attribute devcontainer_path.
-
#project_dir ⇒ Object
readonly
Returns the value of attribute project_dir.
Instance Method Summary collapse
-
#detect ⇒ String?
Detect devcontainer.json in standard locations.
-
#devcontainer_exists? ⇒ Boolean
Check if devcontainer exists.
-
#extract_customizations ⇒ Hash
Extract VS Code customizations.
-
#extract_env ⇒ Hash
Extract container environment variables.
-
#extract_features ⇒ Array<String>
Extract devcontainer features.
-
#extract_image_config ⇒ Hash
Extract the base image or dockerfile reference.
-
#extract_ports ⇒ Array<Hash>
Extract port forwarding configuration.
-
#extract_post_commands ⇒ Hash
Extract post-create and post-start commands.
-
#extract_remote_user ⇒ String?
Extract remote user setting.
-
#extract_workspace_folder ⇒ String?
Extract working directory.
-
#initialize(project_dir = Dir.pwd) ⇒ Parser
constructor
A new instance of Parser.
-
#parse ⇒ Hash
Parse devcontainer.json and extract configuration.
-
#to_h ⇒ Hash
Get complete parsed configuration as hash.
Constructor Details
#initialize(project_dir = Dir.pwd) ⇒ Parser
Returns a new instance of Parser.
23 24 25 26 27 |
# File 'lib/aidp/setup/devcontainer/parser.rb', line 23 def initialize(project_dir = Dir.pwd) @project_dir = project_dir @devcontainer_path = nil @config = nil end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
21 22 23 |
# File 'lib/aidp/setup/devcontainer/parser.rb', line 21 def config @config end |
#devcontainer_path ⇒ Object (readonly)
Returns the value of attribute devcontainer_path.
21 22 23 |
# File 'lib/aidp/setup/devcontainer/parser.rb', line 21 def devcontainer_path @devcontainer_path end |
#project_dir ⇒ Object (readonly)
Returns the value of attribute project_dir.
21 22 23 |
# File 'lib/aidp/setup/devcontainer/parser.rb', line 21 def project_dir @project_dir end |
Instance Method Details
#detect ⇒ String?
Detect devcontainer.json in standard locations
31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/aidp/setup/devcontainer/parser.rb', line 31 def detect STANDARD_LOCATIONS.each do |location| path = File.join(project_dir, location) if File.exist?(path) @devcontainer_path = path Aidp.log_debug("devcontainer_parser", "detected devcontainer", path: path) return path end end Aidp.log_debug("devcontainer_parser", "no devcontainer found") nil end |
#devcontainer_exists? ⇒ Boolean
Check if devcontainer exists
47 48 49 |
# File 'lib/aidp/setup/devcontainer/parser.rb', line 47 def devcontainer_exists? !detect.nil? end |
#extract_customizations ⇒ Hash
Extract VS Code customizations
164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/aidp/setup/devcontainer/parser.rb', line 164 def extract_customizations ensure_parsed customizations = @config["customizations"] || {} vscode = customizations["vscode"] || {} { extensions: Array(vscode["extensions"]), settings: vscode["settings"] || {} } end |
#extract_env ⇒ Hash
Extract container environment variables
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/aidp/setup/devcontainer/parser.rb', line 133 def extract_env ensure_parsed env = @config["containerEnv"] || @config["remoteEnv"] || {} env = {} unless env.is_a?(Hash) # Filter out sensitive values filtered_env = env.reject { |key, value| sensitive_key?(key) || sensitive_value?(value) } Aidp.log_debug("devcontainer_parser", "extracted env vars", total: env.size, filtered: filtered_env.size) filtered_env end |
#extract_features ⇒ Array<String>
Extract devcontainer features
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/aidp/setup/devcontainer/parser.rb', line 112 def extract_features ensure_parsed features = @config["features"] || {} # Handle both object and array format feature_list = case features when Hash features.keys when Array features else [] end Aidp.log_debug("devcontainer_parser", "extracted features", count: feature_list.size) feature_list end |
#extract_image_config ⇒ Hash
Extract the base image or dockerfile reference
192 193 194 195 196 197 198 199 200 201 |
# File 'lib/aidp/setup/devcontainer/parser.rb', line 192 def extract_image_config ensure_parsed { image: @config["image"], dockerfile: @config["dockerFile"] || @config["dockerfile"], context: @config["context"], build: @config["build"] }.compact end |
#extract_ports ⇒ Array<Hash>
Extract port forwarding configuration
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/aidp/setup/devcontainer/parser.rb', line 80 def extract_ports ensure_parsed ports = [] # Extract from forwardPorts array forward_ports = @config["forwardPorts"] || [] forward_ports = [forward_ports] unless forward_ports.is_a?(Array) # Get port attributes for labels port_attrs = @config["portsAttributes"] || {} forward_ports.each do |port| port_num = port.to_i next if port_num <= 0 attrs = port_attrs[port.to_s] || port_attrs[port_num.to_s] || {} ports << { number: port_num, label: attrs["label"], protocol: attrs["protocol"] || "http", on_auto_forward: attrs["onAutoForward"] || "notify" } end Aidp.log_debug("devcontainer_parser", "extracted ports", count: ports.size) ports end |
#extract_post_commands ⇒ Hash
Extract post-create and post-start commands
152 153 154 155 156 157 158 159 160 |
# File 'lib/aidp/setup/devcontainer/parser.rb', line 152 def extract_post_commands ensure_parsed { post_create: @config["postCreateCommand"], post_start: @config["postStartCommand"], post_attach: @config["postAttachCommand"] }.compact end |
#extract_remote_user ⇒ String?
Extract remote user setting
178 179 180 181 |
# File 'lib/aidp/setup/devcontainer/parser.rb', line 178 def extract_remote_user ensure_parsed @config["remoteUser"] end |
#extract_workspace_folder ⇒ String?
Extract working directory
185 186 187 188 |
# File 'lib/aidp/setup/devcontainer/parser.rb', line 185 def extract_workspace_folder ensure_parsed @config["workspaceFolder"] end |
#parse ⇒ Hash
Parse devcontainer.json and extract configuration
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/aidp/setup/devcontainer/parser.rb', line 55 def parse detect unless @devcontainer_path unless @devcontainer_path raise DevcontainerNotFoundError, "No devcontainer.json found in #{project_dir}" end begin content = File.read(@devcontainer_path) @config = JSON.parse(content) Aidp.log_debug("devcontainer_parser", "parsed devcontainer", features_count: extract_features.size, ports_count: extract_ports.size) @config rescue JSON::ParserError => e Aidp.log_error("devcontainer_parser", "invalid JSON", error: e., path: @devcontainer_path) raise InvalidDevcontainerError, "Invalid JSON in #{@devcontainer_path}: #{e.}" rescue => e Aidp.log_error("devcontainer_parser", "failed to read devcontainer", error: e.) raise InvalidDevcontainerError, "Failed to read #{@devcontainer_path}: #{e.}" end end |
#to_h ⇒ Hash
Get complete parsed configuration as hash
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/aidp/setup/devcontainer/parser.rb', line 205 def to_h ensure_parsed { path: @devcontainer_path, ports: extract_ports, features: extract_features, env: extract_env, post_commands: extract_post_commands, customizations: extract_customizations, remote_user: extract_remote_user, workspace_folder: extract_workspace_folder, image_config: extract_image_config, raw: @config } end |