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
{
:platform
{
:os "linux"
}
:repository "alpine"
:tag "latest"
:digest "sha256:686d8c9dfa6f3ccfc8230bc3178d23f84eeaf7e457f36f271ab1acc53015037c"
}
: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: 12 lines
=> echo "Hello, world!" [0.11s]
=> exporting to client [0.00s]
-> copying files 40B [0.00s]
=> resolve image config for docker.io/library/alpine@sha256:686d8c9dfa6f3ccfc8230bc3178d23
f84eeaf7e457f36f271ab1acc53015037c [0.01s]
=> docker-image://docker.io/library/alpine@sha256:686d8c9dfa6f3ccfc8230bc3178d23f84eeaf7e4
57f36f271ab1acc53015037c CACHED [0.00s]
-> resolve docker.io/library/alpine@sha256:686d8c9dfa6f3ccfc8230bc3178d23f84eeaf7e457f36f2
71ab1acc53015037c [0.01s]
=> echo "Hello, world!" [0.15s]
Hello, world!
Hello, world!
(
  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
{
:platform
{
:os "linux"
}
:repository "alpine"
:tag "latest"
:digest "sha256:686d8c9dfa6f3ccfc8230bc3178d23f84eeaf7e457f36f271ab1acc53015037c"
}
: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
{
:platform
{
:os "linux"
}
:repository "alpine"
:tag "latest"
:digest "sha256:686d8c9dfa6f3ccfc8230bc3178d23f84eeaf7e457f36f271ab1acc53015037c"
}
:cmd .cat
:args
(
  1. .sh
    {
    :image
    {
    :platform
    {
    :os "linux"
    }
    :repository "alpine"
    :tag "latest"
    :digest "sha256:686d8c9dfa6f3ccfc8230bc3178d23f84eeaf7e457f36f271ab1acc53015037c"
    }
    :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:686d8c9dfa6f3ccfc8230bc3178d23
f84eeaf7e457f36f271ab1acc53015037c [0.01s]
=> docker-image://docker.io/library/alpine@sha256:686d8c9dfa6f3ccfc8230bc3178d23f84eeaf7e4
57f36f271ab1acc53015037c CACHED [0.00s]
-> resolve docker.io/library/alpine@sha256:686d8c9dfa6f3ccfc8230bc3178d23f84eeaf7e457f36f2
71ab1acc53015037c [0.01s]
=> sh -c "echo hello >> file" [0.21s]
=> cat <thunk 8FWxtM0wY_4=: (.sh)>/file [0.23s]
=> 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:23dcd3edfd1d9c7cbb14f7823d07a49347
16cfa4d4dbc402d37ee011c440a685 [0.35s]
=> docker-image://docker.io/alpine/git@sha256:23dcd3edfd1d9c7cbb14f7823d07a4934716cfa4d4db
c402d37ee011c440a685 CACHED [0.00s]
-> resolve docker.io/alpine/git@sha256:23dcd3edfd1d9c7cbb14f7823d07a4934716cfa4d4dbc402d37
ee011c440a685 [0.01s]
=> git ls-remote https://github.com/vito/bass main [0.40s]
=> exporting to client [0.00s]
-> copying files 83B [0.00s]
.git
{
:image
.git
{
:image
.git
{
:image
.git
{
:image
{
:platform
{
:os "linux"
}
:repository "alpine/git"
:tag "latest"
:digest "sha256:23dcd3edfd1d9c7cbb14f7823d07a4934716cfa4d4dbc402d37ee011c440a685"
}
:cmd .git
:args
(
  1. "clone"
  2. "https://github.com/vito/bass"
  3. ./
)
}
:cmd .git
:args
(
  1. "fetch"
  2. "origin"
  3. "6c037a9d134c8b60d61fcd0023494358b94e265f"
)
}
:cmd .git
:args
(
  1. "checkout"
  2. "6c037a9d134c8b60d61fcd0023494358b94e265f"
)
}
: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
{
:platform
{
:os "linux"
}
:repository "alpine/git"
:tag "latest"
:digest "sha256:23dcd3edfd1d9c7cbb14f7823d07a4934716cfa4d4dbc402d37ee011c440a685"
}
: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: 49 lines
=> resolve image config for docker.io/alpine/git@sha256:23dcd3edfd1d9c7cbb14f7823d07a49347
16cfa4d4dbc402d37ee011c440a685 [0.01s]
=> resolve image config for docker.io/library/golang@sha256:a452d6273ad03a47c2f29b898d6bb5
7630e77baf839651ef77d03e4e049c5bf3 [0.44s]
=> docker-image://docker.io/library/golang@sha256:a452d6273ad03a47c2f29b898d6bb57630e77baf
839651ef77d03e4e049c5bf3 CACHED [0.00s]
-> resolve docker.io/library/golang@sha256:a452d6273ad03a47c2f29b898d6bb57630e77baf839651e
f77d03e4e049c5bf3 [0.01s]
=> docker-image://docker.io/alpine/git@sha256:23dcd3edfd1d9c7cbb14f7823d07a4934716cfa4d4db
c402d37ee011c440a685 CACHED [0.00s]
-> resolve docker.io/alpine/git@sha256:23dcd3edfd1d9c7cbb14f7823d07a4934716cfa4d4dbc402d37
ee011c440a685 [0.02s]
=> git clone https://github.com/vito/booklit ./ [1.25s]
Cloning into '.'...
=> git fetch origin d8dcef4dedfa4e2a96cc16a820e2a97805e91b8c [0.38s]
From https://github.com/vito/booklit
* branch d8dcef4dedfa4e2a96cc16a820e2a97805e91b8c -> FETCH_HEAD
=> git checkout d8dcef4dedfa4e2a96cc16a820e2a97805e91b8c [0.18s]
Note: switching to 'd8dcef4dedfa4e2a96cc16a820e2a97805e91b8c'.
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 d8dcef4 make testflags optional
=> git submodule update --init --recursive [0.14s]
=> go test ./tests/ [4.27s]
go: downloading github.com/onsi/gomega v1.19.0
go: downloading github.com/onsi/ginkgo/v2 v2.1.4
go: downloading github.com/sirupsen/logrus v1.7.0
go: downloading github.com/segmentio/textio v1.2.0
go: downloading github.com/agext/levenshtein v1.2.3
go: downloading golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8
go: downloading gopkg.in/yaml.v2 v2.4.0
go: downloading golang.org/x/net v0.0.0-20220225172249-27dd8689420f
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.136s
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: 326 lines
=> resolve image config for docker.io/library/rust@sha256:8220e4fbb22a07b78e6472cdf8f5fb89
13a04974c26b130177b73a8a64334541 [0.75s]
=> resolve image config for docker.io/alpine/git@sha256:23dcd3edfd1d9c7cbb14f7823d07a49347
16cfa4d4dbc402d37ee011c440a685 [0.01s]
=> docker-image://docker.io/library/rust@sha256:8220e4fbb22a07b78e6472cdf8f5fb8913a04974c2
6b130177b73a8a64334541 CACHED [0.00s]
-> resolve docker.io/library/rust@sha256:8220e4fbb22a07b78e6472cdf8f5fb8913a04974c26b13017
7b73a8a64334541 [0.11s]
=> docker-image://docker.io/alpine/git@sha256:23dcd3edfd1d9c7cbb14f7823d07a4934716cfa4d4db
c402d37ee011c440a685 CACHED [0.00s]
-> resolve docker.io/alpine/git@sha256:23dcd3edfd1d9c7cbb14f7823d07a4934716cfa4d4dbc402d37
ee011c440a685 [0.19s]
=> git clone https://github.com/alacritty/alacritty ./ [2.10s]
Cloning into '.'...
=> git fetch origin ebc6922eaae28173532235222f9790c8ab3fdaa7 [0.44s]
From https://github.com/alacritty/alacritty
* branch ebc6922eaae28173532235222f9790c8ab3fdaa7 -> FETCH_HEAD
=> git checkout ebc6922eaae28173532235222f9790c8ab3fdaa7 [0.24s]
Note: switching to 'ebc6922eaae28173532235222f9790c8ab3fdaa7'.
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 ebc6922e Add `cursor.blink_timeout` config option
=> git submodule update --init --recursive [0.17s]
=> cargo test ./alacritty_terminal/ [48.4s]
Updating crates.io index
Downloading crates ...
Downloaded serde_derive v1.0.137
Downloaded x11-dl v2.19.1
Downloaded xcursor v0.3.4
Downloaded wayland-protocols v0.29.4
Downloaded dirs v4.0.0
Downloaded copypasta v0.8.1
Downloaded downcast-rs v1.2.0
Downloaded cmake v0.1.48
Downloaded memmap2 v0.3.1
Downloaded inotify-sys v0.1.5
Downloaded notify v4.0.17
Downloaded signal-hook v0.3.14
Downloaded wayland-commons v0.29.4
Downloaded wayland-egl v0.29.4
Downloaded x11-clipboard v0.6.1
Downloaded xml-rs v0.8.4
Downloaded xdg v2.4.1
Downloaded log v0.4.17
Downloaded yaml-rust v0.4.5
Downloaded scopeguard v1.1.0
Downloaded strsim v0.10.0
Downloaded proc-macro-error v1.0.4
Downloaded parking_lot_core v0.8.5
Downloaded version_check v0.9.4
Downloaded memoffset v0.6.5
Downloaded heck v0.4.0
Downloaded gl_generator v0.14.0
Downloaded crc32fast v1.3.2
Downloaded glutin_egl_sys v0.1.5
Downloaded serde_yaml v0.8.24
Downloaded foreign-types v0.5.0
Downloaded dirs-sys v0.3.7
Downloaded winit v0.26.1
Downloaded pkg-config v0.3.25
Downloaded termcolor v1.1.3
Downloaded unicode-ident v1.0.1
Downloaded walkdir v2.3.2
Downloaded os_str_bytes v6.1.0
Downloaded signal-hook-registry v1.4.0
Downloaded smallvec v1.8.0
Downloaded nom v7.1.1
Downloaded regex-syntax v0.6.26
Downloaded inotify v0.7.1
Downloaded fnv v1.0.7
Downloaded vte v0.10.1
Downloaded filetime v0.2.16
Downloaded minimal-lexical v0.2.1
Downloaded png v0.16.8
Downloaded same-file v1.0.6
Downloaded once_cell v1.12.0
Downloaded libloading v0.7.3
Downloaded textwrap v0.15.0
Downloaded percent-encoding v2.1.0
Downloaded osmesa-sys v0.1.2
Downloaded ryu v1.0.10
Downloaded freetype-sys v0.13.1
Downloaded khronos_api v3.1.0
Downloaded servo-fontconfig-sys v5.1.0
Downloaded regex-automata v0.1.10
Downloaded slab v0.4.6
Downloaded memchr v2.5.0
Downloaded expat-sys v2.1.6
Downloaded iovec v0.1.4
Downloaded clap_lex v0.2.2
Downloaded quick-xml v0.22.0
Downloaded net2 v0.2.37
Downloaded freetype-rs v0.26.0
Downloaded base64 v0.13.0
Downloaded cc v1.0.73
Downloaded autocfg v1.1.0
Downloaded bitflags v1.3.2
Downloaded cfg-if v0.1.10
Downloaded glutin v0.28.0
Downloaded cfg-if v1.0.0
Downloaded atty v0.2.14
Downloaded unicode-width v0.1.9
Downloaded glutin_glx_sys v0.1.7
Downloaded parking_lot v0.11.2
Downloaded hashbrown v0.12.1
Downloaded foreign-types-shared v0.3.1
Downloaded libc v0.2.126
Downloaded proc-macro-error-attr v1.0.4
Downloaded instant v0.1.12
Downloaded crossfont v0.3.2
Downloaded lock_api v0.4.7
Downloaded itoa v1.0.2
Downloaded dlib v0.5.0
Downloaded clap v3.2.5
Downloaded xcb v1.1.1
Downloaded lazy_static v1.4.0
Downloaded wayland-scanner v0.29.4
Downloaded mio v0.8.3
Downloaded wayland-cursor v0.29.4
Downloaded mio-extras v2.0.6
Downloaded wayland-client v0.29.4
Downloaded mio-uds v0.6.8
Downloaded mio v0.6.23
Downloaded vte_generate_state_changes v0.1.1
Downloaded utf8parse v0.2.0
Downloaded syn v1.0.96
Downloaded smithay-clipboard v0.6.5
Downloaded smithay-client-toolkit v0.15.4
Downloaded shared_library v0.1.9
Downloaded serde_json v1.0.81
Downloaded serde v1.0.137
Downloaded scoped-tls v1.0.0
Downloaded raw-window-handle v0.4.3
Downloaded quote v1.0.18
Downloaded proc-macro2 v1.0.39
Downloaded nix v0.22.3
Downloaded miniz_oxide v0.3.7
Downloaded linked-hash-map v0.5.4
Downloaded lazycell v1.3.0
Downloaded indexmap v1.9.0
Downloaded foreign-types-macros v0.2.2
Downloaded adler32 v1.2.0
Downloaded cty v0.2.2
Downloaded clap_derive v3.2.5
Downloaded clap_complete v3.2.1
Downloaded calloop v0.9.3
Downloaded wayland-sys v0.29.4
Downloaded servo-fontconfig v0.5.1
Downloaded signal-hook-mio v0.2.3
Compiling proc-macro2 v1.0.39
Compiling unicode-ident v1.0.1
Compiling libc v0.2.126
Compiling cfg-if v1.0.0
Compiling syn v1.0.96
Compiling serde_derive v1.0.137
Compiling pkg-config v0.3.25
Compiling serde v1.0.137
Compiling autocfg v1.1.0
Compiling log v0.4.17
Compiling bitflags v1.3.2
Compiling xml-rs v0.8.4
Compiling lazy_static v1.4.0
Compiling smallvec v1.8.0
Compiling memchr v2.5.0
Compiling khronos_api v3.1.0
Compiling once_cell v1.12.0
Compiling cc v1.0.73
Compiling hashbrown v0.12.1
Compiling downcast-rs v1.2.0
Compiling cfg-if v0.1.10
Compiling scoped-tls v1.0.0
Compiling version_check v0.9.4
Compiling slab v0.4.6
Compiling minimal-lexical v0.2.1
Compiling parking_lot_core v0.8.5
Compiling ryu v1.0.10
Compiling scopeguard v1.1.0
Compiling linked-hash-map v0.5.4
Compiling signal-hook v0.3.14
Compiling lazycell v1.3.0
Compiling serde_json v1.0.81
Compiling utf8parse v0.2.0
Compiling regex-syntax v0.6.26
Compiling itoa v1.0.2
Compiling base64 v0.13.0
Compiling heck v0.4.0
Compiling winit v0.26.1
Compiling crc32fast v1.3.2
Compiling unicode-width v0.1.9
Compiling os_str_bytes v6.1.0
Compiling cty v0.2.2
Compiling same-file v1.0.6
Compiling textwrap v0.15.0
Compiling foreign-types-shared v0.3.1
Compiling adler32 v1.2.0
Compiling percent-encoding v2.1.0
Compiling termcolor v1.1.3
Compiling strsim v0.10.0
Compiling fnv v1.0.7
Compiling libloading v0.7.3
Compiling instant v0.1.12
Compiling yaml-rust v0.4.5
Compiling raw-window-handle v0.4.3
Compiling walkdir v2.3.2
Compiling miniz_oxide v0.3.7
Compiling clap_lex v0.2.2
Compiling cmake v0.1.48
Compiling proc-macro-error-attr v1.0.4
Compiling proc-macro-error v1.0.4
Compiling memoffset v0.6.5
Compiling indexmap v1.9.0
Compiling lock_api v0.4.7
Compiling dlib v0.5.0
Compiling wayland-sys v0.29.4
Compiling smithay-client-toolkit v0.15.4
Compiling x11-dl v2.19.1
Compiling servo-fontconfig-sys v5.1.0
Compiling crossfont v0.3.2
Compiling freetype-sys v0.13.1
Compiling expat-sys v2.1.6
Compiling nom v7.1.1
Compiling quick-xml v0.22.0
Compiling png v0.16.8
Compiling quote v1.0.18
Compiling wayland-scanner v0.29.4
Compiling vte_generate_state_changes v0.1.1
Compiling xcb v1.1.1
Compiling vte v0.10.1
Compiling nix v0.22.3
Compiling iovec v0.1.4
Compiling net2 v0.2.37
Compiling dirs-sys v0.3.7
Compiling memmap2 v0.3.1
Compiling signal-hook-registry v1.4.0
Compiling inotify-sys v0.1.5
Compiling shared_library v0.1.9
Compiling atty v0.2.14
Compiling filetime v0.2.16
Compiling wayland-client v0.29.4
Compiling wayland-protocols v0.29.4
Compiling inotify v0.7.1
Compiling osmesa-sys v0.1.2
Compiling dirs v4.0.0
Compiling parking_lot v0.11.2
Compiling regex-automata v0.1.10
Compiling xdg v2.4.1
Compiling freetype-rs v0.26.0
Compiling servo-fontconfig v0.5.1
Compiling xcursor v0.3.4
Compiling wayland-commons v0.29.4
Compiling alacritty_config_derive v0.1.0 (/bass/work/alacritty_config_derive)
Compiling foreign-types-macros v0.2.2
Compiling clap_derive v3.2.5
Compiling wayland-cursor v0.29.4
Compiling wayland-egl v0.29.4
Compiling foreign-types v0.5.0
Compiling clap v3.2.5
Compiling x11-clipboard v0.6.1
Compiling clap_complete v3.2.1
Compiling serde_yaml v0.8.24
Compiling gl_generator v0.14.0
Compiling mio v0.6.23
Compiling calloop v0.9.3
Compiling mio v0.8.3
Compiling mio-extras v2.0.6
Compiling mio-uds v0.6.8
Compiling glutin_egl_sys v0.1.5
Compiling glutin_glx_sys v0.1.7
Compiling alacritty v0.11.0-dev (/bass/work/alacritty)
Compiling signal-hook-mio v0.2.3
Compiling notify v4.0.17
Compiling alacritty_terminal v0.17.0-dev (/bass/work/alacritty_terminal)
Compiling smithay-clipboard v0.6.5
Compiling copypasta v0.8.1
Compiling glutin v0.28.0
Finished test [unoptimized + debuginfo] target(s) in 47.72s
Running unittests src/main.rs (target/debug/deps/alacritty-6fc19acce0f43a2f)
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 65 filtered out; finished
in 0.00s
Running unittests src/lib.rs (target/debug/deps/alacritty_config_derive-59da9f654
e47c341)
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-06f628c23f53425d)
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out; finished i
n 0.00s
Running unittests src/lib.rs (target/debug/deps/alacritty_terminal-715fa16a6173df
fd)
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-bf5a450fd62a81bc)
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 41 filtered out; finished
in 0.00s
true
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: 53 lines
=> resolve image config for docker.io/library/golang@sha256:a452d6273ad03a47c2f29b898d6bb5
7630e77baf839651ef77d03e4e049c5bf3 [0.02s]
=> resolve image config for docker.io/alpine/git@sha256:23dcd3edfd1d9c7cbb14f7823d07a49347
16cfa4d4dbc402d37ee011c440a685 [0.02s]
=> resolve image config for docker.io/library/alpine@sha256:686d8c9dfa6f3ccfc8230bc3178d23
f84eeaf7e457f36f271ab1acc53015037c [0.03s]
=> docker-image://docker.io/alpine/git@sha256:23dcd3edfd1d9c7cbb14f7823d07a4934716cfa4d4db
c402d37ee011c440a685 CACHED [0.00s]
-> resolve docker.io/alpine/git@sha256:23dcd3edfd1d9c7cbb14f7823d07a4934716cfa4d4dbc402d37
ee011c440a685 [0.07s]
=> docker-image://docker.io/library/golang@sha256:a452d6273ad03a47c2f29b898d6bb57630e77baf
839651ef77d03e4e049c5bf3 CACHED [0.00s]
-> resolve docker.io/library/golang@sha256:a452d6273ad03a47c2f29b898d6bb57630e77baf839651e
f77d03e4e049c5bf3 [0.10s]
=> docker-image://docker.io/library/alpine@sha256:686d8c9dfa6f3ccfc8230bc3178d23f84eeaf7e4
57f36f271ab1acc53015037c CACHED [0.00s]
-> resolve docker.io/library/alpine@sha256:686d8c9dfa6f3ccfc8230bc3178d23f84eeaf7e457f36f2
71ab1acc53015037c [0.09s]
=> git clone https://github.com/vito/booklit ./ [1.54s]
Cloning into '.'...
=> git fetch origin d8dcef4dedfa4e2a96cc16a820e2a97805e91b8c [0.55s]
From https://github.com/vito/booklit
* branch d8dcef4dedfa4e2a96cc16a820e2a97805e91b8c -> FETCH_HEAD
=> git checkout d8dcef4dedfa4e2a96cc16a820e2a97805e91b8c [0.20s]
Note: switching to 'd8dcef4dedfa4e2a96cc16a820e2a97805e91b8c'.
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 d8dcef4 make testflags optional
=> git submodule update --init --recursive [0.18s]
=> go build ./cmd/booklit [2.89s]
go: downloading github.com/sirupsen/logrus v1.7.0
go: downloading github.com/jessevdk/go-flags v1.4.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-20220319134239-a9b59b0215f8
=> <thunk gLYx6uvnpdA=: (.go)>/booklit --version [0.18s]
time="2022-07-24T15:30:25Z" 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": {
      "platform": {
        "os": "linux"
      },
      "repository": "golang",
      "tag": "latest",
      "digest": "sha256:a452d6273ad03a47c2f29b898d6bb57630e77baf839651ef77d03e4e049c5bf3"
    }
  },
  "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": {
                            "platform": {
                              "os": "linux"
                            },
                            "repository": "alpine/git",
                            "tag": "latest",
                            "digest": "sha256:23dcd3edfd1d9c7cbb14f7823d07a4934716cfa4d4dbc402d37ee011c440a685"
                          }
                        },
                        "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": "d8dcef4dedfa4e2a96cc16a820e2a97805e91b8c"
                        }
                      }
                    ]
                  }
                },
                "cmd": {
                  "command": {
                    "name": "git"
                  }
                },
                "args": [
                  {
                    "string": {
                      "value": "checkout"
                    }
                  },
                  {
                    "string": {
                      "value": "d8dcef4dedfa4e2a96cc16a820e2a97805e91b8c"
                    }
                  }
                ]
              }
            },
            "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.15s]
=> resolve image config for docker.io/alpine/git@sha256:760aaf0d59c93f87572ec40dee1efd10a7
ea13a78dff1f59a904e908449329ae [0.01s]
=> docker-image://docker.io/alpine/git@sha256:760aaf0d59c93f87572ec40dee1efd10a7ea13a78dff
1f59a904e908449329ae CACHED [0.00s]
-> resolve docker.io/alpine/git@sha256:760aaf0d59c93f87572ec40dee1efd10a7ea13a78dff1f59a90
4e908449329ae [0.02s]
=> local:///tmp/bass-scope3763074961 [0.04s]
-> transferring /tmp/bass-scope3763074961: 2.11kB [0.00s]
=> copy /bass.lock /bass.lock CACHED [0.00s]
=> cat <host: /tmp/bass-scope3763074961/bass.lock> [0.17s]
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: "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"
}
}
}
bindings: {
symbol: "digest"
value: {
string: {
value: "sha256:760aaf0d59c93f87572ec40dee1efd10a7ea13a78dff1f59a904e90
8449329ae"
}
}
}
}
}
}
}
}
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:760aaf0d59c93f87572ec40dee1efd10a7
ea13a78dff1f59a904e908449329ae [0.01s]
=> docker-image://docker.io/alpine/git@sha256:760aaf0d59c93f87572ec40dee1efd10a7ea13a78dff
1f59a904e908449329ae CACHED [0.00s]
-> resolve docker.io/alpine/git@sha256:760aaf0d59c93f87572ec40dee1efd10a7ea13a78dff1f59a90
4e908449329ae [0.01s]
=> git ls-remote https://github.com/vito/booklit master [0.38s]
=> exporting to client [0.00s]
-> copying files 85B [0.00s]
.git
{
:image
.git
{
:image
.git
{
:image
.git
{
:image
{
:platform
{
:os "linux"
}
:repository "alpine/git"
:tag "latest"
:digest "sha256:760aaf0d59c93f87572ec40dee1efd10a7ea13a78dff1f59a904e908449329ae"
}
:cmd .git
:args
(
  1. "clone"
  2. "https://github.com/vito/booklit"
  3. ./
)
}
:cmd .git
:args
(
  1. "fetch"
  2. "origin"
  3. "fa5ac72ee654bc6f81c4c615456d4f71fb20f70e"
)
}
:cmd .git
:args
(
  1. "checkout"
  2. "fa5ac72ee654bc6f81c4c615456d4f71fb20f70e"
)
}
: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: 81 lines
=> resolve image config for docker.io/library/golang@sha256:a452d6273ad03a47c2f29b898d6bb5
7630e77baf839651ef77d03e4e049c5bf3 [0.01s]
=> resolve image config for docker.io/alpine/git@sha256:760aaf0d59c93f87572ec40dee1efd10a7
ea13a78dff1f59a904e908449329ae [0.01s]
=> docker-image://docker.io/alpine/git@sha256:760aaf0d59c93f87572ec40dee1efd10a7ea13a78dff
1f59a904e908449329ae CACHED [0.00s]
-> resolve docker.io/alpine/git@sha256:760aaf0d59c93f87572ec40dee1efd10a7ea13a78dff1f59a90
4e908449329ae [0.02s]
=> docker-image://docker.io/library/golang@sha256:a452d6273ad03a47c2f29b898d6bb57630e77baf
839651ef77d03e4e049c5bf3 CACHED [0.00s]
-> resolve docker.io/library/golang@sha256:a452d6273ad03a47c2f29b898d6bb57630e77baf839651e
f77d03e4e049c5bf3 [0.02s]
=> git clone https://github.com/vito/booklit ./ [1.02s]
Cloning into '.'...
=> git fetch origin fa5ac72ee654bc6f81c4c615456d4f71fb20f70e [0.44s]
From https://github.com/vito/booklit
* branch fa5ac72ee654bc6f81c4c615456d4f71fb20f70e -> FETCH_HEAD
=> git checkout fa5ac72ee654bc6f81c4c615456d4f71fb20f70e [0.20s]
Note: switching to 'fa5ac72ee654bc6f81c4c615456d4f71fb20f70e'.
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 fa5ac72 bump deps
=> git submodule update --init --recursive [0.20s]
=> go install -mod=mod github.com/onsi/ginkgo/v2/ginkgo [1.92s]
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/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0
go: downloading github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38
=> ./scripts/test -p [3.71s]
go: downloading github.com/sirupsen/logrus v1.8.1
go: downloading github.com/jessevdk/go-flags v1.4.0
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 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a
go: downloading github.com/onsi/gomega v1.19.0
go: downloading golang.org/x/net v0.0.0-20220225172249-27dd8689420f
go: downloading gopkg.in/yaml.v2 v2.4.0
go: downloading github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964
go: downloading github.com/dlclark/regexp2 v1.4.0
go: downloading golang.org/x/text v0.3.7
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: 1658676632
Will run 62 of 62 specs
Running in parallel across 31 processes
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
Ran 62 of 62 Specs in 0.056 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.55357351s
Test Suite Passed
.go
{
:image
{
:platform
{
:os "linux"
}
:repository "golang"
: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
{
:platform
{
:os "linux"
}
:repository "alpine/git"
:tag "latest"
:digest "sha256:760aaf0d59c93f87572ec40dee1efd10a7ea13a78dff1f59a904e908449329ae"
}
:cmd .git
:args
(
  1. "clone"
  2. "https://github.com/vito/booklit"
  3. ./
)
}
:cmd .git
:args
(
  1. "fetch"
  2. "origin"
  3. "fa5ac72ee654bc6f81c4c615456d4f71fb20f70e"
)
}
:cmd .git
:args
(
  1. "checkout"
  2. "fa5ac72ee654bc6f81c4c615456d4f71fb20f70e"
)
}
: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 :unix-table)
    next)
stderr: 17 lines
=> resolve image config for docker.io/library/alpine@sha256:686d8c9dfa6f3ccfc8230bc3178d23
f84eeaf7e457f36f271ab1acc53015037c [0.01s]
=> docker-image://docker.io/library/alpine@sha256:686d8c9dfa6f3ccfc8230bc3178d23f84eeaf7e4
57f36f271ab1acc53015037c CACHED [0.00s]
-> resolve docker.io/library/alpine@sha256:686d8c9dfa6f3ccfc8230bc3178d23f84eeaf7e457f36f2
71ab1acc53015037c [0.01s]
=> apk add wget [0.51s]
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-r13.trigger
OK: 8 MiB in 17 packages
=> wget --version [0.18s]
=> exporting to client [0.00s]
-> copying files 889B [0.00s]
(
  1. "GNU"
  2. "Wget"
  3. "1.21.3"
  4. "built"
  5. "on"
  6. "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 :unix-table)
    next)
stderr: 421 lines
=> resolve image config for docker.io/alpine/git@sha256:23dcd3edfd1d9c7cbb14f7823d07a49347
16cfa4d4dbc402d37ee011c440a685 [0.01s]
=> resolve image config for docker.io/nixos/nix@sha256:800bd47a0587a69351155195fb343a8cbf8
bda3b08822324419b95ca940aced6 [0.33s]
=> /shim get-config /image.tar latest /config [0.74s]
=> docker-image://docker.io/alpine/git@sha256:23dcd3edfd1d9c7cbb14f7823d07a4934716cfa4d4db
c402d37ee011c440a685 CACHED [0.00s]
-> resolve docker.io/alpine/git@sha256:23dcd3edfd1d9c7cbb14f7823d07a4934716cfa4d4dbc402d37
ee011c440a685 [0.14s]
=> docker-image://docker.io/nixos/nix@sha256:800bd47a0587a69351155195fb343a8cbf8bda3b08822
324419b95ca940aced6 CACHED [0.00s]
-> resolve docker.io/nixos/nix@sha256:800bd47a0587a69351155195fb343a8cbf8bda3b08822324419b
95ca940aced6 [0.18s]
=> git clone https://github.com/vito/tabs ./ [0.67s]
Cloning into '.'...
Cloning into '.'...
=> git fetch origin b3109bfbd35fd036bb53872e5d96efbe4e70d63c [0.87s]
From https://github.com/vito/tabs
* branch b3109bfbd35fd036bb53872e5d96efbe4e70d63c -> FETCH_HEAD
From https://github.com/vito/tabs
* branch b3109bfbd35fd036bb53872e5d96efbe4e70d63c -> FETCH_HEAD
=> git checkout b3109bfbd35fd036bb53872e5d96efbe4e70d63c [1.87s]
Note: switching to 'b3109bfbd35fd036bb53872e5d96efbe4e70d63c'.
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 b3109bf use proper cache mount
Note: switching to 'b3109bfbd35fd036bb53872e5d96efbe4e70d63c'.
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 b3109bf use proper cache mount
=> cp -anT /nix/ /cache/ [3.53s]
=> git submodule update --init --recursive [0.20s]
=> sh -c "echo accept-flake-config = true >> /etc/nix/nix.conf" [0.16s]
=> sh -c "echo experimental-features = nix-command flakes >> /etc/nix/nix.conf" [0.15s]
=> nix build .#wget [12.1s]
ps://cache.nixos.org'...
copying path '/nix/store/01ymyhl5ckhav09f7p6vk7w227bicglv-jq-1.6-bin' from 'https://ca
che.nixos.org'...
copying path '/nix/store/gxd2dcwrl8md895jv3bdd66h94mp4y45-p11-kit-0.24.1' from 'https:
//cache.nixos.org'...
copying path '/nix/store/bp7pp334492vakq55q6yywcz8zz4aw34-jq-1.6-dev' from 'https://ca
che.nixos.org'...
copying path '/nix/store/mfabz5ca7wvfvcrxvn33g8hm5fa3j444-patch-2.7.6' from 'https://c
ache.nixos.org'...
copying path '/nix/store/zj6yl2nnfnpxs4fyian311qh2g3cqq5n-patchelf-0.14.5' from 'https
://cache.nixos.org'...
copying path '/nix/store/h4p6zlxn610yc5lca8mqhdbb58cii6qf-pcre-8.45' from 'https://cac
he.nixos.org'...
copying path '/nix/store/l38y35dfxnfaykqrwbzw35zia97njxhr-pcsclite-1.9.5' from 'https:
//cache.nixos.org'...
copying path '/nix/store/1rfvqdj1sc27ckiypcw5hnmfb30paj80-gnugrep-3.7' from 'https://c
ache.nixos.org'...
copying path '/nix/store/ps10d4qcxdc3m7b0d3pl2k3mpp4y3w7f-readline-6.3p08' from 'https
://cache.nixos.org'...
copying path '/nix/store/mjv4xxiza91sxxvh81xa4a17kqss1alk-readline-8.1p2' from 'https:
//cache.nixos.org'...
copying path '/nix/store/79mjj0i5pk18b421b18n6l76lc52194j-shadow-4.11.1' from 'https:/
/cache.nixos.org'...
copying path '/nix/store/zxn21d03iv66n147ff90j8m5mh5xl0x6-bash-interactive-5.1-p16' fr
om 'https://cache.nixos.org'...
copying path '/nix/store/lxs208z93abszq4w10519fabfp0yra7k-unbound-1.16.0-lib' from 'ht
tps://cache.nixos.org'...
copying path '/nix/store/4p6wj2g767855c7xm8paiyv5zijmq4zk-util-linux-minimal-2.37.4-li
b' from 'https://cache.nixos.org'...
copying path '/nix/store/134szwf95aw083hyzhb49ck7v6pb69wa-xz-5.2.5' from 'https://cach
e.nixos.org'...
copying path '/nix/store/pisrqv75qx1qka6bfjsb5a4fqgarb92a-zlib-1.2.12' from 'https://c
ache.nixos.org'...
copying path '/nix/store/n2rjs5jhndw6xs3nrssnh2s5sqmjwqch-xz-5.2.5-bin' from 'https://
cache.nixos.org'...
copying path '/nix/store/8ira0m19haxn7ivyljszvv0isrx9wajp-file-5.42' from 'https://cac
he.nixos.org'...
copying path '/nix/store/x1vyq24aikfjrnxlil6jbqn47mlrjjw4-gnutls-3.7.6' from 'https://
cache.nixos.org'...
copying path '/nix/store/lld7b0pmx2q7n7zzrn07na4sh4z4nz9x-kexec-tools-2.0.23' from 'ht
tps://cache.nixos.org'...
copying path '/nix/store/ay1dvxdh51wvszxs3zc9jnr7pz51v5kv-libssh2-1.10.0' from 'https:
//cache.nixos.org'...
copying path '/nix/store/mbq3hagjkl6d71f35ma6l74b0vfm63z2-sqlite-3.38.5' from 'https:/
/cache.nixos.org'...
copying path '/nix/store/n2bxjp8yddyyz9a55ds4rab6qcwq5k6i-stdenv-linux' from 'https://
cache.nixos.org'...
copying path '/nix/store/i6svmmq24wl4i10dx0m8blrpl3m3fq4b-python3-3.10.5' from 'https:
//cache.nixos.org'...
copying path '/nix/store/safvv3qk0a7xpr0v3ja6s3sg05jn3yff-util-linux-minimal-2.37.4-bi
n' from 'https://cache.nixos.org'...
copying path '/nix/store/mas82imyjs4b4alsjvxm5gxys2qgvwdx-python3.10-mccabe-0.7.0' fro
m 'https://cache.nixos.org'...
copying path '/nix/store/afrh9pcw90xd4nk952xwsl687bivvwb3-fuse-3.11.0' from 'https://c
ache.nixos.org'...
copying path '/nix/store/aqd16jkx8gp4zvkdrrgigv8lyxfa8432-python3.10-pycodestyle-2.8.0
' from 'https://cache.nixos.org'...
copying path '/nix/store/d90qc45dpb1mzhpkvv9jg070kzs66n68-fuse-overlayfs-1.9' from 'ht
tps://cache.nixos.org'...
copying path '/nix/store/y9hikj0wyhls32szga4p891w5ia9mg37-python3.10-pyflakes-2.4.0' f
rom 'https://cache.nixos.org'...
copying path '/nix/store/xy1f0jmykvr95i5nid632lpafzbsnd13-wget-1.21.3' from 'https://c
ache.nixos.org'...
copying path '/nix/store/1d9h2xxx98acrx1pklv7bnf8144ydy9h-python3.10-flake8-4.0.1' fro
m 'https://cache.nixos.org'...
copying path '/nix/store/rpc0i8kyawcx1chrj2hsj6jk063qzh9l-zstd-1.5.2' from 'https://ca
che.nixos.org'...
copying path '/nix/store/j5qzvmnx32h4y6c8k21msqp44f0lqxmx-curl-7.83.1' from 'https://c
ache.nixos.org'...
copying path '/nix/store/cggcci4yjli237ip5jkliqx9rfxlyf6i-kmod-29' from 'https://cache
.nixos.org'...
copying path '/nix/store/h6krmpryzmk7f2wdpakbclv45sj02jw2-kmod-29-lib' from 'https://c
ache.nixos.org'...
copying path '/nix/store/7nkgiqn5a7lagcggyp70la8n2w2a44gj-tpm2-tss-3.2.0' from 'https:
//cache.nixos.org'...
copying path '/nix/store/16nv73zp36b9x0j1lrisdjpxpa2wq0fc-zstd-1.5.2-bin' from 'https:
//cache.nixos.org'...
copying path '/nix/store/2yrhgdi9n5dk9xc2k5pzai6kfzk9i00k-kbd-2.4.0' from 'https://cac
he.nixos.org'...
copying path '/nix/store/zckiqvxwy2h0yrwzimdgbz528afx9v92-systemd-minimal-250.4' from
'https://cache.nixos.org'...
copying path '/nix/store/ib0xp9srjpg37mdfpsnjv2940byycrgx-libusb-1.0.26' from 'https:/
/cache.nixos.org'...
copying path '/nix/store/gdys7p77yk3a6h1a6y07218rr91dc016-lvm2-2.03.16-lib' from 'http
s://cache.nixos.org'...
copying path '/nix/store/np5bvhrdlia5kk9f9j9r916nwws7aky5-openldap-2.6.2' from 'https:
//cache.nixos.org'...
copying path '/nix/store/nwhm40qyzk2v4hlr50wc38xd9yd6rwcy-gnupg-2.3.4' from 'https://c
ache.nixos.org'...
copying path '/nix/store/p7i6rs2c62jx0n0k384zjjmag8nbqqd9-gpgme-1.17.1' from 'https://
cache.nixos.org'...
copying path '/nix/store/m9jw2v6f644481i85dlysw7yg7fidfr9-skopeo-1.8.0' from 'https://
cache.nixos.org'...
building '/nix/store/jwcpsk8qdg1q9irrlm1g7paiizk46qfr-pythoncheck.sh.drv'...
building '/nix/store/s5f68z15qnvm68221rcll26h8fnal2jm-wget-base.json.drv'...
building '/nix/store/6xb4rrhbhwkprxxd253zzc3hf2vg9gqw-stream.drv'...
building '/nix/store/5zjm2nqiai0a8z2w5akgv8w2kyh1nf9i-wget-customisation-layer.drv'...
building '/nix/store/hija8fqlzs9pr24zqsbffmqn4jjk4s10-closure.drv'...
building '/nix/store/f609r1j55s4b0ylz5656dk86iz4yswzw-closure-paths.drv'...
building '/nix/store/irxjfrx5l9gkmv9fgy2yr390hvw90b2a-wget-conf.json.drv'...
building '/nix/store/i8r0nmv92vls57hkj8zgml13hb8hcnva-stream-wget.drv'...
building '/nix/store/3j611s3w007r2wmbqfg7mm5jasbgvx3y-convert-to-oci.drv'...
copying path '/nix/store/6h1ra1da5vp1s8jz06gbswh51z66aq3m-source' from 'https://cache.
nixos.org'...
copying path '/nix/store/q1wlsb1xnfszx2sxixh4iidyi71jfch0-iana-etc-20220520' from 'htt
ps://cache.nixos.org'...
copying path '/nix/store/5kvf3bb5ky11d6j0dhh42dvgmyxz1vvd-dns-root-data-2019-01-11' fr
om 'https://cache.nixos.org'...
copying path '/nix/store/m1jcim7wd96p7jzvqygzbsghygwdbnwy-hook' from 'https://cache.ni
xos.org'...
copying path '/nix/store/7k3alvjrd0017ddk87rdnmdvlgh7yq9d-libunistring-1.0' from 'http
s://cache.nixos.org'...
copying path '/nix/store/xxyjm5ym6iiahkxk2z69mjvvqsy82hvl-mailcap-2.1.53' from 'https:
//cache.nixos.org'...
copying path '/nix/store/finq3bf8qy4nwkc447q7msg4g8nliyii-libidn2-2.3.2' from 'https:/
/cache.nixos.org'...
copying path '/nix/store/gkifbcgfg1aagfs4jhpghjp1jyyxgckj-nss-cacert-3.77' from 'https
://cache.nixos.org'...
copying path '/nix/store/d2bpliayddadf6lx6l1i04w265gqw8n6-glibc-2.34-210' from 'https:
//cache.nixos.org'...
copying path '/nix/store/h8cddb1h4v6ji6jk2nb045rss1qglgpq-tzdata-2022a' from 'https://
cache.nixos.org'...
copying path '/nix/store/izcz7c162lbrf5x1p10jdsl3976rqakw-attr-2.5.1' from 'https://ca
che.nixos.org'...
copying path '/nix/store/j9rc786ylq8cid4zgcn6idknilkbd4ax-bash-5.1-p16' from 'https://
cache.nixos.org'...
copying path '/nix/store/slsipgn62dsb3hfpzrajspg4smqf3pbx-acl-2.3.1' from 'https://cac
he.nixos.org'...
copying path '/nix/store/n9lm3r4y9mlws10zyr948bisr94vxv3n-audit-2.8.5' from 'https://c
ache.nixos.org'...
copying path '/nix/store/7ybdhr79mnhk3l9s6gyvz7pysddj98wi-brotli-1.0.9-lib' from 'http
s://cache.nixos.org'...
copying path '/nix/store/rwwnll35xfyvclkln2cfrgclh2h1zn8m-bzip2-1.0.6.0.2' from 'https
://cache.nixos.org'...
copying path '/nix/store/l2xyarvzahpz3fysr9hqbvcsgv5gnrnk-coreutils-9.1' from 'https:/
/cache.nixos.org'...
copying path '/nix/store/79p6fdmfh5j2xcxhyk8m9sl7adzhkdpq-bzip2-1.0.6.0.2-bin' from 'h
ttps://cache.nixos.org'...
copying path '/nix/store/fagksixa18rdzwhm7mnwzdp022nrnv5l-diffutils-3.8' from 'https:/
/cache.nixos.org'...
copying path '/nix/store/0dqrzslb583fg9djf9hyjxxcx7vfmqhd-ed-1.18' from 'https://cache
.nixos.org'...
copying path '/nix/store/vx1zy8hvlxikddh23fvg7hnwnqvrxwcx-expat-2.4.8' from 'https://c
ache.nixos.org'...
copying path '/nix/store/ip1zdc23sqyq15957lbjrxj31m5xh72c-findutils-4.9.0' from 'https
://cache.nixos.org'...
copying path '/nix/store/kd0dqqh4r906b8iwrvim4c0qv3dmamnf-gawk-5.1.1' from 'https://ca
che.nixos.org'...
copying path '/nix/store/q9gfnkp0zaafccpgj4mqngmp9f9y93xh-gcc-11.3.0-lib' from 'https:
//cache.nixos.org'...
copying path '/nix/store/9f4lg3l2apl379c57rn32rwvv156f19i-gdbm-1.23' from 'https://cac
he.nixos.org'...
copying path '/nix/store/0drsizydfkwwajxggm0qzpyl90s1214s-db-4.8.30' from 'https://cac
he.nixos.org'...
copying path '/nix/store/ah5b34v5ijnpqhh3qn5j32x1ndxijwcd-db-5.3.28' from 'https://cac
he.nixos.org'...
copying path '/nix/store/pmvgsqy9vjclaznyhy9s8xvy04imx5rf-getopt-1.1.6' from 'https://
cache.nixos.org'...
copying path '/nix/store/qxq3ph04z32rl87xnxp4yysh1kbgdnz4-glibc-2.34-210-bin' from 'ht
tps://cache.nixos.org'...
copying path '/nix/store/1q9k5apzlndwm35xpqi67xk1l5b7hdhf-gmp-with-cxx-6.2.1' from 'ht
tps://cache.nixos.org'...
copying path '/nix/store/r6vrx8p12zmyj5009k09cjzk1p266jw7-getent-glibc-2.34-210' from
'https://cache.nixos.org'...
copying path '/nix/store/8q06kxhkl4dq3vjd3ai2j8n9kr26c271-gnumake-4.3' from 'https://c
ache.nixos.org'...
copying path '/nix/store/l62i4fn54qry9xamnj209wfizpw2bng5-gnused-4.8' from 'https://ca
che.nixos.org'...
copying path '/nix/store/vq67896gm97w895dv8vj6nyf5313zc58-gnutar-1.34' from 'https://c
ache.nixos.org'...
copying path '/nix/store/dz4qq384sipkgkzxml1cbaakikgp3bbb-fakeroot-1.27' from 'https:/
/cache.nixos.org'...
copying path '/nix/store/nkzahhyaf1yb9isqwyfq9n5gxq7civ0z-gzip-1.12' from 'https://cac
he.nixos.org'...
copying path '/nix/store/9yr1ay52lrf8v5ah84xxhwm8dan1x5qf-hook' from 'https://cache.ni
xos.org'...
copying path '/nix/store/34jc2wa8w5hpylfhmqjc8s4rm30cb1qm-json-c-0.16' from 'https://c
ache.nixos.org'...
copying path '/nix/store/44j1nb4zkam4mh3shm908mmny2dszrlm-keyutils-1.6.3-lib' from 'ht
tps://cache.nixos.org'...
copying path '/nix/store/xxlxkymxhn0qrrw765ijrp0vy42hdx0q-libcap-2.63-lib' from 'https
://cache.nixos.org'...
copying path '/nix/store/679b75nskd8v3cz59l8km3ryp2xv02mz-libcap-ng-0.8.3' from 'https
://cache.nixos.org'...
copying path '/nix/store/jccnhww7mfqiq3n2xlc7q0973m5g8m2l-libevent-2.1.12' from 'https
://cache.nixos.org'...
copying path '/nix/store/486bqy0m7j6apmv18hl4f7v2iz59ldsn-libffi-3.4.2' from 'https://
cache.nixos.org'...
copying path '/nix/store/a5v1jccav7kvix5d7yv08j6kadscg2zh-libgpg-error-1.42' from 'htt
ps://cache.nixos.org'...
copying path '/nix/store/9xbmqfmiqhin5dpl6iachlagnc4n0h3q-libkrb5-1.19.3' from 'https:
//cache.nixos.org'...
copying path '/nix/store/v0xgdbd95j7ycdckyhwpjikzv8g43sf1-libassuan-2.5.5' from 'https
://cache.nixos.org'...
copying path '/nix/store/6mi45403amjh4ak7qa8v5lm196hdmrpi-libgcrypt-1.10.1' from 'http
s://cache.nixos.org'...
copying path '/nix/store/rg3jc87x4z2dcg3k53b9rzj4fqdrh7kw-libksba-1.6.0' from 'https:/
/cache.nixos.org'...
copying path '/nix/store/0lkg220xyxiaxi0npvzc4zs94rp4fg34-libseccomp-2.5.4-lib' from '
https://cache.nixos.org'...
copying path '/nix/store/mg7kp9pnfi3ihbf0dch41yv1p7rkmhk2-libsodium-1.0.18' from 'http
s://cache.nixos.org'...
copying path '/nix/store/xw4rjy3afbpccsr7r5bkc6crrhfr6n39-libtasn1-4.18.0' from 'https
://cache.nixos.org'...
copying path '/nix/store/hglww1nykzp80xamqvi6i0i73p65d6ky-libtool-2.4.7-lib' from 'htt
ps://cache.nixos.org'...
copying path '/nix/store/5vav88j08xi9c52jb9112s4aq0anpsz9-linux-pam-1.5.2' from 'https
://cache.nixos.org'...
copying path '/nix/store/l554d56s6w7ks2nb86v1p6s4fzxzzx3c-lndir-1.0.3' from 'https://c
ache.nixos.org'...
copying path '/nix/store/wicpy8xpj34skkd76y95rfmg1l880qxm-ncurses-6.3-p20220507' from
'https://cache.nixos.org'...
copying path '/nix/store/d0a0kk85rghjbydw9h594r53zcsdr5sn-nettle-3.7.3' from 'https://
cache.nixos.org'...
copying path '/nix/store/8zwfl3159sgxfrj3w3japfrc6ljc6nj3-libedit-20210910-3.1' from '
https://cache.nixos.org'...
copying path '/nix/store/dqn8bydkccbhhyg45pd6jsiahq9ihw0b-nghttp2-1.47.0-lib' from 'ht
tps://cache.nixos.org'...
copying path '/nix/store/c39kadk9r0fqwzd5z5w6fnlnjw0wcq99-dash-0.5.11.5' from 'https:/
/cache.nixos.org'...
copying path '/nix/store/2x258dshrxd1ys7bkgsrz51ddn7rh12g-npth-1.6' from 'https://cach
e.nixos.org'...
copying path '/nix/store/is67c0b7knhd8i930xxfpmrh0dskwymp-onig-6.9.8' from 'https://ca
che.nixos.org'...
copying path '/nix/store/1jdz8w346plnjawqs76q005ygbp7dgzn-openssl-1.1.1p' from 'https:
//cache.nixos.org'...
copying path '/nix/store/wrlj7h8kixc5y8qkjaar24012nw9mr1m-jq-1.6-lib' from 'https://ca
che.nixos.org'...
copying path '/nix/store/k3y0szbcxbf0acyjgkppcwfkrv3kmp24-cyrus-sasl-2.1.28' from 'htt
ps://cache.nixos.org'...
copying path '/nix/store/01ymyhl5ckhav09f7p6vk7w227bicglv-jq-1.6-bin' from 'https://ca
che.nixos.org'...
copying path '/nix/store/gxd2dcwrl8md895jv3bdd66h94mp4y45-p11-kit-0.24.1' from 'https:
//cache.nixos.org'...
copying path '/nix/store/bp7pp334492vakq55q6yywcz8zz4aw34-jq-1.6-dev' from 'https://ca
che.nixos.org'...
copying path '/nix/store/mfabz5ca7wvfvcrxvn33g8hm5fa3j444-patch-2.7.6' from 'https://c
ache.nixos.org'...
copying path '/nix/store/zj6yl2nnfnpxs4fyian311qh2g3cqq5n-patchelf-0.14.5' from 'https
://cache.nixos.org'...
copying path '/nix/store/h4p6zlxn610yc5lca8mqhdbb58cii6qf-pcre-8.45' from 'https://cac
he.nixos.org'...
copying path '/nix/store/l38y35dfxnfaykqrwbzw35zia97njxhr-pcsclite-1.9.5' from 'https:
//cache.nixos.org'...
copying path '/nix/store/1rfvqdj1sc27ckiypcw5hnmfb30paj80-gnugrep-3.7' from 'https://c
ache.nixos.org'...
copying path '/nix/store/ps10d4qcxdc3m7b0d3pl2k3mpp4y3w7f-readline-6.3p08' from 'https
://cache.nixos.org'...
copying path '/nix/store/mjv4xxiza91sxxvh81xa4a17kqss1alk-readline-8.1p2' from 'https:
//cache.nixos.org'...
copying path '/nix/store/79mjj0i5pk18b421b18n6l76lc52194j-shadow-4.11.1' from 'https:/
/cache.nixos.org'...
copying path '/nix/store/zxn21d03iv66n147ff90j8m5mh5xl0x6-bash-interactive-5.1-p16' fr
om 'https://cache.nixos.org'...
copying path '/nix/store/lxs208z93abszq4w10519fabfp0yra7k-unbound-1.16.0-lib' from 'ht
tps://cache.nixos.org'...
copying path '/nix/store/4p6wj2g767855c7xm8paiyv5zijmq4zk-util-linux-minimal-2.37.4-li
b' from 'https://cache.nixos.org'...
copying path '/nix/store/134szwf95aw083hyzhb49ck7v6pb69wa-xz-5.2.5' from 'https://cach
e.nixos.org'...
copying path '/nix/store/pisrqv75qx1qka6bfjsb5a4fqgarb92a-zlib-1.2.12' from 'https://c
ache.nixos.org'...
copying path '/nix/store/n2rjs5jhndw6xs3nrssnh2s5sqmjwqch-xz-5.2.5-bin' from 'https://
cache.nixos.org'...
copying path '/nix/store/8ira0m19haxn7ivyljszvv0isrx9wajp-file-5.42' from 'https://cac
he.nixos.org'...
copying path '/nix/store/x1vyq24aikfjrnxlil6jbqn47mlrjjw4-gnutls-3.7.6' from 'https://
cache.nixos.org'...
copying path '/nix/store/lld7b0pmx2q7n7zzrn07na4sh4z4nz9x-kexec-tools-2.0.23' from 'ht
tps://cache.nixos.org'...
copying path '/nix/store/ay1dvxdh51wvszxs3zc9jnr7pz51v5kv-libssh2-1.10.0' from 'https:
//cache.nixos.org'...
copying path '/nix/store/mbq3hagjkl6d71f35ma6l74b0vfm63z2-sqlite-3.38.5' from 'https:/
/cache.nixos.org'...
copying path '/nix/store/n2bxjp8yddyyz9a55ds4rab6qcwq5k6i-stdenv-linux' from 'https://
cache.nixos.org'...
copying path '/nix/store/i6svmmq24wl4i10dx0m8blrpl3m3fq4b-python3-3.10.5' from 'https:
//cache.nixos.org'...
copying path '/nix/store/safvv3qk0a7xpr0v3ja6s3sg05jn3yff-util-linux-minimal-2.37.4-bi
n' from 'https://cache.nixos.org'...
copying path '/nix/store/mas82imyjs4b4alsjvxm5gxys2qgvwdx-python3.10-mccabe-0.7.0' fro
m 'https://cache.nixos.org'...
copying path '/nix/store/afrh9pcw90xd4nk952xwsl687bivvwb3-fuse-3.11.0' from 'https://c
ache.nixos.org'...
copying path '/nix/store/aqd16jkx8gp4zvkdrrgigv8lyxfa8432-python3.10-pycodestyle-2.8.0
' from 'https://cache.nixos.org'...
copying path '/nix/store/d90qc45dpb1mzhpkvv9jg070kzs66n68-fuse-overlayfs-1.9' from 'ht
tps://cache.nixos.org'...
copying path '/nix/store/y9hikj0wyhls32szga4p891w5ia9mg37-python3.10-pyflakes-2.4.0' f
rom 'https://cache.nixos.org'...
copying path '/nix/store/xy1f0jmykvr95i5nid632lpafzbsnd13-wget-1.21.3' from 'https://c
ache.nixos.org'...
copying path '/nix/store/1d9h2xxx98acrx1pklv7bnf8144ydy9h-python3.10-flake8-4.0.1' fro
m 'https://cache.nixos.org'...
copying path '/nix/store/rpc0i8kyawcx1chrj2hsj6jk063qzh9l-zstd-1.5.2' from 'https://ca
che.nixos.org'...
copying path '/nix/store/j5qzvmnx32h4y6c8k21msqp44f0lqxmx-curl-7.83.1' from 'https://c
ache.nixos.org'...
copying path '/nix/store/cggcci4yjli237ip5jkliqx9rfxlyf6i-kmod-29' from 'https://cache
.nixos.org'...
copying path '/nix/store/h6krmpryzmk7f2wdpakbclv45sj02jw2-kmod-29-lib' from 'https://c
ache.nixos.org'...
copying path '/nix/store/7nkgiqn5a7lagcggyp70la8n2w2a44gj-tpm2-tss-3.2.0' from 'https:
//cache.nixos.org'...
copying path '/nix/store/16nv73zp36b9x0j1lrisdjpxpa2wq0fc-zstd-1.5.2-bin' from 'https:
//cache.nixos.org'...
copying path '/nix/store/2yrhgdi9n5dk9xc2k5pzai6kfzk9i00k-kbd-2.4.0' from 'https://cac
he.nixos.org'...
copying path '/nix/store/zckiqvxwy2h0yrwzimdgbz528afx9v92-systemd-minimal-250.4' from
'https://cache.nixos.org'...
copying path '/nix/store/ib0xp9srjpg37mdfpsnjv2940byycrgx-libusb-1.0.26' from 'https:/
/cache.nixos.org'...
copying path '/nix/store/gdys7p77yk3a6h1a6y07218rr91dc016-lvm2-2.03.16-lib' from 'http
s://cache.nixos.org'...
copying path '/nix/store/np5bvhrdlia5kk9f9j9r916nwws7aky5-openldap-2.6.2' from 'https:
//cache.nixos.org'...
copying path '/nix/store/nwhm40qyzk2v4hlr50wc38xd9yd6rwcy-gnupg-2.3.4' from 'https://c
ache.nixos.org'...
copying path '/nix/store/p7i6rs2c62jx0n0k384zjjmag8nbqqd9-gpgme-1.17.1' from 'https://
cache.nixos.org'...
copying path '/nix/store/m9jw2v6f644481i85dlysw7yg7fidfr9-skopeo-1.8.0' from 'https://
cache.nixos.org'...
building '/nix/store/jwcpsk8qdg1q9irrlm1g7paiizk46qfr-pythoncheck.sh.drv'...
building '/nix/store/s5f68z15qnvm68221rcll26h8fnal2jm-wget-base.json.drv'...
building '/nix/store/6xb4rrhbhwkprxxd253zzc3hf2vg9gqw-stream.drv'...
building '/nix/store/5zjm2nqiai0a8z2w5akgv8w2kyh1nf9i-wget-customisation-layer.drv'...
building '/nix/store/hija8fqlzs9pr24zqsbffmqn4jjk4s10-closure.drv'...
building '/nix/store/f609r1j55s4b0ylz5656dk86iz4yswzw-closure-paths.drv'...
building '/nix/store/irxjfrx5l9gkmv9fgy2yr390hvw90b2a-wget-conf.json.drv'...
building '/nix/store/i8r0nmv92vls57hkj8zgml13hb8hcnva-stream-wget.drv'...
building '/nix/store/3j611s3w007r2wmbqfg7mm5jasbgvx3y-convert-to-oci.drv'...
=> cp -aL ./result ./image.tar [0.22s]
=> /shim unpack /image.tar latest /rootfs [0.40s]
2022/07/24 15:31:32 info unpack layer: sha256:39c614d8028d1c3bec585a3968b8b40d5215939
19a4006c34cf79414ccac45f5
2022/07/24 15:31:32 info unpack layer: sha256:bb3af251ccd8052300dbb138edd20856bf3d484
7b8c6ad0d79397cfe220c1d09
2022/07/24 15:31:32 info unpack layer: sha256:85f22eff71685c69a2fc63fe37f90215409f020
fa54cbd6ec4fde0c1b4cab067
2022/07/24 15:31:32 info unpack layer: sha256:cbac56117026b4954b99a7a547ff02e70507e15
0fa3a77f36bda65497b4d91fb
2022/07/24 15:31:32 info unpack layer: sha256:175203191886ec6c58fe8dae2d03a57c6cdfa44
53cde0e0fbb3e4d0a8abce9e7
2022/07/24 15:31:32 info unpack layer: sha256:4e395cff9c8627f0d7080d6e050759de1d73965
e89ecf17cafed8da986f9d625
2022/07/24 15:31:32 info unpack layer: sha256:f79ce08f6a3789843bb48e1c5c75e8b2be3ca7b
d6fdefb7a40dac74c71adb405
2022/07/24 15:31:32 info unpack layer: sha256:c153ae8ea08f98779953e24fff560b9b16fe29f
647d54773807958394484c523
2022/07/24 15:31:32 info unpack layer: sha256:6abe5c92d343c5f64ea60a3f71ceafc504ed9a5
8513fac7aa72dfac5de4f6400
2022/07/24 15:31:32 info unpack layer: sha256:be3f46dead1d6f2eadda76ef20c0aeda0ed93dd
e9de56cb4fccac10dcd90fb65
=> wget --version [0.14s]
=> exporting to client [0.00s]
-> copying files 712B [0.00s]
(
  1. "GNU"
  2. "Wget"
  3. "1.21.3"
  4. "built"
  5. "on"
  6. "linux-gnu."
)
𝄢

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: 10 lines
=> resolve image config for docker.io/alpine/git:latest [0.19s]
=> resolve image config for docker.io/alpine/git@sha256:760aaf0d59c93f87572ec40dee1efd10a7
ea13a78dff1f59a904e908449329ae [0.01s]
=> docker-image://docker.io/alpine/git@sha256:760aaf0d59c93f87572ec40dee1efd10a7ea13a78dff
1f59a904e908449329ae CACHED [0.00s]
-> resolve docker.io/alpine/git@sha256:760aaf0d59c93f87572ec40dee1efd10a7ea13a78dff1f59a90
4e908449329ae [0.01s]
=> git ls-remote https://github.com/vito/bass-loop main [0.43s]
=> exporting to client [0.00s]
-> copying files 83B [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.