Skip to content

Commit 42768c9

Browse files
feat: add runbooks support for file upload (#1230)
* feat: add runbooks support for file upload * redact runbook parameter file to display parameters when fetching a runbook session * refactor: remove duplicated import --------- Co-authored-by: Sandro <sandromll@gmail.com>
1 parent 542c04c commit 42768c9

File tree

5 files changed

+103
-13
lines changed

5 files changed

+103
-13
lines changed

common/runbooks/git.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,11 @@ import (
2020
const maxTemplateSize = 1_000_000 // 1MB
2121

2222
type File struct {
23-
Name string
24-
EnvVars map[string]string
25-
InputFile []byte
26-
CommitSHA string
23+
Name string
24+
EnvVars map[string]string
25+
TemplateAttributes map[string]any
26+
InputFile []byte
27+
CommitSHA string
2728
}
2829

2930
type Repository struct {
@@ -91,10 +92,11 @@ func (r *Repository) ReadFile(fileName string, parameters map[string]string) (*F
9192
return nil, err
9293
}
9394
return &File{
94-
Name: f.Name,
95-
InputFile: parsedTemplate.Bytes(),
96-
EnvVars: t.EnvVars(),
97-
CommitSHA: f.Hash.String(),
95+
Name: f.Name,
96+
InputFile: parsedTemplate.Bytes(),
97+
TemplateAttributes: t.Attributes(),
98+
EnvVars: t.EnvVars(),
99+
CommitSHA: f.Hash.String(),
98100
}, nil
99101
}
100102

common/runbooks/template_funcs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
ttemplate "text/template"
88
)
99

10-
var defaultInputTypes = []string{"text", "number", "tel", "time", "date", "url", "email", "select", "textarea", "password"}
10+
var defaultInputTypes = []string{"text", "number", "tel", "time", "date", "url", "email", "select", "textarea", "password", "file"}
1111

1212
type templateFnHandler struct {
1313
items map[string]string

gateway/api/runbooks/runbooksV2.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ func RunbookExec(c *gin.Context) {
440440
runbook.EnvVars[key] = val
441441
}
442442

443-
runbookParamsJson, _ := json.Marshal(req.Parameters)
443+
runbookParamsJson := encodeRequestParams(req.Parameters, runbook)
444444
sessionLabels := openapi.SessionLabelsType{
445445
"runbookRepository": config.GetNormalizedGitURL(),
446446
"runbookFile": req.FileName,
@@ -608,3 +608,25 @@ func validateGitURL(urlStr string) error {
608608

609609
return nil
610610
}
611+
612+
func encodeRequestParams(params map[string]string, runbook *runbooks.File) []byte {
613+
newParams := map[string]string{}
614+
for key, val := range params {
615+
newParams[key] = val
616+
if runbook.TemplateAttributes != nil {
617+
attrObj, ok := runbook.TemplateAttributes[key]
618+
if !ok {
619+
continue
620+
}
621+
attr, ok := attrObj.(map[string]any)
622+
if !ok {
623+
continue
624+
}
625+
if attrType, _ := attr["type"].(string); attrType == "file" {
626+
newParams[key] = fmt.Sprintf("[param redacted. type = file, size = %v byte(s)]", len(val))
627+
}
628+
}
629+
}
630+
encoded, _ := json.Marshal(newParams)
631+
return encoded
632+
}

webapp/src/webapp/components/forms.cljs

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
(ns webapp.components.forms
22
(:require
3-
["@radix-ui/themes" :refer [Select Tooltip Text]]
4-
["lucide-react" :refer [Eye EyeOff HelpCircle]]
3+
["@radix-ui/themes" :refer [Box Button Flex IconButton Select Text Tooltip]]
4+
["lucide-react" :refer [Eye EyeOff HelpCircle Upload X]]
55
[clojure.string :as cs]
66
[reagent.core :as r]))
77

@@ -215,3 +215,64 @@
215215
[:> Select.Content {:position "popper"
216216
:color "indigo"}
217217
(map #(option % selected) options)]]])
218+
219+
220+
(defn file
221+
"File input component with base64 encoding support"
222+
[_]
223+
(let [file-input-ref (r/atom nil)
224+
file-name (r/atom nil)]
225+
(fn [{:keys [label on-change value helper-text required]}]
226+
(let [handle-file-change (fn [event]
227+
(when-let [file (-> event .-target .-files (aget 0))]
228+
(reset! file-name (.-name file))
229+
(let [reader (js/FileReader.)]
230+
(set! (.-onload reader)
231+
(fn [e]
232+
(when-let [base64 (second (cs/split (-> e .-target .-result) #"," 2))]
233+
(on-change base64))))
234+
(.readAsDataURL reader file))))
235+
handle-button-click (fn []
236+
(when @file-input-ref
237+
(.click @file-input-ref)))
238+
handle-clear (fn []
239+
(reset! file-name nil)
240+
(when @file-input-ref
241+
(set! (.-value @file-input-ref) ""))
242+
(on-change ""))]
243+
[:> Box {:class "text-sm mb-regular"}
244+
[:> Flex {:class "items-center gap-2 mb-1"}
245+
(when label
246+
[:> Text {:size "1" :as "label" :weight "bold" :class "text-gray-12"}
247+
label])
248+
(when (not (cs/blank? helper-text))
249+
[:> Tooltip {:content helper-text}
250+
[:> HelpCircle {:size 14}]])]
251+
[:> Flex {:class "items-center gap-2"}
252+
[:input
253+
{:type "file"
254+
:ref (fn [el] (reset! file-input-ref el))
255+
:on-change handle-file-change
256+
:required (and
257+
(not= required "false")
258+
(or required (nil? required)))
259+
:style {:display "none"}}]
260+
[:> Button
261+
{:variant "soft"
262+
:size "2"
263+
:type "button"
264+
:on-click handle-button-click}
265+
[:> Flex {:align "center" :gap "2"}
266+
[:> Upload {:size 16}]
267+
"Upload File"]]
268+
(when (not (cs/blank? value))
269+
[:> Flex {:align "center" :gap "2"}
270+
[:> Text {:size "1" :class "text-gray-11"}
271+
(or @file-name "File uploaded")]
272+
[:> IconButton
273+
{:variant "ghost"
274+
:color "gray"
275+
:size "1"
276+
:type "button"
277+
:on-click handle-clear}
278+
[:> X {:size 14}]]])]]))))

webapp/src/webapp/features/runbooks/runner/views/form.cljs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@
5151
(not= required "false")
5252
(or required (nil? required)))
5353
{:required true}))]
54+
"file" [forms/file {:label label
55+
:on-change on-change
56+
:value value
57+
:helper-text helper-text
58+
:required required}]
5459
[forms/input (merge
5560
{:label label
5661
:placeholder (or placeholder (str "Define a value for " label))
@@ -183,7 +188,7 @@
183188
:value (get @state param "")
184189
:type (:type metadata)
185190
:required (:required metadata)
186-
:on-change (if (= "select" (:type metadata))
191+
:on-change (if (contains? #{"select" "file"} (:type metadata))
187192
#(update-state param %)
188193
#(update-state param (-> % .-target .-value)))
189194
:helper-text (:description metadata)

0 commit comments

Comments
 (0)