Wednesday, December 29, 2021

Bass – Lisp dialect for scripting the infrastructure beneath your project

Bass is a low-fidelity Lisp dialect for scripting the infrastructure beneath your project.

Bass's goal is to make the path to production predictable, verifiable, flexible, and most importantly, fun.

go install github.com/vito/bass/cmd/...@latest

WARNING: this project is pre-alpha and these docs need a lot of work to catch up with recent changes in direction. Feel free to tinker, but expect lots of rough edges and breakage in the future. 😅

Bass is built around thunks - hermetic, cacheable commands that produce files and/or a stream of response values.

(from "alpine"
  ($ echo "Hello, world!"))
result

{

args
image
path
platform
response

}

𝄢

Thunks can be run which returns a stream of values which can be read with next.

; load durations stdlib
(def dur (load (.durations)))

; resolves a ref to a sha at the git remote uri
(defn git-ls-remote [uri ref]
  (let [ls (from "alpine/git"
             (-> ($ git ls-remote $uri $ref)
                 ; parse awk-style table output
                 (response-from :stdout :unix-table)
                 ; cache every minute
                 (with-label :at (dur:every-minute))))]
    ; read the first column of the first row
    (first (next (run ls)))))

(git-ls-remote "https://github.com/vito/bass" "main")
result

"5851f662575d6dfe9a3623115bf295ab28a7c4fc"

𝄢

Or you can reference a path created by a thunk - this value is called an artifact thunk.

; returns the repo at the given sha (as a detached HEAD)
(defn git-checkout [uri sha]
  (path
    (from "alpine/git"
      (-> ($ git clone $uri ./)
          ; use sha as a label for cache control
          (with-label :for sha))
      ($ git checkout $sha))
    ./))

(def bass "https://github.com/vito/bass")

(let [sha (git-ls-remote bass "main")]
  (git-checkout bass sha))
result

{

args

(

  1. "checkout"
  2. "5851f662575d6dfe9a3623115bf295ab28a7c4fc"

)

image

{

args

(

  1. "clone"
  2. "https://github.com/vito/bass"

)

image
labels

{

for "5851f662575d6dfe9a3623115bf295ab28a7c4fc"

}

path
platform
response

}

path
platform
response

}

./

𝄢

Artifact thunks may be passed into other thunks, and so on, forming one big thunk.

(defn go-build [src pkg]
  (-> (from "golang"
        (cd src
          ($ go build -o ../out/)))
      (path ./out/)))

(-> (git-checkout bass (git-ls-remote bass "main"))
    (go-build "./cmd/..."))
result

{

args
dir

{

args

(

  1. "checkout"
  2. "5851f662575d6dfe9a3623115bf295ab28a7c4fc"

)

image

{

args

(

  1. "clone"
  2. "https://github.com/vito/bass"

)

image
labels

{

for "5851f662575d6dfe9a3623115bf295ab28a7c4fc"

}

path
platform
response

}

path
platform
response

}

./

image
path
platform
response

}

./out/

𝄢

A typical thing for bass scripts to do is emit an artifact thunk to *stdout* - try piping the JSON below to bass --export!

(-> (git-checkout bass (git-ls-remote bass "main"))
    (go-build "./cmd/...")
    (emit *stdout*))
stdout
{
  "thunk": {
    "platform": {
      "os": "linux"
    },
    "image": {
      "repository": "golang"
    },
    "path": {
      "command": "go"
    },
    "args": [
      "build",
      "-o",
      {
        "dir": "../out"
      }
    ],
    "dir": {
      "thunk": {
        "platform": {
          "os": "linux"
        },
        "image": {
          "args": [
            "clone",
            "https://github.com/vito/bass",
            {
              "dir": "."
            }
          ],
          "image": {
            "repository": "alpine/git"
          },
          "labels": {
            "for": "5851f662575d6dfe9a3623115bf295ab28a7c4fc"
          },
          "path": {
            "command": "git"
          },
          "platform": {
            "os": "linux"
          },
          "stdin": []
        },
        "path": {
          "command": "git"
        },
        "args": [
          "checkout",
          "5851f662575d6dfe9a3623115bf295ab28a7c4fc"
        ],
        "response": {}
      },
      "path": {
        "dir": "."
      }
    },
    "response": {}
  },
  "path": {
    "dir": "./out"
  }
}
𝄢

If you'd like to hop into a thunk and troubleshoot something, you can also emit the thunk itself and pipe it to bass -e | docker load and then run it with docker run. (This will probably be made easier in the future.)

(emit
  (from "ubuntu"
    ($ apt update)
    ($ apt -y install git))
  *stdout*)
stdout
{
  "args": [
    "-y",
    "install",
    "git"
  ],
  "image": {
    "args": [
      "update"
    ],
    "image": {
      "repository": "ubuntu"
    },
    "path": {
      "command": "apt"
    },
    "platform": {
      "os": "linux"
    },
    "stdin": []
  },
  "path": {
    "command": "apt"
  },
  "platform": {
    "os": "linux"
  },
  "stdin": []
}

Intrigued? Check out the other demos!



from Hacker News https://ift.tt/3qwlLdd

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.