clojuregcloudbabashka

How to use gcloud with Babashka


I'm trying to use Babashka to replace a few Bash scripts I use to deploy functions on GCP Cloud Functions.

The script below is working, but I wonder if there is a better way to execute the gcloud shell command:

#!/usr/bin/env bb
(require '[cheshire.core :as json]
         '[clojure.java.shell :refer [sh]])

(let [package-json (json/parse-string (slurp "package.json") true)
      name (:name package-json)
      entry-point "entryPoint"
      region "europe-west3"
      memory "128MB"
      runtime "nodejs14"
      source "dist"
      service-account "sa-function-invoker@prj-kitchen-sink.iam.gserviceaccount.com"
      timeout "10s"]
  (println "deploy function" name "with entry point" entry-point "to GCP Cloud Functions." "Attach service account" service-account)
  (let [output (sh "gcloud" "functions" "deploy" name "--region" region "--entry-point" entry-point "--memory" memory "--runtime" runtime "--service-account" service-account "--source" source "--trigger-http" "--timeout" timeout)]
    (if (= "" (:err output))
      (println (:out output))
      (println (:err output)))))

As a comparison, the Bash script I was using is easier to read:

#!/bin/bash
set -euo pipefail

FUNCTION_NAME=$(cat package.json | jq '{name}' | jq '.name' | sed 's/"//g')
FUNCTION_ENTRY_POINT=entryPoint
ATTACHED_SA=sa-function-invoker@prj-kitchen-sink.iam.gserviceaccount.com
MEMORY=128MB

echo "deploy function `${FUNCTION_NAME}` with entry point `${FUNCTION_ENTRY_POINT}` to GCP Cloud Functions. Attach service account `${ATTACHED_SA}`"

gcloud functions deploy ${FUNCTION_NAME} \
  --project ${GCP_PROJECT_ID} \
  --region ${GCP_REGION} \
  --memory ${MEMORY} \
  --runtime nodejs14 \
  --service-account ${ATTACHED_SA} \
  --source dist \
  --entry-point ${FUNCTION_ENTRY_POINT} \
  --timeout 10s

I guess my question is not very specific to Babashka or gcloud, but it's about how to construct commands with clojure.java.shell in general...


Solution

  • If you want to execute the shell command and see the direct output as it appears, I recommend using babashka.process/process or babashka.tasks/shell:

    
    @(babashka.process/process ["ls" "-la"] {:out :inherit :err :inherit})
    
    @(babashka.process/process ["ls" "-la"] {:inherit true})
    
    (babashka.tasks/shell "ls -la")
    

    The above invocations do pretty much the same, but shell also applied babashka.process/check which throws if the exit code was non-zero. The @ sign before the invocation is the same as calling deref which means: wait for the process to finish. If you don't prepend that, than the process is going to run asynchronously.

    More info: