brainiac-fizzy 0.0.31 → 0.0.32

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
  SHA256:
3
- metadata.gz: 99e73a13d858f22832a0b44acfd689e902e3e35dfc416e891792610f13b42d9f
4
- data.tar.gz: bfc325433038c58471ebe821c9a27b5554e1c73aa3da8f6974813a9af5769233
3
+ metadata.gz: 7db11f41fae35db895516e80e9de7e4c8c058523bd8bcc11b5b6a64b00462c41
4
+ data.tar.gz: 8cff0f7ca421e7ca5a20344a83f0f89a0a6cce4102f2daa5cc5d4fc5c2f1a2ac
5
5
  SHA512:
6
- metadata.gz: 69e3d38e6aba9c10c394c2606020981c414a20bdf766712d07faed4ef2c33012cb1f87abd4b60bc6699c5879bd6cefdc555215dcab6af593e7917e6dfa4f1f62
7
- data.tar.gz: 76c41f2d36849f4226dfb33a1cbf501f223551fccc1831b9baa9eeef7ff2f03ff2020dbb66b07ce4190430c50448981b1c659e9ec51ba38db388dc7f47ba6b8c
6
+ metadata.gz: 66bb5070c162be023a3ed046e9748f4fdf1197841aeb47a07c8b660e3759a48aa01773b587edb68bd762f6ab863280c44578f3ba1cc4c654e4fc9ce74946ccac
7
+ data.tar.gz: 9232d4131f5298d4a3e9190c39c360e0a02296ad05b40dacf12be5b64599517af001b94c56bbd9b032fcfafc89b004e6800f6a2a6372868e20e8dc74da5cd996
@@ -47,7 +47,7 @@ def handle_card_assigned(payload, board_key: nil)
47
47
  worktree_path = setup_assigned_worktree(repo_path, branch, card_internal_id, card_number, project_key, assigned_agent, board_key: board_key)
48
48
 
49
49
  initial_cli = detect_cli_provider(tags: tags)
50
- initial_model = detect_model(project_config, tags: tags)
50
+ initial_model, initial_model_explicit = detect_model_explicit(project_config, tags: tags)
51
51
  initial_effort = detect_effort(project_config, tags: tags)
52
52
  # Profile ([profile:X]/[p:X]) can be specified inline in the card title.
53
53
  # It's a named env bundle (e.g. an alternate kiro-cli account) — see core profiles.rb.
@@ -69,7 +69,8 @@ def handle_card_assigned(payload, board_key: nil)
69
69
  card_number: card_number, card_internal_id: card_internal_id, title: title, tags: tags,
70
70
  branch: branch, worktree_path: worktree_path, project_config: project_config, project_key: project_key,
71
71
  agent_name: assigned_agent, model: initial_model,
72
- effort: initial_effort, cli_provider_override: initial_cli, profile: initial_profile, board_key: board_key
72
+ effort: initial_effort, cli_provider_override: initial_cli, profile: initial_profile, board_key: board_key,
73
+ explicit_model: initial_model_explicit
73
74
  )
74
75
  end
75
76
 
@@ -140,7 +141,7 @@ end
140
141
 
141
142
  def dispatch_assigned_card(card_number:, card_internal_id:, title:, tags:, branch:, worktree_path:,
142
143
  project_config:, project_key:, agent_name:, model:, effort:, cli_provider_override:,
143
- profile: nil, board_key: nil)
144
+ profile: nil, board_key: nil, explicit_model: nil)
144
145
  card_context = prefetch_card_context(card_number, repo_path: project_config["repo_path"], agent_name: agent_name)
145
146
  planning_info = detect_planning_mode(text: title, tags: tags, card_internal_id: card_internal_id, card_number: card_number)
146
147
 
