Skip to content

Commit 441e5f1

Browse files
authored
Merge pull request #40 from terrateamio/add-format-atlantis-comment
ADD Format atlantis-comment support
2 parents 847782f + 51193b2 commit 441e5f1

File tree

3 files changed

+134
-3
lines changed

3 files changed

+134
-3
lines changed

src/oiq/oiq_pricer.ml

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,3 +529,132 @@ let to_markdown_string t =
529529
render_section "🔴 Removed resources" removes;
530530
render_section "⚪ Existing resources" existing;
531531
])
532+
533+
let to_atlantis_comment_string t =
534+
let fmt v = Printf.sprintf "$%.2f" (CCFloat.abs v) in
535+
let fmt_with_sign v = Printf.sprintf "%s$%.2f" (if v >= 0.0 then "" else "-") (CCFloat.abs v) in
536+
537+
(* Initial box header with emojis *)
538+
let lines =
539+
[
540+
"\n";
541+
(* Add an empty line for spacing *)
542+
"╔══════════════════════════════════════════════════════════╗\n";
543+
"║ 💸 OpenInfraQuote Monthly Cost Estimate ║\n";
544+
"╚══════════════════════════════════════════════════════════╝\n";
545+
]
546+
in
547+
548+
(* Price difference section *)
549+
let delta_min = t.price_diff.Oiq_range.min in
550+
let delta_max = t.price_diff.Oiq_range.max in
551+
let lines =
552+
if delta_min = 0.0 && delta_max = 0.0 then lines @ [ "\n"; "No change in monthly cost\n" ]
553+
else if delta_max < 0.0 then
554+
lines
555+
@ [
556+
"\n";
557+
Printf.sprintf
558+
"Decrease: %s → %s/month\n"
559+
(fmt (CCFloat.abs delta_min))
560+
(fmt (CCFloat.abs delta_max));
561+
]
562+
else
563+
lines @ [ "\n"; Printf.sprintf "Increase: %s → %s/month\n" (fmt delta_min) (fmt delta_max) ]
564+
in
565+
566+
(* Before/After summary *)
567+
let lines =
568+
lines
569+
@ [
570+
"\n";
571+
Printf.sprintf
572+
"Before: %s - %s\n"
573+
(fmt_with_sign t.prev_price.Oiq_range.min)
574+
(fmt_with_sign t.prev_price.Oiq_range.max);
575+
Printf.sprintf
576+
"After: %s - %s\n"
577+
(fmt_with_sign t.price.Oiq_range.min)
578+
(fmt_with_sign t.price.Oiq_range.max);
579+
]
580+
in
581+
582+
(* Group resources by change type *)
583+
let adds, removes, existing =
584+
CCList.fold_left
585+
(fun (a, r, e) resource ->
586+
match resource.Resource.change with
587+
| `Add -> (resource :: a, r, e)
588+
| `Remove -> (a, resource :: r, e)
589+
| `Noop -> (a, r, resource :: e))
590+
([], [], [])
591+
t.resources
592+
in
593+
594+
(* Add resource counts *)
595+
let lines =
596+
lines
597+
@ [
598+
"\n";
599+
Printf.sprintf "%-2s %-10s %d\n" "🟢" "Added:" (CCList.length adds);
600+
Printf.sprintf "%-2s %-10s %d\n" "🔴" "Removed:" (CCList.length removes);
601+
Printf.sprintf "%-2s %-10s %d\n" "" "Existing:" (CCList.length existing);
602+
]
603+
in
604+
605+
(* Helper to render a section of resources *)
606+
let render_section title resources =
607+
if CCList.is_empty resources then ""
608+
else
609+
let header = Printf.sprintf "\n%s:\n%s\n" title (String.make (String.length title) '-') in
610+
let table_header =
611+
Printf.sprintf "%-40s %-20s %12s %12s\n" "Resource" "Type" "Before" "After"
612+
in
613+
let table_divider =
614+
Printf.sprintf
615+
"%-40s %-20s %12s %12s\n"
616+
(String.make 40 '-')
617+
(String.make 20 '-')
618+
(String.make 12 '-')
619+
(String.make 12 '-')
620+
in
621+
let rows =
622+
CCString.concat
623+
""
624+
(CCList.map
625+
(fun r ->
626+
let name =
627+
if
628+
not
629+
(CCString.equal r.Resource.address (r.Resource.type_ ^ "." ^ r.Resource.name))
630+
then
631+
CCString.concat "." @@ CCList.tl @@ CCString.split_on_char '.' r.Resource.address
632+
else r.Resource.name
633+
in
634+
let typ = r.Resource.type_ in
635+
let est_min = r.Resource.price.Oiq_range.min in
636+
let est_max = r.Resource.price.Oiq_range.max in
637+
(* Use spaces around hyphens and preserve signs for removed resources *)
638+
let before_range =
639+
Printf.sprintf
640+
"%s - %s"
641+
(fmt_with_sign t.prev_price.Oiq_range.min)
642+
(fmt_with_sign t.prev_price.Oiq_range.max)
643+
in
644+
let after_range =
645+
Printf.sprintf "%s - %s" (fmt_with_sign est_min) (fmt_with_sign est_max)
646+
in
647+
Printf.sprintf "%-40s %-20s %12s %12s\n" name typ before_range after_range)
648+
resources)
649+
in
650+
header ^ table_header ^ table_divider ^ rows
651+
in
652+
653+
CCString.concat
654+
""
655+
(lines
656+
@ [
657+
render_section "Added resources" adds;
658+
render_section "Removed resources" removes;
659+
render_section "Existing resources" existing;
660+
])

src/oiq/oiq_pricer.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ val price :
1414

1515
val pretty_to_string : t -> string
1616
val to_markdown_string : t -> string
17+
val to_atlantis_comment_string : t -> string

src/oiq_cli/oiq_cli.ml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ module Cli = struct
2727

2828
let output_format =
2929
let docv = "FORMAT" in
30-
let doc = "Format of output (text, json, or markdown)." in
30+
let doc = "Format of output (text, json, markdown, atlantis-comment)." in
3131
let env =
3232
let doc = "Specify output format" in
3333
C.Cmd.Env.info ~doc "OIQ_OUTPUT_FORMAT"
3434
in
3535
C.Arg.(
3636
value
37-
& opt (enum [ ("text", `Text); ("json", `Json); ("markdown", `Markdown) ]) `Text
37+
& opt (enum [ ("text", `Text); ("json", `Json); ("markdown", `Markdown); ("atlantis-comment", `Atlantis_comment); ]) `Text
3838
& info [ "f"; "format" ] ~docv ~doc ~env)
3939

4040
let match_query =
@@ -162,7 +162,8 @@ let price usage input output_format match_query regions =
162162
match output_format with
163163
| `Text -> print_endline @@ Oiq_pricer.pretty_to_string priced
164164
| `Json -> print_endline @@ Yojson.Safe.pretty_to_string @@ Oiq_pricer.to_yojson priced
165-
| `Markdown -> print_endline @@ Oiq_pricer.to_markdown_string priced)
165+
| `Markdown -> print_endline @@ Oiq_pricer.to_markdown_string priced
166+
| `Atlantis_comment -> print_endline @@ Oiq_pricer.to_atlantis_comment_string priced)
166167
| Error (#Oiq_match_query.err as err) ->
167168
Logs.err (fun m -> m "%a" Oiq_match_query.pp_err err);
168169
exit 1

0 commit comments

Comments
 (0)