Bass

Bass is a scripting language for running commands and caching the shit out of them.

Bass's goal is to make shipping software predictable, repeatable, and fun. The plan is to support sophisticated CI/CD flows while sticking to familiar ideas. CI/CD boils down to running commands. Bass leverages that instead of trying to replace it.

If you'd like to try it out, grab the latest release and skim the guide!

demo thunks & thunk paths
𝄢

Commands are represented as a data value called a thunk. Thunks are rendered as space invaders.

(from (linux/alpine)
  ($ echo "Hello, world!"))
.echo
{
:image
{
:repository "alpine"
:platform
{
:os "linux"
}
:tag "latest"
:digest "sha256:bc41182d7ef5ffc53a40b044e725193bc10142a1243f395ee852a8d9730fc2ad"
}
:cmd .echo
:args
(
  1. "Hello, world!"
)
}
𝄢

You can run a thunk, read its output, or check if it succeeds?.

(def thunk
  (from (linux/alpine)
    ($ echo "Hello, world!")))

[(run thunk) (next (read thunk :raw)) (succeeds? thunk)]
stderr: 10 lines
=> echo "Hello, world!" [0.20s]
=> exporting to client [0.00s]
-> copying files 40B [0.00s]
=> resolve image config for docker.io/library/alpine@sha256:bc41182d7ef5ffc53a40b044e72519
3bc10142a1243f395ee852a8d9730fc2ad [0.00s]
=> docker-image://docker.io/library/alpine@sha256:bc41182d7ef5ffc53a40b044e725193bc10142a1
243f395ee852a8d9730fc2ad [0.01s]
-> resolve docker.io/library/alpine@sha256:bc41182d7ef5ffc53a40b044e725193bc10142a1243f395
ee852a8d9730fc2ad [0.00s]
=> echo "Hello, world!" CACHED [0.00s]
(
  1. null
  2. "Hello, world!\n"
  3. true
)
𝄢

Files created by a thunk can be referenced as thunk paths.

(def create-file
  (from (linux/alpine)
    ($ sh -c "echo hello >> file")))

create-file/file
.sh
{
:image
{
:repository "alpine"
:platform
{
:os "linux"
}
:tag "latest"
:digest "sha256:bc41182d7ef5ffc53a40b044e725193bc10142a1243f395ee852a8d9730fc2ad"
}
:cmd .sh
:args
(
  1. "-c"
  2. "echo hello >> file"
)
}
./file
𝄢

Thunk paths can be passed to other thunks.

(from (linux/alpine)
  ($ cat create-file/file))
.cat
{
:image
{
:repository "alpine"
:platform
{
:os "linux"
}
:tag "latest"
:digest "sha256:bc41182d7ef5ffc53a40b044e725193bc10142a1243f395ee852a8d9730fc2ad"
}
:cmd .cat
:args
(
  1. .sh
    {
    :image
    {
    :repository "alpine"
    :platform
    {
    :os "linux"
    }
    :tag "latest"
    :digest "sha256:bc41182d7ef5ffc53a40b044e725193bc10142a1243f395ee852a8d9730fc2ad"
    }
    :cmd .sh
    :args
    (
    1. "-c"
    2. "echo hello >> file"
    )
    }
    ./file
)
}
𝄢

Like thunks, thunk paths are just data values. The underlying thunk only runs when another thunk that needs it runs, or when you read the path itself.

(-> (from (linux/alpine)
      ($ cat create-file/file))
    (read :raw)
    next)
stderr: 10 lines
=> resolve image config for docker.io/library/alpine@sha256:bc41182d7ef5ffc53a40b044e72519
3bc10142a1243f395ee852a8d9730fc2ad [0.00s]
=> docker-image://docker.io/library/alpine@sha256:bc41182d7ef5ffc53a40b044e725193bc10142a1
243f395ee852a8d9730fc2ad CACHED [0.00s]
-> resolve docker.io/library/alpine@sha256:bc41182d7ef5ffc53a40b044e725193bc10142a1243f395
ee852a8d9730fc2ad [0.01s]
=> sh -c "echo hello >> file" [0.18s]
=> cat <thunk S7PU9267T3S7K: (.sh)>/file [0.22s]
=> exporting to client [0.00s]
-> copying files 32B [0.00s]
"hello\n"
demo fetching git repos & other inputs
𝄢

To fetch source code from a git repo you should probably use the .git module.

(use (.git (linux/alpine/git)))

(let [url "https://github.com/vito/bass"
      ref "main"]
  (git:checkout url (git:ls-remote url ref)))
stderr: 9 lines
=> resolve image config for docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a05
7176c06a9f266de440be406dcf079b [0.02s]
=> docker-image://docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f
266de440be406dcf079b CACHED [0.00s]
-> resolve docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f266de44
0be406dcf079b [0.01s]
=> git ls-remote https://github.com/vito/bass main [0.49s]
=> exporting to client [0.00s]
-> copying files 83B [0.00s]
.git
{
:image
.git
{
:image
.git
{
:image
.git
{
:image
{
:repository "alpine/git"
:platform
{
:os "linux"
}
:tag "latest"
:digest "sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f266de440be406dcf079b"
}
:cmd .git
:args
(
  1. "clone"
  2. "https://github.com/vito/bass"
  3. ./
)
}
:cmd .git
:args
(
  1. "fetch"
  2. "origin"
  3. "9197325a016c330d7a673ac5afef3edb19335f25"
)
}
:cmd .git
:args
(
  1. "checkout"
  2. "9197325a016c330d7a673ac5afef3edb19335f25"
)
}
:cmd .git
:args
(
  1. "submodule"
  2. "update"
  3. "--init"
  4. "--recursive"
)
}
./
𝄢

Using ls-remote to resolve main to a commit ensures the checkout call is hermetic.

A non-hermetic thunk looks like this:

; BAD
(from (linux/alpine/git)
  ($ git clone "https://github.com/vito/bass" ./))
.git
{
:image
{
:repository "alpine/git"
:platform
{
:os "linux"
}
:tag "latest"
:digest "sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f266de440be406dcf079b"
}
:cmd .git
:args
(
  1. "clone"
  2. "https://github.com/vito/bass"
  3. ./
)
}
𝄢

If you run this thunk somewhere else it might return something different. It'll also be cached forever, so you'll never get new commits.

Each input should specify an exact version to fetch. If you don't know it yet you can run another thunk to figure it out. You can keep that thunk from being cached forever by labeling it with the current time. That's how ls-remote works under the hood.

(defn ls-remote [repo ref & timestamp]
  (-> ($ git ls-remote $repo $ref)
      (with-image *git-image*)
      (with-label :at (now 60)) ; rerun every minute
      (read :unix-table) ; line and space separated table output
      next    ; first row   : <ref> <sha>
      first)) ; first column: <ref>
ls-remote
demo running tests
𝄢

To run tests, just run whatever command you would usually use to run tests.

(use (.git (linux/alpine/git)))

(defn go-test [src & args]
  (from (linux/golang)
    (cd src
      ($ go test & $args))))

(let [src git:github/vito/booklit/ref/master/]
  (succeeds? (go-test src ./tests/)))
stderr: 80 lines
=> git ls-remote https://github.com/vito/booklit master [0.44s]
=> exporting to client [0.00s]
-> copying files 85B [0.00s]
=> resolve image config for docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a05
7176c06a9f266de440be406dcf079b [0.02s]
=> resolve image config for docker.io/library/golang@sha256:2d17ffd12a2cdb25d4a633ad25f8dc
29608ed84f31b3b983427d825280427095 [0.00s]
=> docker-image://docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f
266de440be406dcf079b CACHED [0.00s]
-> resolve docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f266de44
0be406dcf079b [0.04s]
=> docker-image://docker.io/library/golang@sha256:2d17ffd12a2cdb25d4a633ad25f8dc29608ed84f
31b3b983427d825280427095 [0.00s]
-> resolve docker.io/library/golang@sha256:2d17ffd12a2cdb25d4a633ad25f8dc29608ed84f31b3b98
3427d825280427095 [0.04s]
-> sha256:8709771bd9da550643f5f4e3b49e92bb3f90543507ff36b5a998dd461fb8dd28 157B / 157B [0.
22s]
-> sha256:292167c9d1ff24956858651ef9906e9a987b65f7362854e13c28b98d9ae4e09f 148.82MB / 148.
82MB [9.19s]
-> sha256:b7aa120dd02d9fa75bb50861103f7837514028ea6f06e3e821b8c47c2c10d386 85.96MB / 85.96
MB [9.83s]
-> sha256:8471b75885efc7790a16be5328e3b368567b76a60fc3feabd6869c15e175ee05 54.58MB / 54.58
MB [4.59s]
-> sha256:a42821cd14fb31c4aa253203e7f8e34fc3b15d69ce370f1223fbbe4252a64202 10.88MB / 10.88
MB [3.34s]
-> sha256:326f452ade5c33097eba4ba88a24bd77a93a3d994d4dc39b936482655e664857 5.16MB / 5.16MB
[2.08s]
-> sha256:23858da423a6737f0467fab0014e5b53009ea7405d575636af0c3f100bbb2f10 55.03MB / 55.03
MB [3.91s]
-> extracting sha256:23858da423a6737f0467fab0014e5b53009ea7405d575636af0c3f100bbb2f10 [1.0
5s]
-> extracting sha256:326f452ade5c33097eba4ba88a24bd77a93a3d994d4dc39b936482655e664857 [0.1
3s]
-> extracting sha256:a42821cd14fb31c4aa253203e7f8e34fc3b15d69ce370f1223fbbe4252a64202 [0.1
5s]
-> extracting sha256:8471b75885efc7790a16be5328e3b368567b76a60fc3feabd6869c15e175ee05 [1.1
1s]
-> extracting sha256:b7aa120dd02d9fa75bb50861103f7837514028ea6f06e3e821b8c47c2c10d386 [1.1
7s]
-> extracting sha256:292167c9d1ff24956858651ef9906e9a987b65f7362854e13c28b98d9ae4e09f [2.6
8s]
-> extracting sha256:8709771bd9da550643f5f4e3b49e92bb3f90543507ff36b5a998dd461fb8dd28 [0.0
0s]
=> git clone https://github.com/vito/booklit ./ [16.7s]
Cloning into '.'...
=> git fetch origin d62e0d27a9668a8cf3850e405c6b19cd213f545a [0.51s]
From https://github.com/vito/booklit
* branch d62e0d27a9668a8cf3850e405c6b19cd213f545a -> FETCH_HEAD
=> git checkout d62e0d27a9668a8cf3850e405c6b19cd213f545a [0.26s]
Note: switching to 'd62e0d27a9668a8cf3850e405c6b19cd213f545a'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:
git switch -c <new-branch-name>
Or undo this operation with:
git switch -
Turn off this advice by setting config variable advice.detachedHead to false
HEAD is now at d62e0d2 remove stale badge, add description
=> git submodule update --init --recursive [0.24s]
=> go test ./tests/ [4.26s]
go: downloading github.com/onsi/ginkgo/v2 v2.1.4
go: downloading github.com/sirupsen/logrus v1.8.1
go: downloading github.com/onsi/gomega v1.19.0
go: downloading github.com/agext/levenshtein v1.2.3
go: downloading github.com/segmentio/textio v1.2.0
go: downloading golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a
go: downloading golang.org/x/net v0.0.0-20220225172249-27dd8689420f
go: downloading gopkg.in/yaml.v2 v2.4.0
go: downloading github.com/onsi/ginkgo v1.16.4
go: downloading golang.org/x/text v0.3.7
ok github.com/vito/booklit/tests 0.145s
true
𝄢

Don't use Go? Use a different image and run a different command:

(defn cargo-test [src & args]
  (from (linux/rust)
    (cd src
      ($ cargo test & $args))))

(let [src git:github/alacritty/alacritty/ref/master/]
  (succeeds? (cargo-test src ./alacritty_terminal/)))
stderr: 373 lines
=> git ls-remote https://github.com/alacritty/alacritty master [0.66s]
=> exporting to client [0.00s]
-> copying files 85B [0.00s]
=> resolve image config for docker.io/library/rust:latest [0.51s]
=> resolve image config for docker.io/library/rust@sha256:be7a002254f0de0c3f2f90c4d2a11c6d
6d48c28eac8065111d3a2c38785f3300 [0.00s]
=> resolve image config for docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a05
7176c06a9f266de440be406dcf079b [0.00s]
=> docker-image://docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f
266de440be406dcf079b CACHED [0.00s]
-> resolve docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f266de44
0be406dcf079b [0.02s]
=> docker-image://docker.io/library/rust@sha256:be7a002254f0de0c3f2f90c4d2a11c6d6d48c28eac
8065111d3a2c38785f3300 [2.03s]
-> resolve docker.io/library/rust@sha256:be7a002254f0de0c3f2f90c4d2a11c6d6d48c28eac8065111
d3a2c38785f3300 [0.02s]
-> sha256:7f26c5a55164a39e7483db455c6fb3ca57bfedc74b23b155a0880f41ccc63a86 148.95MB / 148.
95MB [7.85s]
-> sha256:8ffa7aaef4041744c03222b6b241a78a3b4ab9e8a8b99fb633a1f14b42f8bc56 196.85MB / 196.
85MB [9.35s]
-> extracting sha256:8ffa7aaef4041744c03222b6b241a78a3b4ab9e8a8b99fb633a1f14b42f8bc56 [2.7
3s]
-> extracting sha256:7f26c5a55164a39e7483db455c6fb3ca57bfedc74b23b155a0880f41ccc63a86 [2.0
3s]
=> git clone https://github.com/alacritty/alacritty ./ [19.3s]
Cloning into '.'...
=> git fetch origin c5ae05e810a5866a9133b2e88edba3a42706319f [0.66s]
From https://github.com/alacritty/alacritty
* branch c5ae05e810a5866a9133b2e88edba3a42706319f -> FETCH_HEAD
=> git checkout c5ae05e810a5866a9133b2e88edba3a42706319f [0.29s]
Note: switching to 'c5ae05e810a5866a9133b2e88edba3a42706319f'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:
git switch -c <new-branch-name>
Or undo this operation with:
git switch -
Turn off this advice by setting config variable advice.detachedHead to false
HEAD is now at c5ae05e8 Fix IPC config overriding previous values
=> git submodule update --init --recursive [0.24s]
=> cargo test ./alacritty_terminal/ [65.4s]
Updating crates.io index
Downloading crates ...
Downloaded arrayref v0.3.6
Downloaded shared_library v0.1.9
Downloaded ryu v1.0.11
Downloaded xcursor v0.3.4
Downloaded serde_derive v1.0.144
Downloaded atty v0.2.14
Downloaded safe_arch v0.5.2
Downloaded regex-syntax v0.6.27
Downloaded xml-rs v0.8.4
Downloaded foreign-types-shared v0.3.1
Downloaded foreign-types-macros v0.2.2
Downloaded glutin_egl_sys v0.1.6
Downloaded instant v0.1.12
Downloaded glutin_glx_sys v0.1.8
Downloaded foreign-types v0.5.0
Downloaded downcast-rs v1.2.0
Downloaded cty v0.2.2
Downloaded dirs v4.0.0
Downloaded crc32fast v1.3.2
Downloaded cmake v0.1.48
Downloaded base64 v0.13.0
Downloaded arrayvec v0.5.2
Downloaded yaml-rust v0.4.5
Downloaded lazycell v1.3.0
Downloaded memoffset v0.6.5
Downloaded xdg v2.4.1
Downloaded vte v0.10.1
Downloaded mio v0.8.4
Downloaded linked-hash-map v0.5.6
Downloaded iovec v0.1.4
Downloaded lock_api v0.4.8
Downloaded libloading v0.7.3
Downloaded clap_complete v3.2.5
Downloaded nom v7.1.1
Downloaded parking_lot_core v0.9.3
Downloaded osmesa-sys v0.1.2
Downloaded pkg-config v0.3.25
Downloaded scopeguard v1.1.0
Downloaded serde v1.0.144
Downloaded signal-hook-registry v1.4.0
Downloaded scoped-tls v1.0.0
Downloaded png v0.17.6
Downloaded net2 v0.2.37
Downloaded same-file v1.0.6
Downloaded raw-window-handle v0.5.0
Downloaded percent-encoding v2.2.0
Downloaded inotify-sys v0.1.5
Downloaded crossfont v0.5.0
Downloaded smallvec v1.9.0
Downloaded sctk-adwaita v0.4.2
Downloaded servo-fontconfig v0.5.1
Downloaded slab v0.4.7
Downloaded raw-window-handle v0.4.3
Downloaded regex-automata v0.1.10
Downloaded smithay-clipboard v0.6.6
Downloaded serde_yaml v0.8.26
Downloaded inotify v0.7.1
Downloaded parking_lot v0.12.1
Downloaded utf8parse v0.2.0
Downloaded signal-hook v0.3.14
Downloaded mio v0.6.23
Downloaded notify v4.0.17
Downloaded mio-uds v0.6.8
Downloaded glutin v0.29.1
Downloaded once_cell v1.14.0
Downloaded mio-extras v2.0.6
Downloaded dlib v0.5.0
Downloaded bytemuck v1.12.1
Downloaded log v0.4.17
Downloaded calloop v0.10.1
Downloaded freetype-rs v0.26.0
Downloaded slotmap v1.0.6
Downloaded signal-hook-mio v0.2.3
Downloaded quick-xml v0.22.0
Downloaded cfg-if v1.0.0
Downloaded strsim v0.10.0
Downloaded thiserror v1.0.35
Downloaded textwrap v0.15.1
Downloaded version_check v0.9.4
Downloaded proc-macro-error v1.0.4
Downloaded unicode-width v0.1.10
Downloaded unicode-ident v1.0.4
Downloaded tiny-skia-path v0.7.0
Downloaded walkdir v2.3.2
Downloaded vec_map v0.8.2
Downloaded filetime v0.2.17
Downloaded proc-macro-error-attr v1.0.4
Downloaded proc-macro2 v1.0.43
Downloaded dirs-sys v0.3.7
Downloaded lazy_static v1.4.0
Downloaded autocfg v1.1.0
Downloaded adler v1.0.2
Downloaded clap_derive v3.2.18
Downloaded minimal-lexical v0.2.1
Downloaded serde_json v1.0.85
Downloaded x11-dl v2.20.0
Downloaded thiserror-impl v1.0.35
Downloaded indexmap v1.9.1
Downloaded bitflags v1.3.2
Downloaded miniz_oxide v0.5.4
Downloaded os_str_bytes v6.3.0
Downloaded itoa v1.0.3
Downloaded wayland-scanner v0.29.5
Downloaded heck v0.4.0
Downloaded memchr v2.5.0
Downloaded fnv v1.0.7
Downloaded clap_lex v0.2.4
Downloaded cfg-if v0.1.10
Downloaded tiny-skia v0.7.0
Downloaded syn v1.0.99
Downloaded termcolor v1.1.3
Downloaded quote v1.0.21
Downloaded libc v0.2.132
Downloaded smithay-client-toolkit v0.16.0
Downloaded khronos_api v3.1.0
Downloaded memmap2 v0.5.7
Downloaded hashbrown v0.12.3
Downloaded cc v1.0.73
Downloaded nix v0.24.2
Downloaded wayland-cursor v0.29.5
Downloaded wayland-commons v0.29.5
Downloaded servo-fontconfig-sys v5.1.0
Downloaded x11-clipboard v0.6.1
Downloaded wayland-sys v0.29.5
Downloaded wayland-egl v0.29.5
Downloaded freetype-sys v0.13.1
Downloaded clap v3.2.21
Downloaded wayland-protocols v0.29.5
Downloaded wayland-client v0.29.5
Downloaded xcb v1.1.1
Downloaded vte_generate_state_changes v0.1.1
Downloaded expat-sys v2.1.6
Downloaded copypasta v0.8.1
Downloaded gl_generator v0.14.0
Downloaded flate2 v1.0.24
Downloaded winit v0.27.3
Compiling proc-macro2 v1.0.43
Compiling quote v1.0.21
Compiling unicode-ident v1.0.4
Compiling libc v0.2.132
Compiling cfg-if v1.0.0
Compiling syn v1.0.99
Compiling autocfg v1.1.0
Compiling serde_derive v1.0.144
Compiling serde v1.0.144
Compiling pkg-config v0.3.25
Compiling log v0.4.17
Compiling bitflags v1.3.2
Compiling xml-rs v0.8.4
Compiling version_check v0.9.4
Compiling memchr v2.5.0
Compiling lazy_static v1.4.0
Compiling smallvec v1.9.0
Compiling cc v1.0.73
Compiling once_cell v1.14.0
Compiling khronos_api v3.1.0
Compiling hashbrown v0.12.3
Compiling downcast-rs v1.2.0
Compiling scoped-tls v1.0.0
Compiling linked-hash-map v0.5.6
Compiling cfg-if v0.1.10
Compiling thiserror v1.0.35
Compiling minimal-lexical v0.2.1
Compiling ryu v1.0.11
Compiling parking_lot_core v0.9.3
Compiling crc32fast v1.3.2
Compiling scopeguard v1.1.0
Compiling vec_map v0.8.2
Compiling adler v1.0.2
Compiling signal-hook v0.3.14
Compiling bytemuck v1.12.1
Compiling foreign-types-shared v0.3.1
Compiling arrayref v0.3.6
Compiling lazycell v1.3.0
Compiling serde_json v1.0.85
Compiling cty v0.2.2
Compiling regex-syntax v0.6.27
Compiling arrayvec v0.5.2
Compiling utf8parse v0.2.0
Compiling os_str_bytes v6.3.0
Compiling base64 v0.13.0
Compiling heck v0.4.0
Compiling itoa v1.0.3
Compiling unicode-width v0.1.10
Compiling strsim v0.10.0
Compiling textwrap v0.15.1
Compiling termcolor v1.1.3
Compiling same-file v1.0.6
Compiling percent-encoding v2.2.0
Compiling fnv v1.0.7
Compiling libloading v0.7.3
Compiling instant v0.1.12
Compiling slotmap v1.0.6
Compiling proc-macro-error-attr v1.0.4
Compiling proc-macro-error v1.0.4
Compiling cmake v0.1.48
Compiling yaml-rust v0.4.5
Compiling miniz_oxide v0.5.4
Compiling memoffset v0.6.5
Compiling indexmap v1.9.1
Compiling slab v0.4.7
Compiling lock_api v0.4.8
Compiling tiny-skia-path v0.7.0
Compiling safe_arch v0.5.2
Compiling raw-window-handle v0.5.0
Compiling raw-window-handle v0.4.3
Compiling clap_lex v0.2.4
Compiling walkdir v2.3.2
Compiling wayland-sys v0.29.5
Compiling servo-fontconfig-sys v5.1.0
Compiling smithay-client-toolkit v0.16.0
Compiling crossfont v0.5.0
Compiling x11-dl v2.20.0
Compiling dlib v0.5.0
Compiling nom v7.1.1
Compiling quick-xml v0.22.0
Compiling freetype-sys v0.13.1
Compiling expat-sys v2.1.6
Compiling flate2 v1.0.24
Compiling regex-automata v0.1.10
Compiling wayland-scanner v0.29.5
Compiling png v0.17.6
Compiling xcb v1.1.1
Compiling vte_generate_state_changes v0.1.1
Compiling nix v0.24.2
Compiling net2 v0.2.37
Compiling iovec v0.1.4
Compiling memmap2 v0.5.7
Compiling signal-hook-registry v1.4.0
Compiling dirs-sys v0.3.7
Compiling inotify-sys v0.1.5
Compiling atty v0.2.14
Compiling shared_library v0.1.9
Compiling filetime v0.2.17
Compiling freetype-rs v0.26.0
Compiling parking_lot v0.12.1
Compiling tiny-skia v0.7.0
Compiling vte v0.10.1
Compiling dirs v4.0.0
Compiling inotify v0.7.1
Compiling servo-fontconfig v0.5.1
Compiling osmesa-sys v0.1.2
Compiling xcursor v0.3.4
Compiling xdg v2.4.1
Compiling wayland-client v0.29.5
Compiling wayland-protocols v0.29.5
Compiling wayland-commons v0.29.5
Compiling wayland-cursor v0.29.5
Compiling wayland-egl v0.29.5
Compiling thiserror-impl v1.0.35
Compiling foreign-types-macros v0.2.2
Compiling alacritty_config_derive v0.2.1-dev (/bass/work/alacritty_config_derive)
Compiling clap_derive v3.2.18
Compiling foreign-types v0.5.0
Compiling x11-clipboard v0.6.1
Compiling clap v3.2.21
Compiling clap_complete v3.2.5
Compiling serde_yaml v0.8.26
Compiling gl_generator v0.14.0
Compiling mio v0.6.23
Compiling calloop v0.10.1
Compiling mio v0.8.4
Compiling alacritty_config v0.1.1-dev (/bass/work/alacritty_config)
Compiling mio-uds v0.6.8
Compiling mio-extras v2.0.6
Compiling signal-hook-mio v0.2.3
Compiling notify v4.0.17
Compiling alacritty_terminal v0.17.1-dev (/bass/work/alacritty_terminal)
Compiling glutin_egl_sys v0.1.6
Compiling glutin_glx_sys v0.1.8
Compiling alacritty v0.12.0-dev (/bass/work/alacritty)
Compiling sctk-adwaita v0.4.2
Compiling smithay-clipboard v0.6.6
Compiling copypasta v0.8.1
Compiling winit v0.27.3
Compiling glutin v0.29.1
Finished test [unoptimized + debuginfo] target(s) in 1m 04s
Running unittests src/main.rs (target/debug/deps/alacritty-f9ba2e8045123e19)
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 69 filtered out; finished
in 0.00s
Running unittests src/lib.rs (target/debug/deps/alacritty_config-44b2038924826b85
)
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished i
n 0.00s
Running unittests src/lib.rs (target/debug/deps/alacritty_config_derive-61b40fb20
40c7a24)
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished i
n 0.00s
Running tests/config.rs (target/debug/deps/config-2866372c6f734931)
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 4 filtered out; finished i
n 0.00s
Running unittests src/lib.rs (target/debug/deps/alacritty_terminal-1e3a60409b0f4f
08)
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 134 filtered out; finished
in 0.00s
Running tests/ref.rs (target/debug/deps/ref-356f743d920db53b)
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 42 filtered out; finished
in 0.00s
true
demo running services
𝄢

To run a service thunk, assign names to its ports using with-port. The provided ports will be healthchecked whenever the service runs.

(defn http-server [index]
  (from (linux/python)
    (-> ($ python -m http.server)
        (with-mount (mkfile ./index.html index) ./index.html)
        (with-port :http 8000))))

(http-server "Hello, world!")
stderr: 1 lines
=> resolve image config for docker.io/library/python:latest [0.69s]
.python
{
:image
{
:repository "python"
:platform
{
:os "linux"
}
:tag "latest"
:digest "sha256:e9c35537103a2801a30b15a77d4a56b35532c964489b125ec1ff24f3d5b53409"
}
:cmd .python
:args
(
  1. "-m"
  2. "http.server"
)
:mounts
(
  1. {
    :source <fs>/index.html
    :target ./index.html
    }
)
}
𝄢

You can use addr to construct a thunk addr. A thunk addr is like a thunk path except it references a named port provided by the thunk rather than a file created by it.

(defn echo [msg]
  (let [server (http-server msg)]
    (from (linux/nixery.dev/shell/curl)
      ($ curl -s (addr server :http "http://$host:$port")))))

(echo "Hello, world!")
stderr: 1 lines
=> resolve image config for nixery.dev/shell/curl:latest [2.48s]
.curl
{
:image
{
:repository "nixery.dev/shell/curl"
:platform
{
:os "linux"
}
:tag "latest"
:digest "sha256:1c1bab7cf7f6e24ddedcc0b0a0d5146bd8037bc18906a466e45cd66da59166d9"
}
:cmd .curl
:args
(
  1. "-s"
  2. .python
    {
    :image
    {
    :repository "python"
    :platform
    {
    :os "linux"
    }
    :tag "latest"
    :digest "sha256:e9c35537103a2801a30b15a77d4a56b35532c964489b125ec1ff24f3d5b53409"
    }
    :cmd .python
    :args
    (
    1. "-m"
    2. "http.server"
    )
    :mounts
    (
    1. {
      :source <fs>/index.html
      :target ./index.html
      }
    )
    }
    http
)
}
𝄢

Like thunks and thunk paths, thunk addrs are just data values. The underlying service thunk only runs when another thunk that needs it runs.

(run (echo "Hello, world!"))
stderr: 89 lines
=> resolve image config for docker.io/library/python@sha256:e9c35537103a2801a30b15a77d4a56
b35532c964489b125ec1ff24f3d5b53409 [0.02s]
=> mkfile /index.html [0.01s]
=> docker-image://docker.io/library/python@sha256:e9c35537103a2801a30b15a77d4a56b35532c964
489b125ec1ff24f3d5b53409 [0.13s]
-> resolve docker.io/library/python@sha256:e9c35537103a2801a30b15a77d4a56b35532c964489b125
ec1ff24f3d5b53409 [0.01s]
-> sha256:736f7bc16867ade5f22aee39d1cb555cd7b21decb004f5fb31d687a0fc3918a6 233B / 233B [0.
07s]
-> sha256:94da21e53a5b674037029cdd798b69d718e9ebaea2eaf16607455beff3d7cee5 3.04MB / 3.04MB
[0.32s]
-> sha256:aaf3b07565c21a6de4f23a918d5eba899ed3f749c7d158af4ab6804d74699dbb 20.03MB / 20.03
MB [2.11s]
-> sha256:15132af733424a0be2249e6045e10414a5fb6db79c68bd769d72e197c01c8336 6.29MB / 6.29MB
[0.37s]
-> extracting sha256:15132af733424a0be2249e6045e10414a5fb6db79c68bd769d72e197c01c8336 [0.1
4s]
-> extracting sha256:aaf3b07565c21a6de4f23a918d5eba899ed3f749c7d158af4ab6804d74699dbb [0.3
2s]
-> extracting sha256:736f7bc16867ade5f22aee39d1cb555cd7b21decb004f5fb31d687a0fc3918a6 [0.0
1s]
-> extracting sha256:94da21e53a5b674037029cdd798b69d718e9ebaea2eaf16607455beff3d7cee5 [0.1
3s]
=> resolve image config for nixery.dev/shell/curl@sha256:1c1bab7cf7f6e24ddedcc0b0a0d5146bd
8037bc18906a466e45cd66da59166d9 [0.00s]
=> docker-image://nixery.dev/shell/curl@sha256:1c1bab7cf7f6e24ddedcc0b0a0d5146bd8037bc1890
6a466e45cd66da59166d9 [0.03s]
-> resolve nixery.dev/shell/curl@sha256:1c1bab7cf7f6e24ddedcc0b0a0d5146bd8037bc18906a466e4
5cd66da59166d9 [0.01s]
-> sha256:933ab91b5fc7e57537edfe1772d9d1bbf2e100277e013c2542962edb70442267 7.19kB / 7.19kB
[0.21s]
-> sha256:a0a8033450c9fe483df83196c4f65cf062bf6740ccd3fd9423d38eb252fc4d3f 801.23kB / 801.
23kB [10.3s]
-> sha256:f1e5f8a267cb474e42478a4317897de85381b00ff941b5be64051ad30a7f4a7d 10.50MB / 10.50
MB [7.39s]
-> sha256:3abf26e38053a835edb9b85ef656c7ec69cf8959b7c44cc698ecfa7a84b807ab 66.22kB / 66.22
kB [5.77s]
-> sha256:1b6c8aa02e35a90110f861ba8eb6c6243ec3eb262307923fb02a9c67d00c4ae6 561.09kB / 561.
09kB [5.95s]
-> sha256:c7039a82ac84cdf605c46e1d68ffc2ce6d7700d2c0a9943ae5a7e5b58a15394e 983.83kB / 983.
83kB [0.62s]
-> sha256:15b0aee257909e1565d94074384feb4408c7ab23893bc5770a1d12b59d64e41e 796.08kB / 796.
08kB [0.28s]
-> sha256:865be752468b79bcbba79404d9297f52f07464790708c5fb317fdf259cd1ef9a 2.78MB / 2.78MB
[0.49s]
-> sha256:9286316badeb525d9a7eba26ee7f3c5f0366a6664b4b451c9152e095c1357337 2.31MB / 2.31MB
[0.31s]
-> sha256:c4eb30a3d211aa261ed9586aa9869ed6c535d8bc60445767144df2d17767779b 1.06MB / 1.06MB
[0.29s]
-> sha256:3d12fab47314110e223ecbbfa88d4132289f4a4a10aa5f9ee2acce118a774233 14.32MB / 14.32
MB [1.32s]
-> sha256:7c92b49e65867ce863cfb079dba09d9a08acc295071ff8b44ac59e0cea470e54 5.38MB / 5.38MB
[0.62s]
-> sha256:4c89de451659bf8af38c3cfcbe8b20b3a9728b2ed0dfe1b15ea07ccaa8ea4b7a 151.59kB / 151.
59kB [0.27s]
-> sha256:0f25e102816cf9e81d0f615b69db2927306849d001f52d62ee5f162f7699f97b 140.17kB / 140.
17kB [0.14s]
-> extracting sha256:0f25e102816cf9e81d0f615b69db2927306849d001f52d62ee5f162f7699f97b [0.0
1s]
-> extracting sha256:4c89de451659bf8af38c3cfcbe8b20b3a9728b2ed0dfe1b15ea07ccaa8ea4b7a [0.0
1s]
-> extracting sha256:7c92b49e65867ce863cfb079dba09d9a08acc295071ff8b44ac59e0cea470e54 [0.0
7s]
-> extracting sha256:3d12fab47314110e223ecbbfa88d4132289f4a4a10aa5f9ee2acce118a774233 [0.4
0s]
-> extracting sha256:c4eb30a3d211aa261ed9586aa9869ed6c535d8bc60445767144df2d17767779b [0.0
3s]
-> extracting sha256:9286316badeb525d9a7eba26ee7f3c5f0366a6664b4b451c9152e095c1357337 [0.0
4s]
-> extracting sha256:865be752468b79bcbba79404d9297f52f07464790708c5fb317fdf259cd1ef9a [0.0
4s]
-> extracting sha256:c7039a82ac84cdf605c46e1d68ffc2ce6d7700d2c0a9943ae5a7e5b58a15394e [0.0
3s]
-> extracting sha256:15b0aee257909e1565d94074384feb4408c7ab23893bc5770a1d12b59d64e41e [0.1
9s]
-> extracting sha256:1b6c8aa02e35a90110f861ba8eb6c6243ec3eb262307923fb02a9c67d00c4ae6 [0.0
1s]
-> extracting sha256:3abf26e38053a835edb9b85ef656c7ec69cf8959b7c44cc698ecfa7a84b807ab [0.0
1s]
-> extracting sha256:f1e5f8a267cb474e42478a4317897de85381b00ff941b5be64051ad30a7f4a7d [0.2
0s]
-> extracting sha256:a0a8033450c9fe483df83196c4f65cf062bf6740ccd3fd9423d38eb252fc4d3f [0.0
3s]
-> extracting sha256:933ab91b5fc7e57537edfe1772d9d1bbf2e100277e013c2542962edb70442267 [0.0
3s]
=> curl -s <thunk 6T3PN9K8NK7NG: (.python)>:http [0.26s]
Hello, world!
=> python -m http.server CANCELED [12.2s]
10.64.5.30 - - [25/Sep/2022 01:56:30] "GET / HTTP/1.1" 200 -
null
demo building & publishing artifacts
𝄢

To build from source just run whatever build command you already use.

(use (.git (linux/alpine/git)))

(defn go-build [src & args]
  (from (linux/golang)
    (cd src
      (-> ($ go build & $args)
          (with-env {:CGO_ENABLED "0"})))))

(let [src git:github/vito/booklit/ref/master/
      built (go-build src "./cmd/booklit")]
  (-> (from (linux/alpine)
        ($ built/booklit --version))
      (read :raw)
      next))
stderr: 32 lines
=> resolve image config for docker.io/library/alpine@sha256:bc41182d7ef5ffc53a40b044e72519
3bc10142a1243f395ee852a8d9730fc2ad [0.02s]
=> resolve image config for docker.io/library/golang@sha256:2d17ffd12a2cdb25d4a633ad25f8dc
29608ed84f31b3b983427d825280427095 [0.00s]
=> resolve image config for docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a05
7176c06a9f266de440be406dcf079b [0.00s]
=> docker-image://docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f
266de440be406dcf079b [0.02s]
-> resolve docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f266de44
0be406dcf079b [0.02s]
=> docker-image://docker.io/library/alpine@sha256:bc41182d7ef5ffc53a40b044e725193bc10142a1
243f395ee852a8d9730fc2ad CACHED [0.00s]
-> resolve docker.io/library/alpine@sha256:bc41182d7ef5ffc53a40b044e725193bc10142a1243f395
ee852a8d9730fc2ad [0.02s]
=> docker-image://docker.io/library/golang@sha256:2d17ffd12a2cdb25d4a633ad25f8dc29608ed84f
31b3b983427d825280427095 CACHED [0.00s]
-> resolve docker.io/library/golang@sha256:2d17ffd12a2cdb25d4a633ad25f8dc29608ed84f31b3b98
3427d825280427095 [0.02s]
=> git clone https://github.com/vito/booklit ./ CACHED [0.00s]
=> git fetch origin d62e0d27a9668a8cf3850e405c6b19cd213f545a CACHED [0.00s]
=> git checkout d62e0d27a9668a8cf3850e405c6b19cd213f545a CACHED [0.00s]
=> git submodule update --init --recursive CACHED [0.00s]
=> go build ./cmd/booklit [4.15s]
go: downloading github.com/jessevdk/go-flags v1.4.0
go: downloading github.com/sirupsen/logrus v1.8.1
go: downloading github.com/agext/levenshtein v1.2.3
go: downloading github.com/segmentio/textio v1.2.0
go: downloading golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a
=> <thunk 3M53QK2GPCO74: (.go)>/booklit --version [0.22s]
time="2022-09-25T01:56:35Z" level=info msg="plugin registered" plugin=baselit
=> exporting to client [0.00s]
-> copying files 36B [0.00s]
"0.0.0-dev\n"
𝄢

Thunk paths can be serialized to JSON. If all thunks involved in its creation are hermetic the JSON structure represents a repeatable artifact.

(def built
  (go-build git:github/vito/booklit/ref/master/ "./cmd/booklit"))

(emit built *stdout*)
{
  "image": {
    "ref": {
      "repository": "golang",
      "platform": {
        "os": "linux"
      },
      "tag": "latest",
      "digest": "sha256:2d17ffd12a2cdb25d4a633ad25f8dc29608ed84f31b3b983427d825280427095"
    }
  },
  "cmd": {
    "command": {
      "name": "go"
    }
  },
  "args": [
    {
      "string": {
        "value": "build"
      }
    },
    {
      "string": {
        "value": "./cmd/booklit"
      }
    }
  ],
  "env": [
    {
      "symbol": "CGO_ENABLED",
      "value": {
        "string": {
          "value": "0"
        }
      }
    }
  ],
  "mounts": [
    {
      "source": {
        "thunk": {
          "thunk": {
            "image": {
              "thunk": {
                "image": {
                  "thunk": {
                    "image": {
                      "thunk": {
                        "image": {
                          "ref": {
                            "repository": "alpine/git",
                            "platform": {
                              "os": "linux"
                            },
                            "tag": "latest",
                            "digest": "sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f266de440be406dcf079b"
                          }
                        },
                        "cmd": {
                          "command": {
                            "name": "git"
                          }
                        },
                        "args": [
                          {
                            "string": {
                              "value": "clone"
                            }
                          },
                          {
                            "string": {
                              "value": "https://github.com/vito/booklit"
                            }
                          },
                          {
                            "dirPath": {
                              "path": "."
                            }
                          }
                        ]
                      }
                    },
                    "cmd": {
                      "command": {
                        "name": "git"
                      }
                    },
                    "args": [
                      {
                        "string": {
                          "value": "fetch"
                        }
                      },
                      {
                        "string": {
                          "value": "origin"
                        }
                      },
                      {
                        "string": {
                          "value": "d62e0d27a9668a8cf3850e405c6b19cd213f545a"
                        }
                      }
                    ]
                  }
                },
                "cmd": {
                  "command": {
                    "name": "git"
                  }
                },
                "args": [
                  {
                    "string": {
                      "value": "checkout"
                    }
                  },
                  {
                    "string": {
                      "value": "d62e0d27a9668a8cf3850e405c6b19cd213f545a"
                    }
                  }
                ]
              }
            },
            "cmd": {
              "command": {
                "name": "git"
              }
            },
            "args": [
              {
                "string": {
                  "value": "submodule"
                }
              },
              {
                "string": {
                  "value": "update"
                }
              },
              {
                "string": {
                  "value": "--init"
                }
              },
              {
                "string": {
                  "value": "--recursive"
                }
              }
            ]
          },
          "path": {
            "dir": {
              "path": "."
            }
          }
        }
      },
      "target": {
        "dir": {
          "path": "."
        }
      }
    }
  ]
}
null
𝄢

The exact format is not finalized and probably needs versioning and deduping.

A thunk path's JSON form can be piped to bass --export to build the artifact and emit a tar stream.

cat thunk-path.json | bass --export | tar -xf -

You can publish thunk path JSON as part of your release as a form of provenance:

(let [repro (mkfile ./file.json (json built))]
  (from (nixery.dev/gh)
    ($ gh release create v0.0.1 $repro)))
stderr: 24 lines
error! call trace (oldest first):
┆ <fs>/literate-6:1:0..3:41
1 │ (let [repro (mkfile ./file.json (json built))]
2 │ (from (nixery.dev/gh)
3 │ ($ gh release create v0.0.1 $repro)))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
┆ (1 internal call elided)
┆ <fs>/literate-6:2:2..3:40
1 │ (let [repro (mkfile ./file.json (json built))]
2 │ (from (nixery.dev/gh)
3 │ ($ gh release create v0.0.1 $repro)))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
┆ <fs>/literate-6:2:8..2:23
2 │ (from (nixery.dev/gh)
^^^^^^^^^^^^^^^
┆ <fs>/literate-6:2:9..2:22
2 │ (from (nixery.dev/gh)
^^^^^^^^^^^^^
unbound symbol: nixery.dev
demo pinning dependencies
𝄢

To pin dependencies, configure a path to a bass.lock file as the magic *memos* binding.

(def *memos* *dir*/bass.lock)
*memos*
𝄢

The linux path root resolves an image reference to a digest and memoizes its result into *memos* if defined.

(use (.git (linux/alpine/git))) ; saves digest into *memos*

(run (from (linux/alpine/git) ; uses the digest from *memos*
        ($ cat $*memos*)))    ; reveal the wizard behind the curtain
stderr: 108 lines
=> resolve image config for docker.io/alpine/git:latest [0.27s]
=> resolve image config for docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a05
7176c06a9f266de440be406dcf079b [0.02s]
=> docker-image://docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f
266de440be406dcf079b CACHED [0.00s]
-> resolve docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f266de44
0be406dcf079b [0.01s]
=> local:///tmp/nix-shell.vFVjLW/bass-scope3768610027 [0.02s]
-> transferring /tmp/nix-shell.vFVjLW/bass-scope3768610027: 2.11kB [0.00s]
=> copy /bass.lock /bass.lock [0.01s]
=> cat <host: /tmp/nix-shell.vFVjLW/bass-scope3768610027/bass.lock> [0.23s]
memos: {
module: {
cmd: {
command: {
name: "run"
}
}
}
calls: {
binding: "resolve"
results: {
input: {
array: {
values: {
object: {
bindings: {
symbol: "platform"
value: {
object: {
bindings: {
symbol: "os"
value: {
string: {
value: "linux"
}
}
}
}
}
}
bindings: {
symbol: "repository"
value: {
string: {
value: "alpine/git"
}
}
}
bindings: {
symbol: "tag"
value: {
string: {
value: "latest"
}
}
}
}
}
}
}
output: {
object: {
bindings: {
symbol: "repository"
value: {
string: {
value: "alpine/git"
}
}
}
bindings: {
symbol: "platform"
value: {
object: {
bindings: {
symbol: "os"
value: {
string: {
value: "linux"
}
}
}
}
}
}
bindings: {
symbol: "tag"
value: {
string: {
value: "latest"
}
}
}
bindings: {
symbol: "digest"
value: {
string: {
value: "sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f266de440be4
06dcf079b"
}
}
}
}
}
}
}
}
null
𝄢

The github path root resolves a branch or tag reference to a commit and returns its checkout, memoizing the commit in *memos* if defined.

git:github/vito/booklit/ref/master/
stderr: 9 lines
=> resolve image config for docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a05
7176c06a9f266de440be406dcf079b [0.02s]
=> docker-image://docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f
266de440be406dcf079b CACHED [0.00s]
-> resolve docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f266de44
0be406dcf079b [0.01s]
=> git ls-remote https://github.com/vito/booklit master [0.47s]
=> exporting to client [0.00s]
-> copying files 85B [0.00s]
.git
{
:image
.git
{
:image
.git
{
:image
.git
{
:image
{
:repository "alpine/git"
:platform
{
:os "linux"
}
:tag "latest"
:digest "sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f266de440be406dcf079b"
}
:cmd .git
:args
(
  1. "clone"
  2. "https://github.com/vito/booklit"
  3. ./
)
}
:cmd .git
:args
(
  1. "fetch"
  2. "origin"
  3. "d62e0d27a9668a8cf3850e405c6b19cd213f545a"
)
}
:cmd .git
:args
(
  1. "checkout"
  2. "d62e0d27a9668a8cf3850e405c6b19cd213f545a"
)
}
:cmd .git
:args
(
  1. "submodule"
  2. "update"
  3. "--init"
  4. "--recursive"
)
}
./
𝄢

Paths like above are often used with use to load Bass modules from thunk paths. Bass doesn't have its own package system; it uses thunks for that too.

(let [src git:github/vito/booklit/ref/master/]
  (use (src/bass/booklit.bass))
  (when (succeeds? (booklit:tests src))
    (booklit:build src "dev" "linux" "amd64")))
stderr: 92 lines
=> exporting to client [0.00s]
-> sending tarball [0.00s]
=> exporting to client [0.00s]
-> sending tarball [0.00s]
=> resolve image config for docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a05
7176c06a9f266de440be406dcf079b [0.02s]
=> resolve image config for docker.io/library/golang@sha256:a452d6273ad03a47c2f29b898d6bb5
7630e77baf839651ef77d03e4e049c5bf3 [0.46s]
=> docker-image://docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f
266de440be406dcf079b [0.01s]
-> resolve docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f266de44
0be406dcf079b [0.01s]
=> git clone https://github.com/vito/booklit ./ CACHED [0.00s]
=> git fetch origin d62e0d27a9668a8cf3850e405c6b19cd213f545a CACHED [0.00s]
=> git checkout d62e0d27a9668a8cf3850e405c6b19cd213f545a CACHED [0.00s]
=> git submodule update --init --recursive CACHED [0.00s]
=> docker-image://docker.io/library/golang@sha256:a452d6273ad03a47c2f29b898d6bb57630e77baf
839651ef77d03e4e049c5bf3 [0.00s]
-> resolve docker.io/library/golang@sha256:a452d6273ad03a47c2f29b898d6bb57630e77baf839651e
f77d03e4e049c5bf3 [0.01s]
-> sha256:faf2829ac3538e681c1c4738fe706f3e165a649d056882221ada493085e65f95 156B / 156B [0.
09s]
-> sha256:691e33f10d2fcc5dbbed7061bd38f67acbbacf8eb32c3f81c29e877e08e57050 141.75MB / 141.
75MB [9.81s]
-> sha256:0f00f9da9be9d951ac50411de5505d1e17e4a9e88cb56f15ca17f9780cff9cec 85.88MB / 85.88
MB [7.05s]
-> sha256:76e5964a957d206950c8c0de99f3c491ecec78887ebe4df0ac5ab9ceb536a4d5 54.58MB / 54.58
MB [4.51s]
-> sha256:14f0d2bd524377dc42d072443c0e5e7cafa14f5df609d39bb1f717f43817a2cd 10.88MB / 10.88
MB [1.49s]
-> sha256:1339eaac5b67d16d6d9f41fb7a7b96f7cebf3ba4beab36cbb60935aa772af583 55.01MB / 55.01
MB [4.83s]
-> sha256:4c78fa1b97999d08408734a61040475ade5bd7e33e91c0d5170dba2c7c7a92fd 5.16MB / 5.16MB
[0.77s]
-> extracting sha256:1339eaac5b67d16d6d9f41fb7a7b96f7cebf3ba4beab36cbb60935aa772af583 [0.8
5s]
-> extracting sha256:4c78fa1b97999d08408734a61040475ade5bd7e33e91c0d5170dba2c7c7a92fd [0.0
9s]
-> extracting sha256:14f0d2bd524377dc42d072443c0e5e7cafa14f5df609d39bb1f717f43817a2cd [0.1
1s]
-> extracting sha256:76e5964a957d206950c8c0de99f3c491ecec78887ebe4df0ac5ab9ceb536a4d5 [0.9
3s]
-> extracting sha256:0f00f9da9be9d951ac50411de5505d1e17e4a9e88cb56f15ca17f9780cff9cec [1.1
6s]
-> extracting sha256:691e33f10d2fcc5dbbed7061bd38f67acbbacf8eb32c3f81c29e877e08e57050 [2.2
8s]
-> extracting sha256:faf2829ac3538e681c1c4738fe706f3e165a649d056882221ada493085e65f95 [0.0
0s]
=> go install -mod=mod github.com/onsi/ginkgo/v2/ginkgo [3.09s]
go: downloading github.com/onsi/ginkgo/v2 v2.1.4
go: downloading github.com/onsi/ginkgo v1.16.4
go: downloading golang.org/x/tools v0.1.10
go: downloading github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38
go: downloading github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0
=> ./scripts/test -p [4.85s]
go: downloading github.com/sirupsen/logrus v1.8.1
go: downloading github.com/alecthomas/chroma v0.9.2
go: downloading github.com/agext/levenshtein v1.2.3
go: downloading github.com/segmentio/textio v1.2.0
go: downloading github.com/jessevdk/go-flags v1.4.0
go: downloading github.com/onsi/gomega v1.19.0
go: downloading golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a
go: downloading golang.org/x/net v0.0.0-20220225172249-27dd8689420f
go: downloading gopkg.in/yaml.v2 v2.4.0
go: downloading golang.org/x/text v0.3.7
go: downloading github.com/dlclark/regexp2 v1.4.0
go: downloading github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964
warning: no packages being tested depend on matches for pattern github.com/vito/bookli
t/booklitcmd
warning: no packages being tested depend on matches for pattern github.com/vito/bookli
t/chroma
warning: no packages being tested depend on matches for pattern github.com/vito/bookli
t/chroma/plugin
warning: no packages being tested depend on matches for pattern github.com/vito/bookli
t/docs/go
Running Suite: Booklit Suite - /bass/work/tests
===============================================
Random Seed: 1664071017
Will run 62 of 62 specs
Running in parallel across 15 processes
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
Ran 62 of 62 Specs in 0.031 seconds
SUCCESS! -- 62 Passed | 0 Failed | 0 Pending | 0 Skipped
coverage: 62.2% of statements
composite coverage: 62.2% of statements
Ginkgo ran 1 suite in 2.209497859s
Test Suite Passed
.go
{
:image
{
:repository "golang"
:platform
{
:os "linux"
}
:tag "latest"
:digest "sha256:a452d6273ad03a47c2f29b898d6bb57630e77baf839651ef77d03e4e049c5bf3"
}
:cmd .go
:args
(
  1. "build"
  2. "-o"
  3. ../booklit_linux_amd64
  4. "--ldflags"
  5. "-X github.com/vito/booklit.Version=dev"
  6. ./cmd/booklit
)
:env
{
:GOOS "linux"
:GOARCH "amd64"
}
:dir
.git
{
:image
.git
{
:image
.git
{
:image
.git
{
:image
{
:repository "alpine/git"
:platform
{
:os "linux"
}
:tag "latest"
:digest "sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f266de440be406dcf079b"
}
:cmd .git
:args
(
  1. "clone"
  2. "https://github.com/vito/booklit"
  3. ./
)
}
:cmd .git
:args
(
  1. "fetch"
  2. "origin"
  3. "d62e0d27a9668a8cf3850e405c6b19cd213f545a"
)
}
:cmd .git
:args
(
  1. "checkout"
  2. "d62e0d27a9668a8cf3850e405c6b19cd213f545a"
)
}
:cmd .git
:args
(
  1. "submodule"
  2. "update"
  3. "--init"
  4. "--recursive"
)
}
./
:mounts
(
  1. {
    :source <cache: booklit-go-cache>/
    :target /go/
    }
)
}
./booklit_linux_amd64
𝄢

To re-evaluate and update all memoized results, run bass --bump:

bass --bump bass.lock

This command loads each module and re-evalutes each memoized call, updating the bass.lock file in-place.

demo building images
𝄢

Bass eliminates the need for one-off Dockerfiles and toilsome image registry push/pull.

You just write thunks instead!

(def wget
  (from (linux/alpine)
    ($ apk add wget)))

(-> (from wget
      ($ wget --version))
    (read :lines)
    next)
stderr: 17 lines
=> resolve image config for docker.io/library/alpine@sha256:bc41182d7ef5ffc53a40b044e72519
3bc10142a1243f395ee852a8d9730fc2ad [0.02s]
=> docker-image://docker.io/library/alpine@sha256:bc41182d7ef5ffc53a40b044e725193bc10142a1
243f395ee852a8d9730fc2ad CACHED [0.00s]
-> resolve docker.io/library/alpine@sha256:bc41182d7ef5ffc53a40b044e725193bc10142a1243f395
ee852a8d9730fc2ad [0.01s]
=> apk add wget [0.58s]
fetch https://dl-cdn.alpinelinux.org/alpine/v3.16/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.16/community/x86_64/APKINDEX.tar.gz
(1/3) Installing libunistring (1.0-r0)
(2/3) Installing libidn2 (2.3.2-r2)
(3/3) Installing wget (1.21.3-r0)
Executing busybox-1.35.0-r17.trigger
OK: 8 MiB in 17 packages
=> wget --version [0.22s]
=> exporting to client [0.00s]
-> copying files 889B [0.00s]
"GNU Wget 1.21.3 built on linux-musl."
𝄢

Nix fans are probably seething right now. This isn't hermetic at all! The version of wget is a total wildcard! What if it changes? The house of cards could come crumbling down!

Worry not: you can use any command you want to build images. You can use nix build or any other tool to create an OCI image tarball and then use that image for other thunks.

(use (.git (linux/alpine/git))
     ; a module for doing cached nix builds
     (git:github/vito/tabs/ref/main/nix.bass))

; an image with wget installed
(def image
  {:file (nix:result
           (cd git:github/vito/tabs/ref/main/
             ($ nix build ".#wget"))
           ./image.tar)
   :platform {:os "linux"}
   :tag "latest"})

(-> (from image
      ($ wget --version))
    (read :lines)
    next)
stderr: 473 lines
=> git ls-remote https://github.com/vito/tabs main [0.62s]
=> exporting to client [0.00s]
-> copying files 83B [0.00s]
=> exporting to client [0.00s]
-> sending tarball [0.00s]
=> exporting to client [0.00s]
-> sending tarball [0.00s]
=> resolve image config for docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a05
7176c06a9f266de440be406dcf079b [0.02s]
=> resolve image config for docker.io/nixos/nix@sha256:c6c9e6bf8d2d87877ef931bbf5c350d84ac
114e33a4abacc3f2e51dcbed25ea1 [0.62s]
=> docker-image://docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f
266de440be406dcf079b [0.01s]
-> resolve docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f266de44
0be406dcf079b [0.01s]
=> git clone https://github.com/vito/tabs ./ CACHED [0.00s]
Cloning into '.'...
=> git fetch origin c97bdc3bc41acb5c1bebec6fba9994ee2fb992a5 CACHED [0.00s]
From https://github.com/vito/tabs
* branch c97bdc3bc41acb5c1bebec6fba9994ee2fb992a5 -> FETCH_HEAD
=> git checkout c97bdc3bc41acb5c1bebec6fba9994ee2fb992a5 CACHED [0.00s]
Note: switching to 'c97bdc3bc41acb5c1bebec6fba9994ee2fb992a5'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:
git switch -c <new-branch-name>
Or undo this operation with:
git switch -
Turn off this advice by setting config variable advice.detachedHead to false
HEAD is now at c97bdc3 use tls for nixery via caddy
=> git submodule update --init --recursive CACHED [0.00s]
=> docker-image://docker.io/nixos/nix@sha256:c6c9e6bf8d2d87877ef931bbf5c350d84ac114e33a4ab
acc3f2e51dcbed25ea1 [0.03s]
-> resolve docker.io/nixos/nix@sha256:c6c9e6bf8d2d87877ef931bbf5c350d84ac114e33a4abacc3f2e
51dcbed25ea1 [0.01s]
-> sha256:2b14dde76908dd5f43137ce032f044c930fc6bec8378f379c50f0d6839f810bd 39.69kB / 39.69
kB [0.24s]
-> sha256:ce685753a8e4d03c2a0f78617080878bb72f9d97c46ace731c9b19d91bc00250 107.49MB / 107.
49MB [5.09s]
-> sha256:d025e148aba21717c26f49cba4b95c75657554b944b647b90fbda93ffc0c986d 2.55MB / 2.55MB
[0.28s]
-> sha256:54365ec110d760dd2e1416e26e1e9b01d60b55498fbd3dd101b4b54384d81dac 2.97MB / 2.97MB
[0.30s]
-> sha256:0a7b7e323bc39114e9b40ad7936ac4d852d5af85975fce95e80af9042820c801 224.86kB / 224.
86kB [0.45s]
-> sha256:39b89855c6effc99eda36378c2286c8ef6d8494db4262068ea5acf8e1a569bb6 22.92kB / 22.92
kB [0.08s]
-> sha256:e8ef8748ddbeaf268e7c72b76b0d99435eef73cd76741f05f52ca50ab7c4470b 3.58MB / 3.58MB
[0.28s]
-> sha256:f28ad8353673c35e3f4e1ee43a37b8df4da36f49fa2ea93c6a2f42e5ae640573 1.89MB / 1.89MB
[0.41s]
-> sha256:b2c0c6341985babef8bdeaa30119a68ad09fbfb8975f2b94d12807a368d01c3b 343.15kB / 343.
15kB [0.09s]
-> sha256:5d53c544c7d839ffd7921a74f7997443b23a0e3bd3cea32e6b2065c9d62408a1 40.43kB / 40.43
kB [0.07s]
-> sha256:69db97dd6e325102d04b31ea1121a0732c478f16ce23e688ccde7d7984cd359d 117.83kB / 117.
83kB [0.10s]
-> sha256:96d673aebc2504890df67be6b35c0ebcf928746e244489adbf531cd7f514ed73 128.52kB / 128.
52kB [0.10s]
-> sha256:18e9ddafd99bdc39f258099de889678e3d6bb22c06be845d3d3ed46a03248a25 479.17kB / 479.
17kB [0.11s]
-> sha256:a18cfd4fad222f42a63c356bb8d7f1ea7b6f86ac52772cbbecf885a83068d3e7 1.60MB / 1.60MB
[0.18s]
-> sha256:8de655e531a479cd5df6654700f8c2624a6944faa3ec5deb6ea4791b2f077528 4.12MB / 4.12MB
[0.56s]
-> sha256:25984f25cfc1f27ac45d21c6cc35950422fe04d8f9ca788678aa1b0e76378fa7 154.30kB / 154.
30kB [0.11s]
-> sha256:bb8f5039f79760416fbbf1e9237f5870a2c34c7192cb57f218fa782dcc9dfdfb 6.22kB / 6.22kB
[0.57s]
-> sha256:f4043794f22a9c8c18f46fbc0f5bd5c4a78721ff9b3ea781643e3a2e9b13509b 2.27kB / 2.27kB
[0.26s]
-> sha256:2e3a96843f4167bf9725d4c619b062770ad568152812d712fcf323ac2d471c64 4.12kB / 4.12kB
[0.22s]
-> sha256:b44071dfc8a9beb82c283348b3fbfcbbb6aa1fb96cc942a410bb3f7bb0ac1330 4.95kB / 4.95kB
[0.33s]
-> sha256:576ebd4999aeca869c2ed3758cc2e28265fdbfcadc7f2e244056b567a2058a19 11.81kB / 11.81
kB [0.46s]
-> sha256:a3e9e94168e8f814527af4a7ffda6c80350a0fdbfac602cf477672a1670738eb 6.80kB / 6.80kB
[0.54s]
-> sha256:d86119eb584112d7eb86b6b3fced80be5bd1b8574e253bc24ba38bd58c9697d3 8.75kB / 8.75kB
[0.36s]
-> sha256:8002be4bee9cf48ce180167f42de80170361dd0ef60c3e3d28cb6d32e3c5c958 12.98kB / 12.98
kB [0.58s]
-> sha256:0ba65e28fa822231561b916aad61b3df726c82ee232040a77365d6fff468e6a5 6.12kB / 6.12kB
[0.10s]
-> sha256:8977114faeb36f655007e426bd1219abacb1cee9f5b4cd713b7a1083e6231eaa 23.89kB / 23.89
kB [0.08s]
-> sha256:78e5bdf4e64a38022a5757e12b5dc2ebc1029b7e05268166cbefcb48feb7fdd7 35.19kB / 35.19
kB [0.56s]
-> sha256:f8ecbb30c52aee2a2accbde4aa7336c3095830e6ca23bed5c753f8b07bab4467 743.58kB / 743.
58kB [0.21s]
-> sha256:2b50ae0e57765858706af584c01a1430a97a4e6520ace4e780e9bdd3b8829bbf 41.25kB / 41.25
kB [0.21s]
-> sha256:e9e0e9aea6d5e169f1ad55d08734f4520ee5c4c314cbe28ed9c8f760bb7a1d8a 288.65kB / 288.
65kB [0.10s]
-> sha256:0083054199ca635652887bc798346711129c213e26152398becba07982bb81a1 33.69kB / 33.69
kB [0.08s]
-> sha256:a1ca1b014e5dcc895a1eb7dddc9647030ee3d9bbbf4a3a08569089089585102f 175.48kB / 175.
48kB [1.37s]
-> sha256:ab720c23f2e7e6c9fb51060e3ff1bbf31c1529450be545bc29222ce478d0d128 102.28kB / 102.
28kB [0.11s]
-> sha256:a4ca34433450821e07a2d5a473cf6db01a3a1e6f64904d9e2a779cfc214b0f93 14.01MB / 14.01
MB [1.36s]
-> sha256:19258425c0dcd828329f7affd14b14ff7cbe6e9611a78a1248fad89333b7fee0 102.89kB / 102.
89kB [0.13s]
-> sha256:88d3758083ce65aa7c3d0e0abcfa624259b143748da5967650bf5aecf87c7889 2.43MB / 2.43MB
[0.33s]
-> sha256:bf844972b36a034d8fdf6276978f494db508b83ed0cd14e2aa091be762fd2e39 28.54kB / 28.54
kB [0.68s]
-> sha256:e93311f2be560d4e8464dfafa260e08150117d107b36870a75b8801416b40db8 53.01kB / 53.01
kB [0.56s]
-> sha256:ec4bd40f92f0c10b5cb396fa14a3f97066611f09b497079e210e094d9285642a 102.97kB / 102.
97kB [0.62s]
-> sha256:54e359541fabd36c7b13a08a94dac1d1aa796ac7aed5191920c38149de1652fa 97.88kB / 97.88
kB [0.20s]
-> sha256:cd2474198fda394cd534b138c0a0a927ad2754a5137bd0e2c5f2f34590e57290 1.26MB / 1.26MB
[0.20s]
-> sha256:ced122dcc8c6fe25c842df344fcee339b1686fd241cbd8a48e23d99fc1b5de1c 259B / 259B [0.
13s]
-> sha256:e0ac404bb6b0c47f03464c695dbeb8c9ec0ee6b14166554b94e4db4623d50fdf 759.81kB / 759.
81kB [0.65s]
-> sha256:ab3be33f13d0ee00d0d5f7e0f94e18f305b5a6a854903e942b49c795d5228b9d 2.12MB / 2.12MB
[0.59s]
-> sha256:f36ee716025d448d4c3c333247834477739c174ac10458cc745d1e173aac6723 9.18kB / 9.18kB
[0.45s]
-> sha256:24810c5ac4e79c5fdcea8bad83c06ab9d00791d4b9674e2d76e4cb7240828494 64.89kB / 64.89
kB [0.09s]
-> sha256:1c8ecfb769884297edda6110666c4027a4189a5aeaa01753990a06469ef410e8 46.50kB / 46.50
kB [0.07s]
-> sha256:2469ce994143b10eeb7768b5f537928b126eb664f950cd0fe09e7afdddbcf25e 58.07kB / 58.07
kB [0.16s]
-> sha256:40acd0c38da241dec59817eb50e6ec419aec8778e8afdef206f0a0876137fea1 58.58kB / 58.58
kB [0.10s]
-> sha256:4dc244c8406d4dc0d86b97e7331f214be754e2cefe061d62cca51d3353b68aa8 49.60kB / 49.60
kB [0.09s]
-> sha256:eb7fd9ecc788fc99dd0c716ebc369efc57accb6d47b180e4b89a4222e19875a3 24.74kB / 24.74
kB [0.08s]
-> sha256:2185e1ae942de9407bbc4fbc82475d8a11d7d6b558601a283e072acbfd819bb8 54.61kB / 54.61
kB [0.09s]
-> sha256:7a4e3b5c72380bea19bf1741ce7c2cd97a8aa48d938e21e56e8d82ed5fd7d828 1.42MB / 1.42MB
[0.17s]
-> sha256:dea03235b8b7ece3520d5411e653666e0912df6297d916088968242663f71200 343.11kB / 343.
11kB [0.10s]
-> sha256:f6e0d7d36d36b761876988a1fdf5142d67aaa1cb8cb6a33403161136310124b4 192.29kB / 192.
29kB [0.08s]
-> sha256:dd03ecccd7d32927cfa524495e999703bd86c74925d1abd08eac097c73992882 130.26kB / 130.
26kB [0.19s]
-> sha256:7dd763ba3b2eeeff08e755d0b765e1cacca7d380a007b1ef1a1acd70f4c5335a 62.56kB / 62.56
kB [0.11s]
-> sha256:7c7500e6a7491927f316b62f2b6435f1a464f9448acc4caa63d667a6ffb33298 728.40kB / 728.
40kB [0.10s]
-> sha256:dffa6d569ce3d29b12bdebbbe5968b5c91341cdc0668a9960d881ceda6ca0d94 54.23kB / 54.23
kB [0.07s]
-> sha256:3003f427cbed2a60728a5df991f5b95fed946f9e5bdc7ddbd3269440edfcd96d 95.21kB / 95.21
kB [0.09s]
-> sha256:81b4ae71597d7cf42cca6d2a459354d1cf6982f1e8632ab1dd625772adf8c5b2 87.86kB / 87.86
kB [0.09s]
-> sha256:f9c1790a94b8123c0049ff2562fde80c00220cafa04a3d19cc08343a9e31344e 124.94kB / 124.
94kB [0.12s]
-> sha256:0781eed041d3295d18d123109181d84854fe7ce45cf325f6dd0107edb9357a6c 1.28MB / 1.28MB
[0.14s]
-> sha256:d6d05d314fc95c2f9389b8b5d5e87dfc93e0aa830cded83d23d2e1af940f21f4 34.01kB / 34.01
kB [0.09s]
-> sha256:b38fef21bbe44f166c5ddae8435db5b17bbcaec5982f787354438b647bb72d18 448.34kB / 448.
34kB [0.10s]
-> sha256:b09f0e7e20d940b1d3b292b096204959258572e9bde76fa8f8bc38823daa025f 272.06kB / 272.
06kB [0.19s]
-> sha256:c346b5d234e9da68aee13e1f5737adfc3d5fce337093fcfa35e5cf7c6f06f775 772.65kB / 772.
65kB [0.13s]
-> sha256:cd15bc057bb9f2360497e372f99c7b65b0ef2c10afe6c8a28e3243188e67dc36 5.87kB / 5.87kB
[0.45s]
-> sha256:0c1b5d0a275f92d2dfaa4ff62dcbe323e2ccebba8ac88e2557af1df1033c2db2 935.94kB / 935.
94kB [0.14s]
-> sha256:8c75f28c635a0ad73cc14d0f4720791588c0726804b901d1d8cd998a3a1ce9cd 41.61kB / 41.61
kB [0.19s]
-> sha256:be20f5e11ae7e5bf136d6ba86402ad794500709c1de2dffd97cfdb5ba836f643 859.74kB / 859.
74kB [0.18s]
-> sha256:cd825aa0dfd5ac9f5a1b8136dcb86824c3f5aaf5957ecf1db51b760ed8b3d3c7 156.40kB / 156.
40kB [0.09s]
-> sha256:8a7a7837f1e0b13fb1ec7fc2a83f77d414c3de119708932c95707eacd9dc3774 17.95kB / 17.95
kB [0.08s]
-> sha256:790e812b4834038326baa6fbd431f9dfd12d86c3000e181d2070754bdf135d54 10.59kB / 10.59
kB [0.10s]
-> sha256:d32ab47f9a78f06062d0f1add8b1a6d61ebdcb949331aac045219f9a7e6c3f79 204.58kB / 204.
58kB [0.18s]
-> sha256:651ebf56993c0d399a26316d8b324828b928cb78d543aceceaec7a20dc3d4db6 232.63kB / 232.
63kB [0.08s]
-> sha256:5f1d3cf0f62d4324f52dce8d48c364926dae46516722043d44879fa03f80e973 1.61MB / 1.61MB
[0.33s]
-> sha256:e4d6d464d5051c704feb429b997defa8558ff9b2d66a3fdb698b988bdf4472db 193.79kB / 193.
79kB [0.09s]
-> sha256:9e3e0960ae529c016b5ca6ea0ba1634de0cd85f817a41d130995b38b2f600963 798.45kB / 798.
45kB [0.11s]
-> sha256:83adfe171493464184728d8fd978ae49a3101f75d568be3a9e05f770c9e39d37 439.98kB / 439.
98kB [0.20s]
-> sha256:e07d3425e084f6a9a5edc90e4229eca95cd40c9e9ec2d247bc85e8dbc8669b01 16.85kB / 16.85
kB [0.09s]
-> sha256:a9bf953f14693b50e6d9c72b79a37201ef3cb246d9732ad4ea4a05fea4b98303 29.12kB / 29.12
kB [0.35s]
-> sha256:32560fb65c145275c465e81ef228cc4b2fbf860d4663f2bf2fa9f95ce4cdd4c7 7.66kB / 7.66kB
[0.07s]
-> sha256:7066b2161a9198e122ac145495e2e02f859c150a571bf4b4553e1e7dffca0a39 5.28kB / 5.28kB
[0.07s]
-> sha256:b5118888e86ab16d42abd9f306ff88ad385dc07d1552a846496e6a1b09291a2c 5.17kB / 5.17kB
[0.07s]
-> sha256:fb3758be395fb7b246c995b6f90ef007071508c49d5f6ea7854832cc20686b2e 45.51kB / 45.51
kB [0.08s]
-> sha256:821dfd7a10f5a592ea1ee4120a6af51c68c87a2689a8cfa3b4581e8f614d6352 22.22kB / 22.22
kB [0.11s]
-> sha256:3cc1e8fed97922a90ea400cc34a2cf8e1ddd9dc11d27fd586154c4adc7095cec 9.53kB / 9.53kB
[0.12s]
-> sha256:1427ba16ad29c22f413f53ca0e06a034b811ca3f28e50a06c24a6dc4e58a218b 19.11kB / 19.11
kB [0.07s]
-> sha256:7f18c8caaa45ea731c7aceefafddc30bd32a378b3b847fd8ab3ed2b0dbdcb195 66.41kB / 66.41
kB [0.07s]
-> sha256:a651c438cfe1acabd281072353f92090eac9a8d9043ff27b7da116c220daf931 561.06kB / 561.
06kB [0.13s]
-> sha256:e84fc6e80fa99aed0b149a0c5a0f3c0b088d3527b1d60992ec39127314f4a864 157.75kB / 157.
75kB [0.34s]
-> sha256:c69c416cbc569afd465ef6e4170f05229e23d74ee2ffbad08d062e1c40fc854b 2.44MB / 2.44MB
[0.18s]
-> sha256:dcbfff89e735f3fc674039c0af0b8767d5e10c4321ed0ad46147a05af1a80732 516.83kB / 516.
83kB [0.22s]
-> sha256:39113223b71a6fc216562644a7f738ef5c14313235ac7c990f50ae32d86aa87f 28.89kB / 28.89
kB [0.11s]
-> sha256:38339e7bd940191e7ff5c07981d748795bc447c6ccaeabc93feae33465c2e8e8 222.88kB / 222.
88kB [0.10s]
-> sha256:07779d87d49be5f9292d6b1460852108e97ad689ca324855df4260738c063dc5 1.82MB / 1.82MB
[0.17s]
-> sha256:a8d81c96212b9af8f601d511198137fb4115ef00e592e84b16d76f8d30a62be3 10.73MB / 10.73
MB [1.80s]
-> sha256:aec9f58ab42abc1cad48fb4c716aa229941774c315d4481c7b10f2314852a714 98.51kB / 98.51
kB [0.34s]
-> sha256:40a20fdeab1274152801a3825faeeff41224f8aac36817dc4c04587ced1eab39 703.83kB / 703.
83kB [0.23s]
-> extracting sha256:40a20fdeab1274152801a3825faeeff41224f8aac36817dc4c04587ced1eab39 [0.0
2s]
-> extracting sha256:aec9f58ab42abc1cad48fb4c716aa229941774c315d4481c7b10f2314852a714 [0.0
2s]
-> extracting sha256:a8d81c96212b9af8f601d511198137fb4115ef00e592e84b16d76f8d30a62be3 [0.2
4s]
-> extracting sha256:07779d87d49be5f9292d6b1460852108e97ad689ca324855df4260738c063dc5 [0.0
2s]
-> extracting sha256:38339e7bd940191e7ff5c07981d748795bc447c6ccaeabc93feae33465c2e8e8 [0.0
2s]
-> extracting sha256:39113223b71a6fc216562644a7f738ef5c14313235ac7c990f50ae32d86aa87f [0.0
1s]
-> extracting sha256:dcbfff89e735f3fc674039c0af0b8767d5e10c4321ed0ad46147a05af1a80732 [0.0
1s]
-> extracting sha256:c69c416cbc569afd465ef6e4170f05229e23d74ee2ffbad08d062e1c40fc854b [0.0
3s]
-> extracting sha256:a651c438cfe1acabd281072353f92090eac9a8d9043ff27b7da116c220daf931 [0.0
1s]
-> extracting sha256:e84fc6e80fa99aed0b149a0c5a0f3c0b088d3527b1d60992ec39127314f4a864 [0.0
1s]
-> extracting sha256:7f18c8caaa45ea731c7aceefafddc30bd32a378b3b847fd8ab3ed2b0dbdcb195 [0.0
1s]
-> extracting sha256:1427ba16ad29c22f413f53ca0e06a034b811ca3f28e50a06c24a6dc4e58a218b [0.0
1s]
-> extracting sha256:3cc1e8fed97922a90ea400cc34a2cf8e1ddd9dc11d27fd586154c4adc7095cec [0.0
1s]
-> extracting sha256:821dfd7a10f5a592ea1ee4120a6af51c68c87a2689a8cfa3b4581e8f614d6352 [0.0
1s]
-> extracting sha256:fb3758be395fb7b246c995b6f90ef007071508c49d5f6ea7854832cc20686b2e [0.0
1s]
-> extracting sha256:b5118888e86ab16d42abd9f306ff88ad385dc07d1552a846496e6a1b09291a2c [0.0
1s]
-> extracting sha256:7066b2161a9198e122ac145495e2e02f859c150a571bf4b4553e1e7dffca0a39 [0.0
1s]
-> extracting sha256:32560fb65c145275c465e81ef228cc4b2fbf860d4663f2bf2fa9f95ce4cdd4c7 [0.0
1s]
-> extracting sha256:e07d3425e084f6a9a5edc90e4229eca95cd40c9e9ec2d247bc85e8dbc8669b01 [0.0
1s]
-> extracting sha256:a9bf953f14693b50e6d9c72b79a37201ef3cb246d9732ad4ea4a05fea4b98303 [0.0
1s]
-> extracting sha256:83adfe171493464184728d8fd978ae49a3101f75d568be3a9e05f770c9e39d37 [0.0
2s]
-> extracting sha256:e4d6d464d5051c704feb429b997defa8558ff9b2d66a3fdb698b988bdf4472db [0.0
1s]
-> extracting sha256:9e3e0960ae529c016b5ca6ea0ba1634de0cd85f817a41d130995b38b2f600963 [0.1
7s]
-> extracting sha256:5d53c544c7d839ffd7921a74f7997443b23a0e3bd3cea32e6b2065c9d62408a1 [0.0
1s]
-> extracting sha256:651ebf56993c0d399a26316d8b324828b928cb78d543aceceaec7a20dc3d4db6 [0.0
1s]
-> extracting sha256:5f1d3cf0f62d4324f52dce8d48c364926dae46516722043d44879fa03f80e973 [0.0
2s]
-> extracting sha256:790e812b4834038326baa6fbd431f9dfd12d86c3000e181d2070754bdf135d54 [0.0
0s]
-> extracting sha256:8a7a7837f1e0b13fb1ec7fc2a83f77d414c3de119708932c95707eacd9dc3774 [0.0
1s]
-> extracting sha256:d32ab47f9a78f06062d0f1add8b1a6d61ebdcb949331aac045219f9a7e6c3f79 [0.0
1s]
-> extracting sha256:cd825aa0dfd5ac9f5a1b8136dcb86824c3f5aaf5957ecf1db51b760ed8b3d3c7 [0.0
1s]
-> extracting sha256:be20f5e11ae7e5bf136d6ba86402ad794500709c1de2dffd97cfdb5ba836f643 [0.0
2s]
-> extracting sha256:8c75f28c635a0ad73cc14d0f4720791588c0726804b901d1d8cd998a3a1ce9cd [0.0
1s]
-> extracting sha256:0c1b5d0a275f92d2dfaa4ff62dcbe323e2ccebba8ac88e2557af1df1033c2db2 [0.0
2s]
-> extracting sha256:cd15bc057bb9f2360497e372f99c7b65b0ef2c10afe6c8a28e3243188e67dc36 [0.0
1s]
-> extracting sha256:c346b5d234e9da68aee13e1f5737adfc3d5fce337093fcfa35e5cf7c6f06f775 [0.0
1s]
-> extracting sha256:b38fef21bbe44f166c5ddae8435db5b17bbcaec5982f787354438b647bb72d18 [0.0
4s]
-> extracting sha256:d6d05d314fc95c2f9389b8b5d5e87dfc93e0aa830cded83d23d2e1af940f21f4 [0.0
1s]
-> extracting sha256:b09f0e7e20d940b1d3b292b096204959258572e9bde76fa8f8bc38823daa025f [0.0
2s]
-> extracting sha256:f9c1790a94b8123c0049ff2562fde80c00220cafa04a3d19cc08343a9e31344e [0.0
1s]
-> extracting sha256:81b4ae71597d7cf42cca6d2a459354d1cf6982f1e8632ab1dd625772adf8c5b2 [0.0
1s]
-> extracting sha256:3003f427cbed2a60728a5df991f5b95fed946f9e5bdc7ddbd3269440edfcd96d [0.0
1s]
-> extracting sha256:0781eed041d3295d18d123109181d84854fe7ce45cf325f6dd0107edb9357a6c [0.0
2s]
-> extracting sha256:dffa6d569ce3d29b12bdebbbe5968b5c91341cdc0668a9960d881ceda6ca0d94 [0.0
1s]
-> extracting sha256:7c7500e6a7491927f316b62f2b6435f1a464f9448acc4caa63d667a6ffb33298 [0.0
1s]
-> extracting sha256:7dd763ba3b2eeeff08e755d0b765e1cacca7d380a007b1ef1a1acd70f4c5335a [0.0
1s]
-> extracting sha256:f6e0d7d36d36b761876988a1fdf5142d67aaa1cb8cb6a33403161136310124b4 [0.0
1s]
-> extracting sha256:dd03ecccd7d32927cfa524495e999703bd86c74925d1abd08eac097c73992882 [0.0
1s]
-> extracting sha256:dea03235b8b7ece3520d5411e653666e0912df6297d916088968242663f71200 [0.0
1s]
-> extracting sha256:2185e1ae942de9407bbc4fbc82475d8a11d7d6b558601a283e072acbfd819bb8 [0.0
1s]
-> extracting sha256:eb7fd9ecc788fc99dd0c716ebc369efc57accb6d47b180e4b89a4222e19875a3 [0.0
1s]
-> extracting sha256:4dc244c8406d4dc0d86b97e7331f214be754e2cefe061d62cca51d3353b68aa8 [0.0
1s]
-> extracting sha256:7a4e3b5c72380bea19bf1741ce7c2cd97a8aa48d938e21e56e8d82ed5fd7d828 [0.0
4s]
-> extracting sha256:40acd0c38da241dec59817eb50e6ec419aec8778e8afdef206f0a0876137fea1 [0.0
1s]
-> extracting sha256:1c8ecfb769884297edda6110666c4027a4189a5aeaa01753990a06469ef410e8 [0.0
1s]
-> extracting sha256:2469ce994143b10eeb7768b5f537928b126eb664f950cd0fe09e7afdddbcf25e [0.0
1s]
-> extracting sha256:24810c5ac4e79c5fdcea8bad83c06ab9d00791d4b9674e2d76e4cb7240828494 [0.0
1s]
-> extracting sha256:f36ee716025d448d4c3c333247834477739c174ac10458cc745d1e173aac6723 [0.0
1s]
-> extracting sha256:ab3be33f13d0ee00d0d5f7e0f94e18f305b5a6a854903e942b49c795d5228b9d [0.0
4s]
-> extracting sha256:e0ac404bb6b0c47f03464c695dbeb8c9ec0ee6b14166554b94e4db4623d50fdf [0.0
1s]
-> extracting sha256:ced122dcc8c6fe25c842df344fcee339b1686fd241cbd8a48e23d99fc1b5de1c [0.0
0s]
-> extracting sha256:cd2474198fda394cd534b138c0a0a927ad2754a5137bd0e2c5f2f34590e57290 [0.0
6s]
-> extracting sha256:54e359541fabd36c7b13a08a94dac1d1aa796ac7aed5191920c38149de1652fa [0.0
1s]
-> extracting sha256:ec4bd40f92f0c10b5cb396fa14a3f97066611f09b497079e210e094d9285642a [0.0
1s]
-> extracting sha256:e93311f2be560d4e8464dfafa260e08150117d107b36870a75b8801416b40db8 [0.0
1s]
-> extracting sha256:bf844972b36a034d8fdf6276978f494db508b83ed0cd14e2aa091be762fd2e39 [0.0
1s]
-> extracting sha256:88d3758083ce65aa7c3d0e0abcfa624259b143748da5967650bf5aecf87c7889 [0.0
4s]
-> extracting sha256:19258425c0dcd828329f7affd14b14ff7cbe6e9611a78a1248fad89333b7fee0 [0.0
1s]
-> extracting sha256:a4ca34433450821e07a2d5a473cf6db01a3a1e6f64904d9e2a779cfc214b0f93 [0.3
4s]
-> extracting sha256:ab720c23f2e7e6c9fb51060e3ff1bbf31c1529450be545bc29222ce478d0d128 [0.0
1s]
-> extracting sha256:0083054199ca635652887bc798346711129c213e26152398becba07982bb81a1 [0.0
1s]
-> extracting sha256:a1ca1b014e5dcc895a1eb7dddc9647030ee3d9bbbf4a3a08569089089585102f [0.0
1s]
-> extracting sha256:e9e0e9aea6d5e169f1ad55d08734f4520ee5c4c314cbe28ed9c8f760bb7a1d8a [0.0
1s]
-> extracting sha256:2b50ae0e57765858706af584c01a1430a97a4e6520ace4e780e9bdd3b8829bbf [0.0
1s]
-> extracting sha256:8977114faeb36f655007e426bd1219abacb1cee9f5b4cd713b7a1083e6231eaa [0.0
1s]
-> extracting sha256:f8ecbb30c52aee2a2accbde4aa7336c3095830e6ca23bed5c753f8b07bab4467 [0.0
1s]
-> extracting sha256:78e5bdf4e64a38022a5757e12b5dc2ebc1029b7e05268166cbefcb48feb7fdd7 [0.0
1s]
-> extracting sha256:0ba65e28fa822231561b916aad61b3df726c82ee232040a77365d6fff468e6a5 [0.0
1s]
-> extracting sha256:8002be4bee9cf48ce180167f42de80170361dd0ef60c3e3d28cb6d32e3c5c958 [0.0
1s]
-> extracting sha256:d86119eb584112d7eb86b6b3fced80be5bd1b8574e253bc24ba38bd58c9697d3 [0.0
1s]
-> extracting sha256:a3e9e94168e8f814527af4a7ffda6c80350a0fdbfac602cf477672a1670738eb [0.0
1s]
-> extracting sha256:576ebd4999aeca869c2ed3758cc2e28265fdbfcadc7f2e244056b567a2058a19 [0.0
1s]
-> extracting sha256:b44071dfc8a9beb82c283348b3fbfcbbb6aa1fb96cc942a410bb3f7bb0ac1330 [0.0
1s]
-> extracting sha256:2e3a96843f4167bf9725d4c619b062770ad568152812d712fcf323ac2d471c64 [0.0
1s]
-> extracting sha256:f4043794f22a9c8c18f46fbc0f5bd5c4a78721ff9b3ea781643e3a2e9b13509b [0.0
1s]
-> extracting sha256:bb8f5039f79760416fbbf1e9237f5870a2c34c7192cb57f218fa782dcc9dfdfb [0.0
1s]
-> extracting sha256:25984f25cfc1f27ac45d21c6cc35950422fe04d8f9ca788678aa1b0e76378fa7 [0.0
1s]
-> extracting sha256:8de655e531a479cd5df6654700f8c2624a6944faa3ec5deb6ea4791b2f077528 [0.0
9s]
-> extracting sha256:18e9ddafd99bdc39f258099de889678e3d6bb22c06be845d3d3ed46a03248a25 [0.0
9s]
-> extracting sha256:a18cfd4fad222f42a63c356bb8d7f1ea7b6f86ac52772cbbecf885a83068d3e7 [0.0
4s]
-> extracting sha256:96d673aebc2504890df67be6b35c0ebcf928746e244489adbf531cd7f514ed73 [0.0
1s]
-> extracting sha256:69db97dd6e325102d04b31ea1121a0732c478f16ce23e688ccde7d7984cd359d [0.0
1s]
-> extracting sha256:b2c0c6341985babef8bdeaa30119a68ad09fbfb8975f2b94d12807a368d01c3b [0.0
1s]
-> extracting sha256:f28ad8353673c35e3f4e1ee43a37b8df4da36f49fa2ea93c6a2f42e5ae640573 [0.0
2s]
-> extracting sha256:39b89855c6effc99eda36378c2286c8ef6d8494db4262068ea5acf8e1a569bb6 [0.0
1s]
-> extracting sha256:e8ef8748ddbeaf268e7c72b76b0d99435eef73cd76741f05f52ca50ab7c4470b [0.0
6s]
-> extracting sha256:54365ec110d760dd2e1416e26e1e9b01d60b55498fbd3dd101b4b54384d81dac [0.1
1s]
-> extracting sha256:0a7b7e323bc39114e9b40ad7936ac4d852d5af85975fce95e80af9042820c801 [0.0
2s]
-> extracting sha256:d025e148aba21717c26f49cba4b95c75657554b944b647b90fbda93ffc0c986d [0.0
7s]
-> extracting sha256:ce685753a8e4d03c2a0f78617080878bb72f9d97c46ace731c9b19d91bc00250 [5.3
0s]
-> extracting sha256:2b14dde76908dd5f43137ce032f044c930fc6bec8378f379c50f0d6839f810bd [0.0
3s]
=> cp -anT /nix/ /cache/ [2.56s]
=> sh -c "echo accept-flake-config = true >> /etc/nix/nix.conf" [0.23s]
=> sh -c "echo experimental-features = nix-command flakes >> /etc/nix/nix.conf" [0.20s]
=> nix build .#wget ERROR [0.24s]
error: flake 'git+file:///bass/work' does not provide attribute 'packages.x86_64-linux
.wget', 'legacyPackages.x86_64-linux.wget' or 'wget'
!!! nix build .#wget
29: [0.19s] error: flake 'git+file:///bass/work' does not provide attribute 'packages.x86_
64-linux.wget', 'legacyPackages.x86_64-linux.wget' or 'wget'
error! call trace (oldest first):
┆ <fs>/literate-5:14:0..17:9
13 │
14 │ (-> (from image
15 │ ($ wget --version))
16 │ (read :lines)
17 │ next)
^^^^^^^^^^^^^^^^^^^^^^^^^
llb build failed: oci unpack failed: read config.json: exit code: 1
run summary:
=> resolve image config for docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a
057176c06a9f266de440be406dcf079b [0.02s]
=> resolve image config for docker.io/nixos/nix@sha256:c6c9e6bf8d2d87877ef931bbf5c350d84
ac114e33a4abacc3f2e51dcbed25ea1 [0.62s]
for more information, refer to the full output above
𝄢

Bass does everything it can to support hermetic thunks, but it stops short of enforcing the practice. If Nix isn't worth the investment yet, YOLO and apt-get away and fix it when it breaks.

demo webhook-driven CI/CD
𝄢

Bass Loop is a public service for calling Bass code in response to webhooks.

First, install the GitHub app and put a script like this in your repo at bass/github-hook:

; file for memoized dependency resolution
(def *memos* *dir*/bass.lock)

; load dependencies
(use (.git (linux/alpine/git))
     (git:github/vito/bass-loop/ref/main/bass/github.bass))

; run Go tests
(defn go-test [src & args]
  (from (linux/golang)
    (cd src
      ($ go test & $args))))

; standard suite of validations for the repo
(defn checks [src]
  {:test (go-test src "./...")})

; called by bass-loop
(defn main []
  (for [event *stdin*]
    (github:check-hook event git:checkout checks)))
stderr: 37 lines
=> resolve image config for docker.io/alpine/git:latest [0.22s]
=> git ls-remote https://github.com/vito/bass-loop main [0.42s]
=> exporting to client [0.00s]
-> copying files 83B [0.00s]
=> resolve image config for docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a05
7176c06a9f266de440be406dcf079b [0.00s]
=> docker-image://docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f
266de440be406dcf079b CACHED [0.00s]
-> resolve docker.io/alpine/git@sha256:3ad0f6025feea6c01f552e467989a79a057176c06a9f266de44
0be406dcf079b [0.01s]
=> git clone https://github.com/vito/bass-loop ./ [2.15s]
Cloning into '.'...
=> git fetch origin 4d2df18701653fc9ec705da34fa9e6d70fab465f [0.49s]
From https://github.com/vito/bass-loop
* branch 4d2df18701653fc9ec705da34fa9e6d70fab465f -> FETCH_HEAD
=> git checkout 4d2df18701653fc9ec705da34fa9e6d70fab465f [0.27s]
Note: switching to '4d2df18701653fc9ec705da34fa9e6d70fab465f'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:
git switch -c <new-branch-name>
Or undo this operation with:
git switch -
Turn off this advice by setting config variable advice.detachedHead to false
HEAD is now at 4d2df18 ignore redundant pull_request.synchronize events
=> git submodule update --init --recursive [0.25s]
=> exporting to client [0.00s]
-> sending tarball [0.00s]
main
𝄢

Next start a Bass runner to let Bass Loop use your local runtimes:

bass --runner myuser@github.bass-lang.org

From here on anything that myuser does to the repo will route an event to the bass/github-hook script with myuser's runners available for running thunks.

The github:check-hook helper handles check-related events by running thunks as GitHub status checks. Other events may be interpreted however you like.