@@ -184,7 +185,8 @@ def dispatch_assigned_card(card_number:, card_internal_id:, title:, tags:, branc
184
185
  log_name: "assigned-#{card_number}", model: model, effort: effort,
185
186
  agent_name: agent_name, card_number: card_number, source: :fizzy,
186
187
  source_context: { card_number: card_number, board_key: board_key, dispatched_at: Time.now },
187
- cli_provider: cli_provider_override, profile: profile, env: agent_github_env)
188
+ cli_provider: cli_provider_override, profile: profile, env: agent_github_env,
189
+ explicit_model: explicit_model)
188
190
  register_session(card_key, pid, log_file: log_file, supersede_key: card_key, agent_name: agent_name)
189
191
 
190
192
  Thread.new { move_card_to_column(card_number, "right_now", project_config: project_config, agent_name: agent_name, board_key: board_key) }
@@ -390,7 +392,14 @@ def create_and_deploy_ephemeral_env(worktree_path:, env_name:, parent_env:, card
390
392
  LOG.info "[EphemeralEnv] Configured #{env_name} in worktree, deploying in background"
391
393
 
392
394
  Thread.new do
393
- frontend_only = BeltEnvironment.frontend_only_changes?(worktree: worktree_path)
395
+ # First provisioning of a fresh env must be a full deploy — it stands up
396
+ # S3/CloudFront/backend. The frontend-only shortcut is only safe once the
397
+ # env is actually live (probe the derived public URL). Otherwise `belt
398
+ # deploy frontend` runs against a bucket that doesn't exist yet and fails
399
+ # with "Could not determine S3 bucket."
400
+ frontend_only =
401
+ ephemeral_env_live?(worktree_path, env_name) &&
402
+ BeltEnvironment.frontend_only_changes?(worktree: worktree_path)
394
403
  BeltEnvironment.deploy(worktree: worktree_path, env_name: env_name, frontend_only: frontend_only)
395
404
  rescue StandardError => e
396
405
  LOG.error "[EphemeralEnv] Error deploying '#{env_name}': #{e.message}"
@@ -18,7 +18,7 @@ CommentContext = Struct.new(
18
18
  :project_config, :project_key, :card_number, :worktree,
19
19
  :model, :effort, :deploy_intent, :cli_provider_override,
20
20
  :comment_vars, :card_tags, :worktree_override, :fresh,
21
- :board_key, :profile,
21
+ :board_key, :profile, :explicit_model,
22
22
  keyword_init: true
23
23
  )
24
24
 
@@ -110,7 +110,7 @@ def build_comment_context(eventable:, plain_text:, tags:, card_internal_id:, car
110
110
  clean_text = tags[:clean_text]
111
111
 
112
112
  inline_cli = detect_cli_provider(text: plain_text, tags: card_tags)
113
- inline_model = detect_model(project_config, text: plain_text)
113
+ inline_model, inline_model_explicit = detect_model_explicit(project_config, text: plain_text)
114
114
  inline_effort = detect_effort(project_config, tags: card_tags, text: plain_text)
115
115
 
116
116
  # Resolve overrides against the work item — merges stored overrides with inline tags
@@ -141,6 +141,7 @@ def build_comment_context(eventable:, plain_text:, tags:, card_internal_id:, car
141
141
  board_key: board_key,
142
142
  model: effective_model,
143
143
  effort: effective_effort,
144
+ explicit_model: inline_model_explicit,
144
145
  deploy_intent: deploy_intent,
145
146
  cli_provider_override: effective_cli,
146
147
  card_tags: card_tags,
@@ -412,7 +413,8 @@ def dispatch_cross_agent_review(ctx, card_key:, card_number:, card_assigned_agen
412
413
  model: ctx.model, effort: ctx.effort, agent_name: ctx.agent_name,
413
414
  card_number: card_number, comment_id: ctx.comment_id,
414
415
  source: :fizzy, source_context: { card_number: card_number, dispatched_at: Time.now },
415
- cli_provider: ctx.cli_provider_override, profile: ctx.profile)
416
+ cli_provider: ctx.cli_provider_override, profile: ctx.profile,
417
+ explicit_model: ctx.explicit_model)
416
418
  return [200, { status: "dispatch_failed", agent: ctx.agent_name, card: card_number }.to_json] unless pid
417
419
 
418
420
  register_session(card_key, pid, log_file: log_file, supersede_key: card_key, agent_name: ctx.agent_name)
@@ -526,7 +528,7 @@ def dispatch_new_mention(ctx, card_key:, card_number:, card_title:, branch:, wor
526
528
  model: ctx.model, effort: ctx.effort, agent_name: ctx.agent_name,
527
529
  card_number: card_number, comment_id: ctx.comment_id,
528
530
  source: :fizzy, cli_provider: ctx.cli_provider_override,
529
- profile: ctx.profile,
531
+ profile: ctx.profile, explicit_model: ctx.explicit_model,
530
532
  source_context: { card_number: card_number, dispatched_at: Time.now })
531
533
  return [200, { status: "dispatch_failed", agent: ctx.agent_name, card: card_number }.to_json] unless pid
532
534
 
@@ -565,7 +567,7 @@ def dispatch_followup_comment(ctx, card_key:, card_number:, work_dir:)
565
567
  model: ctx.model, effort: effort, agent_name: ctx.agent_name,
566
568
  card_number: card_number, comment_id: ctx.comment_id,
567
569
  source: :fizzy, cli_provider: ctx.cli_provider_override, resume: should_resume,
568
- profile: ctx.profile,
570
+ profile: ctx.profile, explicit_model: ctx.explicit_model,
569
571
  source_context: {
570
572
  card_number: card_number, card_internal_id: ctx.card_internal_id,
571
573
  deploy_intent: ctx.deploy_intent, board_key: ctx.board_key, dispatched_at: Time.now
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "shellwords"
4
+ require "net/http"
5
+ require "uri"
4
6
 
5
7
  # Deployment environment tracking.
6
8
  # Tracks which dev environments have active card deploys and which are available.
@@ -383,3 +385,40 @@ def parse_tfvars(contents)
383
385
  end
384
386
  vars
385
387
  end
388
+
389
+ # Is a Belt env's frontend actually live? Derives the public URL from the
390
+ # worktree's infrastructure/<env>/terraform.tfvars and does a HEAD request.
391
+ #
392
+ # This is the honest signal for "already provisioned": a live site means the
393
+ # S3 bucket / CloudFront / backend exist, so the frontend-only deploy shortcut
394
+ # is safe. Anything else (never applied, DNS/CloudFront still propagating,
395
+ # connection refused) reads as not-live and callers should do a full deploy.
396
+ #
397
+ # A false negative during CloudFront/DNS/ACM propagation just triggers a
398
+ # (redundant but harmless) full deploy — never a skipped provisioning step.
399
+ def ephemeral_env_live?(worktree_path, env_name, timeout: 5)
400
+ tfvars = File.join(worktree_path, "infrastructure", env_name, "terraform.tfvars")
401
+ return false unless File.exist?(tfvars)
402
+
403
+ url = ephemeral_url_from_tfvars(tfvars)
404
+ return false unless url
405
+
406
+ frontend_url_live?(url, timeout: timeout)
407
+ end
408
+
409
+ # HEAD the URL; treat any 2xx/3xx as live. Any error (refused, timeout,
410
+ # NXDOMAIN, TLS failure) means not live. HEAD keeps us from pulling the bundle.
411
+ def frontend_url_live?(url, timeout: 5)
412
+ uri = URI.parse(url)
413
+ http = Net::HTTP.new(uri.host, uri.port)
414
+ http.use_ssl = (uri.scheme == "https")
415
+ http.open_timeout = timeout
416
+ http.read_timeout = timeout
417
+
418
+ response = http.request_head(uri.request_uri.empty? ? "/" : uri.request_uri)
419
+ code = response.code.to_i
420
+ code >= 200 && code < 400
421
+ rescue StandardError => e
422
+ LOG.info "[Fizzy:Deploy] Frontend probe for #{url} not live: #{e.class}: #{e.message}" if defined?(LOG)
423
+ false
424
+ end
@@ -3,7 +3,7 @@
3
3
  module Brainiac
4
4
  module Plugins
5
5
  module Fizzy
6
- VERSION = "0.0.31"
6
+ VERSION = "0.0.32"
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brainiac-fizzy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.31
4
+ version: 0.0.32
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Davis